@ai-sdk/xai 4.0.56 → 4.0.58
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 +23 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +238 -34
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
- package/src/xai-batch.ts +280 -29
- package/src/xai-chat-language-model.ts +1 -1
- package/src/xai-provider.ts +4 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ai-sdk/xai",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.58",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"sideEffects": false,
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@ai-sdk/provider": "4.0.
|
|
33
|
-
"@ai-sdk/provider-utils": "5.0.
|
|
32
|
+
"@ai-sdk/provider": "4.0.14",
|
|
33
|
+
"@ai-sdk/provider-utils": "5.0.40"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
|
36
36
|
"@ai-sdk/test-server": "2.0.1",
|
package/src/xai-batch.ts
CHANGED
|
@@ -1,23 +1,33 @@
|
|
|
1
1
|
import {
|
|
2
2
|
InvalidArgumentError,
|
|
3
|
+
UnsupportedFunctionalityError,
|
|
3
4
|
type Experimental_BatchV4 as BatchV4,
|
|
5
|
+
type Experimental_BatchV4CancelResult as BatchV4CancelResult,
|
|
4
6
|
type Experimental_BatchV4Error as BatchV4Error,
|
|
5
7
|
type Experimental_BatchV4ItemResult as BatchV4ItemResult,
|
|
8
|
+
type Experimental_BatchV4ListOptions as BatchV4ListOptions,
|
|
9
|
+
type Experimental_BatchV4ListResult as BatchV4ListResult,
|
|
6
10
|
type Experimental_BatchV4OperationOptions as BatchV4OperationOptions,
|
|
7
11
|
type Experimental_BatchV4StartResult as BatchV4StartResult,
|
|
8
12
|
type Experimental_BatchV4Status as BatchV4Status,
|
|
9
13
|
type Experimental_TextBatchV4Request as TextBatchV4Request,
|
|
14
|
+
type Experimental_ImageBatchV4Request as ImageBatchV4Request,
|
|
15
|
+
type Experimental_ImageBatchV4ItemResult as ImageBatchV4ItemResult,
|
|
10
16
|
type Experimental_TextBatchV4ItemResult as TextBatchV4ItemResult,
|
|
11
17
|
type Experimental_BatchV4StartOptions as BatchV4StartOptions,
|
|
12
18
|
type LanguageModelV4Content,
|
|
13
19
|
type LanguageModelV4GenerateResult,
|
|
14
20
|
type SharedV4ProviderMetadata,
|
|
15
21
|
type SharedV4Warning,
|
|
22
|
+
type ImageModelV4Result,
|
|
16
23
|
} from '@ai-sdk/provider';
|
|
17
24
|
import {
|
|
18
25
|
combineHeaders,
|
|
26
|
+
convertImageModelFileToDataUri,
|
|
27
|
+
convertBase64ToUint8Array,
|
|
19
28
|
convertAsyncIteratorToReadableStream,
|
|
20
29
|
createJsonResponseHandler,
|
|
30
|
+
createBinaryResponseHandler,
|
|
21
31
|
createNullLanguageModelUsage,
|
|
22
32
|
getFromApi,
|
|
23
33
|
lazySchema,
|
|
@@ -45,6 +55,8 @@ import {
|
|
|
45
55
|
type XaiResponsesConfig,
|
|
46
56
|
} from './responses/xai-responses-language-model';
|
|
47
57
|
import type { XaiResponsesModelId } from './responses/xai-responses-language-model-options';
|
|
58
|
+
import type { XaiImageModelId } from './xai-image-settings';
|
|
59
|
+
import { xaiImageModelOptions } from './xai-image-model-options';
|
|
48
60
|
|
|
49
61
|
const xaiBatchEndpoint = '/v1/responses';
|
|
50
62
|
const xaiBatchName = 'ai-sdk-text-batch';
|
|
@@ -68,38 +80,70 @@ const xaiBatchProviderOptionsSchema = lazySchema(() =>
|
|
|
68
80
|
),
|
|
69
81
|
);
|
|
70
82
|
|
|
71
|
-
type XaiBatchModelIds = {
|
|
83
|
+
type XaiBatchModelIds = {
|
|
84
|
+
readonly text: XaiResponsesModelId;
|
|
85
|
+
readonly image: XaiImageModelId;
|
|
86
|
+
};
|
|
72
87
|
type XaiBatchRequest = TextBatchV4Request<XaiResponsesModelId>;
|
|
88
|
+
type XaiImageBatchRequest = ImageBatchV4Request<XaiImageModelId>;
|
|
89
|
+
|
|
90
|
+
function assertSupportedBatchRequests(
|
|
91
|
+
requests: BatchV4StartOptions<XaiBatchModelIds>['requests'],
|
|
92
|
+
) {
|
|
93
|
+
for (const request of requests) {
|
|
94
|
+
const requestType = request.type;
|
|
95
|
+
if (requestType !== 'text' && requestType !== 'image') {
|
|
96
|
+
throw new UnsupportedFunctionalityError({
|
|
97
|
+
functionality: `batch request type: ${requestType}`,
|
|
98
|
+
message: `The xAI Batch API does not support batch requests with type "${requestType}".`,
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
73
103
|
|
|
74
104
|
type XaiBatchPreparedRequest = {
|
|
105
|
+
endpoint: string;
|
|
75
106
|
body: unknown;
|
|
76
107
|
warnings: SharedV4Warning[];
|
|
77
108
|
};
|
|
78
109
|
|
|
110
|
+
const xaiBatchImageResponseSchema = z.object({
|
|
111
|
+
data: z.array(
|
|
112
|
+
z.object({
|
|
113
|
+
url: z.string().nullish(),
|
|
114
|
+
b64_json: z.string().nullish(),
|
|
115
|
+
revised_prompt: z.string().nullish(),
|
|
116
|
+
respect_moderation: z.boolean().nullish(),
|
|
117
|
+
}),
|
|
118
|
+
),
|
|
119
|
+
usage: z.object({ cost_in_usd_ticks: z.number().nullish() }).nullish(),
|
|
120
|
+
});
|
|
121
|
+
|
|
79
122
|
type XaiBatchResponseConversion =
|
|
80
123
|
| { success: true; result: LanguageModelV4GenerateResult }
|
|
81
124
|
| { success: false; error: BatchV4Error };
|
|
82
125
|
|
|
126
|
+
const xaiBatchResponseZodSchema = () =>
|
|
127
|
+
z.object({
|
|
128
|
+
batch_id: z.string(),
|
|
129
|
+
name: z.string().nullish(),
|
|
130
|
+
create_time: z.string().nullish(),
|
|
131
|
+
expire_time: z.string().nullish(),
|
|
132
|
+
cancel_time: z.string().nullish(),
|
|
133
|
+
cancel_by_xai_message: z.string().nullish(),
|
|
134
|
+
state: z
|
|
135
|
+
.object({
|
|
136
|
+
num_requests: z.number().nullish(),
|
|
137
|
+
num_pending: z.number().nullish(),
|
|
138
|
+
num_success: z.number().nullish(),
|
|
139
|
+
num_error: z.number().nullish(),
|
|
140
|
+
num_cancelled: z.number().nullish(),
|
|
141
|
+
})
|
|
142
|
+
.nullish(),
|
|
143
|
+
});
|
|
144
|
+
|
|
83
145
|
const xaiBatchResponseSchema = lazySchema(() =>
|
|
84
|
-
zodSchema(
|
|
85
|
-
z.object({
|
|
86
|
-
batch_id: z.string(),
|
|
87
|
-
name: z.string().nullish(),
|
|
88
|
-
create_time: z.string().nullish(),
|
|
89
|
-
expire_time: z.string().nullish(),
|
|
90
|
-
cancel_time: z.string().nullish(),
|
|
91
|
-
cancel_by_xai_message: z.string().nullish(),
|
|
92
|
-
state: z
|
|
93
|
-
.object({
|
|
94
|
-
num_requests: z.number().nullish(),
|
|
95
|
-
num_pending: z.number().nullish(),
|
|
96
|
-
num_success: z.number().nullish(),
|
|
97
|
-
num_error: z.number().nullish(),
|
|
98
|
-
num_cancelled: z.number().nullish(),
|
|
99
|
-
})
|
|
100
|
-
.nullish(),
|
|
101
|
-
}),
|
|
102
|
-
),
|
|
146
|
+
zodSchema(xaiBatchResponseZodSchema()),
|
|
103
147
|
);
|
|
104
148
|
|
|
105
149
|
type XaiBatchResponse = InferSchema<typeof xaiBatchResponseSchema>;
|
|
@@ -116,6 +160,7 @@ const xaiBatchResultSchema = z.object({
|
|
|
116
160
|
response: z
|
|
117
161
|
.object({
|
|
118
162
|
chat_get_completion: z.unknown().nullish(),
|
|
163
|
+
image_generation: z.unknown().nullish(),
|
|
119
164
|
})
|
|
120
165
|
.nullish(),
|
|
121
166
|
error: xaiBatchErrorSchema.nullish(),
|
|
@@ -135,6 +180,15 @@ const xaiBatchResultsPageSchema = lazySchema(() =>
|
|
|
135
180
|
),
|
|
136
181
|
);
|
|
137
182
|
|
|
183
|
+
const xaiBatchListResponseSchema = lazySchema(() =>
|
|
184
|
+
zodSchema(
|
|
185
|
+
z.object({
|
|
186
|
+
batches: z.array(xaiBatchResponseZodSchema()),
|
|
187
|
+
pagination_token: z.string().nullish(),
|
|
188
|
+
}),
|
|
189
|
+
),
|
|
190
|
+
);
|
|
191
|
+
|
|
138
192
|
export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
139
193
|
readonly specificationVersion = 'v4' as const;
|
|
140
194
|
readonly provider: string;
|
|
@@ -152,6 +206,7 @@ export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
|
152
206
|
async doStartBatch(
|
|
153
207
|
options: BatchV4StartOptions<XaiBatchModelIds>,
|
|
154
208
|
): Promise<BatchV4StartResult> {
|
|
209
|
+
assertSupportedBatchRequests(options.requests);
|
|
155
210
|
const fileParts: string[] = [];
|
|
156
211
|
const warnings: BatchV4StartResult['warnings'] =
|
|
157
212
|
options.webhookUrl == null
|
|
@@ -180,7 +235,7 @@ export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
|
180
235
|
JSON.stringify({
|
|
181
236
|
custom_id: request.id,
|
|
182
237
|
method: 'POST',
|
|
183
|
-
url:
|
|
238
|
+
url: preparedRequest.endpoint,
|
|
184
239
|
body: preparedRequest.body,
|
|
185
240
|
}),
|
|
186
241
|
'\n',
|
|
@@ -262,6 +317,58 @@ export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
|
262
317
|
return convertXaiBatchStatus(await this.retrieveBatch(options));
|
|
263
318
|
}
|
|
264
319
|
|
|
320
|
+
async doCancelBatch(
|
|
321
|
+
options: BatchV4OperationOptions,
|
|
322
|
+
): Promise<BatchV4CancelResult> {
|
|
323
|
+
await postJsonToApi({
|
|
324
|
+
url: this.getUrl(
|
|
325
|
+
`/batches/${encodeURIComponent(options.batchId)}:cancel`,
|
|
326
|
+
),
|
|
327
|
+
headers: combineHeaders(this.options.config.headers?.(), options.headers),
|
|
328
|
+
body: {},
|
|
329
|
+
failedResponseHandler: xaiFailedResponseHandler,
|
|
330
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
331
|
+
xaiBatchResponseSchema,
|
|
332
|
+
),
|
|
333
|
+
abortSignal: options.abortSignal,
|
|
334
|
+
fetch: this.options.config.fetch,
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
return {};
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
async doListBatches(options: BatchV4ListOptions): Promise<BatchV4ListResult> {
|
|
341
|
+
const url = new URL(this.getUrl('/batches'));
|
|
342
|
+
if (options.limit != null) {
|
|
343
|
+
url.searchParams.set('limit', String(options.limit));
|
|
344
|
+
}
|
|
345
|
+
if (options.cursor != null) {
|
|
346
|
+
url.searchParams.set('pagination_token', options.cursor);
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
const { value: page } = await getFromApi({
|
|
350
|
+
url: url.toString(),
|
|
351
|
+
headers: combineHeaders(this.options.config.headers?.(), options.headers),
|
|
352
|
+
failedResponseHandler: xaiFailedResponseHandler,
|
|
353
|
+
successfulResponseHandler: createJsonResponseHandler(
|
|
354
|
+
xaiBatchListResponseSchema,
|
|
355
|
+
),
|
|
356
|
+
abortSignal: options.abortSignal,
|
|
357
|
+
fetch: this.options.config.fetch,
|
|
358
|
+
validateUrl: false,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
return {
|
|
362
|
+
batches: page.batches.map(batch => ({
|
|
363
|
+
batchId: batch.batch_id,
|
|
364
|
+
...convertXaiBatchStatus(batch),
|
|
365
|
+
})),
|
|
366
|
+
...(page.pagination_token != null
|
|
367
|
+
? { nextCursor: page.pagination_token }
|
|
368
|
+
: {}),
|
|
369
|
+
};
|
|
370
|
+
}
|
|
371
|
+
|
|
265
372
|
async doGetBatchResults(
|
|
266
373
|
options: BatchV4OperationOptions,
|
|
267
374
|
): Promise<ReadableStream<BatchV4ItemResult>> {
|
|
@@ -327,7 +434,7 @@ export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
|
327
434
|
});
|
|
328
435
|
|
|
329
436
|
for (const result of page.results) {
|
|
330
|
-
yield await this.convertBatchResult(result);
|
|
437
|
+
yield await this.convertBatchResult(result, options.abortSignal);
|
|
331
438
|
}
|
|
332
439
|
|
|
333
440
|
paginationToken = page.pagination_token ?? undefined;
|
|
@@ -336,7 +443,8 @@ export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
|
336
443
|
|
|
337
444
|
private async convertBatchResult(
|
|
338
445
|
result: XaiBatchResult,
|
|
339
|
-
|
|
446
|
+
abortSignal: AbortSignal | undefined,
|
|
447
|
+
): Promise<TextBatchV4ItemResult | ImageBatchV4ItemResult> {
|
|
340
448
|
const error = result.batch_result?.error;
|
|
341
449
|
if (
|
|
342
450
|
(result.error_message?.length ?? 0) > 0 ||
|
|
@@ -380,18 +488,149 @@ export class XaiBatch implements BatchV4<XaiBatchModelIds> {
|
|
|
380
488
|
};
|
|
381
489
|
}
|
|
382
490
|
|
|
491
|
+
if (response?.image_generation != null) {
|
|
492
|
+
const validation = await safeValidateTypes({
|
|
493
|
+
value: response.image_generation,
|
|
494
|
+
schema: zodSchema(xaiBatchImageResponseSchema),
|
|
495
|
+
});
|
|
496
|
+
if (!validation.success) {
|
|
497
|
+
return invalidXaiImageBatchResult(result.batch_request_id);
|
|
498
|
+
}
|
|
499
|
+
if (
|
|
500
|
+
validation.value.data.some(image => image.respect_moderation === false)
|
|
501
|
+
) {
|
|
502
|
+
return {
|
|
503
|
+
type: 'image',
|
|
504
|
+
id: result.batch_request_id,
|
|
505
|
+
status: 'failed',
|
|
506
|
+
error: {
|
|
507
|
+
message:
|
|
508
|
+
'Image generation was blocked due to a content policy violation.',
|
|
509
|
+
},
|
|
510
|
+
};
|
|
511
|
+
}
|
|
512
|
+
const imageResult = await this.convertImageBatchResponse(
|
|
513
|
+
validation.value,
|
|
514
|
+
abortSignal,
|
|
515
|
+
);
|
|
516
|
+
return {
|
|
517
|
+
type: 'image',
|
|
518
|
+
id: result.batch_request_id,
|
|
519
|
+
status: 'succeeded',
|
|
520
|
+
result: imageResult,
|
|
521
|
+
};
|
|
522
|
+
}
|
|
523
|
+
|
|
383
524
|
return invalidXaiBatchResult(result.batch_request_id);
|
|
384
525
|
}
|
|
385
526
|
|
|
386
527
|
private async prepareRequest(
|
|
387
|
-
request: XaiBatchRequest,
|
|
528
|
+
request: XaiBatchRequest | XaiImageBatchRequest,
|
|
388
529
|
): Promise<XaiBatchPreparedRequest> {
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
530
|
+
if (request.type === 'text') {
|
|
531
|
+
const { args: body, warnings } =
|
|
532
|
+
await XaiResponsesLanguageModel.prepareRequest({
|
|
533
|
+
modelId: request.modelId,
|
|
534
|
+
options: request.options,
|
|
535
|
+
});
|
|
536
|
+
return { endpoint: xaiBatchEndpoint, body, warnings };
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const { prompt, n, size, aspectRatio, seed, files, mask, providerOptions } =
|
|
540
|
+
request.options;
|
|
541
|
+
const warnings: SharedV4Warning[] = [];
|
|
542
|
+
if (size != null) {
|
|
543
|
+
warnings.push({
|
|
544
|
+
type: 'unsupported',
|
|
545
|
+
feature: 'size',
|
|
546
|
+
details:
|
|
547
|
+
'This model does not support the `size` option. Use `aspectRatio` instead.',
|
|
393
548
|
});
|
|
394
|
-
|
|
549
|
+
}
|
|
550
|
+
if (seed != null) warnings.push({ type: 'unsupported', feature: 'seed' });
|
|
551
|
+
if (mask != null) warnings.push({ type: 'unsupported', feature: 'mask' });
|
|
552
|
+
|
|
553
|
+
const xaiOptions = await parseProviderOptions({
|
|
554
|
+
provider: 'xai',
|
|
555
|
+
providerOptions,
|
|
556
|
+
schema: xaiImageModelOptions,
|
|
557
|
+
});
|
|
558
|
+
const imageUrls = (files ?? []).map(convertImageModelFileToDataUri);
|
|
559
|
+
const body: Record<string, unknown> = {
|
|
560
|
+
model: request.modelId,
|
|
561
|
+
prompt,
|
|
562
|
+
n,
|
|
563
|
+
response_format: 'b64_json',
|
|
564
|
+
};
|
|
565
|
+
if (aspectRatio != null) body.aspect_ratio = aspectRatio;
|
|
566
|
+
if (xaiOptions?.output_format != null)
|
|
567
|
+
body.output_format = xaiOptions.output_format;
|
|
568
|
+
if (xaiOptions?.sync_mode != null) body.sync_mode = xaiOptions.sync_mode;
|
|
569
|
+
if (xaiOptions?.aspect_ratio != null && aspectRatio == null)
|
|
570
|
+
body.aspect_ratio = xaiOptions.aspect_ratio;
|
|
571
|
+
if (xaiOptions?.resolution != null) body.resolution = xaiOptions.resolution;
|
|
572
|
+
if (xaiOptions?.quality != null) body.quality = xaiOptions.quality;
|
|
573
|
+
if (xaiOptions?.user != null) body.user = xaiOptions.user;
|
|
574
|
+
if (imageUrls.length === 1) {
|
|
575
|
+
body.image = { url: imageUrls[0], type: 'image_url' };
|
|
576
|
+
} else if (imageUrls.length > 1) {
|
|
577
|
+
body.images = imageUrls.map(url => ({ url, type: 'image_url' }));
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
return {
|
|
581
|
+
endpoint: files?.length ? '/v1/images/edits' : '/v1/images/generations',
|
|
582
|
+
body,
|
|
583
|
+
warnings,
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
private async convertImageBatchResponse(
|
|
588
|
+
response: z.infer<typeof xaiBatchImageResponseSchema>,
|
|
589
|
+
abortSignal: AbortSignal | undefined,
|
|
590
|
+
): Promise<ImageModelV4Result> {
|
|
591
|
+
const hasAllBase64 = response.data.every(image => image.b64_json != null);
|
|
592
|
+
const images = hasAllBase64
|
|
593
|
+
? response.data.map(image => image.b64_json!)
|
|
594
|
+
: await Promise.all(
|
|
595
|
+
response.data.map(async image => {
|
|
596
|
+
if (image.b64_json != null) {
|
|
597
|
+
return convertBase64ToUint8Array(image.b64_json);
|
|
598
|
+
}
|
|
599
|
+
if (image.url == null) {
|
|
600
|
+
throw new InvalidArgumentError({
|
|
601
|
+
argument: 'batchResult',
|
|
602
|
+
message: 'xAI returned an image without data or a URL.',
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
const { value } = await getFromApi({
|
|
606
|
+
url: image.url,
|
|
607
|
+
validateUrl: true,
|
|
608
|
+
trustedOrigin: this.options.config.baseURL,
|
|
609
|
+
abortSignal,
|
|
610
|
+
failedResponseHandler: xaiFailedResponseHandler,
|
|
611
|
+
successfulResponseHandler: createBinaryResponseHandler(),
|
|
612
|
+
fetch: this.options.config.fetch,
|
|
613
|
+
});
|
|
614
|
+
return value;
|
|
615
|
+
}),
|
|
616
|
+
);
|
|
617
|
+
return {
|
|
618
|
+
images,
|
|
619
|
+
warnings: [],
|
|
620
|
+
response: { timestamp: new Date(), modelId: '', headers: undefined },
|
|
621
|
+
providerMetadata: {
|
|
622
|
+
xai: {
|
|
623
|
+
images: response.data.map(item =>
|
|
624
|
+
item.revised_prompt != null
|
|
625
|
+
? { revisedPrompt: item.revised_prompt }
|
|
626
|
+
: {},
|
|
627
|
+
),
|
|
628
|
+
...(response.usage?.cost_in_usd_ticks != null
|
|
629
|
+
? { costInUsdTicks: response.usage.cost_in_usd_ticks }
|
|
630
|
+
: {}),
|
|
631
|
+
},
|
|
632
|
+
},
|
|
633
|
+
};
|
|
395
634
|
}
|
|
396
635
|
|
|
397
636
|
private getUrl(path: string) {
|
|
@@ -487,6 +726,18 @@ function invalidXaiBatchResult(id: string): TextBatchV4ItemResult {
|
|
|
487
726
|
};
|
|
488
727
|
}
|
|
489
728
|
|
|
729
|
+
function invalidXaiImageBatchResult(id: string): ImageBatchV4ItemResult {
|
|
730
|
+
return {
|
|
731
|
+
type: 'image',
|
|
732
|
+
id,
|
|
733
|
+
status: 'failed',
|
|
734
|
+
error: {
|
|
735
|
+
message: 'xAI returned an invalid image batch result.',
|
|
736
|
+
code: 'invalid_response',
|
|
737
|
+
},
|
|
738
|
+
};
|
|
739
|
+
}
|
|
740
|
+
|
|
490
741
|
function convertXaiChatBatchResponse(
|
|
491
742
|
response: XaiChatResponse,
|
|
492
743
|
): XaiBatchResponseConversion {
|
|
@@ -590,7 +590,7 @@ export class XaiChatLanguageModel implements LanguageModelV4 {
|
|
|
590
590
|
}
|
|
591
591
|
|
|
592
592
|
// process tool calls
|
|
593
|
-
if (delta.tool_calls != null) {
|
|
593
|
+
if (delta.tool_calls != null && delta.tool_calls.length > 0) {
|
|
594
594
|
// end active reasoning block before tool calls start
|
|
595
595
|
if (
|
|
596
596
|
activeReasoningBlockId != null &&
|
package/src/xai-provider.ts
CHANGED
|
@@ -56,7 +56,10 @@ export interface XaiProvider extends ProviderV4 {
|
|
|
56
56
|
/**
|
|
57
57
|
* Returns a BatchV4 interface for processing batches with xAI.
|
|
58
58
|
*/
|
|
59
|
-
experimental_batch(): BatchV4<{
|
|
59
|
+
experimental_batch(): BatchV4<{
|
|
60
|
+
text: XaiResponsesModelId;
|
|
61
|
+
image: XaiImageModelId;
|
|
62
|
+
}>;
|
|
60
63
|
|
|
61
64
|
/**
|
|
62
65
|
* Creates an Xai image model for image generation.
|