Repository navigation
fix(agent-runtime): classify every overflow pi-ai recovers from as CONTEXT_TOO_LARGE - #1517
Conversation
…NTEXT_TOO_LARGE The runtime starts provider overflow recovery with pi-ai's isContextOverflow, but classifyAgentError used its own, narrower CONTEXT_PATTERN. Overflow wording that only pi-ai knew (DashScope/Qwen "Range of input length should be", z.ai "Prompt exceeds max length", xAI "maximum prompt length is", Groq, llama.cpp, Bedrock "Input is too long for requested model") was recovered as an overflow but reported as PROVIDER_ERROR. A delegate, which only has the classifier, reported PROVIDER_ERROR instead of SUBAGENT_CONTEXT_OVERFLOW, and a status-less Bedrock overflow was classified retriable, so the delegate re-sent the same oversized request through the transient budget. Ask pi-ai's isContextOverflow from the message text first and keep CONTEXT_PATTERN for the wording already accepted. Probe throttling as rate limiting before overflow wording, so Bedrock's "Throttling error: Too many tokens, please wait" stays PROVIDER_RATE_LIMITED instead of a terminal CONTEXT_TOO_LARGE. Update the error-code and agent-runtime specs (with zh-CN copies).
muzimu217
left a comment
There was a problem hiding this comment.
Verified locally on macOS (patch applied to a detached worktree at current upstream HEAD ed54ce977): agent-runtime full suite 94 files / 1320 tests pass — the +12 over main are the new classification tests.
The design is the correct unification: the terminal classifier now defers to pi-ai's isContextOverflow — the same check that starts provider overflow recovery — instead of maintaining its own narrower CONTEXT_PATTERN. That single change fixes #1516's two failure modes at once:
- vendor wordings pi-ai knows but
CONTEXT_PATTERNmissed (DashScope/Qwen, z.ai, xAI, Groq, llama.cpp, Bedrock) now get the recover-first-then-terminal path instead of being misreported asPROVIDER_ERROR; - delegates stop burning retries on a terminal condition —
CONTEXT_TOO_LARGEis never replayed by either retry budget and surfaces asSUBAGENT_CONTEXT_OVERFLOW.
The ordering guarantee is documented, not just implemented: rate-limit wording (including Bedrock's Throttling error: Too many tokens…) is classified before the overflow check and stays PROVIDER_RATE_LIMITED, and HTTP 413 keeps its own path. Spec updates cover the error-code registry (08-error-codes) and the runtime spec in both languages.
Patch applies cleanly to current HEAD; nothing blocking. fix scope, fits the contribution window — and it pairs naturally with #1495/#1499 as part of the runtime-robustness batch.
|
Thanks for the detailed reproduction and the aligned classifier fix. The regression tests cover main-session recovery, delegate error mapping, and Bedrock throttling; all required checks passed. Merged. |
Fixes #1516
Problem
Two different checks decide what a context overflow is:
runtime.tsstarts provider overflow recovery with pi-ai'sisContextOverflow.classifyAgentErrorchooses the error code with its own, narrowerCONTEXT_PATTERN.pi-ai knows overflow wording that
CONTEXT_PATTERNdoes not: DashScope/QwenRange of input length should be, z.aiPrompt exceeds max length, xAImaximum prompt length is, Groqreduce the length of the messages, llama.cppexceeds the available context size, and BedrockInput is too long for requested model. For these:PROVIDER_ERRORinstead ofCONTEXT_TOO_LARGE, which contradicts08-error-codes.md.PROVIDER_ERRORinstead ofSUBAGENT_CONTEXT_OVERFLOW, so the parent model gets raw provider text instead of the "narrow the task / larger window" guidance. A Bedrock overflow has no status in its message, so it was classified retriable and re-sent unchanged through the transient budget.The reverse also happens: Bedrock's throttle
Throttling error: Too many tokens, please wait before trying again.matchestoo many tokensand became a terminalCONTEXT_TOO_LARGE, so it was never retried. pi-ai'sisContextOverflowalready excludes that message.Change
classifyAgentErrornow asks pi-ai'sisContextOverflowusing only the message text, then falls back toCONTEXT_PATTERN. This applies both to the 400/422 branch and to messages with no status. The terminal code now matches the recovery decision for every wording pi-ai knows, and it stays in sync when pi-ai adds providers.throttland is still checked before overflow wording. Bedrock throttling therefore becomesPROVIDER_RATE_LIMITED.CONTEXT_PATTERNitself, the status table, and retry budgets are unchanged.Specs
docs/spec/03-runtime/08-error-codes.md(provider exception mapping) anddocs/spec/03-runtime/02-agent-runtime.md(provider overflow recovery), plus their zh-CN copies, now say the classifier followsisContextOverflow, that the second overflow isCONTEXT_TOO_LARGE, and that throttling staysPROVIDER_RATE_LIMITED. No ADR changes: ADR 0299's delegate remap already keys offCONTEXT_TOO_LARGE.Verification (base
origin/mained54ce9)agent-errors.test.ts: the six provider overflow messages as pi-ai 1.1.0 formats them assertisContextOverflow === trueandCONTEXT_TOO_LARGE, non-retriable, through bothclassifyAgentErrorandclassifyProviderError. A separate test covers Bedrock throttling →PROVIDER_RATE_LIMITED.subagent.test.ts: DashScope and Bedrock overflows end the delegate asSUBAGENT_CONTEXT_OVERFLOW, with no provider retry claimed and nocontinue(). On main:PROVIDER_ERROR.runtime.test.ts: for DashScope, z.ai, and Bedrock, the first overflow is compacted and retried once, and the second is reported asCONTEXT_TOO_LARGE.openai-completionsadapter against a mocked HTTP 400 body for each provider, so the test strings match what the runtime actually sees (local check, not part of the PR).@pi-desktop/agent-runtimetests: 1320/1320 pass.pnpm build:js, agent-runtime and desktoptypecheck,pnpm lint,pnpm docs:check,node scripts/check-architecture.mjs, andpnpm check:pr-baseall pass.