@ai-sdk/xai 3.0.11 → 3.0.13

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,17 @@
1
1
  # @ai-sdk/xai
2
2
 
3
+ ## 3.0.13
4
+
5
+ ### Patch Changes
6
+
7
+ - 7ac2437: fix(provider/xai): send reasoning-end before text-start in streaming
8
+
9
+ ## 3.0.12
10
+
11
+ ### Patch Changes
12
+
13
+ - e7bdbc7: fix(provider/xai): handle error responses returned with 200 status
14
+
3
15
  ## 3.0.11
4
16
 
5
17
  ### Patch Changes
package/dist/index.js CHANGED
@@ -34,10 +34,11 @@ module.exports = __toCommonJS(src_exports);
34
34
 
35
35
  // src/xai-provider.ts
36
36
  var import_openai_compatible = require("@ai-sdk/openai-compatible");
37
- var import_provider4 = require("@ai-sdk/provider");
37
+ var import_provider5 = require("@ai-sdk/provider");
38
38
  var import_provider_utils11 = require("@ai-sdk/provider-utils");
39
39
 
40
40
  // src/xai-chat-language-model.ts
41
+ var import_provider3 = require("@ai-sdk/provider");
41
42
  var import_provider_utils3 = require("@ai-sdk/provider-utils");
42
43
  var import_v43 = require("zod/v4");
43
44
 
@@ -488,12 +489,13 @@ var XaiChatLanguageModel = class {
488
489
  async doGenerate(options) {
489
490
  var _a, _b;
490
491
  const { args: body, warnings } = await this.getArgs(options);
492
+ const url = `${(_a = this.config.baseURL) != null ? _a : "https://api.x.ai/v1"}/chat/completions`;
491
493
  const {
492
494
  responseHeaders,
493
495
  value: response,
494
496
  rawValue: rawResponse
495
497
  } = await (0, import_provider_utils3.postJsonToApi)({
496
- url: `${(_a = this.config.baseURL) != null ? _a : "https://api.x.ai/v1"}/chat/completions`,
498
+ url,
497
499
  headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers),
498
500
  body,
499
501
  failedResponseHandler: xaiFailedResponseHandler,
@@ -503,6 +505,17 @@ var XaiChatLanguageModel = class {
503
505
  abortSignal: options.abortSignal,
504
506
  fetch: this.config.fetch
505
507
  });
508
+ if (response.error != null) {
509
+ throw new import_provider3.APICallError({
510
+ message: response.error,
511
+ url,
512
+ requestBodyValues: body,
513
+ statusCode: 200,
514
+ responseHeaders,
515
+ responseBody: JSON.stringify(rawResponse),
516
+ isRetryable: response.code === "The service is currently unavailable"
517
+ });
518
+ }
506
519
  const choice = response.choices[0];
507
520
  const content = [];
508
521
  if (choice.message.content != null && choice.message.content.length > 0) {
@@ -532,12 +545,12 @@ var XaiChatLanguageModel = class {
532
545
  }
533
546
  }
534
547
  if (response.citations != null) {
535
- for (const url of response.citations) {
548
+ for (const url2 of response.citations) {
536
549
  content.push({
537
550
  type: "source",
538
551
  sourceType: "url",
539
552
  id: this.config.generateId(),
540
- url
553
+ url: url2
541
554
  });
542
555
  }
543
556
  }
@@ -548,6 +561,7 @@ var XaiChatLanguageModel = class {
548
561
  raw: (_b = choice.finish_reason) != null ? _b : void 0
549
562
  },
550
563
  usage: convertXaiChatUsage(response.usage),
564
+ // defined when there is no error
551
565
  request: { body },
552
566
  response: {
553
567
  ...getResponseMetadata(response),
@@ -567,12 +581,47 @@ var XaiChatLanguageModel = class {
567
581
  include_usage: true
568
582
  }
569
583
  };
584
+ const url = `${(_a = this.config.baseURL) != null ? _a : "https://api.x.ai/v1"}/chat/completions`;
570
585
  const { responseHeaders, value: response } = await (0, import_provider_utils3.postJsonToApi)({
571
- url: `${(_a = this.config.baseURL) != null ? _a : "https://api.x.ai/v1"}/chat/completions`,
586
+ url,
572
587
  headers: (0, import_provider_utils3.combineHeaders)(this.config.headers(), options.headers),
573
588
  body,
574
589
  failedResponseHandler: xaiFailedResponseHandler,
575
- successfulResponseHandler: (0, import_provider_utils3.createEventSourceResponseHandler)(xaiChatChunkSchema),
590
+ successfulResponseHandler: async ({ response: response2 }) => {
591
+ const responseHeaders2 = (0, import_provider_utils3.extractResponseHeaders)(response2);
592
+ const contentType = response2.headers.get("content-type");
593
+ if (contentType == null ? void 0 : contentType.includes("application/json")) {
594
+ const responseBody = await response2.text();
595
+ const parsedError = await (0, import_provider_utils3.safeParseJSON)({
596
+ text: responseBody,
597
+ schema: xaiStreamErrorSchema
598
+ });
599
+ if (parsedError.success) {
600
+ throw new import_provider3.APICallError({
601
+ message: parsedError.value.error,
602
+ url,
603
+ requestBodyValues: body,
604
+ statusCode: 200,
605
+ responseHeaders: responseHeaders2,
606
+ responseBody,
607
+ isRetryable: parsedError.value.code === "The service is currently unavailable"
608
+ });
609
+ }
610
+ throw new import_provider3.APICallError({
611
+ message: "Invalid JSON response",
612
+ url,
613
+ requestBodyValues: body,
614
+ statusCode: 200,
615
+ responseHeaders: responseHeaders2,
616
+ responseBody
617
+ });
618
+ }
619
+ return (0, import_provider_utils3.createEventSourceResponseHandler)(xaiChatChunkSchema)({
620
+ response: response2,
621
+ url,
622
+ requestBodyValues: body
623
+ });
624
+ },
576
625
  abortSignal: options.abortSignal,
577
626
  fetch: this.config.fetch
578
627
  });
@@ -584,6 +633,7 @@ var XaiChatLanguageModel = class {
584
633
  let isFirstChunk = true;
585
634
  const contentBlocks = {};
586
635
  const lastReasoningDeltas = {};
636
+ let activeReasoningBlockId = void 0;
587
637
  const self = this;
588
638
  return {
589
639
  stream: response.pipeThrough(
@@ -608,12 +658,12 @@ var XaiChatLanguageModel = class {
608
658
  isFirstChunk = false;
609
659
  }
610
660
  if (value.citations != null) {
611
- for (const url of value.citations) {
661
+ for (const url2 of value.citations) {
612
662
  controller.enqueue({
613
663
  type: "source",
614
664
  sourceType: "url",
615
665
  id: self.config.generateId(),
616
- url
666
+ url: url2
617
667
  });
618
668
  }
619
669
  }
@@ -634,13 +684,21 @@ var XaiChatLanguageModel = class {
634
684
  const choiceIndex = choice.index;
635
685
  if (delta.content != null && delta.content.length > 0) {
636
686
  const textContent = delta.content;
687
+ if (activeReasoningBlockId != null && !contentBlocks[activeReasoningBlockId].ended) {
688
+ controller.enqueue({
689
+ type: "reasoning-end",
690
+ id: activeReasoningBlockId
691
+ });
692
+ contentBlocks[activeReasoningBlockId].ended = true;
693
+ activeReasoningBlockId = void 0;
694
+ }
637
695
  const lastMessage = body.messages[body.messages.length - 1];
638
696
  if ((lastMessage == null ? void 0 : lastMessage.role) === "assistant" && textContent === lastMessage.content) {
639
697
  return;
640
698
  }
641
699
  const blockId = `text-${value.id || choiceIndex}`;
642
700
  if (contentBlocks[blockId] == null) {
643
- contentBlocks[blockId] = { type: "text" };
701
+ contentBlocks[blockId] = { type: "text", ended: false };
644
702
  controller.enqueue({
645
703
  type: "text-start",
646
704
  id: blockId
@@ -659,7 +717,8 @@ var XaiChatLanguageModel = class {
659
717
  }
660
718
  lastReasoningDeltas[blockId] = delta.reasoning_content;
661
719
  if (contentBlocks[blockId] == null) {
662
- contentBlocks[blockId] = { type: "reasoning" };
720
+ contentBlocks[blockId] = { type: "reasoning", ended: false };
721
+ activeReasoningBlockId = blockId;
663
722
  controller.enqueue({
664
723
  type: "reasoning-start",
665
724
  id: blockId
@@ -672,6 +731,14 @@ var XaiChatLanguageModel = class {
672
731
  });
673
732
  }
674
733
  if (delta.tool_calls != null) {
734
+ if (activeReasoningBlockId != null && !contentBlocks[activeReasoningBlockId].ended) {
735
+ controller.enqueue({
736
+ type: "reasoning-end",
737
+ id: activeReasoningBlockId
738
+ });
739
+ contentBlocks[activeReasoningBlockId].ended = true;
740
+ activeReasoningBlockId = void 0;
741
+ }
675
742
  for (const toolCall of delta.tool_calls) {
676
743
  const toolCallId = toolCall.id;
677
744
  controller.enqueue({
@@ -699,10 +766,12 @@ var XaiChatLanguageModel = class {
699
766
  },
700
767
  flush(controller) {
701
768
  for (const [blockId, block] of Object.entries(contentBlocks)) {
702
- controller.enqueue({
703
- type: block.type === "text" ? "text-end" : "reasoning-end",
704
- id: blockId
705
- });
769
+ if (!block.ended) {
770
+ controller.enqueue({
771
+ type: block.type === "text" ? "text-end" : "reasoning-end",
772
+ id: blockId
773
+ });
774
+ }
706
775
  }
707
776
  controller.enqueue({ type: "finish", finishReason, usage });
708
777
  }
@@ -754,10 +823,12 @@ var xaiChatResponseSchema = import_v43.z.object({
754
823
  index: import_v43.z.number(),
755
824
  finish_reason: import_v43.z.string().nullish()
756
825
  })
757
- ),
758
- object: import_v43.z.literal("chat.completion"),
759
- usage: xaiUsageSchema,
760
- citations: import_v43.z.array(import_v43.z.string().url()).nullish()
826
+ ).nullish(),
827
+ object: import_v43.z.literal("chat.completion").nullish(),
828
+ usage: xaiUsageSchema.nullish(),
829
+ citations: import_v43.z.array(import_v43.z.string().url()).nullish(),
830
+ code: import_v43.z.string().nullish(),
831
+ error: import_v43.z.string().nullish()
761
832
  });
762
833
  var xaiChatChunkSchema = import_v43.z.object({
763
834
  id: import_v43.z.string().nullish(),
@@ -787,6 +858,10 @@ var xaiChatChunkSchema = import_v43.z.object({
787
858
  usage: xaiUsageSchema.nullish(),
788
859
  citations: import_v43.z.array(import_v43.z.string().url()).nullish()
789
860
  });
861
+ var xaiStreamErrorSchema = import_v43.z.object({
862
+ code: import_v43.z.string(),
863
+ error: import_v43.z.string()
864
+ });
790
865
 
791
866
  // src/responses/xai-responses-language-model.ts
792
867
  var import_provider_utils7 = require("@ai-sdk/provider-utils");
@@ -1284,7 +1359,7 @@ var xaiResponsesProviderOptions = import_v45.z.object({
1284
1359
  });
1285
1360
 
1286
1361
  // src/responses/xai-responses-prepare-tools.ts
1287
- var import_provider3 = require("@ai-sdk/provider");
1362
+ var import_provider4 = require("@ai-sdk/provider");
1288
1363
  var import_provider_utils6 = require("@ai-sdk/provider-utils");
1289
1364
 
1290
1365
  // src/tool/web-search.ts
@@ -1528,7 +1603,7 @@ async function prepareResponsesTools({
1528
1603
  }
1529
1604
  default: {
1530
1605
  const _exhaustiveCheck = type;
1531
- throw new import_provider3.UnsupportedFunctionalityError({
1606
+ throw new import_provider4.UnsupportedFunctionalityError({
1532
1607
  functionality: `tool choice type: ${_exhaustiveCheck}`
1533
1608
  });
1534
1609
  }
@@ -2055,7 +2130,7 @@ var xaiTools = {
2055
2130
  };
2056
2131
 
2057
2132
  // src/version.ts
2058
- var VERSION = true ? "3.0.11" : "0.0.0-test";
2133
+ var VERSION = true ? "3.0.13" : "0.0.0-test";
2059
2134
 
2060
2135
  // src/xai-provider.ts
2061
2136
  var xaiErrorStructure = {
@@ -2111,7 +2186,7 @@ function createXai(options = {}) {
2111
2186
  provider.chat = createChatLanguageModel;
2112
2187
  provider.responses = createResponsesLanguageModel;
2113
2188
  provider.embeddingModel = (modelId) => {
2114
- throw new import_provider4.NoSuchModelError({ modelId, modelType: "embeddingModel" });
2189
+ throw new import_provider5.NoSuchModelError({ modelId, modelType: "embeddingModel" });
2115
2190
  };
2116
2191
  provider.textEmbeddingModel = provider.embeddingModel;
2117
2192
  provider.imageModel = createImageModel;