@ai-sdk/gateway 3.0.226 → 3.0.227

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.
@@ -1015,6 +1015,100 @@ for await (const part of result.fullStream) {
1015
1015
  }
1016
1016
  ```
1017
1017
 
1018
+ #### DeepSeek Search and Fetch
1019
+
1020
+ Use `gateway.tools.deepseekSearch()` to search the web and
1021
+ `gateway.tools.deepseekFetch()` to retrieve a page as Markdown. Both tools call
1022
+ DeepSeek's standalone Search/Fetch APIs from AI Gateway and work with supported
1023
+ tool-calling models from any provider. They are separate from a model's built-in
1024
+ web search. No additional model provider package is required.
1025
+
1026
+ ```ts
1027
+ import { gateway, generateText } from 'ai';
1028
+
1029
+ const result = await generateText({
1030
+ model: 'openai/gpt-6-luna',
1031
+ prompt: 'Search for DeepSeek API documentation and fetch a relevant page.',
1032
+ tools: {
1033
+ deepseek_search: gateway.tools.deepseekSearch({
1034
+ count: 5,
1035
+ needContent: true,
1036
+ }),
1037
+ deepseek_fetch: gateway.tools.deepseekFetch(),
1038
+ },
1039
+ });
1040
+
1041
+ console.log(result.text);
1042
+ console.log(result.toolResults);
1043
+ for (const part of result.content) {
1044
+ if (part.type === 'tool-error') console.error('Tool error:', part.error);
1045
+ }
1046
+ ```
1047
+
1048
+ The Search tool supports the following optional configuration options:
1049
+
1050
+ - **query** _string_
1051
+
1052
+ Pin the search query; otherwise the model chooses it. Queries contain 1–128 Unicode characters and cannot be all whitespace.
1053
+
1054
+ - **count** _number_
1055
+
1056
+ Number of results, 1–50 (default: 10).
1057
+
1058
+ - **needContent** _boolean_
1059
+
1060
+ Include available page content (default: false).
1061
+
1062
+ - **oriQuestion** _string | null_
1063
+
1064
+ Original question, 1–128 Unicode characters. `null` means not provided.
1065
+
1066
+ - **localization** _string_
1067
+
1068
+ IP address used to localize results; developer configuration only.
1069
+
1070
+ The model-facing input uses `query`, `count`, `need_content`, and `ori_question`.
1071
+ Queries support search operators including `site:`, `-site:`, `lang:`, `after:`,
1072
+ `before:`, and quoted phrases. Search returns `{ results }`, containing ranked
1073
+ URLs, titles, snippets, summaries, optional page content, and nullable site/date
1074
+ metadata. An empty `results` array is a successful search with no matches.
1075
+
1076
+ Fetch accepts an HTTP(S) `url` up to 8,192 characters, without a username or
1077
+ password, and returns `{ content, title? }`. The content is Markdown. You can
1078
+ pin the URL with `gateway.tools.deepseekFetch({ url: 'https://example.com' })`.
1079
+ The Fetch tool supports the following optional configuration option:
1080
+
1081
+ - **url** _string_
1082
+
1083
+ Pin the HTTP(S) URL; otherwise the model chooses it.
1084
+
1085
+ Tool failures appear as `tool-error` parts in `result.content` (for
1086
+ `generateText`) or `result.fullStream` (for `streamText`). Inspect `part.error`
1087
+ there; failures are not included in `result.toolResults`.
1088
+
1089
+ The tools also work with `streamText`:
1090
+
1091
+ ```ts
1092
+ import { gateway, streamText } from 'ai';
1093
+
1094
+ const result = streamText({
1095
+ model: 'openai/gpt-6-luna',
1096
+ prompt: 'Search for DeepSeek API documentation and fetch a relevant page.',
1097
+ tools: {
1098
+ deepseek_search: gateway.tools.deepseekSearch(),
1099
+ deepseek_fetch: gateway.tools.deepseekFetch(),
1100
+ },
1101
+ });
1102
+
1103
+ for await (const part of result.fullStream) {
1104
+ if (part.type === 'text-delta') process.stdout.write(part.text);
1105
+ if (part.type === 'tool-error') console.error('Tool error:', part.error);
1106
+ }
1107
+ ```
1108
+
1109
+ See the [DeepSeek API guide](https://api-docs.deepseek.com/guides/search/) for the
1110
+ underlying APIs.
1111
+
1018
1112
  ### Usage Tracking with User and Tags
1019
1113
 
1020
1114
  Track usage per end-user and categorize requests with tags:
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ai-sdk/gateway",
3
3
  "private": false,
4
- "version": "3.0.226",
4
+ "version": "3.0.227",
5
5
  "license": "Apache-2.0",
6
6
  "sideEffects": false,
7
7
  "main": "./dist/index.js",
@@ -31,6 +31,15 @@ export async function asGatewayError(
31
31
  error: unknown,
32
32
  authMethod?: 'api-key' | 'oidc',
33
33
  ) {
34
+ // Caller cancellation is not a gateway failure and must not become a retryable 500.
35
+ if (
36
+ (error instanceof Error ||
37
+ (typeof DOMException === 'function' && error instanceof DOMException)) &&
38
+ (error.name === 'AbortError' || error.name === 'TimeoutError')
39
+ ) {
40
+ throw error;
41
+ }
42
+
34
43
  if (GatewayError.isInstance(error)) {
35
44
  return error;
36
45
  }
@@ -59,7 +59,6 @@ export type GatewayModelId =
59
59
  | 'anthropic/claude-sonnet-5-batch'
60
60
  | 'anthropic/claude-sonnet-5.5'
61
61
  | 'anthropic/claude-sonnet-5.5-batch'
62
- | 'arcee-ai/trinity-large-thinking'
63
62
  | 'bytedance/seed-1.6'
64
63
  | 'bytedance/seed-1.8'
65
64
  | 'bytedance/seed-2.1-turbo'
@@ -125,7 +124,7 @@ export type GatewayModelId =
125
124
  | 'inference-net/schematron-v2-turbo'
126
125
  | 'interfaze/interfaze-beta'
127
126
  | 'liquid/lfm2.5-24b-a2b'
128
- | 'meituan/longcat-2.5-preview'
127
+ | 'meituan/longcat-2.5'
129
128
  | 'meta/llama-3.1-70b'
130
129
  | 'meta/llama-3.1-8b'
131
130
  | 'meta/llama-3.3-70b'
@@ -263,7 +262,6 @@ export type GatewayModelId =
263
262
  | 'particle/particle-1'
264
263
  | 'perplexity/sonar'
265
264
  | 'poolside/laguna-s-2.1'
266
- | 'poolside/laguna-s-2.1-free'
267
265
  | 'quiverai/arrow-2'
268
266
  | 'quiverai/arrow-2-telos'
269
267
  | 'reflection/beam'
@@ -320,5 +318,6 @@ export type GatewayModelId =
320
318
  | 'zai/glm-5.3-fast'
321
319
  | 'zai/glm-5.3-flash'
322
320
  | 'zai/glm-5.3-flashx'
321
+ | 'zai/glm-5.3-flashx-legal'
323
322
  | 'zai/glm-5v-turbo'
324
323
  | (string & {});
@@ -1,5 +1,7 @@
1
1
  import { browserbaseFetch } from './tool/browserbase-fetch';
2
2
  import { browserbaseSearch } from './tool/browserbase-search';
3
+ import { deepseekFetch } from './tool/deepseek-fetch';
4
+ import { deepseekSearch } from './tool/deepseek-search';
3
5
  import { exaSearch } from './tool/exa-search';
4
6
  import { parallelSearch } from './tool/parallel-search';
5
7
  import { perplexitySearch } from './tool/perplexity-search';
@@ -25,6 +27,18 @@ export const gatewayTools = {
25
27
  */
26
28
  browserbaseSearch,
27
29
 
30
+ /**
31
+ * Fetch a page as Markdown through DeepSeek's standalone Fetch API.
32
+ * Executed by AI Gateway for any model, separate from native model web search.
33
+ */
34
+ deepseekFetch,
35
+
36
+ /**
37
+ * Search the web through DeepSeek's standalone Search API.
38
+ * Executed by AI Gateway for any model, separate from native model web search.
39
+ */
40
+ deepseekSearch,
41
+
28
42
  /**
29
43
  * Search the web using Exa for current information and token-efficient
30
44
  * excerpts optimized for agent workflows.
@@ -0,0 +1,69 @@
1
+ import {
2
+ createProviderToolFactoryWithOutputSchema,
3
+ lazySchema,
4
+ zodSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod';
7
+ import {
8
+ gatewayToolErrorSchema,
9
+ type GatewayToolError,
10
+ } from './gateway-tool-error';
11
+
12
+ export interface DeepSeekFetchConfig {
13
+ /** Pin the target URL instead of allowing the model to choose it. */
14
+ url?: string;
15
+ }
16
+
17
+ export interface DeepSeekFetchInput {
18
+ url: string;
19
+ }
20
+
21
+ export interface DeepSeekFetchResponse {
22
+ title?: string | null;
23
+ /** Page content as Markdown. */
24
+ content: string;
25
+ }
26
+
27
+ export type DeepSeekFetchOutput = DeepSeekFetchResponse | GatewayToolError;
28
+
29
+ const deepseekFetchInputSchema = lazySchema(() =>
30
+ zodSchema(
31
+ z.object({
32
+ url: z
33
+ .string()
34
+ .describe(
35
+ 'URL to fetch, at most 8192 characters; HTTP(S) only, without a username or password.',
36
+ ),
37
+ }),
38
+ ),
39
+ );
40
+
41
+ const deepseekFetchOutputSchema = lazySchema(() =>
42
+ zodSchema(
43
+ z.union([
44
+ z
45
+ .object({
46
+ title: z.string().nullish(),
47
+ content: z.string(),
48
+ })
49
+ .passthrough(),
50
+ gatewayToolErrorSchema(),
51
+ ]),
52
+ ),
53
+ );
54
+
55
+ export const deepseekFetchToolFactory =
56
+ createProviderToolFactoryWithOutputSchema<
57
+ DeepSeekFetchInput,
58
+ DeepSeekFetchOutput,
59
+ DeepSeekFetchConfig
60
+ >({
61
+ id: 'gateway.deepseek_fetch',
62
+ inputSchema: deepseekFetchInputSchema,
63
+ outputSchema: deepseekFetchOutputSchema,
64
+ });
65
+
66
+ export const deepseekFetch = (
67
+ config: DeepSeekFetchConfig = {},
68
+ ): ReturnType<typeof deepseekFetchToolFactory> =>
69
+ deepseekFetchToolFactory(config);
@@ -0,0 +1,119 @@
1
+ import {
2
+ createProviderToolFactoryWithOutputSchema,
3
+ lazySchema,
4
+ zodSchema,
5
+ } from '@ai-sdk/provider-utils';
6
+ import { z } from 'zod';
7
+ import {
8
+ gatewayToolErrorSchema,
9
+ type GatewayToolError,
10
+ } from './gateway-tool-error';
11
+
12
+ export interface DeepSeekSearchConfig {
13
+ /** Pin the query instead of allowing the model to choose it. */
14
+ query?: string;
15
+ /** Maximum number of results, 1–50 (default: 10). */
16
+ count?: number;
17
+ /** Include available page content (default: false). */
18
+ needContent?: boolean;
19
+ /** Original question, 1–128 Unicode characters; null means absent. */
20
+ oriQuestion?: string | null;
21
+ /** Developer-configured IP address for result localization. */
22
+ localization?: string;
23
+ }
24
+
25
+ export interface DeepSeekSearchInput {
26
+ query: string;
27
+ count?: number;
28
+ need_content?: boolean;
29
+ ori_question?: string | null;
30
+ }
31
+
32
+ export interface DeepSeekSearchResult {
33
+ authority?: number | null;
34
+ content?: string | null;
35
+ date?: string | null;
36
+ rerank_score?: number | null;
37
+ site_icon?: string | null;
38
+ site_name?: string | null;
39
+ snippet?: string | null;
40
+ summary?: string | null;
41
+ title?: string | null;
42
+ url?: string | null;
43
+ }
44
+
45
+ export interface DeepSeekSearchResponse {
46
+ results: DeepSeekSearchResult[];
47
+ }
48
+
49
+ export type DeepSeekSearchOutput = DeepSeekSearchResponse | GatewayToolError;
50
+
51
+ const deepseekSearchInputSchema = lazySchema(() =>
52
+ zodSchema(
53
+ z.object({
54
+ query: z
55
+ .string()
56
+ .describe(
57
+ 'Web search query, 1 to 128 Unicode characters. Supports site:, -site:, lang:, after:, before:, and quoted phrases.',
58
+ ),
59
+ count: z
60
+ .number()
61
+ .int()
62
+ .optional()
63
+ .describe('Number of results, 1 to 50 (default: 10).'),
64
+ need_content: z
65
+ .boolean()
66
+ .optional()
67
+ .describe('Include available page content (default: false).'),
68
+ ori_question: z
69
+ .string()
70
+ .nullable()
71
+ .optional()
72
+ .describe('Original user question, 1 to 128 Unicode characters.'),
73
+ }),
74
+ ),
75
+ );
76
+
77
+ const deepseekSearchOutputSchema = lazySchema(() =>
78
+ zodSchema(
79
+ z.union([
80
+ z
81
+ .object({
82
+ results: z.array(
83
+ z
84
+ .object({
85
+ authority: z.number().nullish(),
86
+ content: z.string().nullish(),
87
+ date: z.string().nullish(),
88
+ rerank_score: z.number().nullish(),
89
+ site_icon: z.string().nullish(),
90
+ site_name: z.string().nullish(),
91
+ snippet: z.string().nullish(),
92
+ summary: z.string().nullish(),
93
+ title: z.string().nullish(),
94
+ url: z.string().nullish(),
95
+ })
96
+ .passthrough(),
97
+ ),
98
+ })
99
+ .passthrough(),
100
+ gatewayToolErrorSchema(),
101
+ ]),
102
+ ),
103
+ );
104
+
105
+ export const deepseekSearchToolFactory =
106
+ createProviderToolFactoryWithOutputSchema<
107
+ DeepSeekSearchInput,
108
+ DeepSeekSearchOutput,
109
+ DeepSeekSearchConfig
110
+ >({
111
+ id: 'gateway.deepseek_search',
112
+ inputSchema: deepseekSearchInputSchema,
113
+ outputSchema: deepseekSearchOutputSchema,
114
+ });
115
+
116
+ export const deepseekSearch = (
117
+ config: DeepSeekSearchConfig = {},
118
+ ): ReturnType<typeof deepseekSearchToolFactory> =>
119
+ deepseekSearchToolFactory(config);
@@ -0,0 +1,39 @@
1
+ import { z } from 'zod';
2
+
3
+ export interface GatewayToolError {
4
+ error:
5
+ | 'api_error'
6
+ | 'configuration_error'
7
+ | 'execution_error'
8
+ | 'gateway_rate_limit'
9
+ | 'invalid_input'
10
+ | 'rate_limit'
11
+ | 'timeout'
12
+ | 'unknown'
13
+ | 'unknown_tool';
14
+ message: string;
15
+ statusCode?: number;
16
+ retryAfter?: string;
17
+ statusText?: string;
18
+ }
19
+
20
+ export const gatewayToolErrorSchema = () =>
21
+ z
22
+ .object({
23
+ error: z.enum([
24
+ 'api_error',
25
+ 'configuration_error',
26
+ 'execution_error',
27
+ 'gateway_rate_limit',
28
+ 'invalid_input',
29
+ 'rate_limit',
30
+ 'timeout',
31
+ 'unknown',
32
+ 'unknown_tool',
33
+ ]),
34
+ message: z.string(),
35
+ statusCode: z.number().optional(),
36
+ retryAfter: z.string().optional(),
37
+ statusText: z.string().optional(),
38
+ })
39
+ .passthrough();
@@ -4,6 +4,10 @@ import {
4
4
  zodSchema,
5
5
  } from '@ai-sdk/provider-utils';
6
6
  import { z } from 'zod';
7
+ import {
8
+ gatewayToolErrorSchema,
9
+ type GatewayToolError,
10
+ } from './gateway-tool-error';
7
11
 
8
12
  const parallelSearchModes = [
9
13
  'turbo',
@@ -153,23 +157,7 @@ export interface ParallelSearchResponse {
153
157
  session_id?: string;
154
158
  }
155
159
 
156
- export interface ParallelSearchError {
157
- /** Error type */
158
- error:
159
- | 'api_error'
160
- | 'configuration_error'
161
- | 'execution_error'
162
- | 'gateway_rate_limit'
163
- | 'invalid_input'
164
- | 'rate_limit'
165
- | 'timeout'
166
- | 'unknown'
167
- | 'unknown_tool';
168
- /** HTTP status code if applicable */
169
- statusCode?: number;
170
- /** Human-readable error message */
171
- message: string;
172
- }
160
+ export type ParallelSearchError = GatewayToolError;
173
161
 
174
162
  export interface ParallelSearchInput {
175
163
  /**
@@ -375,21 +363,7 @@ const parallelSearchOutputSchema = lazySchema(() =>
375
363
  session_id: z.string().optional(),
376
364
  }),
377
365
  // Error response
378
- z.object({
379
- error: z.enum([
380
- 'api_error',
381
- 'configuration_error',
382
- 'execution_error',
383
- 'gateway_rate_limit',
384
- 'invalid_input',
385
- 'rate_limit',
386
- 'timeout',
387
- 'unknown',
388
- 'unknown_tool',
389
- ]),
390
- statusCode: z.number().optional(),
391
- message: z.string(),
392
- }),
366
+ gatewayToolErrorSchema(),
393
367
  ]),
394
368
  ),
395
369
  );
@@ -4,6 +4,10 @@ import {
4
4
  zodSchema,
5
5
  } from '@ai-sdk/provider-utils';
6
6
  import { z } from 'zod';
7
+ import {
8
+ gatewayToolErrorSchema,
9
+ type GatewayToolError,
10
+ } from './gateway-tool-error';
7
11
 
8
12
  export type TakoSearchEffort = 'deep' | 'fast' | 'instant';
9
13
 
@@ -246,18 +250,7 @@ export interface TakoSearchResponse {
246
250
  related?: Array<Record<string, unknown>> | null;
247
251
  }
248
252
 
249
- export interface TakoSearchError {
250
- error:
251
- | 'api_error'
252
- | 'configuration_error'
253
- | 'execution_error'
254
- | 'invalid_input'
255
- | 'rate_limit'
256
- | 'timeout'
257
- | 'unknown_tool';
258
- statusCode?: number;
259
- message: string;
260
- }
253
+ export type TakoSearchError = GatewayToolError;
261
254
 
262
255
  export type TakoSearchOutput = TakoSearchError | TakoSearchResponse;
263
256
 
@@ -570,19 +563,7 @@ const takoSearchOutputSchema = lazySchema(() =>
570
563
  related: z.array(z.object({}).passthrough()).nullish(),
571
564
  })
572
565
  .passthrough(),
573
- z.object({
574
- error: z.enum([
575
- 'api_error',
576
- 'configuration_error',
577
- 'execution_error',
578
- 'invalid_input',
579
- 'rate_limit',
580
- 'timeout',
581
- 'unknown_tool',
582
- ]),
583
- statusCode: z.number().optional(),
584
- message: z.string(),
585
- }),
566
+ gatewayToolErrorSchema(),
586
567
  ]),
587
568
  ),
588
569
  );