fix(agent): drop non-invariant disable-rung test; document thinking-state 400 trade-off (#114460)
test_disable_drop_rung_sets_session_flag_once stays green with agent/turn_recovery.py from
main (that hunk is comment/message text only), so it is not an invariant of this fix; the
spent-path test already carries the flag-false control. Docstring on
is_reasoning_field_rejection records the accepted trade-off for thinking-state 400s
("Function calling is not supported when thinking is enabled"): the marker sits 6 chars from
the token, so no proximity gate separates it from the forward wordings; cost is one
dropped-disable retry before the spent path falls back.
This commit is contained in:
@@ -464,7 +464,12 @@ def is_reasoning_field_rejection(error_msg: str) -> bool:
|
||||
request argument supplied: reasoning_effort", #112781) or a standalone "unsupported" next to the
|
||||
field in either word order ("unsupported reasoning_effort"; "reasoning_effort 'none' unsupported;
|
||||
use minimal|low|medium|high|xhigh", #114460). The route default is the right answer for such a
|
||||
model, so both the main loop and the auxiliary ladder retry once without the disable."""
|
||||
model, so both the main loop and the auxiliary ladder retry once without the disable.
|
||||
|
||||
Known trade-off: a 400 about a thinking *state* ("Function calling is not supported when
|
||||
thinking is enabled") also matches — the marker sits right next to the token, so no proximity
|
||||
rule separates it from the forward wordings. Cost is one dropped-disable retry before the
|
||||
spent path takes the fallback chain; the auxiliary ladder already treated it this way."""
|
||||
msg = (error_msg or "").lower()
|
||||
token = _REASONING_FIELD_TOKEN.search(msg)
|
||||
if token is None:
|
||||
|
||||
@@ -83,24 +83,8 @@ def test_spent_disable_drop_falls_back_instead_of_replaying_the_request():
|
||||
assert verdict.action == "break"
|
||||
assert agent.activated == [True]
|
||||
|
||||
# Control: before the drop has run the verdict stays retryable (the rung gets its shot).
|
||||
# Control: before the drop has run the verdict stays retryable (the rung gets its shot;
|
||||
# the one-shot drop itself is pre-existing ``turn_recovery`` behaviour, not asserted here).
|
||||
agent, verdict = _settle(disable_drop_attempted=False)
|
||||
assert verdict.action == "fallthrough"
|
||||
assert agent.activated == []
|
||||
|
||||
|
||||
def test_disable_drop_rung_sets_session_flag_once():
|
||||
from agent.turn_recovery import recover_after_classification
|
||||
from agent.turn_retry_state import TurnRetryState
|
||||
|
||||
agent = _Agent()
|
||||
err = _FakeApiError(400, _REVERSED_400)
|
||||
classified = classify_api_error(err, provider="custom", model=agent.model)
|
||||
retry = TurnRetryState()
|
||||
with patch("agent.conversation_loop._is_nous_inference_route", lambda *a, **k: False):
|
||||
first, _ = recover_after_classification(
|
||||
agent, err, classified, retry, status_code=400, error_context=None, messages=[], api_messages=[])
|
||||
second, _ = recover_after_classification(
|
||||
agent, err, classified, retry, status_code=400, error_context=None, messages=[], api_messages=[])
|
||||
assert first is True and agent._reasoning_disable_rejected is True
|
||||
assert second is False
|
||||
|
||||
Reference in New Issue
Block a user