Repository navigation
fix(core): cap images per request and compact on image-count errors - #59303
rekram1-node wants to merge 2 commits into
Conversation
There was a problem hiding this comment.
This fixes the 50-image case I tested. With 52 images in history, the base sends all 52 and the provider's count error is not classed as overflow. With this PR, 30 images are sent and the error is classed as context overflow, so compaction runs. Tests pass (session-model-request, provider-error, and the compaction/runner suites). The packages' typecheck script fails here with Script not found "check" (a local bun setup problem, not this PR), so I ran typecheck:tsc in core and ai instead: both clean.
Public API is unchanged: this only touches internal request shaping and error classification.
One gap worth closing before merge: Console Go also enforces a 30-image cap on some routes (#48715, #51073). It rejects with Too many images in request: 31 > 30. None of the new patterns match that message, and the count cap of 40 is above 30, so those sessions stay stuck on the same 400 with no compaction (details inline). Also, the read tool only sets the file's basename as its name, so the placeholder won't contain the full path the description shows (inline).
| /token limit exceeded/i, | ||
| /request_too_large/i, | ||
| // Image-count caps: compaction drops the replayed images, so these recover the same way. | ||
| // OpenCode Console/Zen gateway |
There was a problem hiding this comment.
Console Go also rejects with [invalid_request_error] Too many images in request: 31 > 30 on some routes (#48715, #51073). None of these patterns match it: I checked, and isContextOverflow returns false. Since the count cap of 40 is above 30, those sessions still get stuck with no compaction. Could you add a pattern for it, e.g. /too many images in request/i?
| // A per-model limit would replace this constant; the target stays a fixed fraction of it. | ||
| const IMAGE_COUNT_TRIGGER = 40 | ||
| const IMAGE_COUNT_TARGET = 30 | ||
| const imageRemoved = (name: string | undefined) => |
There was a problem hiding this comment.
The read tool sets name: path.basename(input) in packages/core/src/tool/read-filesystem.ts, so for screenshots the placeholder will say read "shot-3.png" again, not the full /tmp/shot-3.png that the description and the new test use. Relative to the project directory, that bare name can point the model at the wrong file. It may be worth keeping the full path for tool-result files, or making the test use the name read actually produces.
There was a problem hiding this comment.
The new commit handles the Console Go 30-image case: Too many images in request: 31 > 30 is now classed as context overflow, and with the 30/20 cap a 52-image history sends 30 images. Tests pass (session-model-request, provider-error, and the compaction/runner suites), and typecheck:tsc is clean in core and ai. Public API is unchanged. The earlier point that the placeholder gives only the file's basename is still open.
Problem
Sessions that
reada lot of screenshots die once history passes the provider's image cap. Every later request replays the same images and gets a 400 likerequest contains 52 images, exceeding the maximum of 50 allowed per request, even plain text prompts. Nothing recovers: the error isn't classified as overflow, so compaction never runs, andboundImagesonly limits bytes, not count.Fixes #47721 (and the same report in #47487).
Change
Two parts:
The count cut works like the byte cut: it moves in steps of 10 images, so the replaced prefix (and the prompt cache) stays the same between cuts. 30 matches the lowest cap I found (some OpenCode Go routes reject
Too many images in request: 31 > 30; Console/Zen and Azure allow 50). It's a single constant for now, so a per-model limit can replace it later.If a provider rejects on count anyway (lower cap, or images arriving in one turn), it now counts as context overflow, so the runner compacts and the compaction request falls back to text.
Visual
Out of scope
Verification
bun test test/session-model-request.test.ts(core): 12 passbun test test/provider-error.test.ts(ai): 42 passbun test test/session-compaction*.test.ts test/session-runner*.test.ts(core): 323 passbun typecheckin core and ai,bun run checkfrom the root: cleanAdded by the opencode bot (AI-generated).
Related: #48715, #51073, #48095