Skip to content

feat(ai,ai-gemini): add Google Veo video adapter on the typed-duration contract#746

Merged
tombeckenham merged 1 commit into
618-image-to-image-and-image-to-video-supportfrom
634-featgemini-add-google-veo-video-adapter-on-the-typed-duration-contract
Jun 11, 2026
Merged

feat(ai,ai-gemini): add Google Veo video adapter on the typed-duration contract#746
tombeckenham merged 1 commit into
618-image-to-image-and-image-to-video-supportfrom
634-featgemini-add-google-veo-video-adapter-on-the-typed-duration-contract

Conversation

@tombeckenham

Copy link
Copy Markdown
Contributor

🎯 Changes

Closes #634. Draft, stacked on #624 (618-image-to-image-and-image-to-video-support) — adopts its multimodal MediaPrompt format and should land after it.

Supersedes #741, which was accidentally merged into the 618 branch and has been backed out (branch reset 1b525339acd73197); this PR re-stacks the identical commit as its own reviewable unit. Originally stacked on #641 (534-video-duration-support); restacked because #624 is mergeable on current main while the #622#641 stack still needs a layout rebase, and Veo wants the multimodal prompt (image-to-video is its headline capability). To keep #634's premise — Veo never ships with an untyped duration?: number — this PR carries a minimal additive port of the #534 typed-duration contract. When #641 rebases onto main it shrinks to FAL/OpenAI adoption of this contract (plus any strictness changes).

@tanstack/ai — additive typed-duration contract (minor, non-breaking)

  • VideoAdapter / BaseVideoAdapter gain a TModelDurationByName generic. The default (Record<string, number>) preserves today's duration?: number typing for adapters without a map (Sora, fal unchanged).
  • availableDurations()DurationOptions tagged union (discrete | range | mixed | none); default { kind: 'none' }.
  • snapDuration(seconds) → closest valid duration; default undefined. snapToDurationOption exported from @tanstack/ai/adapters for adapter authors.
  • generateVideo({ duration }) typed per model via VideoDurationForAdapter<TAdapter>.

@tanstack/ai-gemini — Veo adapter (minor)

  • GeminiVideoAdapter over @google/genai models.generateVideos (:predictLongRunning) / operations.getVideosOperation; getVideoStatus maps done/error and surfaces all-samples-RAI-filtered as failed with reasons; getVideoUrl returns response.generatedVideos[0].video.uri.
  • MediaPrompt image routing: first un-roled / 'start_frame' image → input image, 'end_frame'lastFrame, 'reference'/'character'referenceImages (ASSET). Image parts convert from data sources, base64 data: URIs, gs:// URIs, or fetched HTTP URLs. Multiple starting images / video / audio parts throw; 'mask'/'control' roles throw.
  • Typed durations: geminiVideo('veo-3.0-generate-001')duration?: 4 | 6 | 8; Veo 2 → 5 | 6 | 8; snapDuration(7)6. size is the aspect ratio ('16:9' | '9:16'); resolution/generateAudio/negativePrompt etc. via modelOptions (vendor GenerateVideosConfig minus adapter-managed fields).
  • Veo model-meta entries uncommented + finalized (GEMINI_VIDEO_MODELS union); the stale GeminiGenerationConfigOptions reference replaced with the intersection the Imagen entries use.
  • 25 unit tests (client stub injected via the protected client seam) including expectTypeOf compile-time duration assertions and MediaPrompt routing coverage.

E2E, docs, skill

  • 'gemini' added to video-gen; global-setup.ts mounts Veo's :predictLongRunning + operations-poll endpoints (aimock 1.29 doesn't model the long-running pair), responding with the raw MLDev wire shape the SDK normalizes. All three transports pass; openai video-gen + image-to-video suites still green. Gemini stays out of the image-to-video e2e set — that spec's journal assertion is tied to aimock's /v1/videos pipeline, which custom mounts bypass; Veo's image routing is unit-tested (noted in feature-support.ts).
  • docs/media/video-generation.md: Veo section (typed durations table, snapDuration example, download-auth note); role-hint and provider-support tables updated from "Veo planned" to actual mappings.
  • media-generation SKILL.md updated alongside.

Duration values vs the issue

The issue's table said Veo 3.x = 4 | 8, Veo 2 = 5–8, and asked to confirm before locking. Current official Veo docs say Veo 3.x: 4 | 6 | 8, Veo 2: 5 | 6 | 8 — those shipped, so snapDuration(7) returns 6 (not 8 as the issue's acceptance line assumed). Live API confirmation was attempted via free invalid-duration probes but the key's prepaid credits are depleted (429 before validation); docs are the source of truth. (Also note durationSeconds is a number in the Gemini API, unlike Sora's string seconds, and the issue's packages/typescript/… paths predate the repo restructure.)

✅ Checklist

  • I have followed the steps in the Contributing guide.
  • I have tested this code locally with pnpm run test:pr.

🚀 Release Impact

  • This change affects published code, and I have generated a changeset.
  • This change is docs/CI/dev-only (no release).

🤖 Generated with Claude Code

…n contract (#634)

Restacked on 618-image-to-image-and-image-to-video-support to adopt the
multimodal MediaPrompt format, carrying a minimal additive port of the
#534 typed-duration contract:

- @tanstack/ai (non-breaking): VideoAdapter/BaseVideoAdapter gain a
  TModelDurationByName generic (default Record<string, number> preserves
  existing duration?: number typing), DurationOptions, snapToDurationOption,
  and default availableDurations()/snapDuration() implementations.
  generateVideo's duration is typed via VideoDurationForAdapter.
- @tanstack/ai-gemini: GeminiVideoAdapter over generateVideos /
  getVideosOperation with per-model typed durations (Veo 3.x 4|6|8,
  Veo 2 5|6|8 per current Veo docs), MediaPrompt image routing
  (start_frame → image, end_frame → lastFrame, reference/character →
  referenceImages), RAI filter surfacing, geminiVideo/createGeminiVideo
  factories, and finalized Veo model-meta entries.
- E2E: gemini added to video-gen with a custom aimock mount for
  :predictLongRunning + operations polling; all transports pass.
- Docs + media-generation skill updated for Veo (typed durations,
  image-to-video role table).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 11, 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: 63d98908-df01-4c35-bb3d-450c1b492a62

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 634-featgemini-add-google-veo-video-adapter-on-the-typed-duration-contract

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 and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

🚀 Changeset Version Preview

8 package(s) bumped directly, 23 bumped as dependents.

🟥 Major bumps

Package Version Reason
@tanstack/ai-event-client 0.5.4 → 1.0.0 Changeset
@tanstack/ai-fal 0.7.23 → 1.0.0 Changeset
@tanstack/ai-gemini 0.15.1 → 1.0.0 Changeset
@tanstack/ai-grok 0.11.2 → 1.0.0 Changeset
@tanstack/ai-openai 0.14.1 → 1.0.0 Changeset
@tanstack/ai-openrouter 0.13.1 → 1.0.0 Changeset
@tanstack/ai-anthropic 0.15.1 → 1.0.0 Dependent
@tanstack/ai-code-mode 0.2.5 → 1.0.0 Dependent
@tanstack/ai-code-mode-skills 0.2.5 → 1.0.0 Dependent
@tanstack/ai-elevenlabs 0.2.20 → 1.0.0 Dependent
@tanstack/ai-groq 0.4.2 → 1.0.0 Dependent
@tanstack/ai-isolate-node 0.1.30 → 1.0.0 Dependent
@tanstack/ai-isolate-quickjs 0.1.30 → 1.0.0 Dependent
@tanstack/ai-ollama 0.8.1 → 1.0.0 Dependent
@tanstack/ai-preact 0.9.4 → 1.0.0 Dependent
@tanstack/ai-react 0.15.4 → 1.0.0 Dependent
@tanstack/ai-react-ui 0.8.6 → 1.0.0 Dependent
@tanstack/ai-solid 0.13.4 → 1.0.0 Dependent
@tanstack/ai-solid-ui 0.7.6 → 1.0.0 Dependent
@tanstack/ai-svelte 0.13.4 → 1.0.0 Dependent
@tanstack/ai-vue 0.13.4 → 1.0.0 Dependent
@tanstack/openai-base 0.8.1 → 1.0.0 Dependent

🟨 Minor bumps

Package Version Reason
@tanstack/ai 0.28.0 → 0.29.0 Changeset
@tanstack/ai-client 0.16.3 → 0.17.0 Changeset

🟩 Patch bumps

Package Version Reason
@tanstack/ai-devtools-core 0.4.8 → 0.4.9 Dependent
@tanstack/ai-isolate-cloudflare 0.2.21 → 0.2.22 Dependent
@tanstack/ai-mcp 0.1.0 → 0.1.1 Dependent
@tanstack/ai-vue-ui 0.2.16 → 0.2.17 Dependent
@tanstack/preact-ai-devtools 0.1.51 → 0.1.52 Dependent
@tanstack/react-ai-devtools 0.2.51 → 0.2.52 Dependent
@tanstack/solid-ai-devtools 0.2.51 → 0.2.52 Dependent

@nx-cloud

nx-cloud Bot commented Jun 11, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 1b52533

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

☁️ Nx Cloud last updated this comment at 2026-06-11 02:28:45 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jun 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

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

@tanstack/ai-anthropic

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

@tanstack/ai-client

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

@tanstack/ai-code-mode

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

@tanstack/ai-code-mode-skills

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

@tanstack/ai-devtools-core

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

@tanstack/ai-elevenlabs

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

@tanstack/ai-event-client

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

@tanstack/ai-fal

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

@tanstack/ai-gemini

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

@tanstack/ai-grok

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

@tanstack/ai-groq

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

@tanstack/ai-isolate-cloudflare

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

@tanstack/ai-isolate-node

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

@tanstack/ai-isolate-quickjs

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

@tanstack/ai-mcp

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

@tanstack/ai-ollama

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

@tanstack/ai-openai

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

@tanstack/ai-openrouter

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

@tanstack/ai-preact

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

@tanstack/ai-react

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

@tanstack/ai-react-ui

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

@tanstack/ai-solid

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

@tanstack/ai-solid-ui

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

@tanstack/ai-svelte

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

@tanstack/ai-utils

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

@tanstack/ai-vue

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

@tanstack/ai-vue-ui

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

@tanstack/openai-base

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

@tanstack/preact-ai-devtools

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

@tanstack/react-ai-devtools

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

@tanstack/solid-ai-devtools

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

commit: 1b52533

@tombeckenham tombeckenham merged commit 1b52533 into 618-image-to-image-and-image-to-video-support Jun 11, 2026
15 of 16 checks passed
@tombeckenham tombeckenham deleted the 634-featgemini-add-google-veo-video-adapter-on-the-typed-duration-contract branch June 11, 2026 02:34
@tombeckenham tombeckenham restored the 634-featgemini-add-google-veo-video-adapter-on-the-typed-duration-contract branch June 11, 2026 02:37
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.

1 participant