This commit is contained in:
@@ -495,6 +495,128 @@ def test_observation_loop_blocks_repeated_broad_reobservation(tmp_path: Path, mo
|
||||
assert blocked["window_summary"] == "Save as [#32770]"
|
||||
|
||||
|
||||
def test_observation_loop_counts_sleep_as_non_progress(tmp_path: Path, monkeypatch) -> None:
|
||||
agent = _build_agent(tmp_path, monkeypatch)
|
||||
agent.step_history = [
|
||||
{
|
||||
"step": 40,
|
||||
"tool_names": ["click"],
|
||||
"window_signature": "123|#32770|Save as",
|
||||
"window_summary": "Save as [#32770]",
|
||||
"had_visual": False,
|
||||
"contains_action": True,
|
||||
},
|
||||
{
|
||||
"step": 41,
|
||||
"tool_names": ["see_screen"],
|
||||
"window_signature": "123|#32770|Save as",
|
||||
"window_summary": "Save as [#32770]",
|
||||
"had_visual": True,
|
||||
"contains_action": False,
|
||||
},
|
||||
{
|
||||
"step": 42,
|
||||
"tool_names": ["sleep"],
|
||||
"window_signature": "123|#32770|Save as",
|
||||
"window_summary": "Save as [#32770]",
|
||||
"had_visual": False,
|
||||
"contains_action": False,
|
||||
},
|
||||
{
|
||||
"step": 43,
|
||||
"tool_names": ["get_active_window"],
|
||||
"window_signature": "123|#32770|Save as",
|
||||
"window_summary": "Save as [#32770]",
|
||||
"had_visual": False,
|
||||
"contains_action": False,
|
||||
},
|
||||
{
|
||||
"step": 44,
|
||||
"tool_names": ["sleep"],
|
||||
"window_signature": "123|#32770|Save as",
|
||||
"window_summary": "Save as [#32770]",
|
||||
"had_visual": False,
|
||||
"contains_action": False,
|
||||
},
|
||||
{
|
||||
"step": 45,
|
||||
"tool_names": ["see_screen"],
|
||||
"window_signature": "123|#32770|Save as",
|
||||
"window_summary": "Save as [#32770]",
|
||||
"had_visual": True,
|
||||
"contains_action": False,
|
||||
},
|
||||
]
|
||||
|
||||
blocked = agent._dispatch_tool("see_screen", {})
|
||||
|
||||
assert blocked["ok"] is False
|
||||
assert blocked["blocked"] is True
|
||||
assert blocked["blocked_reason"] == "observation_loop"
|
||||
assert blocked["repeated_steps"] == 3
|
||||
|
||||
|
||||
def test_observation_loop_treats_focus_window_as_action_progress(tmp_path: Path, monkeypatch) -> None:
|
||||
agent = _build_agent(tmp_path, monkeypatch)
|
||||
|
||||
agent._record_step_history(["focus_window"], {"hwnd": 123, "class_name": "#32770", "title": "Save as"})
|
||||
|
||||
entry = agent.step_history[-1]
|
||||
assert entry["contains_action"] is True
|
||||
|
||||
|
||||
def test_observation_loop_requires_non_empty_window_signature(tmp_path: Path, monkeypatch) -> None:
|
||||
agent = _build_agent(tmp_path, monkeypatch)
|
||||
agent.step_history = [
|
||||
{
|
||||
"step": 50,
|
||||
"tool_names": ["see_screen"],
|
||||
"window_signature": "",
|
||||
"window_summary": "",
|
||||
"had_visual": True,
|
||||
"contains_action": False,
|
||||
},
|
||||
{
|
||||
"step": 51,
|
||||
"tool_names": ["get_active_window"],
|
||||
"window_signature": "",
|
||||
"window_summary": "",
|
||||
"had_visual": False,
|
||||
"contains_action": False,
|
||||
},
|
||||
{
|
||||
"step": 52,
|
||||
"tool_names": ["see_screen"],
|
||||
"window_signature": "",
|
||||
"window_summary": "",
|
||||
"had_visual": True,
|
||||
"contains_action": False,
|
||||
},
|
||||
]
|
||||
|
||||
assert agent._stable_observation_loop() is None
|
||||
|
||||
|
||||
def test_record_step_history_reuses_last_observed_window_for_visual_only_steps(tmp_path: Path, monkeypatch) -> None:
|
||||
agent = _build_agent(tmp_path, monkeypatch)
|
||||
agent.last_observed_window = {
|
||||
"available": True,
|
||||
"hwnd": 321,
|
||||
"class_name": "ApplicationFrameWindow",
|
||||
"title": "Settings",
|
||||
}
|
||||
|
||||
agent._record_step_history(["see_screen"], None, "sig-a")
|
||||
agent._record_step_history(["get_active_window"], None)
|
||||
agent._record_step_history(["detect_dialog"], None)
|
||||
|
||||
stable = agent._stable_observation_loop()
|
||||
|
||||
assert stable is not None
|
||||
assert stable["window_summary"] == "Settings [ApplicationFrameWindow]"
|
||||
assert stable["repeated_steps"] == 3
|
||||
|
||||
|
||||
def test_repeated_ambiguous_action_requires_verification_and_then_blocks(tmp_path: Path, monkeypatch) -> None:
|
||||
agent = _build_agent(tmp_path, monkeypatch)
|
||||
type_args = {"text": "repeat me"}
|
||||
|
||||
Reference in New Issue
Block a user