@ai-sdk/xai 4.0.14 → 4.0.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/index.d.ts +11 -5
- package/dist/index.js +56 -10
- package/dist/index.js.map +1 -1
- package/docs/01-xai.mdx +9 -0
- package/package.json +6 -6
- package/src/responses/convert-to-xai-responses-input.ts +34 -8
- package/src/responses/xai-responses-api.ts +12 -1
- package/src/xai-video-model-options.ts +25 -5
- package/src/xai-video-model.ts +29 -3
package/docs/01-xai.mdx
CHANGED
|
@@ -933,6 +933,7 @@ const { video } = await generateVideo({
|
|
|
933
933
|
duration: 5,
|
|
934
934
|
providerOptions: {
|
|
935
935
|
xai: {
|
|
936
|
+
user: 'user-123',
|
|
936
937
|
pollTimeoutMs: 600000, // 10 minutes
|
|
937
938
|
} satisfies XaiVideoModelOptions,
|
|
938
939
|
},
|
|
@@ -1203,6 +1204,14 @@ You can validate the provider options using the `XaiVideoModelOptions` type.
|
|
|
1203
1204
|
`1280x720` maps to `720p` and `854x480` maps to `480p`.
|
|
1204
1205
|
Use this provider option to pass the native format directly.
|
|
1205
1206
|
|
|
1207
|
+
- **user** _string_
|
|
1208
|
+
|
|
1209
|
+
Optional identifier for the end user responsible for the request. xAI uses
|
|
1210
|
+
this value for abuse monitoring. It is sent unchanged for video generation
|
|
1211
|
+
(including reference-to-video) and video editing requests, and is omitted
|
|
1212
|
+
when not configured. It is not sent for video extension requests. Use an
|
|
1213
|
+
opaque stable identifier and avoid sending unnecessary personal information.
|
|
1214
|
+
|
|
1206
1215
|
- **mode** _'edit-video' | 'extend-video' | 'reference-to-video'_
|
|
1207
1216
|
|
|
1208
1217
|
Selects the explicit video operation. Each mode is mutually exclusive:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/xai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.16",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,17 +29,17 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/openai-compatible": "3.0.
|
|
33
|
-
"@ai-sdk/provider
|
|
34
|
-
"@ai-sdk/provider": "
|
|
32
|
+
"@ai-sdk/openai-compatible": "3.0.12",
|
|
33
|
+
"@ai-sdk/provider": "4.0.3",
|
|
34
|
+
"@ai-sdk/provider-utils": "5.0.11"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/node": "22.19.19",
|
|
38
38
|
"tsup": "^8.5.1",
|
|
39
39
|
"typescript": "5.8.3",
|
|
40
40
|
"zod": "3.25.76",
|
|
41
|
-
"@
|
|
42
|
-
"@ai-
|
|
41
|
+
"@ai-sdk/test-server": "2.0.0",
|
|
42
|
+
"@vercel/ai-tsconfig": "0.0.0"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
45
|
"zod": "^3.25.76 || ^4.1.8"
|
|
@@ -12,6 +12,7 @@ import {
|
|
|
12
12
|
} from '@ai-sdk/provider-utils';
|
|
13
13
|
import { xaiFilePartProviderOptions } from '../xai-file-part-options';
|
|
14
14
|
import type {
|
|
15
|
+
XaiResponsesFunctionCallOutput,
|
|
15
16
|
XaiResponsesInput,
|
|
16
17
|
XaiResponsesUserMessageContentPart,
|
|
17
18
|
} from './xai-responses-api';
|
|
@@ -241,7 +242,7 @@ export async function convertToXaiResponsesInput({
|
|
|
241
242
|
}
|
|
242
243
|
const output = part.output;
|
|
243
244
|
|
|
244
|
-
let outputValue:
|
|
245
|
+
let outputValue: XaiResponsesFunctionCallOutput['output'];
|
|
245
246
|
switch (output.type) {
|
|
246
247
|
case 'text':
|
|
247
248
|
case 'error-text':
|
|
@@ -255,14 +256,39 @@ export async function convertToXaiResponsesInput({
|
|
|
255
256
|
outputValue = JSON.stringify(output.value);
|
|
256
257
|
break;
|
|
257
258
|
case 'content':
|
|
258
|
-
outputValue =
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
259
|
+
outputValue = [];
|
|
260
|
+
for (const item of output.value) {
|
|
261
|
+
switch (item.type) {
|
|
262
|
+
case 'text': {
|
|
263
|
+
outputValue.push({
|
|
264
|
+
type: 'input_text',
|
|
265
|
+
text: item.text,
|
|
266
|
+
});
|
|
267
|
+
break;
|
|
268
|
+
}
|
|
269
|
+
case 'file': {
|
|
270
|
+
if (
|
|
271
|
+
getTopLevelMediaType(item.mediaType) === 'image' &&
|
|
272
|
+
(item.data.type === 'data' || item.data.type === 'url')
|
|
273
|
+
) {
|
|
274
|
+
outputValue.push({
|
|
275
|
+
type: 'input_image',
|
|
276
|
+
image_url:
|
|
277
|
+
item.data.type === 'url'
|
|
278
|
+
? item.data.url.toString()
|
|
279
|
+
: `data:${resolveFullMediaType({ part: item })};base64,${convertToBase64(item.data.data)}`,
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
case 'custom': {
|
|
285
|
+
break;
|
|
262
286
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
287
|
+
default: {
|
|
288
|
+
const _exhaustiveCheck: never = item;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
266
292
|
break;
|
|
267
293
|
default: {
|
|
268
294
|
const _exhaustiveCheck: never = output;
|
|
@@ -48,7 +48,18 @@ export type XaiResponsesAssistantMessage = {
|
|
|
48
48
|
export type XaiResponsesFunctionCallOutput = {
|
|
49
49
|
type: 'function_call_output';
|
|
50
50
|
call_id: string;
|
|
51
|
-
output:
|
|
51
|
+
output:
|
|
52
|
+
| string
|
|
53
|
+
| Array<
|
|
54
|
+
| {
|
|
55
|
+
type: 'input_text';
|
|
56
|
+
text: string;
|
|
57
|
+
}
|
|
58
|
+
| {
|
|
59
|
+
type: 'input_image';
|
|
60
|
+
image_url: string;
|
|
61
|
+
}
|
|
62
|
+
>;
|
|
52
63
|
};
|
|
53
64
|
|
|
54
65
|
export type XaiResponsesReasoning = {
|
|
@@ -14,7 +14,15 @@ interface XaiVideoSharedOptions {
|
|
|
14
14
|
resolution?: XaiVideoResolution | null;
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
interface
|
|
17
|
+
interface XaiVideoUserOptions {
|
|
18
|
+
/**
|
|
19
|
+
* A unique identifier representing the end user, for abuse monitoring.
|
|
20
|
+
*/
|
|
21
|
+
user?: string;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
interface XaiVideoEditModeOptions
|
|
25
|
+
extends XaiVideoSharedOptions, XaiVideoUserOptions {
|
|
18
26
|
/**
|
|
19
27
|
* Select edit-video mode explicitly for best autocomplete and narrowing.
|
|
20
28
|
*/
|
|
@@ -32,7 +40,8 @@ interface XaiVideoExtendModeOptions extends XaiVideoSharedOptions {
|
|
|
32
40
|
videoUrl: string;
|
|
33
41
|
}
|
|
34
42
|
|
|
35
|
-
interface XaiVideoReferenceToVideoOptions
|
|
43
|
+
interface XaiVideoReferenceToVideoOptions
|
|
44
|
+
extends XaiVideoSharedOptions, XaiVideoUserOptions {
|
|
36
45
|
/**
|
|
37
46
|
* Select reference-to-video mode explicitly for best autocomplete and narrowing.
|
|
38
47
|
*/
|
|
@@ -41,13 +50,15 @@ interface XaiVideoReferenceToVideoOptions extends XaiVideoSharedOptions {
|
|
|
41
50
|
referenceImageUrls: string[];
|
|
42
51
|
}
|
|
43
52
|
|
|
44
|
-
interface XaiVideoGenerationOptions
|
|
53
|
+
interface XaiVideoGenerationOptions
|
|
54
|
+
extends XaiVideoSharedOptions, XaiVideoUserOptions {
|
|
45
55
|
mode?: undefined;
|
|
46
56
|
videoUrl?: undefined;
|
|
47
57
|
referenceImageUrls?: undefined;
|
|
48
58
|
}
|
|
49
59
|
|
|
50
|
-
interface XaiLegacyEditVideoOptions
|
|
60
|
+
interface XaiLegacyEditVideoOptions
|
|
61
|
+
extends XaiVideoSharedOptions, XaiVideoUserOptions {
|
|
51
62
|
/**
|
|
52
63
|
* Legacy backward-compatible shape: omitting `mode` while providing
|
|
53
64
|
* `videoUrl` behaves like edit-video.
|
|
@@ -56,7 +67,8 @@ interface XaiLegacyEditVideoOptions extends XaiVideoSharedOptions {
|
|
|
56
67
|
videoUrl: string;
|
|
57
68
|
}
|
|
58
69
|
|
|
59
|
-
interface XaiLegacyReferenceToVideoOptions
|
|
70
|
+
interface XaiLegacyReferenceToVideoOptions
|
|
71
|
+
extends XaiVideoSharedOptions, XaiVideoUserOptions {
|
|
60
72
|
/**
|
|
61
73
|
* Legacy backward-compatible shape: omitting `mode` while providing
|
|
62
74
|
* `referenceImageUrls` behaves like reference-to-video.
|
|
@@ -94,8 +106,13 @@ const baseFields = {
|
|
|
94
106
|
resolution: resolutionSchema.nullish(),
|
|
95
107
|
};
|
|
96
108
|
|
|
109
|
+
const userField = {
|
|
110
|
+
user: z.string().optional(),
|
|
111
|
+
};
|
|
112
|
+
|
|
97
113
|
const editVideoSchema = z.object({
|
|
98
114
|
...baseFields,
|
|
115
|
+
...userField,
|
|
99
116
|
mode: z.literal('edit-video'),
|
|
100
117
|
videoUrl: nonEmptyStringSchema,
|
|
101
118
|
referenceImageUrls: z.undefined().optional(),
|
|
@@ -110,6 +127,7 @@ const extendVideoSchema = z.object({
|
|
|
110
127
|
|
|
111
128
|
const referenceToVideoSchema = z.object({
|
|
112
129
|
...baseFields,
|
|
130
|
+
...userField,
|
|
113
131
|
mode: z.literal('reference-to-video'),
|
|
114
132
|
referenceImageUrls: z.array(nonEmptyStringSchema).min(1).max(7),
|
|
115
133
|
videoUrl: z.undefined().optional(),
|
|
@@ -117,6 +135,7 @@ const referenceToVideoSchema = z.object({
|
|
|
117
135
|
|
|
118
136
|
const autoDetectSchema = z.object({
|
|
119
137
|
...baseFields,
|
|
138
|
+
...userField,
|
|
120
139
|
mode: z.undefined().optional(),
|
|
121
140
|
videoUrl: nonEmptyStringSchema.optional(),
|
|
122
141
|
referenceImageUrls: z.array(nonEmptyStringSchema).min(1).max(7).optional(),
|
|
@@ -133,6 +152,7 @@ const runtimeSchema = z.looseObject({
|
|
|
133
152
|
mode: modeSchema.optional(),
|
|
134
153
|
videoUrl: nonEmptyStringSchema.optional(),
|
|
135
154
|
referenceImageUrls: z.array(nonEmptyStringSchema).min(1).max(7).optional(),
|
|
155
|
+
user: z.string().optional(),
|
|
136
156
|
...baseFields,
|
|
137
157
|
});
|
|
138
158
|
|
package/src/xai-video-model.ts
CHANGED
|
@@ -5,15 +5,18 @@ import {
|
|
|
5
5
|
type SharedV4Warning,
|
|
6
6
|
} from '@ai-sdk/provider';
|
|
7
7
|
import {
|
|
8
|
+
cancelResponseBody,
|
|
8
9
|
combineHeaders,
|
|
9
10
|
convertUint8ArrayToBase64,
|
|
10
11
|
createJsonResponseHandler,
|
|
11
12
|
delay,
|
|
13
|
+
extractResponseHeaders,
|
|
12
14
|
getFromApi,
|
|
13
15
|
getTopLevelMediaType,
|
|
14
16
|
parseProviderOptions,
|
|
15
17
|
postJsonToApi,
|
|
16
18
|
type FetchFunction,
|
|
19
|
+
type ResponseHandler,
|
|
17
20
|
} from '@ai-sdk/provider-utils';
|
|
18
21
|
import { z } from 'zod/v4';
|
|
19
22
|
import { xaiFailedResponseHandler } from './xai-error';
|
|
@@ -359,6 +362,10 @@ export class XaiVideoModel implements Experimental_VideoModelV4 {
|
|
|
359
362
|
});
|
|
360
363
|
}
|
|
361
364
|
|
|
365
|
+
if (!isExtension && xaiOptions?.user !== undefined) {
|
|
366
|
+
body.user = xaiOptions.user;
|
|
367
|
+
}
|
|
368
|
+
|
|
362
369
|
if (xaiOptions != null) {
|
|
363
370
|
for (const [key, value] of Object.entries(xaiOptions)) {
|
|
364
371
|
if (
|
|
@@ -369,6 +376,7 @@ export class XaiVideoModel implements Experimental_VideoModelV4 {
|
|
|
369
376
|
'resolution',
|
|
370
377
|
'videoUrl',
|
|
371
378
|
'referenceImageUrls',
|
|
379
|
+
'user',
|
|
372
380
|
].includes(key)
|
|
373
381
|
) {
|
|
374
382
|
body[key] = value;
|
|
@@ -430,9 +438,7 @@ export class XaiVideoModel implements Experimental_VideoModelV4 {
|
|
|
430
438
|
url: `${baseURL}/videos/${requestId}`,
|
|
431
439
|
validateUrl: false,
|
|
432
440
|
headers: combineHeaders(this.config.headers(), options.headers),
|
|
433
|
-
successfulResponseHandler:
|
|
434
|
-
xaiVideoStatusResponseSchema,
|
|
435
|
-
),
|
|
441
|
+
successfulResponseHandler: xaiVideoStatusResponseHandler,
|
|
436
442
|
failedResponseHandler: xaiFailedResponseHandler,
|
|
437
443
|
abortSignal: options.abortSignal,
|
|
438
444
|
fetch: this.config.fetch,
|
|
@@ -538,3 +544,23 @@ const xaiVideoStatusResponseSchema = z.object({
|
|
|
538
544
|
})
|
|
539
545
|
.nullish(),
|
|
540
546
|
});
|
|
547
|
+
|
|
548
|
+
const xaiVideoStatusJsonResponseHandler = createJsonResponseHandler(
|
|
549
|
+
xaiVideoStatusResponseSchema,
|
|
550
|
+
);
|
|
551
|
+
|
|
552
|
+
const xaiVideoStatusResponseHandler: ResponseHandler<
|
|
553
|
+
z.infer<typeof xaiVideoStatusResponseSchema>
|
|
554
|
+
> = async options => {
|
|
555
|
+
if (options.response.status === 202) {
|
|
556
|
+
const responseHeaders = extractResponseHeaders(options.response);
|
|
557
|
+
await cancelResponseBody(options.response);
|
|
558
|
+
|
|
559
|
+
return {
|
|
560
|
+
responseHeaders,
|
|
561
|
+
value: { status: 'pending' },
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
565
|
+
return xaiVideoStatusJsonResponseHandler(options);
|
|
566
|
+
};
|