mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-10 11:47:43 +02:00
[eric] browser: the post-is-not-a-comment rule now guards the opener, and the composer poll waits ~5s
This commit is contained in:
@@ -249,6 +249,15 @@ async def run_send_script(
|
||||
if not composer:
|
||||
# Reversible-opener hop: prestage often stops on the profile with the "Message" opener visible (its settle raced the overlay). Opening a composer is the allowed opener class; the irreversible bar is unchanged.
|
||||
opener = browser_send_parse.opener_index_in_state(state_text)
|
||||
if opener and browser_send_parse.surface_mismatch(task_sans_brief, opener[1]):
|
||||
# The same post-is-not-a-comment rule the composer already enforces, applied one step
|
||||
# earlier. Measured on linkedin.com with the task "start a post": the only opener listed
|
||||
# was 'Comment', so the script opened a stranger's comment box, found no post composer
|
||||
# inside it, and declined. Opening the wrong surface is not a slower route to the right
|
||||
# one, and here it also burns the reversible-opener hop we only get once.
|
||||
logger.info(f"[browser-sendscript] ignoring opener {opener[1]!r}: a comment box is not "
|
||||
f"where a post goes")
|
||||
opener = None
|
||||
if opener:
|
||||
logger.info(f"[browser-sendscript] firing via opener {opener[1]!r} [{opener[0]}]")
|
||||
r_open = await execute_tool("BrowserClickIndex", {"index": opener[0]}, browser_id, tab_id)
|
||||
@@ -256,7 +265,11 @@ async def run_send_script(
|
||||
return None
|
||||
log.append({"tool": "BrowserClickIndex", "input": {"index": opener[0]}, "ok": True,
|
||||
"result_summary": f"script opened composer via {opener[1]!r}"[:200], "elapsed_ms": 0})
|
||||
for wait_s in (0.6, 1.2):
|
||||
# 1.8s was too short for a compose surface that has to mount. Measured in dry-run:
|
||||
# gmail's compose window and linkedin's post modal both missed it and fell back to the
|
||||
# model loop, which costs 100s+. Waiting up to ~5s to avoid that is a trade worth making
|
||||
# every time; the extra polls only ever run on a run that would otherwise have failed.
|
||||
for wait_s in (0.6, 1.2, 1.5, 2.0):
|
||||
await asyncio.sleep(wait_s)
|
||||
state_text = await fresh_list()
|
||||
composer = browser_send_parse.composer_index_in_state(state_text)
|
||||
|
||||
@@ -97,3 +97,25 @@ def test_a_task_with_no_post_intent_is_left_alone():
|
||||
"""Messaging a person is neither posting nor commenting; the guard must not touch it."""
|
||||
assert not sp.surface_mismatch("text tyler hello", "Write a message")
|
||||
assert not sp.surface_mismatch("", "Add a comment")
|
||||
|
||||
|
||||
# --- the opener is a surface too --------------------------------------------------------------
|
||||
|
||||
def test_a_post_task_rejects_a_comment_OPENER():
|
||||
"""Measured in the dry-run coverage sweep: on linkedin.com with "start a post", the only opener
|
||||
listed was 'Comment'. The script opened a stranger's comment box, found no post composer inside
|
||||
it, and declined. The composer already had this guard; the opener did not, so the wrong surface
|
||||
got opened one step earlier and burned the single reversible-opener hop."""
|
||||
assert sp.surface_mismatch("start a post saying hi", "Comment")
|
||||
assert sp.surface_mismatch('post this, exactly: "hi"', "Reply")
|
||||
|
||||
|
||||
def test_a_comment_task_keeps_its_comment_opener():
|
||||
"""One-directional, same as the composer rule: asking to comment must still open a comment box."""
|
||||
assert not sp.surface_mismatch("comment on the first post saying hi", "Comment")
|
||||
assert not sp.surface_mismatch("reply to that thread with hi", "Reply")
|
||||
|
||||
|
||||
def test_a_post_task_keeps_a_real_post_opener():
|
||||
for opener in ("Post", "Compose", "New message", "Message"):
|
||||
assert not sp.surface_mismatch('post this, exactly: "hi"', opener), opener
|
||||
|
||||
Reference in New Issue
Block a user