mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-31 19:16:29 +00:00
fix(errors): classify throttle messages before token-overflow patterns; add new overflow shapes
Port from anomalyco/opencode#37848 (+ dev-branch twin #37840): expand context-overflow patterns and guard against rate-limit messages that mention tokens. - 'Throttling error: Too many tokens, please wait before trying again.' (AWS Bedrock / proxy shape) classified as context_overflow and routed a healthy session into compression on every throttle. Added 'throttling' to _RATE_LIMIT_PATTERNS, which the message-only path checks BEFORE the overflow list. - 'Input length N exceeds the maximum allowed input length of M tokens.' (Together/Fireworks shape) fell through to unknown — no compression recovery. Added 'maximum allowed input length' to overflow patterns. - 'request_too_large' / 'Request exceeds the maximum size' (Anthropic 413 type re-wrapped without a status code by aggregators/proxies) fell through to unknown. Added to _PAYLOAD_TOO_LARGE_PATTERNS. All three shapes proven live on main before the fix; 265 classifier + bedrock tests and 238 sibling rate-guard/compression tests pass.
This commit is contained in:
parent
c4d1913294
commit
53bfe40a35
2 changed files with 90 additions and 0 deletions
|
|
@ -2170,3 +2170,75 @@ class Test408RequestTimeout:
|
|||
assert result.should_fallback is True
|
||||
assert result.should_compress is False
|
||||
|
||||
|
||||
# ── Test: throttle vs overflow disambiguation + new overflow shapes ─────
|
||||
# Port of anomalyco/opencode#37848 (expand context overflow patterns +
|
||||
# rate-limit exclusion guard).
|
||||
|
||||
class TestThrottleVsOverflowDisambiguation:
|
||||
"""Throttle messages that mention tokens must NOT route to compression."""
|
||||
|
||||
def test_bedrock_throttling_too_many_tokens_is_rate_limit(self):
|
||||
# AWS Bedrock (and some proxies) surface throttling as
|
||||
# "Throttling error: Too many tokens, please wait before trying
|
||||
# again." — the "too many tokens" fragment sits in
|
||||
# _CONTEXT_OVERFLOW_PATTERNS, so before the "throttling" rate-limit
|
||||
# pattern this compressed a healthy session on every throttle.
|
||||
e = Exception(
|
||||
"Throttling error: Too many tokens, please wait before trying again."
|
||||
)
|
||||
result = classify_api_error(e, provider="bedrock", model="claude")
|
||||
assert result.reason == FailoverReason.rate_limit
|
||||
assert result.should_compress is False
|
||||
|
||||
def test_plain_too_many_tokens_still_overflow(self):
|
||||
# Without any throttle wording, "Too many tokens" remains a
|
||||
# context-overflow signal (Z.AI / GLM family wording).
|
||||
e = Exception("Too many tokens")
|
||||
result = classify_api_error(e, provider="zai", model="glm-5")
|
||||
assert result.reason == FailoverReason.context_overflow
|
||||
assert result.should_compress is True
|
||||
|
||||
|
||||
class TestExpandedOverflowPatterns:
|
||||
"""New provider overflow wordings route into compression recovery."""
|
||||
|
||||
def test_maximum_allowed_input_length_is_overflow(self):
|
||||
# Together/Fireworks-style wording — matched no pattern before.
|
||||
e = Exception(
|
||||
"Input length 131393 exceeds the maximum allowed input length "
|
||||
"of 131040 tokens."
|
||||
)
|
||||
result = classify_api_error(e, provider="together", model="m")
|
||||
assert result.reason == FailoverReason.context_overflow
|
||||
assert result.should_compress is True
|
||||
|
||||
def test_request_too_large_message_only_is_payload_too_large(self):
|
||||
# Anthropic's structured 413 type re-wrapped by a proxy with no
|
||||
# status attribute — was falling through to `unknown`.
|
||||
e = Exception(
|
||||
'{"error":{"type":"request_too_large",'
|
||||
'"message":"Request exceeds the maximum size"}}'
|
||||
)
|
||||
result = classify_api_error(e, provider="anthropic", model="m")
|
||||
assert result.reason == FailoverReason.payload_too_large
|
||||
assert result.should_compress is True
|
||||
|
||||
def test_longer_than_context_length_still_overflow(self):
|
||||
# Regression guard for wordings that already matched.
|
||||
e = Exception(
|
||||
"The input (516368 tokens) is longer than the model's context "
|
||||
"length (262144 tokens)."
|
||||
)
|
||||
result = classify_api_error(e, provider="openrouter", model="m")
|
||||
assert result.reason == FailoverReason.context_overflow
|
||||
|
||||
def test_configured_context_size_still_overflow(self):
|
||||
e = Exception(
|
||||
"Prompt has 5,958,968 tokens, but the configured context size "
|
||||
"is 256,000 tokens"
|
||||
)
|
||||
result = classify_api_error(e, provider="ollama", model="m")
|
||||
assert result.reason == FailoverReason.context_overflow
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue