fix(media-understanding): forward scanned PDF page images to vision models on chat channels#96641
fix(media-understanding): forward scanned PDF page images to vision models on chat channels#96641HonorVanEr wants to merge 1 commit into
Conversation
…odels on chat channels
|
Codex review: needs real behavior proof before merge. Reviewed June 24, 2026, 10:57 PM ET / 02:57 UTC. Summary PR surface: Source +78, Tests +99. Total +177 across 6 files. Reproducibility: yes. source-level. Current main can receive PDF-rendered images from Review metrics: 2 noteworthy metrics.
Root-cause cluster Members:
Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything. Merge readiness Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch. Rank-up moves:
Proof guidance:
Mantis proof suggestion Risk before merge
Maintainer options:
Next step before merge
Security Review findings
Review detailsBest possible solution: Land the narrow image-handoff approach after adding ACP changed-path coverage, updating the media-understanding docs, and attaching redacted real chat or high-fidelity runtime proof. Do we have a high-confidence way to reproduce the issue? Yes, source-level. Current main can receive PDF-rendered images from Is this the best way to solve the issue? Yes, with fixes before merge. Reusing the existing current-turn inline-image and ACP attachment plumbing is the right owner boundary, but the PR needs ACP coverage, docs alignment, and real behavior proof. Full review comments:
Overall correctness: patch is incorrect AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning high; reviewed against 643410c1f3c0. Label changesLabel changes:
Label justifications:
Evidence reviewedPR surface: Source +78, Tests +99. Total +177 across 6 files. View PR surface stats
What I checked:
Likely related people:
What the crustacean ranks mean
Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics. How this review workflow works
|
|
Closing this PR — the fix direction is validated (ClawSweeper confirms State of the fix (independently verified by ClawSweeper review):
Why closing: This is a message-delivery change, and the proof gate requires redacted live output / chat recording from a real channel transport. This environment cannot run a real Telegram/WhatsApp round-trip, so the proof dimension is capped at A maintainer is welcome to reopen this branch and accept the Vitest-level proof, or pick up the diff. The branch Thanks for the thorough review. |
What Problem This Solves
Fixes #96541
Scanned / image-only PDFs attached to chat channel messages (Telegram, WhatsApp, Slack, Discord, etc.) are silently dropped: the document extractor rasterizes pages to images, but the chat media-understanding path replaces the missing text with a dead-end placeholder string (
[PDF content rendered to images; images not forwarded to model]) and never forwards the page images to the model. The identical extractor output is forwarded correctly on the/v1/responsesAPI path (openresponses-http.ts), so a scanned receipt/contract that works over the API is ignored on every chat channel.Why This Change Was Made
The chat path (
extractFileBlocksinsrc/media-understanding/apply.ts) had no route to forward extracted page images:extractFileBlocksreturned onlystring[](text blocks) andApplyMediaUnderstandingResulthad no image-carrying field. The page images existed (the extractor returns them when extracted text is belowminTextChars) but were discarded before reaching the model.This adds an image channel parallel to the existing text blocks so extracted PDF page images are forwarded to vision-capable models, mirroring the API path at
openresponses-http.ts:629-630.User Impact
Vision-capable models can now read scanned / image-only PDFs sent on chat channels, instead of receiving only a placeholder string. Behavior for text-extractable PDFs and non-PDF attachments is unchanged.
Behavior addressed: scanned / image-only PDF page images extracted on the chat channel path are dropped, leaving the model a placeholder string.
Approach:
extractFileBlocksnow returns{ blocks, images }alongside its text blocks, collecting extracted page images.applyMediaUnderstandingwrites collected images toctx.CurrentTurnImages(new optionalMsgContextfield).resolveCurrentTurnImages(non-ACP agent path) consumesctx.CurrentTurnImagesviatakeCurrentTurnImagesand merges them into the turn's image payload (with idempotent take-once semantics to prevent double-merge across prepare/run passes).tryDispatchAcpReply(ACP path, which bypassesresolveCurrentTurnImages) consumestakeCurrentTurnImagesdirectly and appends extracted images to inline attachments.[PDF content rendered to images; images not forwarded to model]→[PDF content rendered to images]since images are now forwarded.Evidence
Real environment tested: vitest regression tests driving the real
applyMediaUnderstanding+resolveCurrentTurnImagespaths with the document-extractor boundary stubbed to return one image-only page (the one true external boundary — real base64 canonicalization, real PDF MIME validation, realextractPdfContentorchestration run end-to-end).Exact steps or command run after this patch:
pnpm test src/media-understanding/apply.test.ts src/auto-reply/reply/current-turn-images.test.tsEvidence after fix: New regression test
carries rendered PDF page images into current-turn image payloadsasserts thatctx.CurrentTurnImagesis populated with the extracted page image andctx.Bodyno longer contains "images not forwarded". New testmerges current-turn extracted images with existing inline imagesasserts the merge path. New testdoes not merge extracted images twice across the prepare and run passesasserts idempotent take-once semantics.Observed result after fix:
result.appliedFile === true,ctx.CurrentTurnImagescontains the extractedimage/pngpage raster, placeholder text no longer claims images are dropped. Pre-fix,ctx.CurrentTurnImageswas never set and the only forwarded block was a text block with zero image bytes.What was not tested: The live channel transport end-to-end (a real Telegram/WhatsApp send) was not exercised; the rendering boundary (
extractDocumentContent) was stubbed rather than running clawpdf on real raster bytes.AI-assisted: this PR was prepared with AI assistance. The approach was validated against a prior community attempt (closed PR that confirmed the root cause and fix direction but could not satisfy the proof gate).