@ai-sdk/xai 4.0.57 → 4.0.59

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 CHANGED
@@ -1,5 +1,29 @@
1
1
  # @ai-sdk/xai
2
2
 
3
+ ## 4.0.59
4
+
5
+ ### Patch Changes
6
+
7
+ - 6e405ae: fix(xai): preserve `additionalProperties: false` in tool schemas
8
+ - Updated dependencies [5c0054d]
9
+ - Updated dependencies [39535af]
10
+ - @ai-sdk/provider@4.0.15
11
+ - @ai-sdk/provider-utils@5.0.41
12
+
13
+ ## 4.0.58
14
+
15
+ ### Patch Changes
16
+
17
+ - 5ec21a6: fix: reject unsupported batch request types
18
+ - 7469a3b: feat: support image generation requests in batches
19
+ - 0096850: fix(deepseek): preserve reasoning streams across empty tool-call deltas
20
+ - Updated dependencies [5ec21a6]
21
+ - Updated dependencies [7469a3b]
22
+ - Updated dependencies [813bb36]
23
+ - Updated dependencies [c43e4b7]
24
+ - @ai-sdk/provider@4.0.14
25
+ - @ai-sdk/provider-utils@5.0.40
26
+
3
27
  ## 4.0.57
4
28
 
5
29
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -553,6 +553,7 @@ interface XaiProvider extends ProviderV4 {
553
553
  */
554
554
  experimental_batch(): Experimental_BatchV4<{
555
555
  text: XaiResponsesModelId;
556
+ image: XaiImageModelId;
556
557
  }>;
557
558
  /**
558
559
  * Creates an Xai image model for image generation.
package/dist/index.js CHANGED
@@ -406,26 +406,6 @@ var xaiFailedResponseHandler = createJsonErrorResponseHandler({
406
406
  import {
407
407
  UnsupportedFunctionalityError as UnsupportedFunctionalityError2
408
408
  } from "@ai-sdk/provider";
409
-
410
- // src/remove-additional-properties.ts
411
- function removeAdditionalPropertiesFalse(value) {
412
- if (Array.isArray(value)) {
413
- return value.map(removeAdditionalPropertiesFalse);
414
- }
415
- if (value == null || typeof value !== "object") {
416
- return value;
417
- }
418
- const result = {};
419
- for (const [key, propertyValue] of Object.entries(value)) {
420
- if (key === "additionalProperties" && propertyValue === false) {
421
- continue;
422
- }
423
- result[key] = removeAdditionalPropertiesFalse(propertyValue);
424
- }
425
- return result;
426
- }
427
-
428
- // src/xai-prepare-tools.ts
429
409
  function prepareTools({
430
410
  tools,
431
411
  toolChoice
@@ -448,7 +428,7 @@ function prepareTools({
448
428
  function: {
449
429
  name: tool.name,
450
430
  description: tool.description,
451
- parameters: removeAdditionalPropertiesFalse(tool.inputSchema),
431
+ parameters: tool.inputSchema,
452
432
  ...tool.strict != null ? { strict: tool.strict } : {}
453
433
  }
454
434
  });
@@ -898,7 +878,7 @@ var XaiChatLanguageModel = class _XaiChatLanguageModel {
898
878
  delta: delta.reasoning_content
899
879
  });
900
880
  }
901
- if (delta.tool_calls != null) {
881
+ if (delta.tool_calls != null && delta.tool_calls.length > 0) {
902
882
  if (activeReasoningBlockId != null && !contentBlocks[activeReasoningBlockId].ended) {
903
883
  controller.enqueue({
904
884
  type: "reasoning-end",
@@ -1241,12 +1221,16 @@ var xaiImageResponseSchema = z6.object({
1241
1221
 
1242
1222
  // src/xai-batch.ts
1243
1223
  import {
1244
- InvalidArgumentError
1224
+ InvalidArgumentError,
1225
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError5
1245
1226
  } from "@ai-sdk/provider";
1246
1227
  import {
1247
1228
  combineHeaders as combineHeaders4,
1229
+ convertImageModelFileToDataUri as convertImageModelFileToDataUri2,
1230
+ convertBase64ToUint8Array,
1248
1231
  convertAsyncIteratorToReadableStream,
1249
1232
  createJsonResponseHandler as createJsonResponseHandler4,
1233
+ createBinaryResponseHandler as createBinaryResponseHandler2,
1250
1234
  createNullLanguageModelUsage,
1251
1235
  getFromApi as getFromApi2,
1252
1236
  lazySchema as lazySchema7,
@@ -2413,7 +2397,7 @@ async function prepareResponsesTools({
2413
2397
  type: "function",
2414
2398
  name: tool.name,
2415
2399
  description: tool.description,
2416
- parameters: removeAdditionalPropertiesFalse(tool.inputSchema),
2400
+ parameters: tool.inputSchema,
2417
2401
  ...tool.strict != null ? { strict: tool.strict } : {}
2418
2402
  });
2419
2403
  }
@@ -3531,6 +3515,28 @@ var xaiBatchProviderOptionsSchema = lazySchema7(
3531
3515
  })
3532
3516
  )
3533
3517
  );
3518
+ function assertSupportedBatchRequests(requests) {
3519
+ for (const request of requests) {
3520
+ const requestType = request.type;
3521
+ if (requestType !== "text" && requestType !== "image") {
3522
+ throw new UnsupportedFunctionalityError5({
3523
+ functionality: `batch request type: ${requestType}`,
3524
+ message: `The xAI Batch API does not support batch requests with type "${requestType}".`
3525
+ });
3526
+ }
3527
+ }
3528
+ }
3529
+ var xaiBatchImageResponseSchema = z15.object({
3530
+ data: z15.array(
3531
+ z15.object({
3532
+ url: z15.string().nullish(),
3533
+ b64_json: z15.string().nullish(),
3534
+ revised_prompt: z15.string().nullish(),
3535
+ respect_moderation: z15.boolean().nullish()
3536
+ })
3537
+ ),
3538
+ usage: z15.object({ cost_in_usd_ticks: z15.number().nullish() }).nullish()
3539
+ });
3534
3540
  var xaiBatchResponseZodSchema = () => z15.object({
3535
3541
  batch_id: z15.string(),
3536
3542
  name: z15.string().nullish(),
@@ -3557,7 +3563,8 @@ var xaiBatchResultSchema = z15.object({
3557
3563
  batch_request_id: z15.string(),
3558
3564
  batch_result: z15.object({
3559
3565
  response: z15.object({
3560
- chat_get_completion: z15.unknown().nullish()
3566
+ chat_get_completion: z15.unknown().nullish(),
3567
+ image_generation: z15.unknown().nullish()
3561
3568
  }).nullish(),
3562
3569
  error: xaiBatchErrorSchema.nullish()
3563
3570
  }).nullish(),
@@ -3588,6 +3595,7 @@ var XaiBatch = class {
3588
3595
  }
3589
3596
  async doStartBatch(options) {
3590
3597
  var _a, _b;
3598
+ assertSupportedBatchRequests(options.requests);
3591
3599
  const fileParts = [];
3592
3600
  const warnings = options.webhookUrl == null ? [] : [
3593
3601
  {
@@ -3609,7 +3617,7 @@ var XaiBatch = class {
3609
3617
  JSON.stringify({
3610
3618
  custom_id: request.id,
3611
3619
  method: "POST",
3612
- url: xaiBatchEndpoint,
3620
+ url: preparedRequest.endpoint,
3613
3621
  body: preparedRequest.body
3614
3622
  }),
3615
3623
  "\n"
@@ -3776,12 +3784,12 @@ var XaiBatch = class {
3776
3784
  validateUrl: false
3777
3785
  });
3778
3786
  for (const result of page.results) {
3779
- yield await this.convertBatchResult(result);
3787
+ yield await this.convertBatchResult(result, options.abortSignal);
3780
3788
  }
3781
3789
  paginationToken = (_c = page.pagination_token) != null ? _c : void 0;
3782
3790
  } while (paginationToken != null);
3783
3791
  }
3784
- async convertBatchResult(result) {
3792
+ async convertBatchResult(result, abortSignal) {
3785
3793
  var _a, _b, _c, _d, _e, _f;
3786
3794
  const error = (_a = result.batch_result) == null ? void 0 : _a.error;
3787
3795
  if (((_c = (_b = result.error_message) == null ? void 0 : _b.length) != null ? _c : 0) > 0 || (error == null ? void 0 : error.code) != null && error.code !== 0 && error.code !== "0" || (error == null ? void 0 : error.code) == null && ((_e = (_d = error == null ? void 0 : error.message) == null ? void 0 : _d.length) != null ? _e : 0) > 0) {
@@ -3815,14 +3823,127 @@ var XaiBatch = class {
3815
3823
  error: conversion.error
3816
3824
  };
3817
3825
  }
3826
+ if ((response == null ? void 0 : response.image_generation) != null) {
3827
+ const validation = await safeValidateTypes({
3828
+ value: response.image_generation,
3829
+ schema: zodSchema7(xaiBatchImageResponseSchema)
3830
+ });
3831
+ if (!validation.success) {
3832
+ return invalidXaiImageBatchResult(result.batch_request_id);
3833
+ }
3834
+ if (validation.value.data.some((image) => image.respect_moderation === false)) {
3835
+ return {
3836
+ type: "image",
3837
+ id: result.batch_request_id,
3838
+ status: "failed",
3839
+ error: {
3840
+ message: "Image generation was blocked due to a content policy violation."
3841
+ }
3842
+ };
3843
+ }
3844
+ const imageResult = await this.convertImageBatchResponse(
3845
+ validation.value,
3846
+ abortSignal
3847
+ );
3848
+ return {
3849
+ type: "image",
3850
+ id: result.batch_request_id,
3851
+ status: "succeeded",
3852
+ result: imageResult
3853
+ };
3854
+ }
3818
3855
  return invalidXaiBatchResult(result.batch_request_id);
3819
3856
  }
3820
3857
  async prepareRequest(request) {
3821
- const { args: body, warnings } = await XaiResponsesLanguageModel.prepareRequest({
3822
- modelId: request.modelId,
3823
- options: request.options
3858
+ if (request.type === "text") {
3859
+ const { args: body2, warnings: warnings2 } = await XaiResponsesLanguageModel.prepareRequest({
3860
+ modelId: request.modelId,
3861
+ options: request.options
3862
+ });
3863
+ return { endpoint: xaiBatchEndpoint, body: body2, warnings: warnings2 };
3864
+ }
3865
+ const { prompt, n, size, aspectRatio, seed, files, mask, providerOptions } = request.options;
3866
+ const warnings = [];
3867
+ if (size != null) {
3868
+ warnings.push({
3869
+ type: "unsupported",
3870
+ feature: "size",
3871
+ details: "This model does not support the `size` option. Use `aspectRatio` instead."
3872
+ });
3873
+ }
3874
+ if (seed != null) warnings.push({ type: "unsupported", feature: "seed" });
3875
+ if (mask != null) warnings.push({ type: "unsupported", feature: "mask" });
3876
+ const xaiOptions = await parseProviderOptions6({
3877
+ provider: "xai",
3878
+ providerOptions,
3879
+ schema: xaiImageModelOptions
3824
3880
  });
3825
- return { body, warnings };
3881
+ const imageUrls = (files != null ? files : []).map(convertImageModelFileToDataUri2);
3882
+ const body = {
3883
+ model: request.modelId,
3884
+ prompt,
3885
+ n,
3886
+ response_format: "b64_json"
3887
+ };
3888
+ if (aspectRatio != null) body.aspect_ratio = aspectRatio;
3889
+ if ((xaiOptions == null ? void 0 : xaiOptions.output_format) != null)
3890
+ body.output_format = xaiOptions.output_format;
3891
+ if ((xaiOptions == null ? void 0 : xaiOptions.sync_mode) != null) body.sync_mode = xaiOptions.sync_mode;
3892
+ if ((xaiOptions == null ? void 0 : xaiOptions.aspect_ratio) != null && aspectRatio == null)
3893
+ body.aspect_ratio = xaiOptions.aspect_ratio;
3894
+ if ((xaiOptions == null ? void 0 : xaiOptions.resolution) != null) body.resolution = xaiOptions.resolution;
3895
+ if ((xaiOptions == null ? void 0 : xaiOptions.quality) != null) body.quality = xaiOptions.quality;
3896
+ if ((xaiOptions == null ? void 0 : xaiOptions.user) != null) body.user = xaiOptions.user;
3897
+ if (imageUrls.length === 1) {
3898
+ body.image = { url: imageUrls[0], type: "image_url" };
3899
+ } else if (imageUrls.length > 1) {
3900
+ body.images = imageUrls.map((url) => ({ url, type: "image_url" }));
3901
+ }
3902
+ return {
3903
+ endpoint: (files == null ? void 0 : files.length) ? "/v1/images/edits" : "/v1/images/generations",
3904
+ body,
3905
+ warnings
3906
+ };
3907
+ }
3908
+ async convertImageBatchResponse(response, abortSignal) {
3909
+ var _a;
3910
+ const hasAllBase64 = response.data.every((image) => image.b64_json != null);
3911
+ const images = hasAllBase64 ? response.data.map((image) => image.b64_json) : await Promise.all(
3912
+ response.data.map(async (image) => {
3913
+ if (image.b64_json != null) {
3914
+ return convertBase64ToUint8Array(image.b64_json);
3915
+ }
3916
+ if (image.url == null) {
3917
+ throw new InvalidArgumentError({
3918
+ argument: "batchResult",
3919
+ message: "xAI returned an image without data or a URL."
3920
+ });
3921
+ }
3922
+ const { value } = await getFromApi2({
3923
+ url: image.url,
3924
+ validateUrl: true,
3925
+ trustedOrigin: this.options.config.baseURL,
3926
+ abortSignal,
3927
+ failedResponseHandler: xaiFailedResponseHandler,
3928
+ successfulResponseHandler: createBinaryResponseHandler2(),
3929
+ fetch: this.options.config.fetch
3930
+ });
3931
+ return value;
3932
+ })
3933
+ );
3934
+ return {
3935
+ images,
3936
+ warnings: [],
3937
+ response: { timestamp: /* @__PURE__ */ new Date(), modelId: "", headers: void 0 },
3938
+ providerMetadata: {
3939
+ xai: {
3940
+ images: response.data.map(
3941
+ (item) => item.revised_prompt != null ? { revisedPrompt: item.revised_prompt } : {}
3942
+ ),
3943
+ ...((_a = response.usage) == null ? void 0 : _a.cost_in_usd_ticks) != null ? { costInUsdTicks: response.usage.cost_in_usd_ticks } : {}
3944
+ }
3945
+ }
3946
+ };
3826
3947
  }
3827
3948
  getUrl(path) {
3828
3949
  var _a;
@@ -3888,6 +4009,17 @@ function invalidXaiBatchResult(id) {
3888
4009
  }
3889
4010
  };
3890
4011
  }
4012
+ function invalidXaiImageBatchResult(id) {
4013
+ return {
4014
+ type: "image",
4015
+ id,
4016
+ status: "failed",
4017
+ error: {
4018
+ message: "xAI returned an invalid image batch result.",
4019
+ code: "invalid_response"
4020
+ }
4021
+ };
4022
+ }
3891
4023
  function convertXaiChatBatchResponse(response) {
3892
4024
  var _a, _b, _c, _d, _e, _f;
3893
4025
  if (response.error != null) {
@@ -4410,7 +4542,7 @@ var xaiTools = {
4410
4542
  };
4411
4543
 
4412
4544
  // src/version.ts
4413
- var VERSION = true ? "4.0.57" : "0.0.0-test";
4545
+ var VERSION = true ? "4.0.59" : "0.0.0-test";
4414
4546
 
4415
4547
  // src/files/xai-files.ts
4416
4548
  import {
@@ -5204,8 +5336,8 @@ var xaiVideoStatusResponseHandler = async (options) => {
5204
5336
  // src/xai-speech-model.ts
5205
5337
  import {
5206
5338
  combineHeaders as combineHeaders7,
5207
- convertBase64ToUint8Array,
5208
- createBinaryResponseHandler as createBinaryResponseHandler2,
5339
+ convertBase64ToUint8Array as convertBase64ToUint8Array2,
5340
+ createBinaryResponseHandler as createBinaryResponseHandler3,
5209
5341
  createJsonResponseHandler as createJsonResponseHandler7,
5210
5342
  parseProviderOptions as parseProviderOptions9,
5211
5343
  postJsonToApi as postJsonToApi6,
@@ -5367,7 +5499,7 @@ var XaiSpeechModel = class _XaiSpeechModel {
5367
5499
  ),
5368
5500
  body: requestBody,
5369
5501
  failedResponseHandler: xaiFailedResponseHandler,
5370
- successfulResponseHandler: withTimestamps ? createJsonResponseHandler7(xaiSpeechTimestampsResponseSchema) : createBinaryResponseHandler2(),
5502
+ successfulResponseHandler: withTimestamps ? createJsonResponseHandler7(xaiSpeechTimestampsResponseSchema) : createBinaryResponseHandler3(),
5371
5503
  abortSignal: options.abortSignal,
5372
5504
  fetch: this.config.fetch
5373
5505
  });
@@ -5377,7 +5509,7 @@ var XaiSpeechModel = class _XaiSpeechModel {
5377
5509
  audio = value;
5378
5510
  } else {
5379
5511
  envelope = value;
5380
- audio = envelope.audio != null ? convertBase64ToUint8Array(envelope.audio) : new Uint8Array(0);
5512
+ audio = envelope.audio != null ? convertBase64ToUint8Array2(envelope.audio) : new Uint8Array(0);
5381
5513
  }
5382
5514
  const traceId = responseHeaders == null ? void 0 : responseHeaders["x-trace-id"];
5383
5515
  return {
@@ -5424,7 +5556,7 @@ import {
5424
5556
  } from "@ai-sdk/provider";
5425
5557
  import {
5426
5558
  combineHeaders as combineHeaders8,
5427
- convertBase64ToUint8Array as convertBase64ToUint8Array2,
5559
+ convertBase64ToUint8Array as convertBase64ToUint8Array3,
5428
5560
  createJsonResponseHandler as createJsonResponseHandler8,
5429
5561
  connectToWebSocket,
5430
5562
  mediaTypeToExtension,
@@ -5568,7 +5700,7 @@ var XaiTranscriptionModel = class _XaiTranscriptionModel {
5568
5700
  formData.append("keyterm", keyterm);
5569
5701
  }
5570
5702
  }
5571
- const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array2(audio)]);
5703
+ const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array3(audio)]);
5572
5704
  const fileExtension = mediaTypeToExtension(mediaType);
5573
5705
  formData.append(
5574
5706
  "file",
@@ -5727,7 +5859,7 @@ function createXaiStreamingTranscriptionStream({
5727
5859
  const { done, value } = await audioReader.read();
5728
5860
  if (done || finished) break;
5729
5861
  socket.send(
5730
- value instanceof Uint8Array ? value : convertBase64ToUint8Array2(value)
5862
+ value instanceof Uint8Array ? value : convertBase64ToUint8Array3(value)
5731
5863
  );
5732
5864
  await waitForWebSocketBufferDrain(socket);
5733
5865
  }