test_mode_isolation.py 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169
  1. from __future__ import annotations
  2. from dataclasses import asdict
  3. import pytest
  4. from agent.core.runner import AgentRunner, RunConfig
  5. from agent.orchestration.models import CompletionPolicy, TaskRecord
  6. from agent.tools.builtin.context import get_current_context
  7. from agent.tools.builtin.knowledge import KnowledgeConfig
  8. from agent.trace.goal_models import GoalTree
  9. from agent.trace.models import Trace
  10. from agent.trace.store import FileSystemTraceStore
  11. def _explicit_config(**overrides):
  12. values = {
  13. "agent_type": "planner",
  14. "completion_policy": CompletionPolicy.EXPLICIT_VALIDATION,
  15. "name": "explicit mission",
  16. }
  17. values.update(overrides)
  18. return RunConfig(**values)
  19. def test_legacy_task_goal_id_is_ignored_when_loading_ledger_record():
  20. record = TaskRecord.from_dict(
  21. {
  22. "task_id": "task",
  23. "goal_id": "obsolete-projection",
  24. "parent_task_id": None,
  25. "display_path": "0",
  26. "specs": [
  27. {
  28. "version": 1,
  29. "objective": "mission",
  30. "acceptance_criteria": [
  31. {"criterion_id": "done", "description": "complete"}
  32. ],
  33. }
  34. ],
  35. }
  36. )
  37. assert "goal_id" not in record.__dict__
  38. assert "goal_id" not in asdict(record)
  39. @pytest.mark.asyncio
  40. async def test_new_traces_persist_only_the_selected_plan_model(tmp_path):
  41. store = FileSystemTraceStore(str(tmp_path))
  42. runner = AgentRunner(trace_store=store)
  43. explicit, explicit_tree, _ = await runner._prepare_new_trace(
  44. [],
  45. _explicit_config(new_trace_id="explicit"),
  46. )
  47. legacy, legacy_tree, _ = await runner._prepare_new_trace(
  48. [],
  49. RunConfig(new_trace_id="legacy", name="legacy mission"),
  50. )
  51. assert explicit.agent_role == "planner"
  52. assert explicit.parent_goal_id is None
  53. assert explicit_tree is None
  54. assert await store.get_goal_tree("explicit") is None
  55. assert legacy.agent_role == "legacy"
  56. assert legacy_tree is not None
  57. assert await store.get_goal_tree("legacy") is not None
  58. @pytest.mark.asyncio
  59. async def test_explicit_resume_ignores_historical_goal_file(tmp_path):
  60. store = FileSystemTraceStore(str(tmp_path))
  61. await store.create_trace(
  62. Trace(
  63. trace_id="explicit",
  64. mode="agent",
  65. task="mission",
  66. agent_type="planner",
  67. agent_role="planner",
  68. )
  69. )
  70. await store.update_goal_tree("explicit", GoalTree(mission="obsolete projection"))
  71. runner = AgentRunner(trace_store=store)
  72. _, loaded_tree, _ = await runner._prepare_existing_trace(
  73. _explicit_config(trace_id="explicit")
  74. )
  75. assert loaded_tree is None
  76. assert (await store.get_goal_tree("explicit")).mission == "obsolete projection"
  77. @pytest.mark.asyncio
  78. async def test_explicit_current_context_uses_task_ledger_read_model(tmp_path):
  79. class Coordinator:
  80. async def task_context(self, root_trace_id):
  81. assert root_trace_id == "root"
  82. return "## Current Task Plan\n\n- 0 [running] deliver result"
  83. store = FileSystemTraceStore(str(tmp_path))
  84. await store.create_trace(
  85. Trace(
  86. trace_id="planner",
  87. mode="agent",
  88. agent_role="planner",
  89. context={"root_trace_id": "root"},
  90. )
  91. )
  92. runner = AgentRunner(trace_store=store, task_coordinator=Coordinator())
  93. result = await get_current_context(
  94. {
  95. "runner": runner,
  96. "trace_id": "planner",
  97. "root_trace_id": "root",
  98. "completion_policy": CompletionPolicy.EXPLICIT_VALIDATION.value,
  99. }
  100. )
  101. assert "Current Task Plan" in result.output
  102. assert "deliver result" in result.output
  103. assert "GoalTree" not in result.output
  104. compression_context = await runner._current_execution_context(
  105. "planner",
  106. None,
  107. _explicit_config(),
  108. )
  109. assert compression_context == "## Current Task Plan\n\n- 0 [running] deliver result"
  110. @pytest.mark.asyncio
  111. async def test_explicit_overflow_skips_goal_level_one(monkeypatch, tmp_path):
  112. store = FileSystemTraceStore(str(tmp_path))
  113. await store.create_trace(
  114. Trace(trace_id="root", mode="agent", agent_role="planner")
  115. )
  116. runner = AgentRunner(trace_store=store)
  117. history = [{"role": "user", "content": "large context " * 20}]
  118. monkeypatch.setattr(
  119. "agent.core.runner.CompressionConfig.get_max_tokens",
  120. lambda _self, _model: 1,
  121. )
  122. monkeypatch.setattr(
  123. "agent.core.runner.compress_completed_goals",
  124. lambda *_args, **_kwargs: (_ for _ in ()).throw(
  125. AssertionError("explicit mode must not run Goal Level 1")
  126. ),
  127. )
  128. updated, _, _, needs_level_two = await runner._manage_context_usage(
  129. "root",
  130. history,
  131. GoalTree(mission="must be ignored"),
  132. _explicit_config(
  133. knowledge=KnowledgeConfig(
  134. enable_extraction=False,
  135. enable_completion_extraction=False,
  136. enable_injection=False,
  137. )
  138. ),
  139. sequence=1,
  140. head_seq=0,
  141. )
  142. assert updated == history
  143. assert needs_level_two is True