mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-08-24 13:32:22 +02:00
68 lines
3.2 KiB
Python
68 lines
3.2 KiB
Python
"""The fast lane should not require the user to type quotes.
|
|
|
|
`quoted_payload` refuses a task with no unambiguous quoted span, and that refusal is correct:
|
|
guessing which words to send is how you post the wrong thing. But it made the fast path unreachable
|
|
for the way people actually ask. Reported live by Eric: "send hi to charles zheng on linkedin" fell
|
|
to the slow model path, which made two navigation clicks, three reads, typed nothing, and then
|
|
reported a send it had never attempted.
|
|
|
|
So the JUDGEMENT (which words) moves to the aux model and every SAFETY gate stays put: the surface
|
|
check, the committed-fill receipt, the resend guard, and the completion gate all still run against
|
|
whatever comes back. The model picks the text; the code still refuses to claim what it cannot see.
|
|
|
|
These tests cover the REJECTION rules, because that is where the risk lives. Rejecting costs one
|
|
slow-path run, which is the old behaviour. Accepting something wrong costs a message the user never
|
|
wrote, sent to a real person.
|
|
"""
|
|
|
|
from backend.apps.agents.browser import extract_payload as ep
|
|
|
|
|
|
def test_a_clean_extraction_passes():
|
|
assert ep.clean_payload("hi", "send hi to charles zheng on linkedin") == "hi"
|
|
assert ep.clean_payload("I'll be late", "tell mom I'll be late") == "I'll be late"
|
|
|
|
|
|
def test_quotes_the_model_adds_are_stripped():
|
|
"""The prompt says no quotes; models add them anyway, and posting a quoted string is wrong."""
|
|
assert ep.clean_payload('"hi there"', "send hi there") == "hi there"
|
|
assert ep.clean_payload("'hi there'", "send hi there") == "hi there"
|
|
|
|
|
|
def test_every_shape_of_NONE_is_refused():
|
|
"""The model is told to answer NONE, but a hedge is the same answer in different words and must
|
|
never become a posted message."""
|
|
for reply in ("NONE", "none", "N/A", "nothing", "unclear", "unknown",
|
|
"I can't determine the message", "I cannot tell",
|
|
"Sorry, no message was specified", "There is no message here",
|
|
"no specific message given"):
|
|
assert ep.clean_payload(reply, "check my messages") is None, reply
|
|
|
|
|
|
def test_an_explanation_is_not_a_message():
|
|
"""A model that starts explaining has stopped extracting, and the explanation must not ride
|
|
along into someone's inbox."""
|
|
assert ep.clean_payload("hi\n\nI picked this because you said hi", "send hi") is None
|
|
|
|
|
|
def test_a_reply_longer_than_the_ask_is_invented_content():
|
|
"""Extraction lifts words out of the instruction; it does not compose new ones."""
|
|
long_reply = "x" * 400
|
|
assert ep.clean_payload(long_reply, "send hi") is None
|
|
# ...but a genuinely long instruction may carry a genuinely long message
|
|
long_task = "post this update: " + "y" * 300
|
|
assert ep.clean_payload("y" * 300, long_task) is not None
|
|
|
|
|
|
def test_empty_and_whitespace_are_refused():
|
|
assert ep.clean_payload("", "send hi") is None
|
|
assert ep.clean_payload(" ", "send hi") is None
|
|
assert ep.clean_payload('""', "send hi") is None
|
|
|
|
|
|
def test_the_cheap_gate_skips_absurd_inputs():
|
|
"""No aux call for an empty task or a pasted wall of text."""
|
|
assert not ep.looks_extractable("")
|
|
assert not ep.looks_extractable("z" * 700)
|
|
assert ep.looks_extractable("send hi to charles zheng on linkedin")
|