Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions src/agentos/provider/failures.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,14 @@ def _is_context_overflow(text: str) -> bool:
"context window",
"maximum context",
"prompt is too long",
"prompt_too_long",
"input is too long",
"input exceeds",
"provider_request_budget_exhausted",
"too many tokens",
"exceed context limit",
"request_too_large",
"request size exceeds",
)
)

Expand Down
64 changes: 64 additions & 0 deletions tests/test_provider_failure_classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,3 +290,67 @@ def test_new_transient_status_codes_match_via_text(message: str) -> None:
classify_provider_error("openrouter", None, message=message)
is ProviderFailureKind.PROVIDER_OVERLOADED
)


# -- Anthropic-specific context overflow markers ----------------------------


@pytest.mark.parametrize(
("provider", "status_code", "raw_code", "message", "desc"),
[
(
"anthropic",
400,
"invalid_request_error",
"input length and max_tokens exceed context limit: 188240 + 21333 > 200000",
"canonical Anthropic 400 message",
),
(
"anthropic",
413,
"request_too_large",
"Request exceeds the maximum allowed number of bytes",
"Anthropic 413 error type",
),
(
"anthropic",
413,
"",
"Request size exceeds model context window",
"Anthropic 413 message variant",
),
(
"anthropic",
400,
"prompt_too_long",
"prompt is too long",
"prompt_too_long raw code",
),
],
ids=lambda v: v if isinstance(v, str) and len(v) < 40 else None,
)
def test_anthropic_context_overflow_markers(
provider: str,
status_code: int,
raw_code: str,
message: str,
desc: str,
) -> None:
"""Anthropic context overflow messages must classify as CONTEXT_OVERFLOW."""
assert (
classify_provider_error(provider, status_code, raw_code=raw_code, message=message)
is ProviderFailureKind.CONTEXT_OVERFLOW
), f"Failed for: {desc}"


def test_anthropic_invalid_request_without_overflow_stays_bad_request() -> None:
"""Anthropic invalid_request_error without overflow markers → BAD_REQUEST."""
assert (
classify_provider_error(
"anthropic",
400,
raw_code="invalid_request_error",
message="messages: roles must alternate between user and assistant",
)
is ProviderFailureKind.BAD_REQUEST
)
Loading