Cover runtime bootstrap source contract
- SHA
d67b8f99f005b49de6752069d8a61f84284f2dc0- Parents
-
3c26874 - Tree
ebfca5e
d67b8f9
d67b8f99f005b49de6752069d8a61f84284f2dc03c26874
ebfca5e| Status | File | + | - |
|---|---|---|---|
| M |
tests/test_response_route_handlers.py
|
1 | 1 |
| M |
tests/test_response_routing.py
|
1 | 1 |
| M |
tests/test_runtime_bootstrap.py
|
21 | 7 |
| M |
tests/test_runtime_context.py
|
5 | 3 |
| M |
tests/test_runtime_launcher.py
|
4 | 1 |
| M |
tests/test_turn_iteration.py
|
1 | 1 |
tests/test_response_route_handlers.pymodified@@ -51,7 +51,7 @@ async def _prepare_context( | |||
| 51 | task=prepared.task, | 51 | task=prepared.task, |
| 52 | effective_task=prepared.effective_task, | 52 | effective_task=prepared.effective_task, |
| 53 | iterations=1, | 53 | iterations=1, |
| 54 | - max_iterations=runtime.agent.config.max_iterations, | 54 | + max_iterations=runtime.context.config.max_iterations, |
| 55 | actions_taken=[], | 55 | actions_taken=[], |
| 56 | continuation_count=continuation_count, | 56 | continuation_count=continuation_count, |
| 57 | consecutive_errors=consecutive_errors, | 57 | consecutive_errors=consecutive_errors, |
tests/test_response_routing.pymodified@@ -53,7 +53,7 @@ async def _prepare_context( | |||
| 53 | task=prepared.task, | 53 | task=prepared.task, |
| 54 | effective_task=prepared.effective_task, | 54 | effective_task=prepared.effective_task, |
| 55 | iterations=1, | 55 | iterations=1, |
| 56 | - max_iterations=runtime.agent.config.max_iterations, | 56 | + max_iterations=runtime.context.config.max_iterations, |
| 57 | actions_taken=[], | 57 | actions_taken=[], |
| 58 | continuation_count=continuation_count, | 58 | continuation_count=continuation_count, |
| 59 | consecutive_errors=consecutive_errors, | 59 | consecutive_errors=consecutive_errors, |
tests/test_runtime_bootstrap.pymodified@@ -5,7 +5,12 @@ from __future__ import annotations | |||
| 5 | from pathlib import Path | 5 | from pathlib import Path |
| 6 | 6 | ||
| 7 | from loader.agent.loop import Agent, AgentConfig | 7 | from loader.agent.loop import Agent, AgentConfig |
| 8 | -from loader.runtime.bootstrap import build_runtime_context, sync_runtime_context | 8 | +from loader.runtime.bootstrap import ( |
| 9 | + RuntimeBootstrapView, | ||
| 10 | + build_runtime_bootstrap_source, | ||
| 11 | + build_runtime_context, | ||
| 12 | + sync_runtime_context, | ||
| 13 | +) | ||
| 9 | from loader.runtime.conversation import ConversationRuntime | 14 | from loader.runtime.conversation import ConversationRuntime |
| 10 | from loader.runtime.explore import ExploreRuntime | 15 | from loader.runtime.explore import ExploreRuntime |
| 11 | from loader.runtime.launcher import RuntimeLauncher, build_runtime_launcher | 16 | from loader.runtime.launcher import RuntimeLauncher, build_runtime_launcher |
@@ -21,8 +26,9 @@ def test_build_runtime_context_uses_shared_bootstrap_contract( | |||
| 21 | config=AgentConfig(auto_context=False), | 26 | config=AgentConfig(auto_context=False), |
| 22 | project_root=temp_dir, | 27 | project_root=temp_dir, |
| 23 | ) | 28 | ) |
| 29 | + source = build_runtime_bootstrap_source(agent) | ||
| 24 | 30 | ||
| 25 | - context = build_runtime_context(agent) | 31 | + context = build_runtime_context(source) |
| 26 | 32 | ||
| 27 | assert context.project_root == temp_dir.resolve() | 33 | assert context.project_root == temp_dir.resolve() |
| 28 | assert context.backend is agent.backend | 34 | assert context.backend is agent.backend |
@@ -35,6 +41,7 @@ def test_build_runtime_context_uses_shared_bootstrap_contract( | |||
| 35 | assert context.workflow_mode == agent.workflow_mode | 41 | assert context.workflow_mode == agent.workflow_mode |
| 36 | assert context.prompt_format == agent.prompt_format | 42 | assert context.prompt_format == agent.prompt_format |
| 37 | assert context.prompt_sections == agent.prompt_sections | 43 | assert context.prompt_sections == agent.prompt_sections |
| 44 | + assert source.metadata == {"owner_type": "Agent"} | ||
| 38 | 45 | ||
| 39 | 46 | ||
| 40 | def test_sync_runtime_context_refreshes_prompt_and_capability_state( | 47 | def test_sync_runtime_context_refreshes_prompt_and_capability_state( |
@@ -46,7 +53,8 @@ def test_sync_runtime_context_refreshes_prompt_and_capability_state( | |||
| 46 | config=AgentConfig(auto_context=False), | 53 | config=AgentConfig(auto_context=False), |
| 47 | project_root=temp_dir, | 54 | project_root=temp_dir, |
| 48 | ) | 55 | ) |
| 49 | - context = build_runtime_context(agent) | 56 | + source = build_runtime_bootstrap_source(agent) |
| 57 | + context = build_runtime_context(source) | ||
| 50 | 58 | ||
| 51 | agent.prompt_format = "native" | 59 | agent.prompt_format = "native" |
| 52 | agent.prompt_sections = ["Workflow Context", "Runtime Config"] | 60 | agent.prompt_sections = ["Workflow Context", "Runtime Config"] |
@@ -54,7 +62,7 @@ def test_sync_runtime_context_refreshes_prompt_and_capability_state( | |||
| 54 | backend._supports_native_tools = False # type: ignore[attr-defined] | 62 | backend._supports_native_tools = False # type: ignore[attr-defined] |
| 55 | agent.refresh_capability_profile() | 63 | agent.refresh_capability_profile() |
| 56 | 64 | ||
| 57 | - sync_runtime_context(context, agent) | 65 | + sync_runtime_context(context, source) |
| 58 | 66 | ||
| 59 | assert context.workflow_mode == "clarify" | 67 | assert context.workflow_mode == "clarify" |
| 60 | assert context.prompt_format == "native" | 68 | assert context.prompt_format == "native" |
@@ -83,10 +91,12 @@ def test_conversation_runtime_uses_shared_bootstrap_factory( | |||
| 83 | fake_build_runtime_context, | 91 | fake_build_runtime_context, |
| 84 | ) | 92 | ) |
| 85 | 93 | ||
| 86 | - runtime = ConversationRuntime(agent) | 94 | + source = build_runtime_bootstrap_source(agent) |
| 95 | + runtime = ConversationRuntime(source) | ||
| 87 | 96 | ||
| 88 | assert calls == ["conversation"] | 97 | assert calls == ["conversation"] |
| 89 | assert runtime.context.project_root == temp_dir.resolve() | 98 | assert runtime.context.project_root == temp_dir.resolve() |
| 99 | + assert runtime.source is source | ||
| 90 | 100 | ||
| 91 | 101 | ||
| 92 | def test_explore_runtime_uses_shared_bootstrap_factory( | 102 | def test_explore_runtime_uses_shared_bootstrap_factory( |
@@ -110,10 +120,12 @@ def test_explore_runtime_uses_shared_bootstrap_factory( | |||
| 110 | fake_build_runtime_context, | 120 | fake_build_runtime_context, |
| 111 | ) | 121 | ) |
| 112 | 122 | ||
| 113 | - runtime = ExploreRuntime(agent) | 123 | + source = build_runtime_bootstrap_source(agent) |
| 124 | + runtime = ExploreRuntime(source) | ||
| 114 | 125 | ||
| 115 | assert calls == ["explore"] | 126 | assert calls == ["explore"] |
| 116 | assert runtime.context.project_root == temp_dir.resolve() | 127 | assert runtime.context.project_root == temp_dir.resolve() |
| 128 | + assert runtime.source is source | ||
| 117 | 129 | ||
| 118 | 130 | ||
| 119 | def test_build_runtime_launcher_wraps_shared_bootstrap_source( | 131 | def test_build_runtime_launcher_wraps_shared_bootstrap_source( |
@@ -128,4 +140,6 @@ def test_build_runtime_launcher_wraps_shared_bootstrap_source( | |||
| 128 | launcher = build_runtime_launcher(agent) | 140 | launcher = build_runtime_launcher(agent) |
| 129 | 141 | ||
| 130 | assert isinstance(launcher, RuntimeLauncher) | 142 | assert isinstance(launcher, RuntimeLauncher) |
| 131 | - assert launcher.source is agent | 143 | + assert isinstance(launcher.source, RuntimeBootstrapView) |
| 144 | + assert launcher.source is not agent | ||
| 145 | + assert launcher.source.metadata == {"owner_type": "Agent"} | ||
tests/test_runtime_context.pymodified@@ -5,7 +5,7 @@ from __future__ import annotations | |||
| 5 | from pathlib import Path | 5 | from pathlib import Path |
| 6 | 6 | ||
| 7 | from loader.agent.loop import Agent, AgentConfig | 7 | from loader.agent.loop import Agent, AgentConfig |
| 8 | -from loader.runtime.bootstrap import build_runtime_context | 8 | +from loader.runtime.bootstrap import build_runtime_bootstrap_source, build_runtime_context |
| 9 | from loader.runtime.context import RuntimeContext | 9 | from loader.runtime.context import RuntimeContext |
| 10 | from loader.runtime.recovery import RecoveryContext | 10 | from loader.runtime.recovery import RecoveryContext |
| 11 | from tests.helpers.runtime_harness import ScriptedBackend | 11 | from tests.helpers.runtime_harness import ScriptedBackend |
@@ -18,8 +18,9 @@ def test_agent_builds_typed_runtime_context(temp_dir: Path) -> None: | |||
| 18 | config=AgentConfig(auto_context=False), | 18 | config=AgentConfig(auto_context=False), |
| 19 | project_root=temp_dir, | 19 | project_root=temp_dir, |
| 20 | ) | 20 | ) |
| 21 | + source = build_runtime_bootstrap_source(agent) | ||
| 21 | 22 | ||
| 22 | - context = build_runtime_context(agent) | 23 | + context = build_runtime_context(source) |
| 23 | 24 | ||
| 24 | assert isinstance(context, RuntimeContext) | 25 | assert isinstance(context, RuntimeContext) |
| 25 | assert context.project_root == temp_dir.resolve() | 26 | assert context.project_root == temp_dir.resolve() |
@@ -47,8 +48,9 @@ def test_runtime_context_control_callbacks_stay_in_sync(temp_dir: Path) -> None: | |||
| 47 | config=AgentConfig(auto_context=False), | 48 | config=AgentConfig(auto_context=False), |
| 48 | project_root=temp_dir, | 49 | project_root=temp_dir, |
| 49 | ) | 50 | ) |
| 51 | + source = build_runtime_bootstrap_source(agent) | ||
| 50 | 52 | ||
| 51 | - context = build_runtime_context(agent) | 53 | + context = build_runtime_context(source) |
| 52 | context.queue_steering_message("Re-check the current task.") | 54 | context.queue_steering_message("Re-check the current task.") |
| 53 | 55 | ||
| 54 | assert context.drain_steering_messages() == ["Re-check the current task."] | 56 | assert context.drain_steering_messages() == ["Re-check the current task."] |
tests/test_runtime_launcher.pymodified@@ -8,6 +8,7 @@ import pytest | |||
| 8 | 8 | ||
| 9 | from loader.agent.loop import Agent, AgentConfig, ReasoningConfig | 9 | from loader.agent.loop import Agent, AgentConfig, ReasoningConfig |
| 10 | from loader.llm.base import CompletionResponse, StreamChunk | 10 | from loader.llm.base import CompletionResponse, StreamChunk |
| 11 | +from loader.runtime.bootstrap import RuntimeBootstrapView | ||
| 11 | from loader.runtime.launcher import RuntimeLauncher, build_runtime_launcher | 12 | from loader.runtime.launcher import RuntimeLauncher, build_runtime_launcher |
| 12 | from tests.helpers.runtime_harness import ScriptedBackend | 13 | from tests.helpers.runtime_harness import ScriptedBackend |
| 13 | 14 | ||
@@ -24,7 +25,9 @@ def test_build_runtime_launcher_returns_launcher_for_agent_source( | |||
| 24 | launcher = build_runtime_launcher(agent) | 25 | launcher = build_runtime_launcher(agent) |
| 25 | 26 | ||
| 26 | assert isinstance(launcher, RuntimeLauncher) | 27 | assert isinstance(launcher, RuntimeLauncher) |
| 27 | - assert launcher.source is agent | 28 | + assert isinstance(launcher.source, RuntimeBootstrapView) |
| 29 | + assert launcher.source is not agent | ||
| 30 | + assert launcher.source.metadata == {"owner_type": "Agent"} | ||
| 28 | 31 | ||
| 29 | 32 | ||
| 30 | @pytest.mark.asyncio | 33 | @pytest.mark.asyncio |
tests/test_turn_iteration.pymodified@@ -44,7 +44,7 @@ async def _run_iteration( | |||
| 44 | original_task=original_task, | 44 | original_task=original_task, |
| 45 | effective_max_tokens=prepared.effective_max_tokens, | 45 | effective_max_tokens=prepared.effective_max_tokens, |
| 46 | iterations=1, | 46 | iterations=1, |
| 47 | - max_iterations=runtime.agent.config.max_iterations, | 47 | + max_iterations=runtime.context.config.max_iterations, |
| 48 | actions_taken=[], | 48 | actions_taken=[], |
| 49 | continuation_count=0, | 49 | continuation_count=0, |
| 50 | empty_retry_count=0, | 50 | empty_retry_count=0, |