feat(ai-mistral): support document (PDF) input via document_url#912
feat(ai-mistral): support document (PDF) input via document_url#912jan-kubica wants to merge 1 commit into
Conversation
The Mistral text adapter already snake-cased a `document_url` part in messageToWire, but convertContentPartToMistral never produced one and threw for any `document` content part, and model-meta declared no `document` input modality. Add the document branch (mirroring the image path: hosted URLs pass through, inline bytes become a data: URL) and declare `document` input for the vision-capable models, matching how the other provider adapters expose PDF input. Verified against Mistral's API: /v1/models reports vision=true for these models, and document_url round-trips a PDF on mistral-small-latest and mistral-medium-latest (both hosted-URL and inline base64).
📝 WalkthroughWalkthroughAdds document (PDF) input support to the Mistral adapter: content parts of type ChangesDocument input support
Estimated code review effort: 2 (Simple) | ~10 minutes Related PRs: None identified. Suggested labels: ai-mistral, enhancement Suggested reviewers: None identified. 🐰 A PDF slips in through the door, 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
packages/ai-mistral/src/adapters/text.ts (1)
1031-1033: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueRedundant type assertion flagged by ESLint.
partis already typed asContentPartin the function signature, so(part as ContentPart).typedoesn't change anything and just adds noise.part.typeworks directly.🧹 Proposed fix
- throw new Error( - `Mistral text adapter does not support content part of type '${(part as ContentPart).type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest or mistral-small-latest) for images and documents.`, - ) + throw new Error( + `Mistral text adapter does not support content part of type '${part.type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest or mistral-small-latest) for images and documents.`, + )🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@packages/ai-mistral/src/adapters/text.ts` around lines 1031 - 1033, Remove the unnecessary type assertion in the Mistral text adapter error path by using the existing ContentPart-typed variable directly in the thrown error message. In the text adapter logic that builds the unsupported-part error, update the reference from the casted form to the plain part.type access so ESLint no longer flags redundant assertions.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@packages/ai-mistral/src/adapters/text.ts`:
- Line 1032: The unsupported content error in the Mistral text adapter is too
narrow and points users only to mistral-medium-latest and mistral-small-latest.
Update the message in the text adapter logic to reflect all vision-capable
models that support images/documents, including pixtral-large-latest and
pixtral-12b-2409 as defined in model-meta.ts. Keep the wording aligned with the
actual model capability list so the error guidance matches the supported models.
---
Nitpick comments:
In `@packages/ai-mistral/src/adapters/text.ts`:
- Around line 1031-1033: Remove the unnecessary type assertion in the Mistral
text adapter error path by using the existing ContentPart-typed variable
directly in the thrown error message. In the text adapter logic that builds the
unsupported-part error, update the reference from the casted form to the plain
part.type access so ESLint no longer flags redundant assertions.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 27f03394-7c56-455d-97fb-edaf29ac9337
📒 Files selected for processing (4)
.changeset/mistral-document-input.mdpackages/ai-mistral/src/adapters/text.tspackages/ai-mistral/src/model-meta.tspackages/ai-mistral/tests/document-input.test.ts
|
|
||
| throw new Error( | ||
| `Mistral text adapter does not support content part of type '${(part as ContentPart).type}'. Supported types: text, image. Use a vision-capable model (pixtral-large-latest, pixtral-12b-2409, mistral-medium-latest, or mistral-small-latest) for images.`, | ||
| `Mistral text adapter does not support content part of type '${(part as ContentPart).type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest or mistral-small-latest) for images and documents.`, |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Error message understates which models actually support images/documents.
The message only names mistral-medium-latest and mistral-small-latest, but model-meta.ts shows pixtral-large-latest and pixtral-12b-2409 also declare vision in their features and now include document in supports.input. Users on Pixtral models hitting this error would be pointed to the wrong models.
📝 Proposed fix
- `Mistral text adapter does not support content part of type '${(part as ContentPart).type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest or mistral-small-latest) for images and documents.`,
+ `Mistral text adapter does not support content part of type '${part.type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest, mistral-small-latest, pixtral-large-latest, or pixtral-12b-2409) for images and documents.`,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| `Mistral text adapter does not support content part of type '${(part as ContentPart).type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest or mistral-small-latest) for images and documents.`, | |
| `Mistral text adapter does not support content part of type '${part.type}'. Supported types: text, image, document. Use a vision-capable model (mistral-medium-latest, mistral-small-latest, pixtral-large-latest, or pixtral-12b-2409) for images and documents.`, |
🧰 Tools
🪛 ESLint
[error] 1032-1032: This assertion is unnecessary since it does not change the type of the expression.
(@typescript-eslint/no-unnecessary-type-assertion)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@packages/ai-mistral/src/adapters/text.ts` at line 1032, The unsupported
content error in the Mistral text adapter is too narrow and points users only to
mistral-medium-latest and mistral-small-latest. Update the message in the text
adapter logic to reflect all vision-capable models that support
images/documents, including pixtral-large-latest and pixtral-12b-2409 as defined
in model-meta.ts. Keep the wording aligned with the actual model capability list
so the error guidance matches the supported models.
|
View your CI Pipeline Execution ↗ for commit e45dd3c
☁️ Nx Cloud last updated this comment at |
@tanstack/ai
@tanstack/ai-acp
@tanstack/ai-angular
@tanstack/ai-anthropic
@tanstack/ai-bedrock
@tanstack/ai-claude-code
@tanstack/ai-client
@tanstack/ai-code-mode
@tanstack/ai-code-mode-skills
@tanstack/ai-codex
@tanstack/ai-devtools-core
@tanstack/ai-elevenlabs
@tanstack/ai-event-client
@tanstack/ai-fal
@tanstack/ai-gemini
@tanstack/ai-grok
@tanstack/ai-grok-build
@tanstack/ai-groq
@tanstack/ai-isolate-cloudflare
@tanstack/ai-isolate-node
@tanstack/ai-isolate-quickjs
@tanstack/ai-mcp
@tanstack/ai-mistral
@tanstack/ai-ollama
@tanstack/ai-openai
@tanstack/ai-opencode
@tanstack/ai-openrouter
@tanstack/ai-preact
@tanstack/ai-react
@tanstack/ai-react-ui
@tanstack/ai-sandbox
@tanstack/ai-sandbox-cloudflare
@tanstack/ai-sandbox-daytona
@tanstack/ai-sandbox-docker
@tanstack/ai-sandbox-local-process
@tanstack/ai-sandbox-sprites
@tanstack/ai-sandbox-vercel
@tanstack/ai-solid
@tanstack/ai-solid-ui
@tanstack/ai-svelte
@tanstack/ai-utils
@tanstack/ai-vue
@tanstack/ai-vue-ui
@tanstack/openai-base
@tanstack/preact-ai-devtools
@tanstack/react-ai-devtools
@tanstack/solid-ai-devtools
commit: |
Summary
The Mistral text adapter is half-wired for document (PDF) input:
messageToWirealready snake-cases adocument_urlpart, butconvertContentPartToMistralnever produces one — it throws"Supported types: text, image"for anydocumentcontent part — andmodel-metadeclares nodocumentinput modality. As a result,documentcontent parts can't be sent to Mistral even though the API supports them and the other provider adapters (Anthropic, Gemini, Bedrock, OpenAI) already expose PDF input.This PR closes that gap.
Changes
adapters/text.ts: add adocumentbranch toconvertContentPartToMistral, mirroring the existingimagebranch — hosted URLs pass through, inlinedatabytes are wrapped in adata:<mime>;base64,…URL — returning{ type: 'document_url', documentUrl }(whichmessageToWirealready maps to the wiredocument_url). Updated the fallback error message accordingly.model-meta.ts: add'document'to thesupports.inputmodality union and to the vision-capable models that already declareimage.tests/document-input.test.ts: unit tests for the new mapping (hosted URL, inline base64, already-formatteddata:URL).Verification
Checked against Mistral's own API (not just docs):
GET /v1/modelsreportsvision: truefor the affected models.document_urlround-trips a PDF end-to-end onmistral-small-latestandmistral-medium-latest, for both a hosted URL and an inline base64data:URL — the model returns the document's text.nx build ai-mistral(typecheck + dts) passes; new unit tests pass;eslintclean on the changed files.Notes
documentis added to the four models that already declareimage, since Mistral routes both through the same vision pipeline;mistral-small-latestandmistral-medium-latestwere verified live. Happy to narrow or expand the set (e.g. Mistral's API now also reportsvision: trueformistral-large-latest,magistral-*, andministral-*) if maintainers prefer.documentinput path; no changes to the OCR endpoint or other modalities.Summary by CodeRabbit
New Features
Bug Fixes