@ai-sdk/xai 4.0.33 → 4.0.35
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 +15 -0
- package/dist/index.d.ts +40 -1
- package/dist/index.js +378 -200
- package/dist/index.js.map +1 -1
- package/docs/01-xai.mdx +41 -0
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/responses/xai-responses-api.ts +26 -0
- package/src/responses/xai-responses-language-model.ts +137 -0
- package/src/responses/xai-responses-prepare-tools.ts +14 -0
- package/src/tool/image-generation.ts +62 -0
- package/src/tool/index.ts +3 -0
package/docs/01-xai.mdx
CHANGED
|
@@ -369,6 +369,47 @@ const { text } = await generateText({
|
|
|
369
369
|
});
|
|
370
370
|
```
|
|
371
371
|
|
|
372
|
+
### Image Generation Tool
|
|
373
|
+
|
|
374
|
+
The image generation tool lets the model create and edit images with Grok Imagine as part of a conversation. The model decides when to call the tool, writes the image prompt, and returns the finished image alongside its text response:
|
|
375
|
+
|
|
376
|
+
```ts
|
|
377
|
+
import { xai } from '@ai-sdk/xai';
|
|
378
|
+
import { generateText } from 'ai';
|
|
379
|
+
|
|
380
|
+
const result = await generateText({
|
|
381
|
+
model: xai.responses('grok-4.5'),
|
|
382
|
+
prompt:
|
|
383
|
+
'Generate an image of a corgi surfing a big wave, in the style of a Japanese woodblock print',
|
|
384
|
+
tools: {
|
|
385
|
+
image_generation: xai.tools.imageGeneration(),
|
|
386
|
+
},
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
for (const toolResult of result.staticToolResults) {
|
|
390
|
+
if (toolResult.toolName === 'image_generation') {
|
|
391
|
+
const base64Image = toolResult.output.result;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
The tool result also contains the prompt that the model wrote for the image model, which is useful for understanding and debugging what was generated.
|
|
397
|
+
|
|
398
|
+
#### Image Generation Parameters
|
|
399
|
+
|
|
400
|
+
- **action** _'auto' | 'generate' | 'edit'_
|
|
401
|
+
|
|
402
|
+
Restricts what the tool can do. Defaults to `'auto'`.
|
|
403
|
+
- `'auto'`: the model can generate and edit images.
|
|
404
|
+
- `'generate'`: text-to-image generation only.
|
|
405
|
+
- `'edit'`: image editing only (edits images already in the conversation, including images the model generated earlier).
|
|
406
|
+
|
|
407
|
+
<Note>
|
|
408
|
+
The tool takes no size or format parameters; the model picks an aspect ratio
|
|
409
|
+
for each call. To control it, ask in your prompt (e.g. "in a 9:16 vertical
|
|
410
|
+
aspect ratio").
|
|
411
|
+
</Note>
|
|
412
|
+
|
|
372
413
|
### MCP Server Tool
|
|
373
414
|
|
|
374
415
|
The MCP server tool enables the model to connect to remote [Model Context Protocol (MCP)](https://modelcontextprotocol.io/) servers and use their tools:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/xai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.35",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -30,7 +30,7 @@
|
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@ai-sdk/provider": "4.0.7",
|
|
33
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
33
|
+
"@ai-sdk/provider-utils": "5.0.27"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@types/node": "22.19.19",
|
package/src/index.ts
CHANGED
|
@@ -30,6 +30,7 @@ export { XaiRealtimeModel as Experimental_XaiRealtimeModel } from './realtime/xa
|
|
|
30
30
|
export type { XaiRealtimeModelConfig as Experimental_XaiRealtimeModelConfig } from './realtime/xai-realtime-model';
|
|
31
31
|
export {
|
|
32
32
|
codeExecution,
|
|
33
|
+
imageGeneration,
|
|
33
34
|
mcpServer,
|
|
34
35
|
viewImage,
|
|
35
36
|
viewXVideo,
|
|
@@ -109,6 +109,10 @@ export type XaiResponsesTool =
|
|
|
109
109
|
| { type: 'code_interpreter' }
|
|
110
110
|
| { type: 'view_image' }
|
|
111
111
|
| { type: 'view_x_video' }
|
|
112
|
+
| {
|
|
113
|
+
type: 'image_generation';
|
|
114
|
+
action?: 'auto' | 'generate' | 'edit';
|
|
115
|
+
}
|
|
112
116
|
| {
|
|
113
117
|
type: 'file_search';
|
|
114
118
|
vector_store_ids?: string[];
|
|
@@ -215,6 +219,13 @@ const outputItemSchema = z.discriminatedUnion('type', [
|
|
|
215
219
|
)
|
|
216
220
|
.nullish(),
|
|
217
221
|
}),
|
|
222
|
+
z.object({
|
|
223
|
+
type: z.literal('image_generation_call'),
|
|
224
|
+
id: z.string(),
|
|
225
|
+
status: z.string(),
|
|
226
|
+
prompt: z.string().nullish(),
|
|
227
|
+
result: z.string().nullish(),
|
|
228
|
+
}),
|
|
218
229
|
z.object({
|
|
219
230
|
type: z.literal('custom_tool_call'),
|
|
220
231
|
...toolCallSchema.shape,
|
|
@@ -423,6 +434,21 @@ export const xaiResponsesChunkSchema = z.union([
|
|
|
423
434
|
item_id: z.string(),
|
|
424
435
|
output_index: z.number(),
|
|
425
436
|
}),
|
|
437
|
+
z.object({
|
|
438
|
+
type: z.literal('response.image_generation_call.in_progress'),
|
|
439
|
+
item_id: z.string(),
|
|
440
|
+
output_index: z.number(),
|
|
441
|
+
}),
|
|
442
|
+
z.object({
|
|
443
|
+
type: z.literal('response.image_generation_call.generating'),
|
|
444
|
+
item_id: z.string(),
|
|
445
|
+
output_index: z.number(),
|
|
446
|
+
}),
|
|
447
|
+
z.object({
|
|
448
|
+
type: z.literal('response.image_generation_call.completed'),
|
|
449
|
+
item_id: z.string(),
|
|
450
|
+
output_index: z.number(),
|
|
451
|
+
}),
|
|
426
452
|
z.object({
|
|
427
453
|
type: z.literal('response.code_execution_call.in_progress'),
|
|
428
454
|
item_id: z.string(),
|
|
@@ -149,6 +149,10 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
149
149
|
tool => tool.type === 'provider' && tool.id === 'xai.file_search',
|
|
150
150
|
)?.name;
|
|
151
151
|
|
|
152
|
+
const imageGenerationToolName = tools?.find(
|
|
153
|
+
tool => tool.type === 'provider' && tool.id === 'xai.image_generation',
|
|
154
|
+
)?.name;
|
|
155
|
+
|
|
152
156
|
const { input, inputWarnings } = await convertToXaiResponsesInput({
|
|
153
157
|
prompt,
|
|
154
158
|
store: options.store ?? true,
|
|
@@ -269,6 +273,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
269
273
|
codeExecutionToolName,
|
|
270
274
|
mcpToolName,
|
|
271
275
|
fileSearchToolName,
|
|
276
|
+
imageGenerationToolName,
|
|
272
277
|
};
|
|
273
278
|
}
|
|
274
279
|
|
|
@@ -283,6 +288,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
283
288
|
codeExecutionToolName,
|
|
284
289
|
mcpToolName,
|
|
285
290
|
fileSearchToolName,
|
|
291
|
+
imageGenerationToolName,
|
|
286
292
|
} = await this.getArgs(options);
|
|
287
293
|
|
|
288
294
|
const {
|
|
@@ -347,6 +353,40 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
347
353
|
continue;
|
|
348
354
|
}
|
|
349
355
|
|
|
356
|
+
if (part.type === 'image_generation_call') {
|
|
357
|
+
const toolName = imageGenerationToolName ?? 'image_generation';
|
|
358
|
+
|
|
359
|
+
content.push({
|
|
360
|
+
type: 'tool-call',
|
|
361
|
+
toolCallId: part.id,
|
|
362
|
+
toolName,
|
|
363
|
+
input: '{}',
|
|
364
|
+
providerExecuted: true,
|
|
365
|
+
});
|
|
366
|
+
|
|
367
|
+
if (part.result != null) {
|
|
368
|
+
content.push({
|
|
369
|
+
type: 'tool-result',
|
|
370
|
+
toolCallId: part.id,
|
|
371
|
+
toolName,
|
|
372
|
+
result: {
|
|
373
|
+
result: part.result,
|
|
374
|
+
...(part.prompt != null && { prompt: part.prompt }),
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
} else {
|
|
378
|
+
content.push({
|
|
379
|
+
type: 'tool-result',
|
|
380
|
+
toolCallId: part.id,
|
|
381
|
+
toolName,
|
|
382
|
+
isError: true,
|
|
383
|
+
result: `Image generation failed (status: ${part.status}).`,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
|
|
350
390
|
if (
|
|
351
391
|
part.type === 'web_search_call' ||
|
|
352
392
|
part.type === 'x_search_call' ||
|
|
@@ -514,6 +554,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
514
554
|
codeExecutionToolName,
|
|
515
555
|
mcpToolName,
|
|
516
556
|
fileSearchToolName,
|
|
557
|
+
imageGenerationToolName,
|
|
517
558
|
} = await this.getArgs(options);
|
|
518
559
|
const body = {
|
|
519
560
|
...args,
|
|
@@ -801,6 +842,45 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
801
842
|
return;
|
|
802
843
|
}
|
|
803
844
|
|
|
845
|
+
if (
|
|
846
|
+
event.type === 'response.image_generation_call.in_progress' ||
|
|
847
|
+
event.type === 'response.image_generation_call.generating' ||
|
|
848
|
+
event.type === 'response.image_generation_call.completed'
|
|
849
|
+
) {
|
|
850
|
+
if (!seenToolCalls.has(event.item_id)) {
|
|
851
|
+
seenToolCalls.add(event.item_id);
|
|
852
|
+
|
|
853
|
+
const toolName = imageGenerationToolName ?? 'image_generation';
|
|
854
|
+
|
|
855
|
+
controller.enqueue({
|
|
856
|
+
type: 'tool-input-start',
|
|
857
|
+
id: event.item_id,
|
|
858
|
+
toolName,
|
|
859
|
+
});
|
|
860
|
+
|
|
861
|
+
controller.enqueue({
|
|
862
|
+
type: 'tool-input-delta',
|
|
863
|
+
id: event.item_id,
|
|
864
|
+
delta: '{}',
|
|
865
|
+
});
|
|
866
|
+
|
|
867
|
+
controller.enqueue({
|
|
868
|
+
type: 'tool-input-end',
|
|
869
|
+
id: event.item_id,
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
controller.enqueue({
|
|
873
|
+
type: 'tool-call',
|
|
874
|
+
toolCallId: event.item_id,
|
|
875
|
+
toolName,
|
|
876
|
+
input: '{}',
|
|
877
|
+
providerExecuted: true,
|
|
878
|
+
});
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
return;
|
|
882
|
+
}
|
|
883
|
+
|
|
804
884
|
if (
|
|
805
885
|
event.type === 'response.output_item.added' ||
|
|
806
886
|
event.type === 'response.output_item.done'
|
|
@@ -895,6 +975,63 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
|
895
975
|
return;
|
|
896
976
|
}
|
|
897
977
|
|
|
978
|
+
if (part.type === 'image_generation_call') {
|
|
979
|
+
const toolName = imageGenerationToolName ?? 'image_generation';
|
|
980
|
+
|
|
981
|
+
if (!seenToolCalls.has(part.id)) {
|
|
982
|
+
seenToolCalls.add(part.id);
|
|
983
|
+
|
|
984
|
+
controller.enqueue({
|
|
985
|
+
type: 'tool-input-start',
|
|
986
|
+
id: part.id,
|
|
987
|
+
toolName,
|
|
988
|
+
});
|
|
989
|
+
|
|
990
|
+
controller.enqueue({
|
|
991
|
+
type: 'tool-input-delta',
|
|
992
|
+
id: part.id,
|
|
993
|
+
delta: '{}',
|
|
994
|
+
});
|
|
995
|
+
|
|
996
|
+
controller.enqueue({
|
|
997
|
+
type: 'tool-input-end',
|
|
998
|
+
id: part.id,
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
controller.enqueue({
|
|
1002
|
+
type: 'tool-call',
|
|
1003
|
+
toolCallId: part.id,
|
|
1004
|
+
toolName,
|
|
1005
|
+
input: '{}',
|
|
1006
|
+
providerExecuted: true,
|
|
1007
|
+
});
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
if (event.type === 'response.output_item.done') {
|
|
1011
|
+
if (part.result != null) {
|
|
1012
|
+
controller.enqueue({
|
|
1013
|
+
type: 'tool-result',
|
|
1014
|
+
toolCallId: part.id,
|
|
1015
|
+
toolName,
|
|
1016
|
+
result: {
|
|
1017
|
+
result: part.result,
|
|
1018
|
+
...(part.prompt != null && { prompt: part.prompt }),
|
|
1019
|
+
},
|
|
1020
|
+
});
|
|
1021
|
+
} else {
|
|
1022
|
+
controller.enqueue({
|
|
1023
|
+
type: 'tool-result',
|
|
1024
|
+
toolCallId: part.id,
|
|
1025
|
+
toolName,
|
|
1026
|
+
isError: true,
|
|
1027
|
+
result: `Image generation failed (status: ${part.status}).`,
|
|
1028
|
+
});
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
return;
|
|
1033
|
+
}
|
|
1034
|
+
|
|
898
1035
|
if (
|
|
899
1036
|
part.type === 'web_search_call' ||
|
|
900
1037
|
part.type === 'x_search_call' ||
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
import { validateTypes } from '@ai-sdk/provider-utils';
|
|
7
7
|
import { removeAdditionalPropertiesFalse } from '../remove-additional-properties';
|
|
8
8
|
import { fileSearchArgsSchema } from '../tool/file-search';
|
|
9
|
+
import { imageGenerationArgsSchema } from '../tool/image-generation';
|
|
9
10
|
import { mcpServerArgsSchema } from '../tool/mcp-server';
|
|
10
11
|
import { webSearchArgsSchema } from '../tool/web-search';
|
|
11
12
|
import { xSearchArgsSchema } from '../tool/x-search';
|
|
@@ -99,6 +100,19 @@ export async function prepareResponsesTools({
|
|
|
99
100
|
break;
|
|
100
101
|
}
|
|
101
102
|
|
|
103
|
+
case 'xai.image_generation': {
|
|
104
|
+
const args = await validateTypes({
|
|
105
|
+
value: tool.args,
|
|
106
|
+
schema: imageGenerationArgsSchema,
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
xaiTools.push({
|
|
110
|
+
type: 'image_generation',
|
|
111
|
+
action: args.action,
|
|
112
|
+
});
|
|
113
|
+
break;
|
|
114
|
+
}
|
|
115
|
+
|
|
102
116
|
case 'xai.file_search': {
|
|
103
117
|
const args = await validateTypes({
|
|
104
118
|
value: tool.args,
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import {
|
|
2
|
+
createProviderExecutedToolFactory,
|
|
3
|
+
lazySchema,
|
|
4
|
+
zodSchema,
|
|
5
|
+
} from '@ai-sdk/provider-utils';
|
|
6
|
+
import { z } from 'zod/v4';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Schema for image generation tool arguments.
|
|
10
|
+
* @see https://docs.x.ai/developers/tools/overview
|
|
11
|
+
*/
|
|
12
|
+
export const imageGenerationArgsSchema = lazySchema(() =>
|
|
13
|
+
zodSchema(
|
|
14
|
+
z.object({
|
|
15
|
+
action: z.enum(['auto', 'generate', 'edit']).optional(),
|
|
16
|
+
}),
|
|
17
|
+
),
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
const imageGenerationInputSchema = lazySchema(() => zodSchema(z.object({})));
|
|
21
|
+
|
|
22
|
+
const imageGenerationOutputSchema = lazySchema(() =>
|
|
23
|
+
zodSchema(
|
|
24
|
+
z.object({
|
|
25
|
+
result: z.string(),
|
|
26
|
+
prompt: z.string().optional(),
|
|
27
|
+
}),
|
|
28
|
+
),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
const imageGenerationToolFactory = createProviderExecutedToolFactory<
|
|
32
|
+
{},
|
|
33
|
+
{
|
|
34
|
+
/**
|
|
35
|
+
* The generated image encoded in base64.
|
|
36
|
+
*/
|
|
37
|
+
result: string;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* The prompt that the model wrote for the image model.
|
|
41
|
+
*/
|
|
42
|
+
prompt?: string;
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
/**
|
|
46
|
+
* Restricts what the tool can do. Defaults to 'auto'.
|
|
47
|
+
*
|
|
48
|
+
* - 'auto': the model can generate and edit images.
|
|
49
|
+
* - 'generate': text-to-image generation only.
|
|
50
|
+
* - 'edit': image editing only.
|
|
51
|
+
*/
|
|
52
|
+
action?: 'auto' | 'generate' | 'edit';
|
|
53
|
+
}
|
|
54
|
+
>({
|
|
55
|
+
id: 'xai.image_generation',
|
|
56
|
+
inputSchema: imageGenerationInputSchema,
|
|
57
|
+
outputSchema: imageGenerationOutputSchema,
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
export const imageGeneration = (
|
|
61
|
+
args: Parameters<typeof imageGenerationToolFactory>[0] = {},
|
|
62
|
+
) => imageGenerationToolFactory(args);
|
package/src/tool/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { codeExecution } from './code-execution';
|
|
2
2
|
import { fileSearch } from './file-search';
|
|
3
|
+
import { imageGeneration } from './image-generation';
|
|
3
4
|
import { mcpServer } from './mcp-server';
|
|
4
5
|
import { viewImage } from './view-image';
|
|
5
6
|
import { viewXVideo } from './view-x-video';
|
|
@@ -9,6 +10,7 @@ import { xSearch } from './x-search';
|
|
|
9
10
|
export {
|
|
10
11
|
codeExecution,
|
|
11
12
|
fileSearch,
|
|
13
|
+
imageGeneration,
|
|
12
14
|
mcpServer,
|
|
13
15
|
viewImage,
|
|
14
16
|
viewXVideo,
|
|
@@ -19,6 +21,7 @@ export {
|
|
|
19
21
|
export const xaiTools = {
|
|
20
22
|
codeExecution,
|
|
21
23
|
fileSearch,
|
|
24
|
+
imageGeneration,
|
|
22
25
|
mcpServer,
|
|
23
26
|
viewImage,
|
|
24
27
|
viewXVideo,
|