mirror of
https://github.com/openswarm-ai/openswarm.git
synced 2026-09-02 23:38:46 +02:00
72 lines
3.6 KiB
Python
72 lines
3.6 KiB
Python
"""The CLI hands the filter's verdict back as prose, and it used to be stored as the model's words.
|
|
|
|
Production 1.7.9, 2026-08-26: sub-agents came home with
|
|
"Claude Code is unable to respond to this request, which appears to violate our Usage Policy" as
|
|
their ANSWER. There is no "API Error:" prefix and no status code in it, so every envelope check in
|
|
the codebase said "this is the agent talking" and the refusal became transcript content: the parent
|
|
then carried policy-violation language into every later request (the exact class CLAUDE.md forbids).
|
|
|
|
Two separate misses, both sealed here: the wording ("Usage Policy", not "Acceptable Use Policy") and
|
|
the shape (prose, not an envelope).
|
|
"""
|
|
|
|
import re
|
|
|
|
from backend.apps.agents.core.error_classify import (
|
|
is_content_policy_block, neutralize_provider_refusal, opens_with_provider_refusal,
|
|
)
|
|
from backend.apps.agents.manager.streaming.provider_error_speech import (
|
|
POLICY, classify_provider_error, looks_like_provider_envelope,
|
|
)
|
|
|
|
REAL = ("Claude Code is unable to respond to this request, which appears to violate our Usage Policy "
|
|
"(https://www.anthropic.com/legal/aup). Please double press esc to edit your last message or "
|
|
"start a new session for a fresh start.")
|
|
|
|
|
|
def test_the_clis_own_wording_is_recognised_without_the_url():
|
|
# It only ever matched via "legal/aup" in the URL, so a truncated preview read as a clean turn.
|
|
assert is_content_policy_block("appears to violate our Usage Policy.")
|
|
assert is_content_policy_block("violates our Acceptable Use Policy")
|
|
assert is_content_policy_block("reverse engineering or duplicating model outputs")
|
|
|
|
|
|
def test_prose_with_no_envelope_is_still_the_provider_talking():
|
|
assert "API Error" not in REAL and not re.search(r"\b4\d\d\b", REAL)
|
|
assert opens_with_provider_refusal(REAL)
|
|
assert looks_like_provider_envelope(REAL)
|
|
c = classify_provider_error(REAL)
|
|
assert c is not None and c.kind == POLICY
|
|
|
|
|
|
def test_the_refusal_never_travels_home_as_a_delegated_answer():
|
|
out = neutralize_provider_refusal(REAL)
|
|
assert out != REAL
|
|
assert "Usage Policy" not in out and "violate" not in out
|
|
|
|
|
|
def test_a_real_answer_that_discusses_policy_keeps_every_word():
|
|
# The innocent case: this is what an agent asked to summarise a terms page actually returns.
|
|
innocent = ("Their Acceptable Use Policy forbids reverse engineering. Section 3 also bans "
|
|
"duplicating model outputs, and accounts may be suspended for it.")
|
|
assert neutralize_provider_refusal(innocent) == innocent
|
|
assert classify_provider_error(innocent) is None
|
|
|
|
|
|
def test_the_refusal_must_OPEN_the_message_to_count():
|
|
# A long real answer that quotes the refusal late is work, not a refusal; eating it would be
|
|
# silent work loss, which is worse than the bug this guard exists for.
|
|
embedded = ("Here is what I found across the three pages you asked about, with the quotas and "
|
|
"the pricing table reproduced below in full detail for each tier of the plan. "
|
|
"One page did say it is unable to respond to this request, which appears to "
|
|
"violate our Usage Policy, so I skipped it.")
|
|
assert not opens_with_provider_refusal(embedded)
|
|
assert neutralize_provider_refusal(embedded) == embedded
|
|
|
|
|
|
def test_the_model_refusing_on_its_own_is_not_scored_as_a_policy_block():
|
|
# No policy wording at all, so it stays the agent's own speech.
|
|
own = "I'm unable to respond to this request because the file you named does not exist."
|
|
assert not opens_with_provider_refusal(own)
|
|
assert classify_provider_error(own) is None
|