@ai-sdk/xai 4.0.0-beta.35 → 4.0.0-beta.37

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-sdk/xai",
3
- "version": "4.0.0-beta.35",
3
+ "version": "4.0.0-beta.37",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -29,9 +29,9 @@
29
29
  }
30
30
  },
31
31
  "dependencies": {
32
- "@ai-sdk/openai-compatible": "3.0.0-beta.24",
33
- "@ai-sdk/provider": "4.0.0-beta.11",
34
- "@ai-sdk/provider-utils": "5.0.0-beta.19"
32
+ "@ai-sdk/provider-utils": "5.0.0-beta.20",
33
+ "@ai-sdk/openai-compatible": "3.0.0-beta.25",
34
+ "@ai-sdk/provider": "4.0.0-beta.12"
35
35
  },
36
36
  "devDependencies": {
37
37
  "@types/node": "20.17.24",
@@ -135,7 +135,48 @@ export async function convertToXaiResponsesInput({
135
135
  break;
136
136
  }
137
137
 
138
- case 'reasoning':
138
+ case 'reasoning': {
139
+ const itemId =
140
+ typeof part.providerOptions?.xai?.itemId === 'string'
141
+ ? part.providerOptions.xai.itemId
142
+ : undefined;
143
+ const encryptedContent =
144
+ typeof part.providerOptions?.xai?.reasoningEncryptedContent ===
145
+ 'string'
146
+ ? part.providerOptions.xai.reasoningEncryptedContent
147
+ : undefined;
148
+
149
+ if (itemId != null || encryptedContent != null) {
150
+ const summaryParts: Array<{
151
+ type: 'summary_text';
152
+ text: string;
153
+ }> = [];
154
+ if (part.text.length > 0) {
155
+ summaryParts.push({
156
+ type: 'summary_text',
157
+ text: part.text,
158
+ });
159
+ }
160
+
161
+ input.push({
162
+ type: 'reasoning',
163
+ id: itemId ?? '',
164
+ summary: summaryParts,
165
+ status: 'completed',
166
+ ...(encryptedContent != null && {
167
+ encrypted_content: encryptedContent,
168
+ }),
169
+ });
170
+ } else {
171
+ inputWarnings.push({
172
+ type: 'other',
173
+ message:
174
+ 'Reasoning parts without itemId or encrypted content cannot be sent back to xAI. Skipping.',
175
+ });
176
+ }
177
+ break;
178
+ }
179
+
139
180
  case 'reasoning-file':
140
181
  case 'custom':
141
182
  case 'file': {
@@ -19,6 +19,9 @@ import {
19
19
  parseProviderOptions,
20
20
  ParseResult,
21
21
  postJsonToApi,
22
+ serializeModelOptions,
23
+ WORKFLOW_SERIALIZE,
24
+ WORKFLOW_DESERIALIZE,
22
25
  } from '@ai-sdk/provider-utils';
23
26
  import { z } from 'zod/v4';
24
27
  import { getResponseMetadata } from '../get-response-metadata';
@@ -40,7 +43,7 @@ import { prepareResponsesTools } from './xai-responses-prepare-tools';
40
43
  type XaiResponsesConfig = {
41
44
  provider: string;
42
45
  baseURL: string | undefined;
43
- headers: () => Record<string, string | undefined>;
46
+ headers?: () => Record<string, string | undefined>;
44
47
  generateId: () => string;
45
48
  fetch?: FetchFunction;
46
49
  };
@@ -52,6 +55,20 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
52
55
 
53
56
  private readonly config: XaiResponsesConfig;
54
57
 
58
+ static [WORKFLOW_SERIALIZE](model: XaiResponsesLanguageModel) {
59
+ return serializeModelOptions({
60
+ modelId: model.modelId,
61
+ config: model.config,
62
+ });
63
+ }
64
+
65
+ static [WORKFLOW_DESERIALIZE](options: {
66
+ modelId: XaiResponsesModelId;
67
+ config: XaiResponsesConfig;
68
+ }) {
69
+ return new XaiResponsesLanguageModel(options.modelId, options.config);
70
+ }
71
+
55
72
  constructor(modelId: XaiResponsesModelId, config: XaiResponsesConfig) {
56
73
  this.modelId = modelId;
57
74
  this.config = config;
@@ -113,7 +130,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
113
130
 
114
131
  const { input, inputWarnings } = await convertToXaiResponsesInput({
115
132
  prompt,
116
- store: true,
133
+ store: options.store ?? true,
117
134
  });
118
135
  warnings.push(...inputWarnings);
119
136
 
@@ -246,7 +263,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
246
263
  rawValue: rawResponse,
247
264
  } = await postJsonToApi({
248
265
  url: `${this.config.baseURL ?? 'https://api.x.ai/v1'}/responses`,
249
- headers: combineHeaders(this.config.headers(), options.headers),
266
+ headers: combineHeaders(this.config.headers?.(), options.headers),
250
267
  body,
251
268
  failedResponseHandler: xaiFailedResponseHandler,
252
269
  successfulResponseHandler: createJsonResponseHandler(
@@ -400,11 +417,13 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
400
417
  .filter(text => text && text.length > 0)
401
418
  .join('');
402
419
 
403
- if (reasoningText) {
404
- if (part.encrypted_content || part.id) {
405
- content.push({
406
- type: 'reasoning',
407
- text: reasoningText,
420
+ // condition changed here since encrypted content can now come with empty reasoning text
421
+ if (reasoningText || part.encrypted_content) {
422
+ const hasMetadata = part.encrypted_content || part.id;
423
+ content.push({
424
+ type: 'reasoning',
425
+ text: reasoningText,
426
+ ...(hasMetadata && {
408
427
  providerMetadata: {
409
428
  xai: {
410
429
  ...(part.encrypted_content && {
@@ -413,13 +432,8 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
413
432
  ...(part.id && { itemId: part.id }),
414
433
  },
415
434
  },
416
- });
417
- } else {
418
- content.push({
419
- type: 'reasoning',
420
- text: reasoningText,
421
- });
422
- }
435
+ }),
436
+ });
423
437
  }
424
438
  break;
425
439
  }
@@ -473,7 +487,7 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
473
487
 
474
488
  const { responseHeaders, value: response } = await postJsonToApi({
475
489
  url: `${this.config.baseURL ?? 'https://api.x.ai/v1'}/responses`,
476
- headers: combineHeaders(this.config.headers(), options.headers),
490
+ headers: combineHeaders(this.config.headers?.(), options.headers),
477
491
  body,
478
492
  failedResponseHandler: xaiFailedResponseHandler,
479
493
  successfulResponseHandler: createEventSourceResponseHandler(
@@ -25,6 +25,8 @@ export const xaiLanguageModelResponsesOptions = z.object({
25
25
  topLogprobs: z.number().int().min(0).max(8).optional(),
26
26
  /**
27
27
  * Whether to store the input message(s) and model response for later retrieval.
28
+ * Must be set to `false` for teams with Zero Data Retention (ZDR) enabled,
29
+ * otherwise the API will return an error.
28
30
  * @default true
29
31
  */
30
32
  store: z.boolean().optional(),
@@ -22,6 +22,9 @@ import {
22
22
  ParseResult,
23
23
  postJsonToApi,
24
24
  safeParseJSON,
25
+ serializeModelOptions,
26
+ WORKFLOW_SERIALIZE,
27
+ WORKFLOW_DESERIALIZE,
25
28
  } from '@ai-sdk/provider-utils';
26
29
  import { z } from 'zod/v4';
27
30
  import { convertToXaiChatMessages } from './convert-to-xai-chat-messages';
@@ -38,7 +41,7 @@ import { prepareTools } from './xai-prepare-tools';
38
41
  type XaiChatConfig = {
39
42
  provider: string;
40
43
  baseURL: string | undefined;
41
- headers: () => Record<string, string | undefined>;
44
+ headers?: () => Record<string, string | undefined>;
42
45
  generateId: () => string;
43
46
  fetch?: FetchFunction;
44
47
  };
@@ -50,6 +53,20 @@ export class XaiChatLanguageModel implements LanguageModelV4 {
50
53
 
51
54
  private readonly config: XaiChatConfig;
52
55
 
56
+ static [WORKFLOW_SERIALIZE](model: XaiChatLanguageModel) {
57
+ return serializeModelOptions({
58
+ modelId: model.modelId,
59
+ config: model.config,
60
+ });
61
+ }
62
+
63
+ static [WORKFLOW_DESERIALIZE](options: {
64
+ modelId: XaiChatModelId;
65
+ config: XaiChatConfig;
66
+ }) {
67
+ return new XaiChatLanguageModel(options.modelId, options.config);
68
+ }
69
+
53
70
  constructor(modelId: XaiChatModelId, config: XaiChatConfig) {
54
71
  this.modelId = modelId;
55
72
  this.config = config;
@@ -233,7 +250,7 @@ export class XaiChatLanguageModel implements LanguageModelV4 {
233
250
  rawValue: rawResponse,
234
251
  } = await postJsonToApi({
235
252
  url,
236
- headers: combineHeaders(this.config.headers(), options.headers),
253
+ headers: combineHeaders(this.config.headers?.(), options.headers),
237
254
  body,
238
255
  failedResponseHandler: xaiFailedResponseHandler,
239
256
  successfulResponseHandler: createJsonResponseHandler(
@@ -346,7 +363,7 @@ export class XaiChatLanguageModel implements LanguageModelV4 {
346
363
 
347
364
  const { responseHeaders, value: response } = await postJsonToApi({
348
365
  url,
349
- headers: combineHeaders(this.config.headers(), options.headers),
366
+ headers: combineHeaders(this.config.headers?.(), options.headers),
350
367
  body,
351
368
  failedResponseHandler: xaiFailedResponseHandler,
352
369
  successfulResponseHandler: async ({ response }) => {
@@ -9,6 +9,9 @@ import {
9
9
  getFromApi,
10
10
  parseProviderOptions,
11
11
  postJsonToApi,
12
+ serializeModelOptions,
13
+ WORKFLOW_SERIALIZE,
14
+ WORKFLOW_DESERIALIZE,
12
15
  } from '@ai-sdk/provider-utils';
13
16
  import { z } from 'zod/v4';
14
17
  import { xaiFailedResponseHandler } from './xai-error';
@@ -18,7 +21,7 @@ import { XaiImageModelId } from './xai-image-settings';
18
21
  interface XaiImageModelConfig {
19
22
  provider: string;
20
23
  baseURL: string | undefined;
21
- headers: () => Record<string, string | undefined>;
24
+ headers?: () => Record<string, string | undefined>;
22
25
  fetch?: FetchFunction;
23
26
  _internal?: {
24
27
  currentDate?: () => Date;
@@ -33,6 +36,20 @@ export class XaiImageModel implements ImageModelV4 {
33
36
  return this.config.provider;
34
37
  }
35
38
 
39
+ static [WORKFLOW_SERIALIZE](model: XaiImageModel) {
40
+ return serializeModelOptions({
41
+ modelId: model.modelId,
42
+ config: model.config,
43
+ });
44
+ }
45
+
46
+ static [WORKFLOW_DESERIALIZE](options: {
47
+ modelId: XaiImageModelId;
48
+ config: XaiImageModelConfig;
49
+ }) {
50
+ return new XaiImageModel(options.modelId, options.config);
51
+ }
52
+
36
53
  constructor(
37
54
  readonly modelId: XaiImageModelId,
38
55
  private config: XaiImageModelConfig,
@@ -135,7 +152,7 @@ export class XaiImageModel implements ImageModelV4 {
135
152
  const currentDate = this.config._internal?.currentDate?.() ?? new Date();
136
153
  const { value: response, responseHeaders } = await postJsonToApi({
137
154
  url: `${baseURL}${endpoint}`,
138
- headers: combineHeaders(this.config.headers(), headers),
155
+ headers: combineHeaders(this.config.headers?.(), headers),
139
156
  body,
140
157
  failedResponseHandler: xaiFailedResponseHandler,
141
158
  successfulResponseHandler: createJsonResponseHandler(