fix(images): correct image media types that disagree with their bytes - #176
ian-de-marcellus wants to merge 1 commit into
Conversation
A Discord attachment labelled image/webp whose bytes were PNG entered a resident's history; the provider rejects the whole request on such a mismatch, so every subsequent turn failed (Fable, 2026-09-24). Correct base64 image blocks' mediaType from their magic bytes when context is compiled for a request (including images nested in tool results). Stored history is not modified; compiled messages get new objects only where something changed. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
|
| ); | ||
| if (!budget) this.settleRuntimeSettingsTransition(); | ||
| return result; | ||
| return { ...result, messages: correctImageMediaTypes(result.messages) }; |
There was a problem hiding this comment.
Live tool images bypass correction When an MCPL tool returns a PNG labeled
image/webp, the framework passes the image directly to the existing stream for the next inference round. That round does not recompile the context, so this correction never runs on the tool result and the provider can still reject the request. Correct image blocks at the live continuation boundary too.
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agent.ts
Line: 546
Comment:
**Live tool images bypass correction** When an MCPL tool returns a PNG labeled `image/webp`, the framework passes the image directly to the existing stream for the next inference round. That round does not recompile the context, so this correction never runs on the tool result and the provider can still reject the request. Correct image blocks at the live continuation boundary too.
---
For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.
Problem. A resident's turns all started failing with a provider 400. The context held an image whose
media_typesaidimage/webpbut whose bytes were a PNG; it arrived through a surface (Portal) that trusted the uploader's label. The API rejects any request where the label and bytes disagree, and the image stays in context, so every later turn failed the same way until an operator intervened.Fix.
src/image-media-type.tssniffs the magic bytes (PNG, JPEG, GIF, WebP) of base64 image blocks.correctImageMediaTypesrewrites a disagreeing media type on the compiled messages (compileContext/compileWithInjections), including images nested intool_result, before they go to the provider, and logs how many blocks it corrected. Unrecognized formats and non-base64 sources pass through untouched; stored history is never modified (new objects only for changed blocks).Tests.
test/image-media-type.test.ts: a PNG labeledimage/webpis corrected, including insidetool_result, without mutating the input; correct and unknown images are returned as the same objects. Full suite: 956 pass / 0 fail.(The surface side is being fixed separately in portal. This makes the framework robust to any surface that mislabels.)
🤖 Generated with Claude Code