188 lines
5.8 KiB
Python
188 lines
5.8 KiB
Python
from types import SimpleNamespace
|
||
|
||
from agent_v0.server_v1 import replay_memory
|
||
from core.learning.target_memory_store import TargetMemoryStore
|
||
|
||
|
||
class _DummyStore:
|
||
def __init__(self, fp):
|
||
self._fp = fp
|
||
|
||
def lookup(self, screen_sig, spec_shim):
|
||
return self._fp
|
||
|
||
|
||
def test_memory_lookup_uses_window_relative_coords_when_available(monkeypatch):
|
||
fp = SimpleNamespace(
|
||
bbox=(0.566016, 0.400625, 0.0, 0.0),
|
||
etype="position_fallback",
|
||
confidence=0.2,
|
||
)
|
||
monkeypatch.setattr(replay_memory, "get_memory_store", lambda: _DummyStore(fp))
|
||
|
||
result = replay_memory.memory_lookup(
|
||
window_title="Rechercher",
|
||
target_spec={
|
||
"by_text": "Bloc-notes",
|
||
"window_capture": {
|
||
"click_relative": [681, 448],
|
||
"window_size": [1287, 1407],
|
||
},
|
||
},
|
||
)
|
||
|
||
assert result is not None
|
||
assert result["method"] == "memory_position_fallback"
|
||
assert result["x_pct"] == 681 / 1287
|
||
assert result["y_pct"] == 448 / 1407
|
||
|
||
|
||
def test_memory_lookup_keeps_bbox_coords_without_window_capture(monkeypatch):
|
||
fp = SimpleNamespace(
|
||
bbox=(0.566016, 0.400625, 0.0, 0.0),
|
||
etype="position_fallback",
|
||
confidence=0.2,
|
||
)
|
||
monkeypatch.setattr(replay_memory, "get_memory_store", lambda: _DummyStore(fp))
|
||
|
||
result = replay_memory.memory_lookup(
|
||
window_title="Rechercher",
|
||
target_spec={"by_text": "Bloc-notes"},
|
||
)
|
||
|
||
assert result is not None
|
||
assert result["x_pct"] == 0.566016
|
||
assert result["y_pct"] == 0.400625
|
||
|
||
|
||
def test_memory_lookup_keeps_learned_visual_coords_with_window_capture(monkeypatch):
|
||
fp = SimpleNamespace(
|
||
bbox=(0.402734375, 0.578125, 0.0, 0.0),
|
||
etype="anchor_template",
|
||
confidence=0.99,
|
||
)
|
||
monkeypatch.setattr(replay_memory, "get_memory_store", lambda: _DummyStore(fp))
|
||
|
||
result = replay_memory.memory_lookup(
|
||
window_title="*test – Bloc-notes",
|
||
target_spec={
|
||
"by_text": "Enregistrer",
|
||
"by_role": "yolo",
|
||
"context_hints": {
|
||
"expected_window_before": "*test – Bloc-notes",
|
||
"interaction": "toolbar_save_button",
|
||
},
|
||
"window_capture": {
|
||
"click_relative": [860, 634],
|
||
"window_size": [1920, 1116],
|
||
},
|
||
},
|
||
)
|
||
|
||
assert result is not None
|
||
assert result["method"] == "memory_anchor_template"
|
||
assert result["x_pct"] == 0.402734375
|
||
assert result["y_pct"] == 0.578125
|
||
|
||
|
||
def test_memory_lookup_skips_window_transition_even_if_record_exists(monkeypatch):
|
||
fp = SimpleNamespace(
|
||
bbox=(0.5, 0.8, 0.0, 0.0),
|
||
etype="grounding_vlm",
|
||
confidence=0.85,
|
||
)
|
||
monkeypatch.setattr(replay_memory, "get_memory_store", lambda: _DummyStore(fp))
|
||
|
||
result = replay_memory.memory_lookup(
|
||
window_title="*test – Bloc-notes",
|
||
target_spec={
|
||
"by_text": "Enregistrer",
|
||
"by_role": "button",
|
||
"context_hints": {
|
||
"expected_window_before": "*test – Bloc-notes",
|
||
"expected_window_after": "Enregistrer sous",
|
||
"requires_window_transition": True,
|
||
},
|
||
},
|
||
)
|
||
|
||
assert result is None
|
||
|
||
|
||
def test_memory_lookup_rejects_generic_button_without_context(monkeypatch):
|
||
fp = SimpleNamespace(
|
||
bbox=(0.5, 0.8, 0.0, 0.0),
|
||
etype="grounding_vlm",
|
||
confidence=0.85,
|
||
)
|
||
monkeypatch.setattr(replay_memory, "get_memory_store", lambda: _DummyStore(fp))
|
||
|
||
result = replay_memory.memory_lookup(
|
||
window_title="*test – Bloc-notes",
|
||
target_spec={"by_text": "Enregistrer", "by_role": "button"},
|
||
)
|
||
|
||
assert result is None
|
||
|
||
|
||
def test_memory_lookup_allows_generic_button_with_context(monkeypatch):
|
||
fp = SimpleNamespace(
|
||
bbox=(0.5, 0.8, 0.0, 0.0),
|
||
etype="grounding_vlm",
|
||
confidence=0.85,
|
||
)
|
||
monkeypatch.setattr(replay_memory, "get_memory_store", lambda: _DummyStore(fp))
|
||
|
||
result = replay_memory.memory_lookup(
|
||
window_title="Enregistrer sous",
|
||
target_spec={
|
||
"by_text": "Enregistrer",
|
||
"by_role": "button",
|
||
"window_title": "Enregistrer sous",
|
||
"context_hints": {
|
||
"expected_window_before": "Enregistrer sous",
|
||
"interaction": "save_dialog_primary_button",
|
||
},
|
||
},
|
||
)
|
||
|
||
assert result is not None
|
||
assert result["method"] == "memory_grounding_vlm"
|
||
|
||
|
||
def test_target_spec_hash_distinguishes_same_text_with_different_spatial_hints(tmp_path):
|
||
store = TargetMemoryStore(base_path=str(tmp_path / "learning"))
|
||
|
||
spec_left = replay_memory._TargetSpecLike(
|
||
{
|
||
"by_text": "Enregistrer",
|
||
"by_role": "yolo",
|
||
"vlm_description": "Dans la fenêtre '*test – Bloc-notes', l'élément cliqué se trouve au milieu au centre de l'écran",
|
||
"window_capture": {
|
||
"click_relative": [860, 634],
|
||
"window_size": [1920, 1116],
|
||
},
|
||
"som_element": {
|
||
"bbox_norm": [0.40234375, 0.701875, 0.46640625, 0.74125],
|
||
"center_norm": [0.434375, 0.72125],
|
||
},
|
||
}
|
||
)
|
||
spec_right = replay_memory._TargetSpecLike(
|
||
{
|
||
"by_text": "Enregistrer",
|
||
"by_role": "yolo",
|
||
"vlm_description": "Dans la fenêtre '*test – Bloc-notes', l'élément cliqué se trouve au milieu au centre de l'écran",
|
||
"window_capture": {
|
||
"click_relative": [1491, 38],
|
||
"window_size": [1920, 1116],
|
||
},
|
||
"som_element": {
|
||
"bbox_norm": [0.697265625, 0.335625, 0.715625, 0.3625],
|
||
"center_norm": [0.70625, 0.34875],
|
||
},
|
||
}
|
||
)
|
||
|
||
assert store._hash_target_spec(spec_left) != store._hash_target_spec(spec_right)
|