Repository navigation
Conversation
…y compaction Proxies and gateways often reject huge bodies with a generic 400 instead of a classified size error, while media counts flat toward tokens and dominates bytes. Treat an unclassified 4xx against a request at or above 4 MiB as a payload rejection: one text-only compaction rebuild before durable output, reusing the existing single-rebuild and opt-out guards. Small requests and non-4xx failures behave exactly as before.
|
This PR doesn't fully meet our contributing guidelines and PR template. What needs to be fixed:
Please edit this PR description to address the above within 72 hours, or it will be automatically closed. If you believe this was flagged incorrectly, please let a maintainer know. |
|
The following comment was made by an LLM, it may be inaccurate: |
There was a problem hiding this comment.
The new recovery works for the case it targets: I copied the PR's runner scenarios onto the base, where the unclassified oversized-rejection recovery fails, and it passes with the PR. With the PR, the core runner/step tests (235), the packages/ai provider-error tests (38) and both typechecks pass.
The main concern is how broad the new check is. On any request of 4 MiB or more, it treats a streamed provider-error event that has no classification as a size rejection, with no check on what the error actually says. I confirmed this with a temporary test: a session with a large image, then a streamed Overloaded error before any output, got compacted instead of failing. Streamed provider errors almost never carry a classification today (overloads, server errors, mid-stream failures), so long, media-heavy sessions would be summarized whenever the provider has a transient problem. On the non-streamed path, every 4xx InvalidRequest without a classification also counts once the body is large: an unknown model, an unsupported parameter, a bad tool schema. Those spend a summary call and then fail again. Details are inline.
The classified payload-too-large half of this change (isPayloadTooLargeFailure, the payload trigger, the text-only start, recoverOverflow(reason), the AGENTS.md line) is almost word for word the same as the still-open #53108. The two will conflict. It would be cleaner to build the size heuristic on top of #53108, or credit it, than to land both separately.
Public API: the only external change is the new isPayloadTooLargeFailure export from @opencode/ai, which is backwards compatible. Config, events and the HTTP API are unchanged.
| * rejection against a huge request is most likely size-caused, so it recovers like a payload | ||
| * rejection. Genuine client bugs stay untouched: small requests never qualify. | ||
| */ | ||
| const isOversizedRejection = (failure: unknown, requestBytes: number) => |
There was a problem hiding this comment.
On the AIError path, the 4 MiB threshold is the only thing separating a size rejection from any other deterministic 4xx. The classifier returns an unclassified InvalidRequestError for every leftover 4xx (404 model not found, unsupported parameter, bad tool schema; see the end of classifyProviderFailure). Once a session holds a few MB of media, all of those trigger a compaction (an extra summary call that replaces the model-visible context) and then fail again. Some narrower signal would help, e.g. only status 400, or a body with no specific code/param, as in the #54690 response.
This branch counts any streamed provider-error with no classification on a request of 4 MiB or more as a size rejection. Unlike the AIError branch above it, it has no 4xx/client-side gate. I checked with a temporary scenario: an image session over 4 MiB that receives LLMEvent.providerError({ message: "Overloaded" }) before output gets compacted and continues. On base, the step fails instead. Streamed errors are mostly overloads and server-side failures, so this would summarize large sessions on transient errors. Could this branch be dropped, or limited to events that actually look like a client-side size rejection?
|
This pull request has been automatically closed because it was not updated to meet our contributing guidelines within the 72-hour window. Feel free to open a new pull request that follows our guidelines. |
Related #46564, #53107. Resolves the #54690 repro (default config).
Proxies and gateways often reject huge bodies with a generic 400 instead of a classified size error, while media counts flat toward tokens and dominates bytes, so neither overflow nor payload recovery triggers and the session dead-ends. This treats an unclassified 4xx against a request at or above 4 MiB as a payload rejection: one text-only compaction rebuild before durable output, reusing the existing single-rebuild limit and opt-out. Small requests and non-4xx failures are untouched.
Note: with
compaction.auto: falserecovery still declines (existing opt-out semantics), so #46564's exact env needs a separate policy call.Verified: packages/ai (1811 pass) and packages/core (6639 pass) suites, both typechecks, oxlint clean. New scenarios cover recovery, small-request and 5xx boundaries, plus a classifier test locking in that generic 400s stay unclassified.
Added by the opencode bot (AI-generated).
Fixes #53107
Related: #46564, #54690
Public API: adds the isPayloadTooLargeFailure export to @opencode/ai (backwards compatible)