@ai-sdk/xai 4.0.47 → 4.0.48

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.47",
3
+ "version": "4.0.48",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
@@ -168,6 +168,31 @@ const toolCallSchema = z.object({
168
168
  action: z.any().optional(),
169
169
  });
170
170
 
171
+ export const webSearchWireSourceSchema = z.object({
172
+ type: z.literal('url'),
173
+ url: z.string(),
174
+ });
175
+
176
+ export const webSearchWireActionSchema = z.discriminatedUnion('type', [
177
+ z.object({
178
+ type: z.literal('search'),
179
+ query: z.string().nullish(),
180
+ queries: z.array(z.string()).nullish(),
181
+ sources: z.array(z.unknown()).nullish(),
182
+ }),
183
+ z.object({
184
+ type: z.literal('open_page'),
185
+ url: z.string().nullish(),
186
+ sources: z.array(z.unknown()).nullish(),
187
+ }),
188
+ z.object({
189
+ type: z.literal('find_in_page'),
190
+ url: z.string().nullish(),
191
+ pattern: z.string().nullish(),
192
+ sources: z.array(z.unknown()).nullish(),
193
+ }),
194
+ ]);
195
+
171
196
  const mcpCallSchema = z.object({
172
197
  name: z.string().optional(),
173
198
  arguments: z.string().optional(),
@@ -22,16 +22,20 @@ import {
22
22
  WORKFLOW_SERIALIZE,
23
23
  WORKFLOW_DESERIALIZE,
24
24
  type FetchFunction,
25
+ type InferSchema,
25
26
  type ParseResult,
26
27
  } from '@ai-sdk/provider-utils';
27
28
  import type { z } from 'zod/v4';
28
29
  import { getResponseMetadata } from '../get-response-metadata';
29
30
  import { supportsReasoningEffort } from '../supports-reasoning-effort';
31
+ import type { webSearchOutputSchema } from '../tool/web-search';
30
32
  import { xaiFailedResponseHandler } from '../xai-error';
31
33
  import { convertToXaiResponsesInput } from './convert-to-xai-responses-input';
32
34
  import { convertXaiResponsesUsage } from './convert-xai-responses-usage';
33
35
  import { mapXaiResponsesFinishReason } from './map-xai-responses-finish-reason';
34
36
  import {
37
+ webSearchWireActionSchema,
38
+ webSearchWireSourceSchema,
35
39
  xaiResponsesChunkSchema,
36
40
  xaiResponsesResponseSchema,
37
41
  type XaiResponsesIncludeOptions,
@@ -522,6 +526,15 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
522
526
  providerExecuted: true,
523
527
  });
524
528
 
529
+ if (part.type === 'web_search_call') {
530
+ content.push({
531
+ type: 'tool-result',
532
+ toolCallId: part.id,
533
+ toolName,
534
+ result: mapWebSearchAction(part.action),
535
+ });
536
+ }
537
+
525
538
  continue;
526
539
  }
527
540
 
@@ -1239,7 +1252,10 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
1239
1252
  type: 'tool-result',
1240
1253
  toolCallId: part.id,
1241
1254
  toolName,
1242
- result: {},
1255
+ result:
1256
+ part.type === 'web_search_call'
1257
+ ? mapWebSearchAction(part.action)
1258
+ : {},
1243
1259
  });
1244
1260
  }
1245
1261
 
@@ -1357,3 +1373,36 @@ export class XaiResponsesLanguageModel implements LanguageModelV4 {
1357
1373
  };
1358
1374
  }
1359
1375
  }
1376
+
1377
+ function mapWebSearchAction(
1378
+ action: unknown,
1379
+ ): InferSchema<typeof webSearchOutputSchema> {
1380
+ const parsed = webSearchWireActionSchema.safeParse(action);
1381
+ if (!parsed.success) return {};
1382
+
1383
+ const a = parsed.data;
1384
+ const sources = a.sources?.flatMap(s => {
1385
+ const source = webSearchWireSourceSchema.safeParse(s);
1386
+ return source.success ? [source.data] : [];
1387
+ });
1388
+ const sourcesExtra = sources != null && sources.length > 0 ? { sources } : {};
1389
+
1390
+ switch (a.type) {
1391
+ case 'search':
1392
+ return {
1393
+ action: {
1394
+ type: 'search',
1395
+ ...(a.query != null && { query: a.query }),
1396
+ ...(a.queries != null && { queries: a.queries }),
1397
+ },
1398
+ ...sourcesExtra,
1399
+ };
1400
+ case 'open_page':
1401
+ return { action: { type: 'openPage', url: a.url }, ...sourcesExtra };
1402
+ case 'find_in_page':
1403
+ return {
1404
+ action: { type: 'findInPage', url: a.url, pattern: a.pattern },
1405
+ ...sourcesExtra,
1406
+ };
1407
+ }
1408
+ }
@@ -16,17 +16,30 @@ export const webSearchArgsSchema = lazySchema(() =>
16
16
  ),
17
17
  );
18
18
 
19
- const webSearchOutputSchema = lazySchema(() =>
19
+ export const webSearchOutputSchema = lazySchema(() =>
20
20
  zodSchema(
21
21
  z.object({
22
- query: z.string(),
23
- sources: z.array(
24
- z.object({
25
- title: z.string(),
26
- url: z.string(),
27
- snippet: z.string(),
28
- }),
29
- ),
22
+ action: z
23
+ .discriminatedUnion('type', [
24
+ z.object({
25
+ type: z.literal('search'),
26
+ query: z.string().optional(),
27
+ queries: z.array(z.string()).optional(),
28
+ }),
29
+ z.object({
30
+ type: z.literal('openPage'),
31
+ url: z.string().nullish(),
32
+ }),
33
+ z.object({
34
+ type: z.literal('findInPage'),
35
+ url: z.string().nullish(),
36
+ pattern: z.string().nullish(),
37
+ }),
38
+ ])
39
+ .optional(),
40
+ sources: z
41
+ .array(z.object({ type: z.literal('url'), url: z.string() }))
42
+ .optional(),
30
43
  }),
31
44
  ),
32
45
  );
@@ -34,12 +47,22 @@ const webSearchOutputSchema = lazySchema(() =>
34
47
  const webSearchToolFactory = createProviderExecutedToolFactory<
35
48
  {},
36
49
  {
37
- query: string;
38
- sources: Array<{
39
- title: string;
40
- url: string;
41
- snippet: string;
42
- }>;
50
+ action?:
51
+ | {
52
+ type: 'search';
53
+ query?: string;
54
+ queries?: string[];
55
+ }
56
+ | {
57
+ type: 'openPage';
58
+ url?: string | null;
59
+ }
60
+ | {
61
+ type: 'findInPage';
62
+ url?: string | null;
63
+ pattern?: string | null;
64
+ };
65
+ sources?: Array<{ type: 'url'; url: string }>;
43
66
  },
44
67
  {
45
68
  allowedDomains?: string[];