-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix(responses): classify non-streaming provider input overflow #4127
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -424,7 +424,7 @@ import { | |
| } from "../responses-undeclared-tool-guard"; | ||
| import { createGithubCopilotResponsesBlockRewrite } from "../github-copilot-responses-repair"; | ||
| import { responsesJsonToSseStream } from "../responses-json-events"; | ||
| import { streamingContextOverflowResponse } from "./context-overflow"; | ||
| import { jsonContextOverflowResponse, streamingContextOverflowResponse } from "./context-overflow"; | ||
| import { guardTerminalEventStream } from "./terminal-guard"; | ||
| import { | ||
| emptyCompletionRetryEnabled, | ||
|
|
@@ -2986,6 +2986,11 @@ export async function handleComboResponses( | |
| const failureDecision = comboFailureDecision(failure.response.status, failure.classificationText, { | ||
| code: failure.upstreamCode, | ||
| }); | ||
| const wantsStream = (rawBody as { stream?: unknown } | null)?.stream === true; | ||
| // Local byte admission has its own diagnostic; do not relabel it as an upstream refusal. | ||
| const classifyOverflow = failure.response.status === 413 | ||
| && (wantsStream || (failure.upstreamCode !== "outbound_body_too_large" | ||
| && failure.upstreamCode !== "translation_buffer_limit")); | ||
|
Comment on lines
+2991
to
+2993
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift Do not use provider error codes as local-failure provenance.
The combo path then returns its generic Track locally generated admission failures with trusted provenance. Exclude only that trusted marker. Add a combo regression where an upstream HTTP 413 uses each excluded code and assert the fixed JSON response with status 413. As per coding guidelines, adapter changes must preserve error mapping. 🤖 Prompt for AI AgentsSource: Coding guidelines |
||
| if (storedPool401ReplayDispatched) { | ||
| if (failureDecision === "hop" && unreadableEncryptedAgentTask && !comboPayloadReadable) { | ||
| const recoveredTarget = await pickWithWait({ | ||
|
|
@@ -3010,15 +3015,19 @@ export async function handleComboResponses( | |
| // Keep the spent Pool budget sticky even after a recovered routed child: | ||
| // no later failure may reopen ordinary combo/native account hopping. | ||
| adoptFailedChildLog(childLog); | ||
| if (classifyOverflow && failureDecision === "stop") { | ||
| return wantsStream | ||
| ? streamingContextOverflowResponse(requestedModel, options.translatorBudget) | ||
| : jsonContextOverflowResponse(); | ||
| } | ||
| return lastFailure; | ||
| } | ||
| if (failureDecision === "stop") { | ||
| adoptFailedChildLog(childLog); | ||
| if ( | ||
| failure.response.status === 413 | ||
| && (rawBody as { stream?: unknown } | null)?.stream === true | ||
| ) { | ||
| return streamingContextOverflowResponse(requestedModel, options.translatorBudget); | ||
| if (classifyOverflow) { | ||
| return wantsStream | ||
| ? streamingContextOverflowResponse(requestedModel, options.translatorBudget) | ||
| : jsonContextOverflowResponse(); | ||
| } | ||
| return lastFailure; | ||
| } | ||
|
|
@@ -5699,7 +5708,8 @@ async function handleResponsesInner( | |
|
|
||
| // Non-2xx passthrough failures must never reach Codex as an empty body — | ||
| // Codex renders that as the opaque "Unknown error" (#452). Combo attempts | ||
| // keep their typed failure envelope. Non-empty bodies are relayed verbatim | ||
| // keep their typed failure envelope. Except for the classified 413 below, | ||
| // non-empty bodies are relayed verbatim | ||
| // (headers included) so pool-retry Activation B/D and client diagnostics stay intact. | ||
| // Manual-redirect policy (#914): a 3xx is relayed as-is (Location preserved | ||
| // through sanitizePassthroughHeaders) so a redirect to a dead host can never | ||
|
|
@@ -5727,11 +5737,10 @@ async function handleResponsesInner( | |
| // The bounded reader owns the original body, deadline, abort settlement, and lock. | ||
| // Unsafe partial data falls back to #452's non-empty status-only JSON. | ||
| const errorText = await readDisplaySafeErrorText(upstreamResponse, upstream.signal, ""); | ||
| if (upstreamResponse.status === 413 && clientRequestedStream) { | ||
| return streamingContextOverflowResponse( | ||
| parsed._responseModelId ?? parsed.modelId, | ||
| translatorBudget, | ||
| ); | ||
| if (upstreamResponse.status === 413) { | ||
| return clientRequestedStream | ||
| ? streamingContextOverflowResponse(parsed._responseModelId ?? parsed.modelId, translatorBudget) | ||
| : jsonContextOverflowResponse(); | ||
| } | ||
| return formatPassthroughUpstreamError(upstreamResponse.status, errorText, { | ||
| statusText: upstreamResponse.statusText, | ||
|
|
@@ -7463,11 +7472,10 @@ async function handleResponsesInner( | |
| } finally { | ||
| cleanupUpstreamAbort(); | ||
| } | ||
| if (upstreamResponse.status === 413 && clientRequestedStream && !options.comboAttempt) { | ||
| return streamingContextOverflowResponse( | ||
| parsed._responseModelId ?? parsed.modelId, | ||
| translatorBudget, | ||
| ); | ||
| if (upstreamResponse.status === 413) { | ||
| return clientRequestedStream | ||
| ? streamingContextOverflowResponse(parsed._responseModelId ?? parsed.modelId, translatorBudget) | ||
| : jsonContextOverflowResponse(); | ||
| } | ||
| if (!isFixedCodexAccount(authCtx)) { | ||
| recordSubagentQuotaFailureForThreadSpawn( | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Remove the stale pending qualifier.
Line 84 still describes the behavior as a “pending
devimplementation,” butsrc/server/responses/context-overflow.ts:9-17already implements the HTTP 413 JSON contract described by Lines 85-90. Before publishing this documentation change, describe the behavior as current.Proposed wording
As per path instructions: "
docs-site/**is the public user-documentation source. Document current shipped or intentionally pending behavior."📝 Committable suggestion
🤖 Prompt for AI Agents
Source: Path instructions