You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
core: boundImages spends its image-budget cut on remote images that carry no payload #61391
boundImages sizes the inline image budget with mediaBytes, which returns 0 for url and ref sources — the comment at packages/core/src/session/model-request.ts:153-154 states that "Remote and provider-referenced media carry no local payload and never count toward the inline budget".
The cut is then chosen by walking sizes in order (:208-214) but applied by document position (:217-221), so zero-cost media occupies slots in the removal queue. When the loop reaches a remote image it subtracts 0 from kept and still advances cut, spending a removal that frees nothing. Remote images are therefore replaced with IMAGE_REMOVED even though deleting them cannot help the budget, and the session loses content that was free to keep.
Steps to reproduce
Two remote images followed by two 13 MiB inline images (26 MiB passes the 25 MiB trigger; one inline image returns it under the 15 MiB target):
Thanks for the clear report. I reproduced this on the latest dev (3ba597f) with a unit test for boundImages, using two remote (Media.url) images followed by two 13 MiB inline images. The first three images were all replaced with the removal notice: both remote ones and c.png. Removing only c.png would have been enough, so the count was 3 instead of 1.
The cause is in the cut loop: it moves past remote images even though they count 0 bytes toward the budget, so those slots free nothing. The script below reproduces it.
Related: #53304 (keeping the removed set stable for the prompt cache, same function).
Reproduction script (repro-61391.test.ts)
import{expect,test}from"bun:test"import{Message,Media}from"@opencode/ai/effect"import{boundImages}from"@opencode/core/session/model-request"// #61391: remote (url) images carry no inline payload, yet boundImages spends cut slots on them.constremote=(name: string)=>Message.user({type: "media",media: Media.url(`https://example.com/${name}`,{mediaType: "image/png"}),filename: name})constinline=(name: string)=>Message.user({type: "media",media: Media.base64("a".repeat(13*1024*1024),"image/png"),filename: name})constremoved=(messages: ReturnType<typeofboundImages>)=>messages.filter((message)=>message.content[0]?.type==="text").lengthtest("spends the image budget only on images with a payload",()=>{constresult=boundImages([remote("a.png"),remote("b.png"),inline("c.png"),inline("d.png")])console.log("replaced:",result.map((m,i)=>`${["a","b","c","d"][i]}=${m.content[0]?.type}`).join(" "))expect(removed(result)).toBe(1)})
I'll take this one. The bot's reproduction matches the report: boundImages spends cut slots on remote/ref images that carry 0 bytes, so two free images plus one inline image get replaced where only the inline one should be.
Plan: reproduce first with the boundImages unit case (2 remote + 2 x 13 MiB inline, expect 1 removed), then fix the cut loop to skip zero-byte media when choosing what to remove, and run the neighbouring session-model-request tests plus the package typecheck before opening a PR.
Activity
opencodejr commentedon Nov 3, 2026
Thanks for the clear report. I reproduced this on the latest
dev(3ba597f) with a unit test forboundImages, using two remote (Media.url) images followed by two 13 MiB inline images. The first three images were all replaced with the removal notice: both remote ones andc.png. Removing onlyc.pngwould have been enough, so the count was 3 instead of 1.The cause is in the cut loop: it moves past remote images even though they count 0 bytes toward the budget, so those slots free nothing. The script below reproduces it.
Related: #53304 (keeping the removed set stable for the prompt cache, same function).
Reproduction script (repro-61391.test.ts)
Run it:
bun repro-61391.test.tsjimmyallinai commentedon Nov 3, 2026
I'll take this one. The bot's reproduction matches the report:
boundImagesspends cut slots on remote/ref images that carry 0 bytes, so two free images plus one inline image get replaced where only the inline one should be.Plan: reproduce first with the
boundImagesunit case (2 remote + 2 x 13 MiB inline, expect 1 removed), then fix the cut loop to skip zero-byte media when choosing what to remove, and run the neighbouringsession-model-requesttests plus the package typecheck before opening a PR.