Python · 4695 bytes Raw Blame History
1 """Tests for shared runtime bootstrap and context synchronization."""
2
3 from __future__ import annotations
4
5 from pathlib import Path
6
7 from loader.agent.loop import Agent, AgentConfig
8 from loader.runtime.bootstrap import (
9 RuntimeBootstrapView,
10 build_runtime_bootstrap_source,
11 build_runtime_context,
12 sync_runtime_context,
13 )
14 from loader.runtime.conversation import ConversationRuntime
15 from loader.runtime.explore import ExploreRuntime
16 from loader.runtime.launcher import RuntimeLauncher, build_runtime_launcher
17 from tests.helpers.runtime_harness import ScriptedBackend
18
19
20 def test_build_runtime_context_uses_shared_bootstrap_contract(
21 temp_dir: Path,
22 ) -> None:
23 backend = ScriptedBackend()
24 agent = Agent(
25 backend=backend,
26 config=AgentConfig(auto_context=False),
27 project_root=temp_dir,
28 )
29 source = build_runtime_bootstrap_source(agent)
30
31 context = build_runtime_context(source)
32
33 assert context.project_root == temp_dir.resolve()
34 assert context.backend is agent.backend
35 assert context.registry is agent.registry
36 assert context.session is agent.session
37 assert context.config is agent.config
38 assert context.capability_profile == agent.capability_profile
39 assert context.permission_policy is agent.permission_policy
40 assert context.permission_config_status is agent.permission_config_status
41 assert context.workflow_mode == agent.workflow_mode
42 assert context.prompt_format == agent.prompt_format
43 assert context.prompt_sections == agent.prompt_sections
44 assert source.metadata == {"owner_type": "Agent"}
45
46
47 def test_sync_runtime_context_refreshes_prompt_and_capability_state(
48 temp_dir: Path,
49 ) -> None:
50 backend = ScriptedBackend(supports_native_tools=True)
51 agent = Agent(
52 backend=backend,
53 config=AgentConfig(auto_context=False),
54 project_root=temp_dir,
55 )
56 source = build_runtime_bootstrap_source(agent)
57 context = build_runtime_context(source)
58
59 agent.prompt_format = "native"
60 agent.prompt_sections = ["Workflow Context", "Runtime Config"]
61 agent.set_workflow_mode("clarify")
62 backend._supports_native_tools = False # type: ignore[attr-defined]
63 agent.refresh_capability_profile()
64
65 sync_runtime_context(context, source)
66
67 assert context.workflow_mode == "clarify"
68 assert context.prompt_format == "native"
69 assert context.prompt_sections == ["Workflow Context", "Runtime Config"]
70 assert context.capability_profile.supports_native_tools is False
71
72
73 def test_conversation_runtime_uses_shared_bootstrap_factory(
74 temp_dir: Path,
75 monkeypatch,
76 ) -> None:
77 agent = Agent(
78 backend=ScriptedBackend(),
79 config=AgentConfig(auto_context=False, stream=False),
80 project_root=temp_dir,
81 )
82 calls: list[str] = []
83 real_build_runtime_context = build_runtime_context
84
85 def fake_build_runtime_context(source) -> object:
86 calls.append("conversation")
87 return real_build_runtime_context(source)
88
89 monkeypatch.setattr(
90 "loader.runtime.conversation.build_runtime_context",
91 fake_build_runtime_context,
92 )
93
94 source = build_runtime_bootstrap_source(agent)
95 runtime = ConversationRuntime(source)
96
97 assert calls == ["conversation"]
98 assert runtime.context.project_root == temp_dir.resolve()
99 assert runtime.source is source
100
101
102 def test_explore_runtime_uses_shared_bootstrap_factory(
103 temp_dir: Path,
104 monkeypatch,
105 ) -> None:
106 agent = Agent(
107 backend=ScriptedBackend(),
108 config=AgentConfig(auto_context=False, stream=False),
109 project_root=temp_dir,
110 )
111 calls: list[str] = []
112 real_build_runtime_context = build_runtime_context
113
114 def fake_build_runtime_context(source) -> object:
115 calls.append("explore")
116 return real_build_runtime_context(source)
117
118 monkeypatch.setattr(
119 "loader.runtime.explore.build_runtime_context",
120 fake_build_runtime_context,
121 )
122
123 source = build_runtime_bootstrap_source(agent)
124 runtime = ExploreRuntime(source)
125
126 assert calls == ["explore"]
127 assert runtime.context.project_root == temp_dir.resolve()
128 assert runtime.source is source
129
130
131 def test_build_runtime_launcher_wraps_shared_bootstrap_source(
132 temp_dir: Path,
133 ) -> None:
134 agent = Agent(
135 backend=ScriptedBackend(),
136 config=AgentConfig(auto_context=False, stream=False),
137 project_root=temp_dir,
138 )
139
140 launcher = build_runtime_launcher(agent)
141
142 assert isinstance(launcher, RuntimeLauncher)
143 assert isinstance(launcher.source, RuntimeBootstrapView)
144 assert launcher.source is not agent
145 assert launcher.source.metadata == {"owner_type": "Agent"}