Skip to content

feat(ai): native Files API support across providers (upload adapters + file content source)#915

Draft
tombeckenham wants to merge 3 commits into
mainfrom
909-featai-native-files-api-support-across-providers-upload-adapters-+-file-content-source
Draft

feat(ai): native Files API support across providers (upload adapters + file content source)#915
tombeckenham wants to merge 3 commits into
mainfrom
909-featai-native-files-api-support-across-providers-upload-adapters-+-file-content-source

Conversation

@tombeckenham

@tombeckenham tombeckenham commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Closes #909.

Adds first-class support for provider Files / storage APIs so callers can upload media once and reference it by a provider-issued handle instead of re-sending base64 (or relying on the provider to re-fetch a public URL) each request — lower latency/bandwidth, no re-buffering of base64 on memory-constrained runtimes (the #907 OOM class), and access to provider-side file lifecycle.

What's included

1. Tree-shakeable files adapter kind (packages/ai/src/activities/files/)

  • openaiFiles(), anthropicFiles(), geminiFiles(), falFiles() — each with upload(), plus get() / delete() where the provider has a lifecycle API. fal storage is upload-only (its get/delete throw a clear error).
  • New uploadFile() / getFile() / deleteFile() activity dispatchers + FileHandle / FileUploadInput types.

2. New { type: 'file' } arm on ContentPartSource

  • Reference an uploaded handle in a chat message. fileSourceFromHandle(handle) builds the source (uses the handle URL for Gemini/fal, the opaque id for OpenAI/Anthropic).
  • Adapters map it to the native wire field: OpenAI Responses input_image/input_file file_id, Anthropic file_id source (sends the files-api-2025-04-14 beta), Gemini fileData.fileUri, fal storage URL.

3. Runtime provider routing (chosen over compile-time — see below)

  • A handle only routes to its issuing provider; a cross-provider handle throws.
  • Endpoints/providers that can't consume a handle — OpenAI image edits & Sora, Gemini Veo, OpenAI Chat Completions images, Bedrock, Mistral, Grok, OpenRouter, Ollama — throw a clear "unsupported file source" error instead of silently mis-mapping. (Every source.type discrimination site was swept; a new arm would otherwise fall through to the URL/data branch.)

4. Docs + a worked example

  • New docs/advanced/files-api.md guide + a "File Handle" section in the multimodal-content page.
  • examples/ts-react-media now uploads reference images (Gemini) and image-to-video start frames (fal) once via the Files API and references them by handle, instead of re-sending base64 each request.

Notes / decisions

  • Runtime, not compile-time, provider enforcement. True inline-literal compile-time enforcement isn't reachable today: chat()'s messages union includes a deliberately-permissive ModelMessage arm (for AG-UI wire-forwarding) that structurally subsumes any well-formed content-parts array, so even the existing modality constraint doesn't hard-error at a call site. Runtime routing matches how modality is already validated. Narrowing that union is a larger, separate change.
  • Anthropic already posts to client.beta.messages.create, so consuming file_id sources meant switching that adapter's message-content block types to the Beta param variants (a superset) and adding the Files beta when a file source is present — not a new client.
  • Gemini upload + Nitro. @google/genai's resumable upload sets an explicit Content-Length on a Blob-body request, which older Nitro runtimes reject with "invalid content-length header" (surfaced as "fetch failed"). Verified fixed on current Nitro; the example bumps nitro accordingly and docs/advanced/files-api.md documents the requirement. Native Node and the production node-server build are unaffected.
  • Testing is unit-first (per the issue — aimock likely can't mock upload endpoints): core helpers/guard/dispatch, plus per-provider mapping + wrong-provider-throw tests for the issuers.
  • Deferred (issue's optional follow-ups): the auto-upload-above-threshold helper, and per-model supports.files capability typing.

Testing

Green locally: test:types (all touched packages and the examples/** + testing/** call sites), test:lib, test:eslint, build, test:build, test:knip, test:sherif, test:docs. Rebased onto latest main (which includes #919 / #920, fixing an unrelated pre-existing GeminiClientConfig / .d.ts resolution issue that had been failing the e2e type-check).

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d4da802f-0ad1-4fb7-bda5-fbeeba025bcb

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 909-featai-native-files-api-support-across-providers-upload-adapters-+-file-content-source

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions

github-actions Bot commented Jul 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

21 package(s) bumped directly, 25 bumped as dependents.

🟥 Major bumps

Package Version Reason
@tanstack/ai-angular 0.2.3 → 1.0.0 Changeset
@tanstack/ai-anthropic 0.16.1 → 1.0.0 Changeset
@tanstack/ai-bedrock 0.1.2 → 1.0.0 Changeset
@tanstack/ai-fal 0.9.10 → 1.0.0 Changeset
@tanstack/ai-gemini 0.19.1 → 1.0.0 Changeset
@tanstack/ai-grok 0.14.7 → 1.0.0 Changeset
@tanstack/ai-groq 0.5.1 → 1.0.0 Changeset
@tanstack/ai-mistral 0.2.1 → 1.0.0 Changeset
@tanstack/ai-ollama 0.8.14 → 1.0.0 Changeset
@tanstack/ai-openai 0.16.0 → 1.0.0 Changeset
@tanstack/ai-openrouter 0.15.8 → 1.0.0 Changeset
@tanstack/ai-preact 0.10.3 → 1.0.0 Changeset
@tanstack/ai-react 0.16.4 → 1.0.0 Changeset
@tanstack/ai-sandbox 0.2.2 → 1.0.0 Changeset
@tanstack/ai-solid 0.14.3 → 1.0.0 Changeset
@tanstack/ai-svelte 0.14.3 → 1.0.0 Changeset
@tanstack/ai-vue 0.14.3 → 1.0.0 Changeset
@tanstack/openai-base 0.9.7 → 1.0.0 Changeset
@tanstack/ai-acp 0.2.1 → 1.0.0 Dependent
@tanstack/ai-claude-code 0.2.1 → 1.0.0 Dependent
@tanstack/ai-code-mode 0.3.6 → 1.0.0 Dependent
@tanstack/ai-code-mode-skills 0.3.9 → 1.0.0 Dependent
@tanstack/ai-codex 0.2.1 → 1.0.0 Dependent
@tanstack/ai-elevenlabs 0.2.32 → 1.0.0 Dependent
@tanstack/ai-grok-build 0.2.1 → 1.0.0 Dependent
@tanstack/ai-isolate-node 0.1.45 → 1.0.0 Dependent
@tanstack/ai-isolate-quickjs 0.1.45 → 1.0.0 Dependent
@tanstack/ai-opencode 0.2.1 → 1.0.0 Dependent
@tanstack/ai-react-ui 0.8.13 → 1.0.0 Dependent
@tanstack/ai-sandbox-cloudflare 0.2.2 → 1.0.0 Dependent
@tanstack/ai-sandbox-daytona 0.2.0 → 1.0.0 Dependent
@tanstack/ai-sandbox-docker 0.2.0 → 1.0.0 Dependent
@tanstack/ai-sandbox-local-process 0.2.0 → 1.0.0 Dependent
@tanstack/ai-sandbox-sprites 0.2.1 → 1.0.0 Dependent
@tanstack/ai-sandbox-vercel 0.2.0 → 1.0.0 Dependent
@tanstack/ai-solid-ui 0.7.12 → 1.0.0 Dependent

🟨 Minor bumps

Package Version Reason
@tanstack/ai 0.40.0 → 0.41.0 Changeset
@tanstack/ai-client 0.20.0 → 0.21.0 Changeset
@tanstack/ai-event-client 0.6.8 → 0.7.0 Changeset

🟩 Patch bumps

Package Version Reason
@tanstack/ai-devtools-core 0.4.22 → 0.4.23 Dependent
@tanstack/ai-isolate-cloudflare 0.2.36 → 0.2.37 Dependent
@tanstack/ai-mcp 0.2.3 → 0.2.4 Dependent
@tanstack/ai-vue-ui 0.2.31 → 0.2.32 Dependent
@tanstack/preact-ai-devtools 0.1.65 → 0.1.66 Dependent
@tanstack/react-ai-devtools 0.2.65 → 0.2.66 Dependent
@tanstack/solid-ai-devtools 0.2.65 → 0.2.66 Dependent

@nx-cloud

nx-cloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 160e1d0

Command Status Duration Result
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 2m View ↗

☁️ Nx Cloud last updated this comment at 2026-07-10 11:13:24 UTC

@nx-cloud

nx-cloud Bot commented Jul 8, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 83e6d90

Command Status Duration Result
nx run-many --targets=build --exclude=examples/... ✅ Succeeded 1m 59s View ↗

☁️ Nx Cloud last updated this comment at 2026-07-08 05:53:52 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jul 8, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

npm i https://pkg.pr.new/@tanstack/ai@915

@tanstack/ai-acp

npm i https://pkg.pr.new/@tanstack/ai-acp@915

@tanstack/ai-angular

npm i https://pkg.pr.new/@tanstack/ai-angular@915

@tanstack/ai-anthropic

npm i https://pkg.pr.new/@tanstack/ai-anthropic@915

@tanstack/ai-bedrock

npm i https://pkg.pr.new/@tanstack/ai-bedrock@915

@tanstack/ai-claude-code

npm i https://pkg.pr.new/@tanstack/ai-claude-code@915

@tanstack/ai-client

npm i https://pkg.pr.new/@tanstack/ai-client@915

@tanstack/ai-code-mode

npm i https://pkg.pr.new/@tanstack/ai-code-mode@915

@tanstack/ai-code-mode-skills

npm i https://pkg.pr.new/@tanstack/ai-code-mode-skills@915

@tanstack/ai-codex

npm i https://pkg.pr.new/@tanstack/ai-codex@915

@tanstack/ai-devtools-core

npm i https://pkg.pr.new/@tanstack/ai-devtools-core@915

@tanstack/ai-elevenlabs

npm i https://pkg.pr.new/@tanstack/ai-elevenlabs@915

@tanstack/ai-event-client

npm i https://pkg.pr.new/@tanstack/ai-event-client@915

@tanstack/ai-fal

npm i https://pkg.pr.new/@tanstack/ai-fal@915

@tanstack/ai-gemini

npm i https://pkg.pr.new/@tanstack/ai-gemini@915

@tanstack/ai-grok

npm i https://pkg.pr.new/@tanstack/ai-grok@915

@tanstack/ai-grok-build

npm i https://pkg.pr.new/@tanstack/ai-grok-build@915

@tanstack/ai-groq

npm i https://pkg.pr.new/@tanstack/ai-groq@915

@tanstack/ai-isolate-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-isolate-cloudflare@915

@tanstack/ai-isolate-node

npm i https://pkg.pr.new/@tanstack/ai-isolate-node@915

@tanstack/ai-isolate-quickjs

npm i https://pkg.pr.new/@tanstack/ai-isolate-quickjs@915

@tanstack/ai-mcp

npm i https://pkg.pr.new/@tanstack/ai-mcp@915

@tanstack/ai-mistral

npm i https://pkg.pr.new/@tanstack/ai-mistral@915

@tanstack/ai-ollama

npm i https://pkg.pr.new/@tanstack/ai-ollama@915

@tanstack/ai-openai

npm i https://pkg.pr.new/@tanstack/ai-openai@915

@tanstack/ai-opencode

npm i https://pkg.pr.new/@tanstack/ai-opencode@915

@tanstack/ai-openrouter

npm i https://pkg.pr.new/@tanstack/ai-openrouter@915

@tanstack/ai-preact

npm i https://pkg.pr.new/@tanstack/ai-preact@915

@tanstack/ai-react

npm i https://pkg.pr.new/@tanstack/ai-react@915

@tanstack/ai-react-ui

npm i https://pkg.pr.new/@tanstack/ai-react-ui@915

@tanstack/ai-sandbox

npm i https://pkg.pr.new/@tanstack/ai-sandbox@915

@tanstack/ai-sandbox-cloudflare

npm i https://pkg.pr.new/@tanstack/ai-sandbox-cloudflare@915

@tanstack/ai-sandbox-daytona

npm i https://pkg.pr.new/@tanstack/ai-sandbox-daytona@915

@tanstack/ai-sandbox-docker

npm i https://pkg.pr.new/@tanstack/ai-sandbox-docker@915

@tanstack/ai-sandbox-local-process

npm i https://pkg.pr.new/@tanstack/ai-sandbox-local-process@915

@tanstack/ai-sandbox-sprites

npm i https://pkg.pr.new/@tanstack/ai-sandbox-sprites@915

@tanstack/ai-sandbox-vercel

npm i https://pkg.pr.new/@tanstack/ai-sandbox-vercel@915

@tanstack/ai-solid

npm i https://pkg.pr.new/@tanstack/ai-solid@915

@tanstack/ai-solid-ui

npm i https://pkg.pr.new/@tanstack/ai-solid-ui@915

@tanstack/ai-svelte

npm i https://pkg.pr.new/@tanstack/ai-svelte@915

@tanstack/ai-utils

npm i https://pkg.pr.new/@tanstack/ai-utils@915

@tanstack/ai-vue

npm i https://pkg.pr.new/@tanstack/ai-vue@915

@tanstack/ai-vue-ui

npm i https://pkg.pr.new/@tanstack/ai-vue-ui@915

@tanstack/openai-base

npm i https://pkg.pr.new/@tanstack/openai-base@915

@tanstack/preact-ai-devtools

npm i https://pkg.pr.new/@tanstack/preact-ai-devtools@915

@tanstack/react-ai-devtools

npm i https://pkg.pr.new/@tanstack/react-ai-devtools@915

@tanstack/solid-ai-devtools

npm i https://pkg.pr.new/@tanstack/solid-ai-devtools@915

commit: 160e1d0

tombeckenham and others added 3 commits July 10, 2026 21:04
…+ `file` content source)

Add first-class support for provider Files / storage APIs so callers can
upload media once and reference it by a provider-issued handle instead of
re-sending base64 or a public URL each request.

- New tree-shakeable `files` adapter kind: openaiFiles(), anthropicFiles(),
  geminiFiles(), falFiles() — each with upload(), plus get()/delete() where
  the provider has a lifecycle API (fal is upload-only). Driven by the new
  uploadFile()/getFile()/deleteFile() activity functions.
- New `{ type: 'file' }` arm on ContentPartSource. Adapters map it to the
  provider's native reference: OpenAI (Responses) input_image/input_file
  file_id, Anthropic file_id source (sends the files-api-2025-04-14 beta),
  Gemini fileData.fileUri, fal storage URL. fileSourceFromHandle() builds
  the source from an uploaded FileHandle.
- Runtime provider routing: a handle only routes to its issuing provider;
  cross-provider handles and endpoints that require raw bytes (image edits,
  Veo, Chat Completions images, Bedrock, Mistral, Grok, OpenRouter, Ollama)
  throw a clear error instead of silently mis-mapping.

Closes #909

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
… + Nitro note

Upload reference images (Gemini) and image-to-video start frames (fal) once via
the Files API (`geminiFiles()` / `falFiles()`) and reference them by handle,
instead of re-sending the base64 payload inline on every generation request.

Bump the example's `nitro` to `latest` (3.0.260610-beta) — older Nitro rejected
`@google/genai`'s resumable upload (explicit `Content-Length` on a Blob body)
with "invalid content-length header", surfaced as "fetch failed". Document that
runtime requirement in the Files API guide.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tombeckenham tombeckenham force-pushed the 909-featai-native-files-api-support-across-providers-upload-adapters-+-file-content-source branch from d440425 to 160e1d0 Compare July 10, 2026 11:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(ai): native Files API support across providers (upload adapters + file content source)

1 participant