88import subprocess
99import sys
1010import tempfile
11+ import threading
1112import unittest
1213from unittest import mock
1314
14- from python_agent_harness .tools .base import ToolContext
15+ from python_agent_harness .tools .base import ToolContext , ToolRuntime
1516from python_agent_harness .tools .edit_mac import EditMac
1617from python_agent_harness .tools .filesystem import (
1718 Edit ,
@@ -38,18 +39,50 @@ def _big_output(lines: int = 6000, width: int = 80) -> str:
3839
3940
4041class FakeSession :
41- """Minimal session double satisfying the ToolContext protocol."""
42+ """Session double satisfying the full ToolRuntime protocol.
43+
44+ The filesystem tools only touch ``project_dir`` and ``record_diff``,
45+ but the double implements every ToolRuntime member so ``ToolContext``
46+ can proxy unconditionally (no ``hasattr`` guard) — the static
47+ assertion below enforces that the double never drifts from the
48+ protocol.
49+ """
4250
4351 def __init__ (self ) -> None :
4452 self .recorded_diffs : list [str ] = []
53+ self ._cancel = threading .Event ()
4554
4655 @property
4756 def project_dir (self ) -> str :
4857 return "/tmp"
4958
59+ @property
60+ def cancel_event (self ) -> threading .Event :
61+ return self ._cancel
62+
63+ def ask_questions (self , questions : list [dict ]) -> str :
64+ return "answer"
65+
5066 def record_diff (self , diff_text : str ) -> None :
5167 self .recorded_diffs .append (diff_text )
5268
69+ def update_todos (self , todos : list [dict ]) -> None :
70+ pass
71+
72+ def find_skill (self , name : str ) -> str | None :
73+ return None
74+
75+ def run_subagent (self , subagent_type : str , description : str , prompt : str ) -> str :
76+ return f"ran { description } "
77+
78+ def plan_exit (self ) -> str :
79+ return "approved"
80+
81+
82+ # static conformance: the double must satisfy the same ToolRuntime
83+ # interface the real Session does (pyright fails here on any drift).
84+ _fake_session_is_tool_runtime : ToolRuntime = FakeSession ()
85+
5386
5487def make_ctx () -> tuple [ToolContext , FakeSession ]:
5588 sess = FakeSession ()
0 commit comments