feat(providers/anthropic): add PDF document support for file content blocks#37
Merged
Merged
Conversation
…blocks Cherry-picks charmbracelet#197 (commit 95dcd6e) onto coder_2_33. Previously, fantasy.FilePart parts with MediaType "application/pdf" were silently dropped from the Anthropic content list, so a user message whose only content was a PDF attachment produced zero Anthropic messages and a 'dropping empty user message' warning. The model never saw the document. Add an explicit application/pdf case that emits a NewDocumentBlock with a Base64PDFSourceParam, mirroring the image branch's cache-control wiring, and also wire cache-control into the existing text/* document branch. Treat OfDocument as user-visible content so PDF-only user messages are no longer culled as empty. Co-authored-by: Nic-vdwalt <36562088+Nic-vdwalt@users.noreply.github.com>
ethanndickson
added a commit
to coder/coder
that referenced
this pull request
Jun 2, 2026
Previously, user-uploaded PDFs were silently dropped by fantasy's Anthropic provider adapter, so Claude (direct or via Bedrock) only saw the user's text and replied as if no document had been attached. Other providers (OpenAI, Gemini, OpenRouter, Vercel) were unaffected. Bumps `coder/fantasy` past [coder/fantasy#37](coder/fantasy#37) (cherry-pick of upstream [charmbracelet/fantasy#197](charmbracelet/fantasy#197)), which emits an Anthropic `document` content block with a base64 PDF source for `fantasy.FilePart{MediaType: "application/pdf"}` and counts `OfDocument` as user-visible so a PDF-only user message is no longer culled as empty. Adds a regression test (`TestModelFromConfig_AnthropicPDFFilePartReachesProvider`) that drives a `fantasy.FilePart` through the real Anthropic provider against a `chattest.NewAnthropic` stub and asserts the outbound request contains a base64 document block. The test was verified to fail on the previous fantasy pin (the request leaves with zero messages and `Generate` returns EOF) and pass on the new one. Manually verified end-to-end with `./scripts/develop.sh`: uploading a PDF to a Claude-backed Coder Agents chat now lets the model read it. Closes CODAGT-540
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Cherry-picks upstream charmbracelet#197 (commit
95dcd6e, merged 2026-04-22) ontocoder_2_33. No conflicts; the Anthropic adapter on this branch is identical to upstream at the patch sites, sogit applyis clean.Problem
fantasy.FilePartparts withMediaType: "application/pdf"were silently dropped from the Anthropic content list. Thecase fantasy.ContentTypeFile:switch inproviders/anthropic/anthropic.go(around line 925) only handledimage/*andtext/*, with a// TODO: handle other file typescomment. A user message whose only content was a PDF produced zero Anthropic messages and aCallWarningTypeOther"dropping empty user message"warning. The model never saw the document.In
coder/coder, this is reachable from any Coder Agents chat that routes through Anthropic or Bedrock (Bedrock is a thin wrapper around the Anthropic adapter). The PDF gets uploaded, allowlisted, stored inchat_files, resolved bychatprompt.go, and emitted as afantasy.FilePart{MediaType: "application/pdf", Data: bytes}— then dropped here. Users see Claude reply that it cannot find their PDF and ask for a link or URL instead. Other providers (openai,openrouter,openaicompat,vercel,google,azure) already had working PDF branches.Fix
Add an
application/pdfcase that emitsanthropic.NewDocumentBlock(anthropic.Base64PDFSourceParam{Data: base64Encoded}), parallel to the existing image branch and honouringcacheControl. WirecacheControlinto the existingtext/*document branch too (it was missing). UpdatehasVisibleUserContentsoOfDocumentcounts as user-visible content; without this a PDF-only user message would still be culled as empty.The upstream-forked
anthropic-sdk-goalready exposesBase64PDFSourceParamandNewDocumentBlock, so no SDK change is needed.Tests
Two new subtests under
TestToPrompt_DropsEmptyMessages:should keep user messages with PDF content— sends a PDF-only user message and asserts one message is produced with no warnings.should keep user messages with text document content— same shape fortext/markdown.The existing
should drop user messages without visible contentsubtest is repointed toapplication/zip(still genuinely unsupported) so it keeps pinning the "no visible content" warning path without locking in the PDF drop.Two pre-existing test failures on this branch (
TestPrepareParams_PreviousResponseID_Validation/allows_tool_messagesinproviders/openai, and a Go 1.26 build failure inprovidertests/openai_computer_use_test.go) are unrelated and unchanged by this commit.Why cherry-pick onto
coder_2_33instead of upstream synccoder_2_33is whatcoder/codercurrently pins via itsgo.modreplace directive (github.com/coder/fantasy v0.0.0-20260514123132-cfca5fd82c5d). A full upstream sync would pull in 74 unrelated commits; this is the smallest viable change to unblock PDF attachments for Anthropic / Bedrock deployments.Relates to CODAGT-540