mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-08 02:37:45 +02:00
[eric] browser: prune abandoned-navigate detours at distill so recorded skills and route hints stay clean
This commit is contained in:
@@ -309,7 +309,23 @@ def distill_steps(action_log: list[dict]) -> list[dict]:
|
||||
productive_count += 1
|
||||
if productive_count == 0:
|
||||
return []
|
||||
return steps
|
||||
return _prune_detours(steps)
|
||||
|
||||
|
||||
def _prune_detours(steps: list[dict]) -> list[dict]:
|
||||
"""Drop an abandoned-page detour: a BrowserNavigate whose page was never
|
||||
acted on because the very next step navigates somewhere else. Conservative
|
||||
on purpose, only consecutive navigates qualify (if a page had been used,
|
||||
a Type/Click/etc would sit between them), so a needed step is never removed.
|
||||
This keeps a wrong-turn (e.g. the wrong profile, then the right one) out of
|
||||
a recorded macro without any reachability guesswork."""
|
||||
out: list[dict] = []
|
||||
for i, s in enumerate(steps):
|
||||
nxt = steps[i + 1] if i + 1 < len(steps) else None
|
||||
if s.get("tool") == "BrowserNavigate" and nxt is not None and nxt.get("tool") == "BrowserNavigate":
|
||||
continue # this navigate's page was abandoned immediately; skip it
|
||||
out.append(s)
|
||||
return out
|
||||
|
||||
|
||||
def first_unsafe_step(steps: list[dict]) -> tuple[int, str]:
|
||||
|
||||
@@ -665,3 +665,35 @@ def test_route_hint_adoption_matching(_isolated_skills):
|
||||
# the Message and Send clicks did not run
|
||||
assert adopted[0] and adopted[1] and adopted[3]
|
||||
assert not adopted[2] and not adopted[4]
|
||||
|
||||
|
||||
# --- conservative detour pruning ---------------------------------------------
|
||||
def test_distill_prunes_abandoned_navigate_detour():
|
||||
# wrong profile opened (navigate), abandoned for a search (navigate), then
|
||||
# the right profile + the real productive steps. The first navigate is a
|
||||
# detour: nothing acted on its page before the next navigate.
|
||||
log = [
|
||||
{"tool": "BrowserNavigate", "input": {"url": "https://x.com/in/wrong"}, "ok": True},
|
||||
{"tool": "BrowserNavigate", "input": {"url": "https://x.com/search?q=tyler"}, "ok": True},
|
||||
{"tool": "BrowserClickIndex", "input": {"index": 1}, "ok": True,
|
||||
"clicked_role": "link", "clicked_name": "Tyler Chen"},
|
||||
{"tool": "BrowserType", "input": {"selector": "#msg", "text": "hi"}, "ok": True},
|
||||
]
|
||||
steps = sk.distill_steps(log)
|
||||
urls = [s["params"].get("url") for s in steps if s["tool"] == "BrowserNavigate"]
|
||||
assert urls == ["https://x.com/search?q=tyler"] # the abandoned wrong nav dropped
|
||||
assert [s["tool"] for s in steps] == ["BrowserNavigate", "BrowserClickByName", "BrowserType"]
|
||||
|
||||
|
||||
def test_distill_keeps_navigate_that_was_acted_on():
|
||||
# a navigate followed by a real action on that page is NOT a detour.
|
||||
log = [
|
||||
{"tool": "BrowserNavigate", "input": {"url": "https://x.com/form"}, "ok": True},
|
||||
{"tool": "BrowserType", "input": {"selector": "#q", "text": "hi"}, "ok": True},
|
||||
{"tool": "BrowserNavigate", "input": {"url": "https://x.com/results"}, "ok": True},
|
||||
{"tool": "BrowserClickIndex", "input": {"index": 2}, "ok": True,
|
||||
"clicked_role": "button", "clicked_name": "Go"},
|
||||
]
|
||||
steps = sk.distill_steps(log)
|
||||
urls = [s["params"].get("url") for s in steps if s["tool"] == "BrowserNavigate"]
|
||||
assert urls == ["https://x.com/form", "https://x.com/results"] # both kept
|
||||
|
||||
Reference in New Issue
Block a user