@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 CHANGED
@@ -1,5 +1,28 @@
1
1
  # @ai-sdk/xai
2
2
 
3
+ ## 4.0.58
4
+
5
+ ### Patch Changes
6
+
7
+ - 5ec21a6: fix: reject unsupported batch request types
8
+ - 7469a3b: feat: support image generation requests in batches
9
+ - 0096850: fix(deepseek): preserve reasoning streams across empty tool-call deltas
10
+ - Updated dependencies [5ec21a6]
11
+ - Updated dependencies [7469a3b]
12
+ - Updated dependencies [813bb36]
13
+ - Updated dependencies [c43e4b7]
14
+ - @ai-sdk/provider@4.0.14
15
+ - @ai-sdk/provider-utils@5.0.40
16
+
17
+ ## 4.0.57
18
+
19
+ ### Patch Changes
20
+
21
+ - 4b8c4fa: feat(xai): add batch cancellation and listing
22
+ - Updated dependencies [9942196]
23
+ - @ai-sdk/provider@4.0.13
24
+ - @ai-sdk/provider-utils@5.0.39
25
+
3
26
  ## 4.0.56
4
27
 
5
28
  ### 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
@@ -898,7 +898,7 @@ var XaiChatLanguageModel = class _XaiChatLanguageModel {
898
898
  delta: delta.reasoning_content
899
899
  });
900
900
  }
901
- if (delta.tool_calls != null) {
901
+ if (delta.tool_calls != null && delta.tool_calls.length > 0) {
902
902
  if (activeReasoningBlockId != null && !contentBlocks[activeReasoningBlockId].ended) {
903
903
  controller.enqueue({
904
904
  type: "reasoning-end",
@@ -1241,12 +1241,16 @@ var xaiImageResponseSchema = z6.object({
1241
1241
 
1242
1242
  // src/xai-batch.ts
1243
1243
  import {
1244
- InvalidArgumentError
1244
+ InvalidArgumentError,
1245
+ UnsupportedFunctionalityError as UnsupportedFunctionalityError5
1245
1246
  } from "@ai-sdk/provider";
1246
1247
  import {
1247
1248
  combineHeaders as combineHeaders4,
1249
+ convertImageModelFileToDataUri as convertImageModelFileToDataUri2,
1250
+ convertBase64ToUint8Array,
1248
1251
  convertAsyncIteratorToReadableStream,
1249
1252
  createJsonResponseHandler as createJsonResponseHandler4,
1253
+ createBinaryResponseHandler as createBinaryResponseHandler2,
1250
1254
  createNullLanguageModelUsage,
1251
1255
  getFromApi as getFromApi2,
1252
1256
  lazySchema as lazySchema7,
@@ -3531,24 +3535,45 @@ var xaiBatchProviderOptionsSchema = lazySchema7(
3531
3535
  })
3532
3536
  )
3533
3537
  );
3534
- var xaiBatchResponseSchema = lazySchema7(
3535
- () => zodSchema7(
3538
+ function assertSupportedBatchRequests(requests) {
3539
+ for (const request of requests) {
3540
+ const requestType = request.type;
3541
+ if (requestType !== "text" && requestType !== "image") {
3542
+ throw new UnsupportedFunctionalityError5({
3543
+ functionality: `batch request type: ${requestType}`,
3544
+ message: `The xAI Batch API does not support batch requests with type "${requestType}".`
3545
+ });
3546
+ }
3547
+ }
3548
+ }
3549
+ var xaiBatchImageResponseSchema = z15.object({
3550
+ data: z15.array(
3536
3551
  z15.object({
3537
- batch_id: z15.string(),
3538
- name: z15.string().nullish(),
3539
- create_time: z15.string().nullish(),
3540
- expire_time: z15.string().nullish(),
3541
- cancel_time: z15.string().nullish(),
3542
- cancel_by_xai_message: z15.string().nullish(),
3543
- state: z15.object({
3544
- num_requests: z15.number().nullish(),
3545
- num_pending: z15.number().nullish(),
3546
- num_success: z15.number().nullish(),
3547
- num_error: z15.number().nullish(),
3548
- num_cancelled: z15.number().nullish()
3549
- }).nullish()
3552
+ url: z15.string().nullish(),
3553
+ b64_json: z15.string().nullish(),
3554
+ revised_prompt: z15.string().nullish(),
3555
+ respect_moderation: z15.boolean().nullish()
3550
3556
  })
3551
- )
3557
+ ),
3558
+ usage: z15.object({ cost_in_usd_ticks: z15.number().nullish() }).nullish()
3559
+ });
3560
+ var xaiBatchResponseZodSchema = () => z15.object({
3561
+ batch_id: z15.string(),
3562
+ name: z15.string().nullish(),
3563
+ create_time: z15.string().nullish(),
3564
+ expire_time: z15.string().nullish(),
3565
+ cancel_time: z15.string().nullish(),
3566
+ cancel_by_xai_message: z15.string().nullish(),
3567
+ state: z15.object({
3568
+ num_requests: z15.number().nullish(),
3569
+ num_pending: z15.number().nullish(),
3570
+ num_success: z15.number().nullish(),
3571
+ num_error: z15.number().nullish(),
3572
+ num_cancelled: z15.number().nullish()
3573
+ }).nullish()
3574
+ });
3575
+ var xaiBatchResponseSchema = lazySchema7(
3576
+ () => zodSchema7(xaiBatchResponseZodSchema())
3552
3577
  );
3553
3578
  var xaiBatchErrorSchema = z15.object({
3554
3579
  code: z15.union([z15.string(), z15.number()]).nullish(),
@@ -3558,7 +3583,8 @@ var xaiBatchResultSchema = z15.object({
3558
3583
  batch_request_id: z15.string(),
3559
3584
  batch_result: z15.object({
3560
3585
  response: z15.object({
3561
- chat_get_completion: z15.unknown().nullish()
3586
+ chat_get_completion: z15.unknown().nullish(),
3587
+ image_generation: z15.unknown().nullish()
3562
3588
  }).nullish(),
3563
3589
  error: xaiBatchErrorSchema.nullish()
3564
3590
  }).nullish(),
@@ -3572,6 +3598,14 @@ var xaiBatchResultsPageSchema = lazySchema7(
3572
3598
  })
3573
3599
  )
3574
3600
  );
3601
+ var xaiBatchListResponseSchema = lazySchema7(
3602
+ () => zodSchema7(
3603
+ z15.object({
3604
+ batches: z15.array(xaiBatchResponseZodSchema()),
3605
+ pagination_token: z15.string().nullish()
3606
+ })
3607
+ )
3608
+ );
3575
3609
  var XaiBatch = class {
3576
3610
  constructor(options) {
3577
3611
  this.options = options;
@@ -3581,6 +3615,7 @@ var XaiBatch = class {
3581
3615
  }
3582
3616
  async doStartBatch(options) {
3583
3617
  var _a, _b;
3618
+ assertSupportedBatchRequests(options.requests);
3584
3619
  const fileParts = [];
3585
3620
  const warnings = options.webhookUrl == null ? [] : [
3586
3621
  {
@@ -3602,7 +3637,7 @@ var XaiBatch = class {
3602
3637
  JSON.stringify({
3603
3638
  custom_id: request.id,
3604
3639
  method: "POST",
3605
- url: xaiBatchEndpoint,
3640
+ url: preparedRequest.endpoint,
3606
3641
  body: preparedRequest.body
3607
3642
  }),
3608
3643
  "\n"
@@ -3670,6 +3705,51 @@ var XaiBatch = class {
3670
3705
  async doGetBatchStatus(options) {
3671
3706
  return convertXaiBatchStatus(await this.retrieveBatch(options));
3672
3707
  }
3708
+ async doCancelBatch(options) {
3709
+ var _a, _b;
3710
+ await postJsonToApi4({
3711
+ url: this.getUrl(
3712
+ `/batches/${encodeURIComponent(options.batchId)}:cancel`
3713
+ ),
3714
+ headers: combineHeaders4((_b = (_a = this.options.config).headers) == null ? void 0 : _b.call(_a), options.headers),
3715
+ body: {},
3716
+ failedResponseHandler: xaiFailedResponseHandler,
3717
+ successfulResponseHandler: createJsonResponseHandler4(
3718
+ xaiBatchResponseSchema
3719
+ ),
3720
+ abortSignal: options.abortSignal,
3721
+ fetch: this.options.config.fetch
3722
+ });
3723
+ return {};
3724
+ }
3725
+ async doListBatches(options) {
3726
+ var _a, _b;
3727
+ const url = new URL(this.getUrl("/batches"));
3728
+ if (options.limit != null) {
3729
+ url.searchParams.set("limit", String(options.limit));
3730
+ }
3731
+ if (options.cursor != null) {
3732
+ url.searchParams.set("pagination_token", options.cursor);
3733
+ }
3734
+ const { value: page } = await getFromApi2({
3735
+ url: url.toString(),
3736
+ headers: combineHeaders4((_b = (_a = this.options.config).headers) == null ? void 0 : _b.call(_a), options.headers),
3737
+ failedResponseHandler: xaiFailedResponseHandler,
3738
+ successfulResponseHandler: createJsonResponseHandler4(
3739
+ xaiBatchListResponseSchema
3740
+ ),
3741
+ abortSignal: options.abortSignal,
3742
+ fetch: this.options.config.fetch,
3743
+ validateUrl: false
3744
+ });
3745
+ return {
3746
+ batches: page.batches.map((batch) => ({
3747
+ batchId: batch.batch_id,
3748
+ ...convertXaiBatchStatus(batch)
3749
+ })),
3750
+ ...page.pagination_token != null ? { nextCursor: page.pagination_token } : {}
3751
+ };
3752
+ }
3673
3753
  async doGetBatchResults(options) {
3674
3754
  const batch = await this.retrieveBatch(options);
3675
3755
  if (convertXaiBatchStatus(batch).status === "pending") {
@@ -3724,12 +3804,12 @@ var XaiBatch = class {
3724
3804
  validateUrl: false
3725
3805
  });
3726
3806
  for (const result of page.results) {
3727
- yield await this.convertBatchResult(result);
3807
+ yield await this.convertBatchResult(result, options.abortSignal);
3728
3808
  }
3729
3809
  paginationToken = (_c = page.pagination_token) != null ? _c : void 0;
3730
3810
  } while (paginationToken != null);
3731
3811
  }
3732
- async convertBatchResult(result) {
3812
+ async convertBatchResult(result, abortSignal) {
3733
3813
  var _a, _b, _c, _d, _e, _f;
3734
3814
  const error = (_a = result.batch_result) == null ? void 0 : _a.error;
3735
3815
  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) {
@@ -3763,14 +3843,127 @@ var XaiBatch = class {
3763
3843
  error: conversion.error
3764
3844
  };
3765
3845
  }
3846
+ if ((response == null ? void 0 : response.image_generation) != null) {
3847
+ const validation = await safeValidateTypes({
3848
+ value: response.image_generation,
3849
+ schema: zodSchema7(xaiBatchImageResponseSchema)
3850
+ });
3851
+ if (!validation.success) {
3852
+ return invalidXaiImageBatchResult(result.batch_request_id);
3853
+ }
3854
+ if (validation.value.data.some((image) => image.respect_moderation === false)) {
3855
+ return {
3856
+ type: "image",
3857
+ id: result.batch_request_id,
3858
+ status: "failed",
3859
+ error: {
3860
+ message: "Image generation was blocked due to a content policy violation."
3861
+ }
3862
+ };
3863
+ }
3864
+ const imageResult = await this.convertImageBatchResponse(
3865
+ validation.value,
3866
+ abortSignal
3867
+ );
3868
+ return {
3869
+ type: "image",
3870
+ id: result.batch_request_id,
3871
+ status: "succeeded",
3872
+ result: imageResult
3873
+ };
3874
+ }
3766
3875
  return invalidXaiBatchResult(result.batch_request_id);
3767
3876
  }
3768
3877
  async prepareRequest(request) {
3769
- const { args: body, warnings } = await XaiResponsesLanguageModel.prepareRequest({
3770
- modelId: request.modelId,
3771
- options: request.options
3878
+ if (request.type === "text") {
3879
+ const { args: body2, warnings: warnings2 } = await XaiResponsesLanguageModel.prepareRequest({
3880
+ modelId: request.modelId,
3881
+ options: request.options
3882
+ });
3883
+ return { endpoint: xaiBatchEndpoint, body: body2, warnings: warnings2 };
3884
+ }
3885
+ const { prompt, n, size, aspectRatio, seed, files, mask, providerOptions } = request.options;
3886
+ const warnings = [];
3887
+ if (size != null) {
3888
+ warnings.push({
3889
+ type: "unsupported",
3890
+ feature: "size",
3891
+ details: "This model does not support the `size` option. Use `aspectRatio` instead."
3892
+ });
3893
+ }
3894
+ if (seed != null) warnings.push({ type: "unsupported", feature: "seed" });
3895
+ if (mask != null) warnings.push({ type: "unsupported", feature: "mask" });
3896
+ const xaiOptions = await parseProviderOptions6({
3897
+ provider: "xai",
3898
+ providerOptions,
3899
+ schema: xaiImageModelOptions
3772
3900
  });
3773
- return { body, warnings };
3901
+ const imageUrls = (files != null ? files : []).map(convertImageModelFileToDataUri2);
3902
+ const body = {
3903
+ model: request.modelId,
3904
+ prompt,
3905
+ n,
3906
+ response_format: "b64_json"
3907
+ };
3908
+ if (aspectRatio != null) body.aspect_ratio = aspectRatio;
3909
+ if ((xaiOptions == null ? void 0 : xaiOptions.output_format) != null)
3910
+ body.output_format = xaiOptions.output_format;
3911
+ if ((xaiOptions == null ? void 0 : xaiOptions.sync_mode) != null) body.sync_mode = xaiOptions.sync_mode;
3912
+ if ((xaiOptions == null ? void 0 : xaiOptions.aspect_ratio) != null && aspectRatio == null)
3913
+ body.aspect_ratio = xaiOptions.aspect_ratio;
3914
+ if ((xaiOptions == null ? void 0 : xaiOptions.resolution) != null) body.resolution = xaiOptions.resolution;
3915
+ if ((xaiOptions == null ? void 0 : xaiOptions.quality) != null) body.quality = xaiOptions.quality;
3916
+ if ((xaiOptions == null ? void 0 : xaiOptions.user) != null) body.user = xaiOptions.user;
3917
+ if (imageUrls.length === 1) {
3918
+ body.image = { url: imageUrls[0], type: "image_url" };
3919
+ } else if (imageUrls.length > 1) {
3920
+ body.images = imageUrls.map((url) => ({ url, type: "image_url" }));
3921
+ }
3922
+ return {
3923
+ endpoint: (files == null ? void 0 : files.length) ? "/v1/images/edits" : "/v1/images/generations",
3924
+ body,
3925
+ warnings
3926
+ };
3927
+ }
3928
+ async convertImageBatchResponse(response, abortSignal) {
3929
+ var _a;
3930
+ const hasAllBase64 = response.data.every((image) => image.b64_json != null);
3931
+ const images = hasAllBase64 ? response.data.map((image) => image.b64_json) : await Promise.all(
3932
+ response.data.map(async (image) => {
3933
+ if (image.b64_json != null) {
3934
+ return convertBase64ToUint8Array(image.b64_json);
3935
+ }
3936
+ if (image.url == null) {
3937
+ throw new InvalidArgumentError({
3938
+ argument: "batchResult",
3939
+ message: "xAI returned an image without data or a URL."
3940
+ });
3941
+ }
3942
+ const { value } = await getFromApi2({
3943
+ url: image.url,
3944
+ validateUrl: true,
3945
+ trustedOrigin: this.options.config.baseURL,
3946
+ abortSignal,
3947
+ failedResponseHandler: xaiFailedResponseHandler,
3948
+ successfulResponseHandler: createBinaryResponseHandler2(),
3949
+ fetch: this.options.config.fetch
3950
+ });
3951
+ return value;
3952
+ })
3953
+ );
3954
+ return {
3955
+ images,
3956
+ warnings: [],
3957
+ response: { timestamp: /* @__PURE__ */ new Date(), modelId: "", headers: void 0 },
3958
+ providerMetadata: {
3959
+ xai: {
3960
+ images: response.data.map(
3961
+ (item) => item.revised_prompt != null ? { revisedPrompt: item.revised_prompt } : {}
3962
+ ),
3963
+ ...((_a = response.usage) == null ? void 0 : _a.cost_in_usd_ticks) != null ? { costInUsdTicks: response.usage.cost_in_usd_ticks } : {}
3964
+ }
3965
+ }
3966
+ };
3774
3967
  }
3775
3968
  getUrl(path) {
3776
3969
  var _a;
@@ -3836,6 +4029,17 @@ function invalidXaiBatchResult(id) {
3836
4029
  }
3837
4030
  };
3838
4031
  }
4032
+ function invalidXaiImageBatchResult(id) {
4033
+ return {
4034
+ type: "image",
4035
+ id,
4036
+ status: "failed",
4037
+ error: {
4038
+ message: "xAI returned an invalid image batch result.",
4039
+ code: "invalid_response"
4040
+ }
4041
+ };
4042
+ }
3839
4043
  function convertXaiChatBatchResponse(response) {
3840
4044
  var _a, _b, _c, _d, _e, _f;
3841
4045
  if (response.error != null) {
@@ -4358,7 +4562,7 @@ var xaiTools = {
4358
4562
  };
4359
4563
 
4360
4564
  // src/version.ts
4361
- var VERSION = true ? "4.0.56" : "0.0.0-test";
4565
+ var VERSION = true ? "4.0.58" : "0.0.0-test";
4362
4566
 
4363
4567
  // src/files/xai-files.ts
4364
4568
  import {
@@ -5152,8 +5356,8 @@ var xaiVideoStatusResponseHandler = async (options) => {
5152
5356
  // src/xai-speech-model.ts
5153
5357
  import {
5154
5358
  combineHeaders as combineHeaders7,
5155
- convertBase64ToUint8Array,
5156
- createBinaryResponseHandler as createBinaryResponseHandler2,
5359
+ convertBase64ToUint8Array as convertBase64ToUint8Array2,
5360
+ createBinaryResponseHandler as createBinaryResponseHandler3,
5157
5361
  createJsonResponseHandler as createJsonResponseHandler7,
5158
5362
  parseProviderOptions as parseProviderOptions9,
5159
5363
  postJsonToApi as postJsonToApi6,
@@ -5315,7 +5519,7 @@ var XaiSpeechModel = class _XaiSpeechModel {
5315
5519
  ),
5316
5520
  body: requestBody,
5317
5521
  failedResponseHandler: xaiFailedResponseHandler,
5318
- successfulResponseHandler: withTimestamps ? createJsonResponseHandler7(xaiSpeechTimestampsResponseSchema) : createBinaryResponseHandler2(),
5522
+ successfulResponseHandler: withTimestamps ? createJsonResponseHandler7(xaiSpeechTimestampsResponseSchema) : createBinaryResponseHandler3(),
5319
5523
  abortSignal: options.abortSignal,
5320
5524
  fetch: this.config.fetch
5321
5525
  });
@@ -5325,7 +5529,7 @@ var XaiSpeechModel = class _XaiSpeechModel {
5325
5529
  audio = value;
5326
5530
  } else {
5327
5531
  envelope = value;
5328
- audio = envelope.audio != null ? convertBase64ToUint8Array(envelope.audio) : new Uint8Array(0);
5532
+ audio = envelope.audio != null ? convertBase64ToUint8Array2(envelope.audio) : new Uint8Array(0);
5329
5533
  }
5330
5534
  const traceId = responseHeaders == null ? void 0 : responseHeaders["x-trace-id"];
5331
5535
  return {
@@ -5372,7 +5576,7 @@ import {
5372
5576
  } from "@ai-sdk/provider";
5373
5577
  import {
5374
5578
  combineHeaders as combineHeaders8,
5375
- convertBase64ToUint8Array as convertBase64ToUint8Array2,
5579
+ convertBase64ToUint8Array as convertBase64ToUint8Array3,
5376
5580
  createJsonResponseHandler as createJsonResponseHandler8,
5377
5581
  connectToWebSocket,
5378
5582
  mediaTypeToExtension,
@@ -5516,7 +5720,7 @@ var XaiTranscriptionModel = class _XaiTranscriptionModel {
5516
5720
  formData.append("keyterm", keyterm);
5517
5721
  }
5518
5722
  }
5519
- const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array2(audio)]);
5723
+ const blob = audio instanceof Uint8Array ? new Blob([audio]) : new Blob([convertBase64ToUint8Array3(audio)]);
5520
5724
  const fileExtension = mediaTypeToExtension(mediaType);
5521
5725
  formData.append(
5522
5726
  "file",
@@ -5675,7 +5879,7 @@ function createXaiStreamingTranscriptionStream({
5675
5879
  const { done, value } = await audioReader.read();
5676
5880
  if (done || finished) break;
5677
5881
  socket.send(
5678
- value instanceof Uint8Array ? value : convertBase64ToUint8Array2(value)
5882
+ value instanceof Uint8Array ? value : convertBase64ToUint8Array3(value)
5679
5883
  );
5680
5884
  await waitForWebSocketBufferDrain(socket);
5681
5885
  }