Skip to content

feat(ai-grok): video generation adapter for the grok-imagine video models#742

Open
tombeckenham wants to merge 1 commit into
mainfrom
705-featai-grok-video-generation-adapter-for-the-grok-imagine-video-models
Open

feat(ai-grok): video generation adapter for the grok-imagine video models#742
tombeckenham wants to merge 1 commit into
mainfrom
705-featai-grok-video-generation-adapter-for-the-grok-imagine-video-models

Conversation

@tombeckenham

@tombeckenham tombeckenham commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

🎯 Changes

Adds a grokVideo adapter to @tanstack/ai-grok for xAI's Imagine video models, closing #705:

  • Models: grok-imagine-video ($0.05/s) and grok-imagine-video-1.5-preview ($0.08/s), added to model-meta.ts with GROK_VIDEO_MODELS / GrokVideoModel exports.
  • Adapter: GrokVideoAdapter (+ grokVideo / createGrokVideo factories) extends BaseVideoAdapter with the jobs/polling pattern — createVideoJob posts to /v1/videos/generations, getVideoStatus / getVideoUrl read /v1/videos/{request_id}. The Imagine video endpoints are plain JSON and not part of the OpenAI SDK surface, so the adapter issues direct requests with an injectable fetch seam (no global stubs needed in tests).
  • Sizing: aspect-ratio size template consistent with the grok-imagine image models — '16:9_720p'aspect_ratio / resolution. Video accepts 1:1 | 16:9 | 9:16 | 4:3 | 3:4 | 3:2 | 2:3 and 480p | 720p | 1080p (a narrower set than the image models — verified against the live API, which rejects phone ratios and auto).
  • Duration: integer seconds 1–15, validated client-side to match the API's enforcement.
  • Image-to-video: modelOptions.image: { url } passes a starting frame (public URL or base64 data URI).
  • Usage: completed jobs report usage.unitsBilled (billed seconds) and usage.cost (exact USD from the API's cost_in_usd_ticks; 10^10 ticks per dollar).
  • Docs/skill: docs/adapters/grok.md, docs/media/video-generation.md (+ config.json updatedAt), and the media-generation agent skill.

Note on #624

The issue assumed the Imagine plumbing from #624 had landed; that PR is still open, so this is built directly against main and is independently mergeable. The core imageInputs / metadata.role flow from #618/#624 isn't available on main yet — image-to-video is exposed through typed modelOptions.image for now, and wiring imageInputs into this adapter is a small follow-up once #624 merges.

Testing

  • Unit tests (packages/ai-grok/tests/video-adapter.test.ts, 27 tests) cover request shape, size-template mapping, validation, status mapping, usage, and error paths via the injected fetch seam. aimock doesn't mock the Imagine video endpoints, so coverage is unit-test based (same approach the issue calls out for image-to-image / image-to-video).
  • Live-verified end-to-end against the real xAI API through generateVideo() / getVideoJobStatus(): text-to-video (16:9_480p, 1s, unitsBilled: 1, cost: 0.05) and image-to-video via modelOptions.image (cost: 0.052 — the API bills slightly more with an image input, which is why cost is read from the API rather than computed).
  • API behaviors (status values, error shapes, parameter enums, 404 handling) were probed against the live endpoints before implementation.

✅ 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

Summary by CodeRabbit

  • New Features

    • Added Grok Imagine video generation with asynchronous job creation and polling capabilities.
    • Customize aspect ratios, resolutions, and video durations (up to 15 seconds).
    • Support for image-to-video generation using static frames as starting points.
    • Automatic usage and cost tracking for all generated videos.
  • Documentation

    • Updated guides covering Grok video generation setup and configuration.

…dels

Adds a grokVideo adapter to @tanstack/ai-grok for xAI's Imagine video
models (grok-imagine-video at $0.05/s, grok-imagine-video-1.5-preview at
$0.08/s) using the experimental generateVideo() jobs/polling
architecture: POST /v1/videos/generations to create, GET
/v1/videos/{request_id} to poll, hosted mp4 URL plus usage (billed
seconds + exact USD cost) on completion.

Sizing follows the grok-imagine aspect-ratio template ('16:9_720p' →
aspect_ratio/resolution); durations are 1-15 integer seconds;
image-to-video starting frames go through modelOptions.image. The
Imagine video endpoints are plain JSON (not in the OpenAI SDK), so the
adapter issues direct requests with an injectable fetch seam.

Closes #705.

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

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

This PR introduces a complete Grok Imagine video generation adapter for the TanStack AI library, adding video model definitions, an async create-and-poll adapter implementation, comprehensive type safety for provider-specific constraints, full test coverage, and documentation updates to the Grok adapter guide and general video generation resources.

Changes

Grok Imagine Video Adapter

Layer / File(s) Summary
Video model definitions and provider options
packages/ai-grok/src/model-meta.ts, packages/ai-grok/src/video/video-provider-options.ts
Introduces two Grok Imagine video models (grok-imagine-video, grok-imagine-video-1.5-preview) with video/audio modalities and per-second pricing. Defines literal union types for aspect ratios (16:9, 9:16), resolutions (720p, 1080p), duration bounds (1–15 seconds), and validation helpers for size templates and duration constraints. Exports provider-specific options interface with optional aspect ratio, resolution, duration, and image-to-video frame input.
Grok video adapter core
packages/ai-grok/src/adapters/video.ts
Implements GrokVideoAdapter extending BaseVideoAdapter to manage async video generation against xAI's Imagine API. Includes createVideoJob POST to /v1/videos/generations with size/duration/modelOptions validation and mapping, getVideoStatus polling with status mapping (pending/processing/completed/failed), getVideoUrl for terminal states with usage cost calculation from cost_in_usd_ticks, bearer auth setup, JSON headers, structured error-message extraction, and factory helpers createGrokVideo (explicit key) and grokVideo (env-based key resolution).
Public API exports
packages/ai-grok/src/index.ts
Re-exports adapter class, factory functions, and all configuration and provider option types to make the video generation capability available from the package root.
Comprehensive test coverage
packages/ai-grok/tests/video-adapter.test.ts
Full Vitest suite with 458 lines covering adapter instantiation and model support, createVideoJob request construction with payload mapping and pre-request validation, getVideoStatus state mapping and error handling (including 404 as failed state without throw), getVideoUrl completion and cost/usage calculation, and provider option validation helpers.
Documentation and release notes
.changeset/grok-imagine-video-adapter.md, docs/adapters/grok.md, docs/media/video-generation.md, docs/config.json, packages/ai/skills/ai-core/media-generation/SKILL.md
Adds changelog entry for minor release. Updates Grok adapter docs with "Video Generation (Experimental)" section showing job creation/polling examples and size/duration rules. Expands general video-generation guide from OpenAI-only to include Grok and fal.ai providers. Updates skill documentation to name video adapters explicitly. Updates doc metadata timestamps.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related issues

Suggested reviewers

  • AlemTuzlak

Poem

🐰 Hops through Imagine's frames so bright,
Grok videos polling through the night,
Aspects, resolutions, durations set just right,
From size to URL—a feature so fine!
Async jobs completed in perfect design. 🎬

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title directly and clearly describes the main change: adding a video generation adapter for the grok-imagine video models to the ai-grok package, which aligns with the substantial additions to model definitions, adapter implementation, and documentation in the changeset.
Description check ✅ Passed The pull request description comprehensively addresses all required template sections: it details the changes made (models, adapter, sizing, duration, image-to-video, usage, docs), includes both checklist items properly marked as completed, and clearly indicates release impact with a changeset generated.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch 705-featai-grok-video-generation-adapter-for-the-grok-imagine-video-models

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

7 package(s) bumped directly, 24 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-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-openrouter 0.13.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 10, 2026

Copy link
Copy Markdown

View your CI Pipeline Execution ↗ for commit 7d63f7a

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

☁️ Nx Cloud last updated this comment at 2026-06-10 08:54:57 UTC

@pkg-pr-new

pkg-pr-new Bot commented Jun 10, 2026

Copy link
Copy Markdown

Open in StackBlitz

@tanstack/ai

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

@tanstack/ai-anthropic

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

@tanstack/ai-client

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

@tanstack/ai-code-mode

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

@tanstack/ai-code-mode-skills

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

@tanstack/ai-devtools-core

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

@tanstack/ai-elevenlabs

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

@tanstack/ai-event-client

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

@tanstack/ai-fal

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

@tanstack/ai-gemini

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

@tanstack/ai-grok

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

@tanstack/ai-groq

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

@tanstack/ai-isolate-cloudflare

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

@tanstack/ai-isolate-node

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

@tanstack/ai-isolate-quickjs

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

@tanstack/ai-mcp

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

@tanstack/ai-ollama

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

@tanstack/ai-openai

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

@tanstack/ai-openrouter

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

@tanstack/ai-preact

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

@tanstack/ai-react

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

@tanstack/ai-react-ui

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

@tanstack/ai-solid

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

@tanstack/ai-solid-ui

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

@tanstack/ai-svelte

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

@tanstack/ai-utils

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

@tanstack/ai-vue

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

@tanstack/ai-vue-ui

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

@tanstack/openai-base

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

@tanstack/preact-ai-devtools

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

@tanstack/react-ai-devtools

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

@tanstack/solid-ai-devtools

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

commit: 7d63f7a

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/media/video-generation.md (1)

315-315: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Remove as any type assertion from documentation code sample.

The coding guidelines explicitly prohibit as type-assertion casts in documentation code samples (except as const). Examples must type-check without type casts.

Consider properly typing the size parameter in the input validator or using a type guard instead:

.inputValidator((data: { prompt: string; size?: '1280x720' | '720x1280' | '1792x1024' | '1024x1792'; duration?: number }) => data)
🤖 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 `@docs/media/video-generation.md` at line 315, Remove the "as any" cast on the
size assignment in the docs sample and ensure the sample types-check without
casts: update the .inputValidator signature to type the incoming data.size as
the allowed union ('1280x720' | '720x1280' | '1792x1024' | '1024x1792') or add a
short type guard that validates/normalizes data.size before assigning to size;
reference the .inputValidator callback and the size property so the sample
compiles without using "as any".

Source: Coding guidelines

🧹 Nitpick comments (1)
packages/ai-grok/tests/video-adapter.test.ts (1)

1-1: ⚡ Quick win

Place this unit test alongside the source file per repo rule.

video-adapter.test.ts currently lives under packages/ai-grok/tests/, but the guideline requires *.test.ts files to be colocated with source. Please move it next to the adapter/provider source it validates (for example under packages/ai-grok/src/...).

As per coding guidelines, "**/*.test.ts: Place unit tests alongside source code in *.test.ts files".

🤖 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-grok/tests/video-adapter.test.ts` at line 1, The test file
video-adapter.test.ts must be moved from packages/ai-grok/tests/ to be colocated
with the adapter/provider source it validates (e.g., under packages/ai-grok/src/
alongside the video adapter implementation), update any relative import paths in
video-adapter.test.ts to reflect the new location, and adjust any test-runner or
build config references if they rely on the old tests/ directory; locate the
adapter/provider source by name (video-adapter, VideoAdapter, or similar) and
place the test file next to that module so imports and module resolution remain
correct.

Source: Coding guidelines

🤖 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-grok/src/adapters/video.ts`:
- Around line 151-208: The validation calls (validateVideoSize,
validateVideoDuration) in createVideoJob can throw before the existing
try/catch, so wrap those validations and the rest of the function body inside
the same try block (or add an outer try that encloses validations) so any thrown
validation errors are caught; in the catch call logger.errors with
toRunErrorPayload and source `${this.name}.createVideoJob` (same shape as
current catch) and rethrow the error to preserve behavior.

---

Outside diff comments:
In `@docs/media/video-generation.md`:
- Line 315: Remove the "as any" cast on the size assignment in the docs sample
and ensure the sample types-check without casts: update the .inputValidator
signature to type the incoming data.size as the allowed union ('1280x720' |
'720x1280' | '1792x1024' | '1024x1792') or add a short type guard that
validates/normalizes data.size before assigning to size; reference the
.inputValidator callback and the size property so the sample compiles without
using "as any".

---

Nitpick comments:
In `@packages/ai-grok/tests/video-adapter.test.ts`:
- Line 1: The test file video-adapter.test.ts must be moved from
packages/ai-grok/tests/ to be colocated with the adapter/provider source it
validates (e.g., under packages/ai-grok/src/ alongside the video adapter
implementation), update any relative import paths in video-adapter.test.ts to
reflect the new location, and adjust any test-runner or build config references
if they rely on the old tests/ directory; locate the adapter/provider source by
name (video-adapter, VideoAdapter, or similar) and place the test file next to
that module so imports and module resolution remain correct.
🪄 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: b6eef03c-6d23-44d3-b96b-75cc68878c1b

📥 Commits

Reviewing files that changed from the base of the PR and between ff267a5 and 7d63f7a.

📒 Files selected for processing (10)
  • .changeset/grok-imagine-video-adapter.md
  • docs/adapters/grok.md
  • docs/config.json
  • docs/media/video-generation.md
  • packages/ai-grok/src/adapters/video.ts
  • packages/ai-grok/src/index.ts
  • packages/ai-grok/src/model-meta.ts
  • packages/ai-grok/src/video/video-provider-options.ts
  • packages/ai-grok/tests/video-adapter.test.ts
  • packages/ai/skills/ai-core/media-generation/SKILL.md

Comment on lines +151 to +208
async createVideoJob(
options: VideoGenerationOptions<GrokVideoProviderOptions>,
): Promise<VideoJobResult> {
const { model, prompt, size, modelOptions, logger } = options

validateVideoSize(model, size)
validateVideoDuration(model, options.duration)
validateVideoDuration(model, modelOptions?.duration)
const duration = options.duration ?? modelOptions?.duration

// The generic `size` option carries an "aspectRatio_resolution" template
// (e.g. '16:9_720p') and maps to the Imagine API's `aspect_ratio` /
// `resolution` parameters; explicit modelOptions win over the template.
const parsedSize = size !== undefined ? parseGrokVideoSize(size) : undefined
const request = {
model,
prompt,
...(parsedSize && {
aspect_ratio: parsedSize.aspectRatio,
...(parsedSize.resolution !== undefined && {
resolution: parsedSize.resolution,
}),
}),
...(duration !== undefined && { duration }),
...modelOptions,
}

try {
logger.request(
`activity=video.create provider=${this.name} model=${model} size=${size ?? 'default'} duration=${duration ?? 'default'}`,
{ provider: this.name, model },
)

const response = await this.request('/videos/generations', {
method: 'POST',
body: JSON.stringify(request),
})
if (!response.ok) {
throw new Error(
`grok: video generation request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`,
)
}

const result = (await response.json()) as GrokVideoCreateResponse
if (!result.request_id) {
throw new Error(
'grok: video generation response contained no request_id',
)
}
return { jobId: result.request_id, model }
} catch (error: unknown) {
logger.errors(`${this.name}.createVideoJob fatal`, {
error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),
source: `${this.name}.createVideoJob`,
})
throw error
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Verify that validation errors before the API call are properly logged.

The validation calls validateVideoSize and validateVideoDuration (lines 156-158) can throw errors before the try block starts at line 178. If validation fails, the error bypasses the catch block's logger, so validation failures won't be logged with the structured error format.

Consider wrapping the entire function body in the try-catch or adding a separate catch wrapper:

🛡️ Proposed fix to ensure validation errors are logged
 async createVideoJob(
   options: VideoGenerationOptions<GrokVideoProviderOptions>,
 ): Promise<VideoJobResult> {
+  try {
     const { model, prompt, size, modelOptions, logger } = options

     validateVideoSize(model, size)
     validateVideoDuration(model, options.duration)
     validateVideoDuration(model, modelOptions?.duration)
     const duration = options.duration ?? modelOptions?.duration

     // The generic `size` option carries an "aspectRatio_resolution" template
     // (e.g. '16:9_720p') and maps to the Imagine API's `aspect_ratio` /
     // `resolution` parameters; explicit modelOptions win over the template.
     const parsedSize = size !== undefined ? parseGrokVideoSize(size) : undefined
     const request = {
       model,
       prompt,
       ...(parsedSize && {
         aspect_ratio: parsedSize.aspectRatio,
         ...(parsedSize.resolution !== undefined && {
           resolution: parsedSize.resolution,
         }),
       }),
       ...(duration !== undefined && { duration }),
       ...modelOptions,
     }

-    try {
       logger.request(
         `activity=video.create provider=${this.name} model=${model} size=${size ?? 'default'} duration=${duration ?? 'default'}`,
         { provider: this.name, model },
       )

       const response = await this.request('/videos/generations', {
         method: 'POST',
         body: JSON.stringify(request),
       })
       if (!response.ok) {
         throw new Error(
           `grok: video generation request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`,
         )
       }

       const result = (await response.json()) as GrokVideoCreateResponse
       if (!result.request_id) {
         throw new Error(
           'grok: video generation response contained no request_id',
         )
       }
       return { jobId: result.request_id, model }
-    } catch (error: unknown) {
+  } catch (error: unknown) {
       logger.errors(`${this.name}.createVideoJob fatal`, {
         error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),
         source: `${this.name}.createVideoJob`,
       })
       throw error
-    }
+  }
 }
📝 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.

Suggested change
async createVideoJob(
options: VideoGenerationOptions<GrokVideoProviderOptions>,
): Promise<VideoJobResult> {
const { model, prompt, size, modelOptions, logger } = options
validateVideoSize(model, size)
validateVideoDuration(model, options.duration)
validateVideoDuration(model, modelOptions?.duration)
const duration = options.duration ?? modelOptions?.duration
// The generic `size` option carries an "aspectRatio_resolution" template
// (e.g. '16:9_720p') and maps to the Imagine API's `aspect_ratio` /
// `resolution` parameters; explicit modelOptions win over the template.
const parsedSize = size !== undefined ? parseGrokVideoSize(size) : undefined
const request = {
model,
prompt,
...(parsedSize && {
aspect_ratio: parsedSize.aspectRatio,
...(parsedSize.resolution !== undefined && {
resolution: parsedSize.resolution,
}),
}),
...(duration !== undefined && { duration }),
...modelOptions,
}
try {
logger.request(
`activity=video.create provider=${this.name} model=${model} size=${size ?? 'default'} duration=${duration ?? 'default'}`,
{ provider: this.name, model },
)
const response = await this.request('/videos/generations', {
method: 'POST',
body: JSON.stringify(request),
})
if (!response.ok) {
throw new Error(
`grok: video generation request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`,
)
}
const result = (await response.json()) as GrokVideoCreateResponse
if (!result.request_id) {
throw new Error(
'grok: video generation response contained no request_id',
)
}
return { jobId: result.request_id, model }
} catch (error: unknown) {
logger.errors(`${this.name}.createVideoJob fatal`, {
error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),
source: `${this.name}.createVideoJob`,
})
throw error
}
}
async createVideoJob(
options: VideoGenerationOptions<GrokVideoProviderOptions>,
): Promise<VideoJobResult> {
try {
const { model, prompt, size, modelOptions, logger } = options
validateVideoSize(model, size)
validateVideoDuration(model, options.duration)
validateVideoDuration(model, modelOptions?.duration)
const duration = options.duration ?? modelOptions?.duration
// The generic `size` option carries an "aspectRatio_resolution" template
// (e.g. '16:9_720p') and maps to the Imagine API's `aspect_ratio` /
// `resolution` parameters; explicit modelOptions win over the template.
const parsedSize = size !== undefined ? parseGrokVideoSize(size) : undefined
const request = {
model,
prompt,
...(parsedSize && {
aspect_ratio: parsedSize.aspectRatio,
...(parsedSize.resolution !== undefined && {
resolution: parsedSize.resolution,
}),
}),
...(duration !== undefined && { duration }),
...modelOptions,
}
logger.request(
`activity=video.create provider=${this.name} model=${model} size=${size ?? 'default'} duration=${duration ?? 'default'}`,
{ provider: this.name, model },
)
const response = await this.request('/videos/generations', {
method: 'POST',
body: JSON.stringify(request),
})
if (!response.ok) {
throw new Error(
`grok: video generation request failed (${response.status} ${response.statusText}): ${await this.errorMessage(response)}`,
)
}
const result = (await response.json()) as GrokVideoCreateResponse
if (!result.request_id) {
throw new Error(
'grok: video generation response contained no request_id',
)
}
return { jobId: result.request_id, model }
} catch (error: unknown) {
logger.errors(`${this.name}.createVideoJob fatal`, {
error: toRunErrorPayload(error, `${this.name}.createVideoJob failed`),
source: `${this.name}.createVideoJob`,
})
throw error
}
}
🤖 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-grok/src/adapters/video.ts` around lines 151 - 208, The
validation calls (validateVideoSize, validateVideoDuration) in createVideoJob
can throw before the existing try/catch, so wrap those validations and the rest
of the function body inside the same try block (or add an outer try that
encloses validations) so any thrown validation errors are caught; in the catch
call logger.errors with toRunErrorPayload and source
`${this.name}.createVideoJob` (same shape as current catch) and rethrow the
error to preserve behavior.

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-grok): video generation adapter for the grok-imagine video models

1 participant