@ai-sdk/xai
Advanced tools
+7
-0
| # @ai-sdk/xai | ||
| ## 3.0.121 | ||
| ### Patch Changes | ||
| - 70a6c3b: feat (provider/xai): support Grok Imagine Video 1.5. Adds the `grok-imagine-video-1.5` model id and native `1080p` for text-to-video and image-to-video (the standard `resolution: '1920x1080'` now maps to `1080p`). Reference-to-video remains capped at `720p`, so a `1080p` request in that mode is downgraded with a warning. Also fixes reference routing: previously any non-empty `inputReferences` array selected reference-to-video, so an array holding only a non-image reference sent `reference_images: []` with no usable references. | ||
| - 70a6c3b: feat (provider/xai): add `referenceVoiceIds` for reference-to-video reference audio. Pass up to 3 xAI preset voice ids (e.g. `['eve']`) and reference them from the prompt with `<AUDIO_0>`–`<AUDIO_2>`; they are sent as `reference_audios: [{ voice_id }]` on `POST /v1/videos/generations`. | ||
| ## 3.0.120 | ||
@@ -4,0 +11,0 @@ |
+13
-1
@@ -123,3 +123,3 @@ import { z } from 'zod/v4'; | ||
| type XaiVideoModelId = 'grok-imagine-video' | (string & {}); | ||
| type XaiVideoModelId = 'grok-imagine-video' | 'grok-imagine-video-1.5' | (string & {}); | ||
@@ -129,2 +129,3 @@ declare const resolutionSchema: z.ZodEnum<{ | ||
| "720p": "720p"; | ||
| "1080p": "1080p"; | ||
| }>; | ||
@@ -166,2 +167,6 @@ type XaiVideoResolution = z.infer<typeof resolutionSchema>; | ||
| referenceImageUrls: string[]; | ||
| /** | ||
| * Preset voice ids (up to 3) that give the subject a voice. | ||
| */ | ||
| referenceVoiceIds?: string[]; | ||
| } | ||
@@ -188,2 +193,6 @@ interface XaiVideoGenerationOptions extends XaiVideoSharedOptions, XaiVideoUserOptions { | ||
| referenceImageUrls: string[]; | ||
| /** | ||
| * Preset voice ids (up to 3) that give the subject a voice. | ||
| */ | ||
| referenceVoiceIds?: string[]; | ||
| } | ||
@@ -200,2 +209,5 @@ /** | ||
| * | ||
| * Reference images may also come from the top-level `inputReferences` option | ||
| * instead of `referenceImageUrls`. | ||
| * | ||
| * Runtime remains backward compatible with legacy auto-detected provider | ||
@@ -202,0 +214,0 @@ * options, but the public TypeScript type is intentionally explicit so editors |
+13
-1
@@ -123,3 +123,3 @@ import { z } from 'zod/v4'; | ||
| type XaiVideoModelId = 'grok-imagine-video' | (string & {}); | ||
| type XaiVideoModelId = 'grok-imagine-video' | 'grok-imagine-video-1.5' | (string & {}); | ||
@@ -129,2 +129,3 @@ declare const resolutionSchema: z.ZodEnum<{ | ||
| "720p": "720p"; | ||
| "1080p": "1080p"; | ||
| }>; | ||
@@ -166,2 +167,6 @@ type XaiVideoResolution = z.infer<typeof resolutionSchema>; | ||
| referenceImageUrls: string[]; | ||
| /** | ||
| * Preset voice ids (up to 3) that give the subject a voice. | ||
| */ | ||
| referenceVoiceIds?: string[]; | ||
| } | ||
@@ -188,2 +193,6 @@ interface XaiVideoGenerationOptions extends XaiVideoSharedOptions, XaiVideoUserOptions { | ||
| referenceImageUrls: string[]; | ||
| /** | ||
| * Preset voice ids (up to 3) that give the subject a voice. | ||
| */ | ||
| referenceVoiceIds?: string[]; | ||
| } | ||
@@ -200,2 +209,5 @@ /** | ||
| * | ||
| * Reference images may also come from the top-level `inputReferences` option | ||
| * instead of `referenceImageUrls`. | ||
| * | ||
| * Runtime remains backward compatible with legacy auto-detected provider | ||
@@ -202,0 +214,0 @@ * options, but the public TypeScript type is intentionally explicit so editors |
+3
-3
| { | ||
| "name": "@ai-sdk/xai", | ||
| "version": "3.0.120", | ||
| "version": "3.0.121", | ||
| "license": "Apache-2.0", | ||
@@ -33,4 +33,4 @@ "sideEffects": false, | ||
| "@ai-sdk/openai-compatible": "2.0.67", | ||
| "@ai-sdk/provider-utils": "4.0.45", | ||
| "@ai-sdk/provider": "3.0.15" | ||
| "@ai-sdk/provider": "3.0.15", | ||
| "@ai-sdk/provider-utils": "4.0.45" | ||
| }, | ||
@@ -37,0 +37,0 @@ "devDependencies": { |
+108
-22
@@ -40,2 +40,3 @@ import { | ||
| const RESOLUTION_MAP: Record<string, string> = { | ||
| '1920x1080': '1080p', | ||
| '1280x720': '720p', | ||
@@ -78,2 +79,7 @@ '854x480': '480p', | ||
| // References without a media type (only possible for URLs) are treated as | ||
| // images, matching the legacy `referenceImageUrls` behavior. | ||
| const isImageReference = (file: Experimental_VideoModelV3File): boolean => | ||
| file.mediaType == null || getTopLevelMediaType(file.mediaType) === 'image'; | ||
| function fileToXaiImageUrl(file: Experimental_VideoModelV3File): string { | ||
@@ -93,4 +99,4 @@ if (file.type === 'url') { | ||
| // `inputReferences` win over the legacy `referenceImageUrls` provider option. | ||
| // Video references are not supported for reference-to-video and are skipped | ||
| // with a warning. | ||
| // Non-image references (video or audio) are not supported for | ||
| // reference-to-video and are skipped with a warning. | ||
| function resolveReferenceImages( | ||
@@ -102,20 +108,28 @@ options: XaiVideoDoGenerateOptions, | ||
| if (options.inputReferences != null && options.inputReferences.length > 0) { | ||
| const imageReferences = options.inputReferences.filter(reference => { | ||
| if (isVideoFile(reference)) { | ||
| const imageFiles: Experimental_VideoModelV3File[] = []; | ||
| for (const reference of options.inputReferences) { | ||
| if (!isImageReference(reference)) { | ||
| warnings.push({ | ||
| type: 'unsupported', | ||
| feature: 'inputReferences', | ||
| details: | ||
| 'xAI reference-to-video accepts image references only. The video ' + | ||
| 'reference was ignored. Use providerOptions.xai.mode ' + | ||
| '"extend-video" to continue from a video.', | ||
| details: isVideoFile(reference) | ||
| ? 'xAI reference-to-video accepts image references only. The ' + | ||
| 'video reference was ignored. Use providerOptions.xai.mode ' + | ||
| '"extend-video" to continue from a video.' | ||
| : 'xAI reference-to-video accepts image references only. The ' + | ||
| 'non-image reference was ignored.', | ||
| }); | ||
| return false; | ||
| continue; | ||
| } | ||
| return true; | ||
| }); | ||
| return imageReferences.map(reference => ({ | ||
| url: fileToXaiImageUrl(reference), | ||
| })); | ||
| imageFiles.push(reference); | ||
| } | ||
| // Every reference may have been filtered out (audio- or video-only input), | ||
| // so collapse an empty list to undefined rather than sending an empty | ||
| // `reference_images` array. | ||
| return imageFiles.length > 0 | ||
| ? imageFiles.map(reference => ({ url: fileToXaiImageUrl(reference) })) | ||
| : undefined; | ||
| } | ||
@@ -133,2 +147,7 @@ | ||
| // True when at least one reference would survive as an image. | ||
| function hasImageInputReference(options: XaiVideoDoGenerateOptions): boolean { | ||
| return options.inputReferences?.some(isImageReference) ?? false; | ||
| } | ||
| function resolveVideoMode( | ||
@@ -150,4 +169,2 @@ options: XaiVideoDoGenerateOptions, | ||
| options.frameImages != null && options.frameImages.length > 0; | ||
| const hasInputReferences = | ||
| options.inputReferences != null && options.inputReferences.length > 0; | ||
| const hasLegacyReferenceUrls = | ||
@@ -157,3 +174,9 @@ xaiOptions?.referenceImageUrls != null && | ||
| if (!hasFrameImages && (hasInputReferences || hasLegacyReferenceUrls)) { | ||
| // Reference-to-video needs at least one image reference. An audio-only (or | ||
| // video-only) `inputReferences` array must not flip a text- or | ||
| // image-to-video request into R2V. | ||
| if ( | ||
| !hasFrameImages && | ||
| (hasImageInputReference(options) || hasLegacyReferenceUrls) | ||
| ) { | ||
| return 'reference-to-video'; | ||
@@ -299,3 +322,4 @@ } | ||
| `Unrecognized resolution "${options.resolution}". ` + | ||
| 'Use providerOptions.xai.resolution with "480p" or "720p" instead.', | ||
| 'Use providerOptions.xai.resolution with "480p", "720p", or ' + | ||
| '"1080p" instead.', | ||
| }); | ||
@@ -357,9 +381,53 @@ } | ||
| ); | ||
| if (referenceImages != null) { | ||
| body.reference_images = referenceImages; | ||
| } else { | ||
| // Explicit R2V with no usable image references would silently send | ||
| // a plain generations request; tell the user it is no longer R2V. | ||
| warnings.push({ | ||
| type: 'unsupported', | ||
| feature: 'referenceImages', | ||
| details: | ||
| 'xAI reference-to-video requires at least one image reference. ' + | ||
| 'The video will be generated without reference images.', | ||
| }); | ||
| } | ||
| const referenceVoiceIds = xaiOptions?.referenceVoiceIds; | ||
| if (referenceVoiceIds != null && referenceVoiceIds.length > 0) { | ||
| body.reference_audios = referenceVoiceIds.map(voiceId => ({ | ||
| voice_id: voiceId, | ||
| })); | ||
| } | ||
| // Reference-to-video is capped at 720p; downgrade a 1080p request. | ||
| if (body.resolution === '1080p') { | ||
| warnings.push({ | ||
| type: 'unsupported', | ||
| feature: 'resolution', | ||
| details: | ||
| 'xAI reference-to-video is limited to 720p. The request was ' + | ||
| 'downgraded from 1080p to 720p.', | ||
| }); | ||
| body.resolution = '720p'; | ||
| } | ||
| } | ||
| // Warn when reference images were provided but cannot be used in the | ||
| // resolved mode (e.g. alongside frameImages, or in edit/extend modes). | ||
| // 1080p requires grok-imagine-video-1.5; the original grok-imagine-video | ||
| // rejects it. Warn, but send the request as the user asked. | ||
| if (body.resolution === '1080p' && this.modelId === 'grok-imagine-video') { | ||
| warnings.push({ | ||
| type: 'unsupported', | ||
| feature: 'resolution', | ||
| details: | ||
| 'xAI model "grok-imagine-video" does not support 1080p. Use ' + | ||
| '"grok-imagine-video-1.5" for 1080p, or a lower resolution. The ' + | ||
| 'request was sent with 1080p.', | ||
| }); | ||
| } | ||
| // Warn when references were provided but cannot be used in the resolved | ||
| // mode (e.g. alongside frameImages, in edit/extend modes, or when the | ||
| // references carried no usable image to drive reference-to-video). | ||
| if ( | ||
@@ -373,5 +441,22 @@ options.inputReferences != null && | ||
| feature: 'inputReferences', | ||
| details: hasImageInputReference(options) | ||
| ? 'xAI only supports inputReferences for reference-to-video ' + | ||
| 'generation. The reference images were ignored.' | ||
| : 'xAI reference-to-video requires at least one image reference. ' + | ||
| 'The references were ignored.', | ||
| }); | ||
| } | ||
| // Preset reference voices only apply to reference-to-video generation. | ||
| if ( | ||
| xaiOptions?.referenceVoiceIds != null && | ||
| xaiOptions.referenceVoiceIds.length > 0 && | ||
| !hasReferenceImages | ||
| ) { | ||
| warnings.push({ | ||
| type: 'unsupported', | ||
| feature: 'referenceVoiceIds', | ||
| details: | ||
| 'xAI only supports inputReferences for reference-to-video ' + | ||
| 'generation. The reference images were ignored.', | ||
| 'xAI only supports reference voices for reference-to-video ' + | ||
| 'generation. The reference voices were ignored.', | ||
| }); | ||
@@ -394,2 +479,3 @@ } | ||
| 'referenceImageUrls', | ||
| 'referenceVoiceIds', | ||
| 'user', | ||
@@ -396,0 +482,0 @@ ].includes(key) |
@@ -5,3 +5,3 @@ import { lazySchema, zodSchema } from '@ai-sdk/provider-utils'; | ||
| const nonEmptyStringSchema = z.string().min(1); | ||
| const resolutionSchema = z.enum(['480p', '720p']); | ||
| const resolutionSchema = z.enum(['480p', '720p', '1080p']); | ||
| const modeSchema = z.enum(['edit-video', 'extend-video', 'reference-to-video']); | ||
@@ -52,2 +52,6 @@ | ||
| referenceImageUrls: string[]; | ||
| /** | ||
| * Preset voice ids (up to 3) that give the subject a voice. | ||
| */ | ||
| referenceVoiceIds?: string[]; | ||
| } | ||
@@ -80,2 +84,6 @@ | ||
| referenceImageUrls: string[]; | ||
| /** | ||
| * Preset voice ids (up to 3) that give the subject a voice. | ||
| */ | ||
| referenceVoiceIds?: string[]; | ||
| } | ||
@@ -93,2 +101,5 @@ | ||
| * | ||
| * Reference images may also come from the top-level `inputReferences` option | ||
| * instead of `referenceImageUrls`. | ||
| * | ||
| * Runtime remains backward compatible with legacy auto-detected provider | ||
@@ -117,2 +128,6 @@ * options, but the public TypeScript type is intentionally explicit so editors | ||
| const referenceVoiceIdsField = { | ||
| referenceVoiceIds: z.array(nonEmptyStringSchema).max(3).optional(), | ||
| }; | ||
| const editVideoSchema = z.object({ | ||
@@ -124,2 +139,3 @@ ...baseFields, | ||
| referenceImageUrls: z.undefined().optional(), | ||
| referenceVoiceIds: z.undefined().optional(), | ||
| }); | ||
@@ -132,2 +148,3 @@ | ||
| referenceImageUrls: z.undefined().optional(), | ||
| referenceVoiceIds: z.undefined().optional(), | ||
| }); | ||
@@ -138,2 +155,3 @@ | ||
| ...userField, | ||
| ...referenceVoiceIdsField, | ||
| mode: z.literal('reference-to-video'), | ||
@@ -147,2 +165,3 @@ referenceImageUrls: z.array(nonEmptyStringSchema).min(1).max(7), | ||
| ...userField, | ||
| ...referenceVoiceIdsField, | ||
| mode: z.undefined().optional(), | ||
@@ -165,2 +184,3 @@ videoUrl: nonEmptyStringSchema.optional(), | ||
| referenceImageUrls: z.array(nonEmptyStringSchema).min(1).max(7).optional(), | ||
| referenceVoiceIds: z.array(nonEmptyStringSchema).max(3).optional(), | ||
| user: z.string().optional(), | ||
@@ -167,0 +187,0 @@ ...baseFields, |
@@ -1,1 +0,4 @@ | ||
| export type XaiVideoModelId = 'grok-imagine-video' | (string & {}); | ||
| export type XaiVideoModelId = | ||
| | 'grok-imagine-video' | ||
| | 'grok-imagine-video-1.5' | ||
| | (string & {}); |
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
1008535
2.53%12282
1.7%