@ai-sdk/xai 4.0.0-beta.2 → 4.0.0-beta.21
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 +156 -8
- package/README.md +2 -0
- package/dist/index.d.mts +51 -43
- package/dist/index.d.ts +51 -43
- package/dist/index.js +110 -53
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +111 -50
- package/dist/index.mjs.map +1 -1
- package/docs/01-xai.mdx +30 -336
- package/package.json +4 -6
- package/src/convert-to-xai-chat-messages.ts +5 -5
- package/src/convert-xai-chat-usage.ts +2 -2
- package/src/map-xai-finish-reason.ts +2 -2
- package/src/responses/convert-to-xai-responses-input.ts +7 -5
- package/src/responses/convert-xai-responses-usage.ts +2 -2
- package/src/responses/map-xai-responses-finish-reason.ts +2 -2
- package/src/responses/xai-responses-api.ts +3 -0
- package/src/responses/xai-responses-language-model.ts +71 -30
- package/src/responses/xai-responses-options.ts +4 -0
- package/src/responses/xai-responses-prepare-tools.ts +6 -6
- package/src/xai-chat-language-model.ts +41 -22
- package/src/xai-chat-options.ts +3 -6
- package/src/xai-image-model.ts +43 -28
- package/src/xai-image-options.ts +2 -0
- package/src/xai-image-settings.ts +0 -2
- package/src/xai-prepare-tools.ts +6 -6
- package/src/xai-provider.ts +18 -21
- package/src/xai-video-model.ts +23 -7
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
2
|
+
LanguageModelV4,
|
|
3
|
+
LanguageModelV4CallOptions,
|
|
4
|
+
LanguageModelV4Content,
|
|
5
|
+
LanguageModelV4FinishReason,
|
|
6
|
+
LanguageModelV4GenerateResult,
|
|
7
|
+
LanguageModelV4StreamPart,
|
|
8
|
+
LanguageModelV4StreamResult,
|
|
9
|
+
LanguageModelV4Usage,
|
|
10
|
+
SharedV4Warning,
|
|
11
11
|
} from '@ai-sdk/provider';
|
|
12
12
|
import {
|
|
13
13
|
combineHeaders,
|
|
14
14
|
createEventSourceResponseHandler,
|
|
15
15
|
createJsonResponseHandler,
|
|
16
16
|
FetchFunction,
|
|
17
|
+
isCustomReasoning,
|
|
18
|
+
mapReasoningToProviderEffort,
|
|
17
19
|
parseProviderOptions,
|
|
18
20
|
ParseResult,
|
|
19
21
|
postJsonToApi,
|
|
@@ -43,8 +45,8 @@ type XaiResponsesConfig = {
|
|
|
43
45
|
fetch?: FetchFunction;
|
|
44
46
|
};
|
|
45
47
|
|
|
46
|
-
export class XaiResponsesLanguageModel implements
|
|
47
|
-
readonly specificationVersion = '
|
|
48
|
+
export class XaiResponsesLanguageModel implements LanguageModelV4 {
|
|
49
|
+
readonly specificationVersion = 'v4';
|
|
48
50
|
|
|
49
51
|
readonly modelId: XaiResponsesModelId;
|
|
50
52
|
|
|
@@ -74,8 +76,9 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
74
76
|
providerOptions,
|
|
75
77
|
tools,
|
|
76
78
|
toolChoice,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
+
reasoning,
|
|
80
|
+
}: LanguageModelV4CallOptions) {
|
|
81
|
+
const warnings: SharedV4Warning[] = [];
|
|
79
82
|
|
|
80
83
|
const options =
|
|
81
84
|
(await parseProviderOptions({
|
|
@@ -139,6 +142,24 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
139
142
|
}
|
|
140
143
|
}
|
|
141
144
|
|
|
145
|
+
const resolvedReasoningEffort =
|
|
146
|
+
options.reasoningEffort ??
|
|
147
|
+
(isCustomReasoning(reasoning)
|
|
148
|
+
? reasoning === 'none'
|
|
149
|
+
? undefined
|
|
150
|
+
: mapReasoningToProviderEffort({
|
|
151
|
+
reasoning,
|
|
152
|
+
effortMap: {
|
|
153
|
+
minimal: 'low',
|
|
154
|
+
low: 'low',
|
|
155
|
+
medium: 'medium',
|
|
156
|
+
high: 'high',
|
|
157
|
+
xhigh: 'high',
|
|
158
|
+
},
|
|
159
|
+
warnings,
|
|
160
|
+
})
|
|
161
|
+
: undefined);
|
|
162
|
+
|
|
142
163
|
const baseArgs: Record<string, unknown> = {
|
|
143
164
|
model: this.modelId,
|
|
144
165
|
input,
|
|
@@ -165,8 +186,16 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
165
186
|
: { type: 'json_object' },
|
|
166
187
|
},
|
|
167
188
|
}),
|
|
168
|
-
...(
|
|
169
|
-
|
|
189
|
+
...((resolvedReasoningEffort != null ||
|
|
190
|
+
options.reasoningSummary != null) && {
|
|
191
|
+
reasoning: {
|
|
192
|
+
...(resolvedReasoningEffort != null && {
|
|
193
|
+
effort: resolvedReasoningEffort,
|
|
194
|
+
}),
|
|
195
|
+
...(options.reasoningSummary != null && {
|
|
196
|
+
summary: options.reasoningSummary,
|
|
197
|
+
}),
|
|
198
|
+
},
|
|
170
199
|
}),
|
|
171
200
|
...(options.store === false && {
|
|
172
201
|
store: options.store,
|
|
@@ -199,8 +228,8 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
199
228
|
}
|
|
200
229
|
|
|
201
230
|
async doGenerate(
|
|
202
|
-
options:
|
|
203
|
-
): Promise<
|
|
231
|
+
options: LanguageModelV4CallOptions,
|
|
232
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
204
233
|
const {
|
|
205
234
|
args: body,
|
|
206
235
|
warnings,
|
|
@@ -227,7 +256,8 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
227
256
|
fetch: this.config.fetch,
|
|
228
257
|
});
|
|
229
258
|
|
|
230
|
-
const content: Array<
|
|
259
|
+
const content: Array<LanguageModelV4Content> = [];
|
|
260
|
+
let hasFunctionCall = false;
|
|
231
261
|
|
|
232
262
|
const webSearchSubTools = [
|
|
233
263
|
'web_search',
|
|
@@ -350,6 +380,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
350
380
|
}
|
|
351
381
|
|
|
352
382
|
case 'function_call': {
|
|
383
|
+
hasFunctionCall = true;
|
|
353
384
|
content.push({
|
|
354
385
|
type: 'tool-call',
|
|
355
386
|
toolCallId: part.call_id,
|
|
@@ -360,12 +391,16 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
360
391
|
}
|
|
361
392
|
|
|
362
393
|
case 'reasoning': {
|
|
363
|
-
const
|
|
364
|
-
.
|
|
365
|
-
|
|
394
|
+
const texts =
|
|
395
|
+
part.summary.length > 0
|
|
396
|
+
? part.summary.map(s => s.text)
|
|
397
|
+
: (part.content ?? []).map(c => c.text);
|
|
398
|
+
|
|
399
|
+
const reasoningText = texts
|
|
400
|
+
.filter(text => text && text.length > 0)
|
|
401
|
+
.join('');
|
|
366
402
|
|
|
367
|
-
if (
|
|
368
|
-
const reasoningText = summaryTexts.join('');
|
|
403
|
+
if (reasoningText) {
|
|
369
404
|
if (part.encrypted_content || part.id) {
|
|
370
405
|
content.push({
|
|
371
406
|
type: 'reasoning',
|
|
@@ -398,7 +433,9 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
398
433
|
return {
|
|
399
434
|
content,
|
|
400
435
|
finishReason: {
|
|
401
|
-
unified:
|
|
436
|
+
unified: hasFunctionCall
|
|
437
|
+
? 'tool-calls'
|
|
438
|
+
: mapXaiResponsesFinishReason(response.status),
|
|
402
439
|
raw: response.status ?? undefined,
|
|
403
440
|
},
|
|
404
441
|
usage: response.usage
|
|
@@ -418,8 +455,8 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
418
455
|
}
|
|
419
456
|
|
|
420
457
|
async doStream(
|
|
421
|
-
options:
|
|
422
|
-
): Promise<
|
|
458
|
+
options: LanguageModelV4CallOptions,
|
|
459
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
423
460
|
const {
|
|
424
461
|
args,
|
|
425
462
|
warnings,
|
|
@@ -446,11 +483,12 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
446
483
|
fetch: this.config.fetch,
|
|
447
484
|
});
|
|
448
485
|
|
|
449
|
-
let finishReason:
|
|
486
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
450
487
|
unified: 'other',
|
|
451
488
|
raw: undefined,
|
|
452
489
|
};
|
|
453
|
-
let
|
|
490
|
+
let hasFunctionCall = false;
|
|
491
|
+
let usage: LanguageModelV4Usage | undefined = undefined;
|
|
454
492
|
let isFirstChunk = true;
|
|
455
493
|
const contentBlocks: Record<string, { type: 'text' }> = {};
|
|
456
494
|
const seenToolCalls = new Set<string>();
|
|
@@ -473,7 +511,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
473
511
|
stream: response.pipeThrough(
|
|
474
512
|
new TransformStream<
|
|
475
513
|
ParseResult<z.infer<typeof xaiResponsesChunkSchema>>,
|
|
476
|
-
|
|
514
|
+
LanguageModelV4StreamPart
|
|
477
515
|
>({
|
|
478
516
|
start(controller) {
|
|
479
517
|
controller.enqueue({ type: 'stream-start', warnings });
|
|
@@ -643,7 +681,9 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
643
681
|
|
|
644
682
|
if (response.status) {
|
|
645
683
|
finishReason = {
|
|
646
|
-
unified:
|
|
684
|
+
unified: hasFunctionCall
|
|
685
|
+
? 'tool-calls'
|
|
686
|
+
: mapXaiResponsesFinishReason(response.status),
|
|
647
687
|
raw: response.status,
|
|
648
688
|
};
|
|
649
689
|
}
|
|
@@ -911,6 +951,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV3 {
|
|
|
911
951
|
toolName: part.name,
|
|
912
952
|
});
|
|
913
953
|
} else if (event.type === 'response.output_item.done') {
|
|
954
|
+
hasFunctionCall = true;
|
|
914
955
|
ongoingToolCalls[event.output_index] = undefined;
|
|
915
956
|
|
|
916
957
|
controller.enqueue({
|
|
@@ -6,6 +6,9 @@ export type XaiResponsesModelId =
|
|
|
6
6
|
| 'grok-4'
|
|
7
7
|
| 'grok-4-fast-non-reasoning'
|
|
8
8
|
| 'grok-4-fast-reasoning'
|
|
9
|
+
| 'grok-4.20-0309-non-reasoning'
|
|
10
|
+
| 'grok-4.20-0309-reasoning'
|
|
11
|
+
| 'grok-4.20-multi-agent-0309'
|
|
9
12
|
| (string & {});
|
|
10
13
|
|
|
11
14
|
/**
|
|
@@ -17,6 +20,7 @@ export const xaiLanguageModelResponsesOptions = z.object({
|
|
|
17
20
|
* Possible values are `low` (uses fewer reasoning tokens), `medium` and `high` (uses more reasoning tokens).
|
|
18
21
|
*/
|
|
19
22
|
reasoningEffort: z.enum(['low', 'medium', 'high']).optional(),
|
|
23
|
+
reasoningSummary: z.enum(['auto', 'concise', 'detailed']).optional(),
|
|
20
24
|
logprobs: z.boolean().optional(),
|
|
21
25
|
topLogprobs: z.number().int().min(0).max(8).optional(),
|
|
22
26
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
LanguageModelV4CallOptions,
|
|
3
|
+
SharedV4Warning,
|
|
4
4
|
UnsupportedFunctionalityError,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import { validateTypes } from '@ai-sdk/provider-utils';
|
|
@@ -20,16 +20,16 @@ export async function prepareResponsesTools({
|
|
|
20
20
|
tools,
|
|
21
21
|
toolChoice,
|
|
22
22
|
}: {
|
|
23
|
-
tools:
|
|
24
|
-
toolChoice?:
|
|
23
|
+
tools: LanguageModelV4CallOptions['tools'];
|
|
24
|
+
toolChoice?: LanguageModelV4CallOptions['toolChoice'];
|
|
25
25
|
}): Promise<{
|
|
26
26
|
tools: Array<XaiResponsesTool> | undefined;
|
|
27
27
|
toolChoice: XaiResponsesToolChoice | undefined;
|
|
28
|
-
toolWarnings:
|
|
28
|
+
toolWarnings: SharedV4Warning[];
|
|
29
29
|
}> {
|
|
30
30
|
const normalizedTools = tools?.length ? tools : undefined;
|
|
31
31
|
|
|
32
|
-
const toolWarnings:
|
|
32
|
+
const toolWarnings: SharedV4Warning[] = [];
|
|
33
33
|
|
|
34
34
|
if (normalizedTools == null) {
|
|
35
35
|
return { tools: undefined, toolChoice: undefined, toolWarnings };
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import {
|
|
2
2
|
APICallError,
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
3
|
+
LanguageModelV4,
|
|
4
|
+
LanguageModelV4CallOptions,
|
|
5
|
+
LanguageModelV4Content,
|
|
6
|
+
LanguageModelV4FinishReason,
|
|
7
|
+
LanguageModelV4GenerateResult,
|
|
8
|
+
LanguageModelV4StreamPart,
|
|
9
|
+
LanguageModelV4StreamResult,
|
|
10
|
+
LanguageModelV4Usage,
|
|
11
|
+
SharedV4Warning,
|
|
12
12
|
} from '@ai-sdk/provider';
|
|
13
13
|
import {
|
|
14
14
|
combineHeaders,
|
|
@@ -16,6 +16,8 @@ import {
|
|
|
16
16
|
createJsonResponseHandler,
|
|
17
17
|
extractResponseHeaders,
|
|
18
18
|
FetchFunction,
|
|
19
|
+
isCustomReasoning,
|
|
20
|
+
mapReasoningToProviderEffort,
|
|
19
21
|
parseProviderOptions,
|
|
20
22
|
ParseResult,
|
|
21
23
|
postJsonToApi,
|
|
@@ -41,8 +43,8 @@ type XaiChatConfig = {
|
|
|
41
43
|
fetch?: FetchFunction;
|
|
42
44
|
};
|
|
43
45
|
|
|
44
|
-
export class XaiChatLanguageModel implements
|
|
45
|
-
readonly specificationVersion = '
|
|
46
|
+
export class XaiChatLanguageModel implements LanguageModelV4 {
|
|
47
|
+
readonly specificationVersion = 'v4';
|
|
46
48
|
|
|
47
49
|
readonly modelId: XaiChatModelId;
|
|
48
50
|
|
|
@@ -71,12 +73,13 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
71
73
|
presencePenalty,
|
|
72
74
|
stopSequences,
|
|
73
75
|
seed,
|
|
76
|
+
reasoning,
|
|
74
77
|
responseFormat,
|
|
75
78
|
providerOptions,
|
|
76
79
|
tools,
|
|
77
80
|
toolChoice,
|
|
78
|
-
}:
|
|
79
|
-
const warnings:
|
|
81
|
+
}: LanguageModelV4CallOptions) {
|
|
82
|
+
const warnings: SharedV4Warning[] = [];
|
|
80
83
|
|
|
81
84
|
// parse xai-specific provider options
|
|
82
85
|
const options =
|
|
@@ -133,7 +136,23 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
133
136
|
temperature,
|
|
134
137
|
top_p: topP,
|
|
135
138
|
seed,
|
|
136
|
-
reasoning_effort:
|
|
139
|
+
reasoning_effort:
|
|
140
|
+
options.reasoningEffort ??
|
|
141
|
+
(isCustomReasoning(reasoning)
|
|
142
|
+
? reasoning === 'none'
|
|
143
|
+
? undefined
|
|
144
|
+
: mapReasoningToProviderEffort({
|
|
145
|
+
reasoning,
|
|
146
|
+
effortMap: {
|
|
147
|
+
minimal: 'low',
|
|
148
|
+
low: 'low',
|
|
149
|
+
medium: 'low',
|
|
150
|
+
high: 'high',
|
|
151
|
+
xhigh: 'high',
|
|
152
|
+
},
|
|
153
|
+
warnings,
|
|
154
|
+
})
|
|
155
|
+
: undefined),
|
|
137
156
|
|
|
138
157
|
// parallel function calling
|
|
139
158
|
parallel_function_calling: options.parallel_function_calling,
|
|
@@ -202,8 +221,8 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
202
221
|
}
|
|
203
222
|
|
|
204
223
|
async doGenerate(
|
|
205
|
-
options:
|
|
206
|
-
): Promise<
|
|
224
|
+
options: LanguageModelV4CallOptions,
|
|
225
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
207
226
|
const { args: body, warnings } = await this.getArgs(options);
|
|
208
227
|
|
|
209
228
|
const url = `${this.config.baseURL ?? 'https://api.x.ai/v1'}/chat/completions`;
|
|
@@ -237,7 +256,7 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
237
256
|
}
|
|
238
257
|
|
|
239
258
|
const choice = response.choices![0];
|
|
240
|
-
const content: Array<
|
|
259
|
+
const content: Array<LanguageModelV4Content> = [];
|
|
241
260
|
|
|
242
261
|
// extract text content
|
|
243
262
|
if (choice.message.content != null && choice.message.content.length > 0) {
|
|
@@ -312,8 +331,8 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
312
331
|
}
|
|
313
332
|
|
|
314
333
|
async doStream(
|
|
315
|
-
options:
|
|
316
|
-
): Promise<
|
|
334
|
+
options: LanguageModelV4CallOptions,
|
|
335
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
317
336
|
const { args, warnings } = await this.getArgs(options);
|
|
318
337
|
const body = {
|
|
319
338
|
...args,
|
|
@@ -375,11 +394,11 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
375
394
|
fetch: this.config.fetch,
|
|
376
395
|
});
|
|
377
396
|
|
|
378
|
-
let finishReason:
|
|
397
|
+
let finishReason: LanguageModelV4FinishReason = {
|
|
379
398
|
unified: 'other',
|
|
380
399
|
raw: undefined,
|
|
381
400
|
};
|
|
382
|
-
let usage:
|
|
401
|
+
let usage: LanguageModelV4Usage | undefined = undefined;
|
|
383
402
|
let isFirstChunk = true;
|
|
384
403
|
const contentBlocks: Record<
|
|
385
404
|
string,
|
|
@@ -394,7 +413,7 @@ export class XaiChatLanguageModel implements LanguageModelV3 {
|
|
|
394
413
|
stream: response.pipeThrough(
|
|
395
414
|
new TransformStream<
|
|
396
415
|
ParseResult<z.infer<typeof xaiChatChunkSchema>>,
|
|
397
|
-
|
|
416
|
+
LanguageModelV4StreamPart
|
|
398
417
|
>({
|
|
399
418
|
start(controller) {
|
|
400
419
|
controller.enqueue({ type: 'stream-start', warnings });
|
package/src/xai-chat-options.ts
CHANGED
|
@@ -6,6 +6,9 @@ export type XaiChatModelId =
|
|
|
6
6
|
| 'grok-4-1-fast-non-reasoning'
|
|
7
7
|
| 'grok-4-fast-non-reasoning'
|
|
8
8
|
| 'grok-4-fast-reasoning'
|
|
9
|
+
| 'grok-4.20-0309-non-reasoning'
|
|
10
|
+
| 'grok-4.20-0309-reasoning'
|
|
11
|
+
| 'grok-4.20-multi-agent-0309'
|
|
9
12
|
| 'grok-code-fast-1'
|
|
10
13
|
| 'grok-4'
|
|
11
14
|
| 'grok-4-0709'
|
|
@@ -14,12 +17,6 @@ export type XaiChatModelId =
|
|
|
14
17
|
| 'grok-3-latest'
|
|
15
18
|
| 'grok-3-mini'
|
|
16
19
|
| 'grok-3-mini-latest'
|
|
17
|
-
| 'grok-2-vision-1212'
|
|
18
|
-
| 'grok-2-vision'
|
|
19
|
-
| 'grok-2-vision-latest'
|
|
20
|
-
| 'grok-2-image-1212'
|
|
21
|
-
| 'grok-2-image'
|
|
22
|
-
| 'grok-2-image-latest'
|
|
23
20
|
| (string & {});
|
|
24
21
|
|
|
25
22
|
// search source schemas
|
package/src/xai-image-model.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ImageModelV4, SharedV4Warning } from '@ai-sdk/provider';
|
|
2
2
|
import {
|
|
3
3
|
combineHeaders,
|
|
4
4
|
convertImageModelFileToDataUri,
|
|
@@ -25,9 +25,9 @@ interface XaiImageModelConfig {
|
|
|
25
25
|
};
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
export class XaiImageModel implements
|
|
29
|
-
readonly specificationVersion = '
|
|
30
|
-
readonly maxImagesPerCall =
|
|
28
|
+
export class XaiImageModel implements ImageModelV4 {
|
|
29
|
+
readonly specificationVersion = 'v4';
|
|
30
|
+
readonly maxImagesPerCall = 3;
|
|
31
31
|
|
|
32
32
|
get provider(): string {
|
|
33
33
|
return this.config.provider;
|
|
@@ -49,10 +49,10 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
49
49
|
abortSignal,
|
|
50
50
|
files,
|
|
51
51
|
mask,
|
|
52
|
-
}: Parameters<
|
|
53
|
-
Awaited<ReturnType<
|
|
52
|
+
}: Parameters<ImageModelV4['doGenerate']>[0]): Promise<
|
|
53
|
+
Awaited<ReturnType<ImageModelV4['doGenerate']>>
|
|
54
54
|
> {
|
|
55
|
-
const warnings: Array<
|
|
55
|
+
const warnings: Array<SharedV4Warning> = [];
|
|
56
56
|
|
|
57
57
|
if (size != null) {
|
|
58
58
|
warnings.push({
|
|
@@ -84,19 +84,9 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
84
84
|
});
|
|
85
85
|
|
|
86
86
|
const hasFiles = files != null && files.length > 0;
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
imageUrl = convertImageModelFileToDataUri(files[0]);
|
|
91
|
-
|
|
92
|
-
if (files.length > 1) {
|
|
93
|
-
warnings.push({
|
|
94
|
-
type: 'other',
|
|
95
|
-
message:
|
|
96
|
-
'xAI only supports a single input image. Additional images are ignored.',
|
|
97
|
-
});
|
|
98
|
-
}
|
|
99
|
-
}
|
|
87
|
+
const imageUrls = hasFiles
|
|
88
|
+
? files.map(file => convertImageModelFileToDataUri(file))
|
|
89
|
+
: [];
|
|
100
90
|
|
|
101
91
|
const endpoint = hasFiles ? '/images/edits' : '/images/generations';
|
|
102
92
|
|
|
@@ -104,7 +94,7 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
104
94
|
model: this.modelId,
|
|
105
95
|
prompt,
|
|
106
96
|
n,
|
|
107
|
-
response_format: '
|
|
97
|
+
response_format: 'b64_json',
|
|
108
98
|
};
|
|
109
99
|
|
|
110
100
|
if (aspectRatio != null) {
|
|
@@ -127,8 +117,18 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
127
117
|
body.resolution = xaiOptions.resolution;
|
|
128
118
|
}
|
|
129
119
|
|
|
130
|
-
if (
|
|
131
|
-
body.
|
|
120
|
+
if (xaiOptions?.quality != null) {
|
|
121
|
+
body.quality = xaiOptions.quality;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (xaiOptions?.user != null) {
|
|
125
|
+
body.user = xaiOptions.user;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
if (imageUrls.length === 1) {
|
|
129
|
+
body.image = { url: imageUrls[0], type: 'image_url' };
|
|
130
|
+
} else if (imageUrls.length > 1) {
|
|
131
|
+
body.images = imageUrls.map(url => ({ url, type: 'image_url' }));
|
|
132
132
|
}
|
|
133
133
|
|
|
134
134
|
const baseURL = this.config.baseURL ?? 'https://api.x.ai/v1';
|
|
@@ -145,12 +145,18 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
145
145
|
fetch: this.config.fetch,
|
|
146
146
|
});
|
|
147
147
|
|
|
148
|
-
const
|
|
149
|
-
|
|
150
|
-
|
|
148
|
+
const hasAllBase64 = response.data.every(image => image.b64_json != null);
|
|
149
|
+
|
|
150
|
+
const images = hasAllBase64
|
|
151
|
+
? response.data.map(image => image.b64_json!)
|
|
152
|
+
: await Promise.all(
|
|
153
|
+
response.data.map(image =>
|
|
154
|
+
this.downloadImage(image.url!, abortSignal),
|
|
155
|
+
),
|
|
156
|
+
);
|
|
151
157
|
|
|
152
158
|
return {
|
|
153
|
-
images
|
|
159
|
+
images,
|
|
154
160
|
warnings,
|
|
155
161
|
response: {
|
|
156
162
|
timestamp: currentDate,
|
|
@@ -164,6 +170,9 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
164
170
|
? { revisedPrompt: item.revised_prompt }
|
|
165
171
|
: {}),
|
|
166
172
|
})),
|
|
173
|
+
...(response.usage?.cost_in_usd_ticks != null
|
|
174
|
+
? { costInUsdTicks: response.usage.cost_in_usd_ticks }
|
|
175
|
+
: {}),
|
|
167
176
|
},
|
|
168
177
|
},
|
|
169
178
|
};
|
|
@@ -187,8 +196,14 @@ export class XaiImageModel implements ImageModelV3 {
|
|
|
187
196
|
const xaiImageResponseSchema = z.object({
|
|
188
197
|
data: z.array(
|
|
189
198
|
z.object({
|
|
190
|
-
url: z.string(),
|
|
199
|
+
url: z.string().nullish(),
|
|
200
|
+
b64_json: z.string().nullish(),
|
|
191
201
|
revised_prompt: z.string().nullish(),
|
|
192
202
|
}),
|
|
193
203
|
),
|
|
204
|
+
usage: z
|
|
205
|
+
.object({
|
|
206
|
+
cost_in_usd_ticks: z.number().nullish(),
|
|
207
|
+
})
|
|
208
|
+
.nullish(),
|
|
194
209
|
});
|
package/src/xai-image-options.ts
CHANGED
|
@@ -5,6 +5,8 @@ export const xaiImageModelOptions = z.object({
|
|
|
5
5
|
output_format: z.string().optional(),
|
|
6
6
|
sync_mode: z.boolean().optional(),
|
|
7
7
|
resolution: z.enum(['1k', '2k']).optional(),
|
|
8
|
+
quality: z.enum(['low', 'medium', 'high']).optional(),
|
|
9
|
+
user: z.string().optional(),
|
|
8
10
|
});
|
|
9
11
|
|
|
10
12
|
export type XaiImageModelOptions = z.infer<typeof xaiImageModelOptions>;
|
package/src/xai-prepare-tools.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
LanguageModelV4CallOptions,
|
|
3
|
+
SharedV4Warning,
|
|
4
4
|
UnsupportedFunctionalityError,
|
|
5
5
|
} from '@ai-sdk/provider';
|
|
6
6
|
import { XaiToolChoice } from './xai-chat-prompt';
|
|
@@ -9,8 +9,8 @@ export function prepareTools({
|
|
|
9
9
|
tools,
|
|
10
10
|
toolChoice,
|
|
11
11
|
}: {
|
|
12
|
-
tools:
|
|
13
|
-
toolChoice?:
|
|
12
|
+
tools: LanguageModelV4CallOptions['tools'];
|
|
13
|
+
toolChoice?: LanguageModelV4CallOptions['toolChoice'];
|
|
14
14
|
}): {
|
|
15
15
|
tools:
|
|
16
16
|
| Array<{
|
|
@@ -24,12 +24,12 @@ export function prepareTools({
|
|
|
24
24
|
}>
|
|
25
25
|
| undefined;
|
|
26
26
|
toolChoice: XaiToolChoice | undefined;
|
|
27
|
-
toolWarnings:
|
|
27
|
+
toolWarnings: SharedV4Warning[];
|
|
28
28
|
} {
|
|
29
29
|
// when the tools array is empty, change it to undefined to prevent errors
|
|
30
30
|
tools = tools?.length ? tools : undefined;
|
|
31
31
|
|
|
32
|
-
const toolWarnings:
|
|
32
|
+
const toolWarnings: SharedV4Warning[] = [];
|
|
33
33
|
|
|
34
34
|
if (tools == null) {
|
|
35
35
|
return { tools: undefined, toolChoice: undefined, toolWarnings };
|