@ai-sdk/gateway 4.0.92 → 4.0.95

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.
@@ -985,6 +985,132 @@ token-efficient content controls. Deep synthesis modes and generated summaries
985
985
  are intentionally not exposed yet because they have separate pricing from
986
986
  standard Search.
987
987
 
988
+ #### Browserbase Search
989
+
990
+ The Browserbase Search tool enables models to search the web using [Browserbase's Search API](https://docs.browserbase.com/reference/api/web-search). It is executed by AI Gateway and returns fast, structured search results without opening a browser session.
991
+
992
+ ```ts
993
+ import { gateway, generateText } from 'ai';
994
+
995
+ const result = await generateText({
996
+ model: 'openai/gpt-5.6-luna',
997
+ prompt:
998
+ 'Find official guidance on traveling with power banks on U.S. flights. Return the most relevant page titles and URLs.',
999
+ tools: {
1000
+ browserbase_search: gateway.tools.browserbaseSearch(),
1001
+ },
1002
+ });
1003
+
1004
+ console.log(result.text);
1005
+ console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2));
1006
+ console.log('Tool results:', JSON.stringify(result.toolResults, null, 2));
1007
+ ```
1008
+
1009
+ You can configure the maximum number of results returned by each search:
1010
+
1011
+ ```ts
1012
+ import { gateway, generateText } from 'ai';
1013
+
1014
+ const result = await generateText({
1015
+ model: 'openai/gpt-5.6-luna',
1016
+ prompt:
1017
+ 'Find three recent reviews comparing e-readers for outdoor reading. Return their titles and URLs.',
1018
+ tools: {
1019
+ browserbase_search: gateway.tools.browserbaseSearch({
1020
+ numResults: 3,
1021
+ }),
1022
+ },
1023
+ });
1024
+
1025
+ console.log(result.text);
1026
+ ```
1027
+
1028
+ The Browserbase Search tool supports this optional configuration option:
1029
+
1030
+ - **numResults** _number_
1031
+
1032
+ Maximum number of search results to return (1-25, default: 10).
1033
+
1034
+ The tool works with both `generateText` and `streamText`.
1035
+
1036
+ #### Browserbase Fetch
1037
+
1038
+ The Browserbase Fetch tool enables models to retrieve page content using [Browserbase's Fetch API](https://docs.browserbase.com/platform/fetch/overview). It is a lightweight option for pages that do not require JavaScript execution or browser interaction, and it supports raw, Markdown, and schema-driven JSON output.
1039
+
1040
+ ```ts
1041
+ import { gateway, generateText } from 'ai';
1042
+
1043
+ const result = await generateText({
1044
+ model: 'openai/gpt-5.6-luna',
1045
+ prompt:
1046
+ 'Fetch https://www.nps.gov/yose/planyourvisit/halfdome.htm and summarize the permit requirements and main safety warnings.',
1047
+ tools: {
1048
+ browserbase_fetch: gateway.tools.browserbaseFetch(),
1049
+ },
1050
+ });
1051
+
1052
+ console.log(result.text);
1053
+ console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2));
1054
+ console.log('Tool results:', JSON.stringify(result.toolResults, null, 2));
1055
+ ```
1056
+
1057
+ You can configure the output format and request behavior. For example, use JSON extraction to return content matching a JSON Schema:
1058
+
1059
+ ```ts
1060
+ import { gateway, generateText } from 'ai';
1061
+
1062
+ const result = await generateText({
1063
+ model: 'openai/gpt-5.6-luna',
1064
+ prompt:
1065
+ 'Fetch https://www.nps.gov/yose/planyourvisit/halfdome.htm and extract its page title, whether a permit is required, and three safety tips.',
1066
+ tools: {
1067
+ browserbase_fetch: gateway.tools.browserbaseFetch({
1068
+ allowRedirects: true,
1069
+ format: 'json',
1070
+ schema: {
1071
+ type: 'object',
1072
+ properties: {
1073
+ pageTitle: { type: 'string' },
1074
+ permitRequired: { type: 'boolean' },
1075
+ safetyTips: {
1076
+ type: 'array',
1077
+ items: { type: 'string' },
1078
+ maxItems: 3,
1079
+ },
1080
+ },
1081
+ required: ['pageTitle', 'permitRequired', 'safetyTips'],
1082
+ },
1083
+ }),
1084
+ },
1085
+ });
1086
+
1087
+ console.log(result.text);
1088
+ ```
1089
+
1090
+ The Browserbase Fetch tool supports these optional configuration options:
1091
+
1092
+ - **format** _'raw' | 'markdown' | 'json'_
1093
+
1094
+ Output format for the fetched content. `raw` returns the upstream response body unchanged and is the default. `markdown` converts the page to Markdown. `json` performs structured extraction and requires `schema`.
1095
+
1096
+ - **schema** _object_
1097
+
1098
+ JSON Schema describing the desired structured content. Only used when `format` is `json`.
1099
+
1100
+ - **allowRedirects** _boolean_
1101
+
1102
+ Follow HTTP redirects. Defaults to `false`.
1103
+
1104
+ - **proxies** _boolean_
1105
+
1106
+ Route the request through Browserbase's proxy network. Defaults to `false`.
1107
+
1108
+ - **allowInsecureSsl** _boolean_
1109
+
1110
+ Bypass TLS certificate verification. Defaults to `false`; only enable it for trusted hosts.
1111
+
1112
+ The Fetch API does not execute JavaScript. Use a browser session for interactive or JavaScript-rendered pages. The tool works with both `generateText` and `streamText`.
1113
+
988
1114
  #### Tako Search
989
1115
 
990
1116
  The Tako Search tool enables models to search the web and Tako's curated knowledge graph in a single call using [Tako's Search API](https://docs.tako.com/documentation/integrating-tako/search/overview). This tool is executed by the AI Gateway and returns token-efficient web excerpts, plus knowledge-graph results that carry structured data, premium source attribution, and an embed-ready visualization.
@@ -1346,12 +1472,16 @@ The following gateway provider options are available:
1346
1472
 
1347
1473
  When `sort` is active, the response's `providerMetadata.gateway.routing.sort` object contains the sort option used, the resulting execution order, per-provider metric values, and any providers that were deprioritized.
1348
1474
 
1349
- - **models** _string[]_
1475
+ - **models** _string[] | [GatewayModelFallback, ...string[]]_
1350
1476
 
1351
- Specifies fallback models to use when the primary model fails or is unavailable. The gateway will try the primary model first (specified in the `model` parameter), then try each model in this array in order until one succeeds.
1477
+ Specifies fallback models in attempt order. String entries keep their existing behavior: the gateway tries them when the primary model fails or is unavailable. Evaluation requests can also start the list with one conditional `{ model, when }` entry to retry a successful but uncertain evaluation with another model. Only the first entry can be conditional, and only one conditional entry is allowed. If the primary model fails, the gateway also advances to the conditional entry under its existing error fallback behavior. Conditional entries are rejected on non-evaluation requests. Type evaluation options with `GatewayEvaluationProviderOptions`, since `GatewayProviderOptions` only accepts string entries.
1352
1478
 
1353
1479
  Example: `models: ['openai/gpt-5.4-nano', 'google/gemini-3.8-flash']` will try the fallback models in order if the primary model fails.
1354
1480
 
1481
+ A direct condition uses `{ question, confidenceBelow }` for Choice and Score questions, or `{ question, probabilityBetween: [minimum, maximum] }` for Boolean questions. Boolean probability is P(true), not confidence in the selected Boolean outcome. Bounds are inclusive, finite, ordered, and within `[0, 1]`.
1482
+
1483
+ Combine conditions with `{ any: [...] }`, `{ all: [...] }`, or `{ atLeast: { count, conditions: [...] } }`. Each condition list holds 1 to 20 conditions. `atLeast.count` must be an integer from `1` through the number of conditions. Conditions nest at most 5 levels deep. Question IDs and the conditional `model` are 1 to 256 characters. The SDK checks these bounds before sending the request, and the gateway also checks that each question exists and has a kind that matches its condition. String error fallbacks may follow the conditional entry.
1484
+
1355
1485
  - **user** _string_
1356
1486
 
1357
1487
  Optional identifier for the end user on whose behalf the request is being made. This is used for spend tracking and attribution purposes, allowing you to track usage per end-user in your application.
@@ -1390,13 +1520,14 @@ The following gateway provider options are available:
1390
1520
 
1391
1521
  The unique identifier for the entity against which quota is tracked. Used for quota management and enforcement purposes.
1392
1522
 
1393
- - **has** _Array<'implicit-caching' | 'reasoning' | 'tool-use' | 'vision' | `quantization:${string}` | `!quantization:${string}`>_
1523
+ - **has** _Array<'implicit-caching' | 'reasoning' | 'structured-output' | 'tool-use' | 'vision' | `quantization:${string}` | `!quantization:${string}`>_
1394
1524
 
1395
1525
  Restricts routing to provider models that have all of the specified capabilities. Applies to both BYOK and system credentials, since the capability is a property of the model rather than the credential. If no provider model for the requested model satisfies the capabilities, the request fails. Unsupported values are rejected.
1396
1526
 
1397
1527
  Supported capabilities:
1398
1528
  - `'implicit-caching'` — models that perform automatic (implicit) prompt caching.
1399
1529
  - `'reasoning'` — models that support reasoning.
1530
+ - `'structured-output'` — models that support schema-constrained output.
1400
1531
  - `'tool-use'` — models that support tool calling.
1401
1532
  - `'vision'` — models that accept image input.
1402
1533
 
@@ -1481,6 +1612,63 @@ const { text } = await generateText({
1481
1612
  // 4. Return the result from the first model that succeeds
1482
1613
  ```
1483
1614
 
1615
+ #### Conditional Evaluation Fallbacks Example
1616
+
1617
+ Conditional model entries are available only for evaluation requests. Keep the
1618
+ configuration under `providerOptions.gateway.models`. `experimental_evaluate`
1619
+ does not have a top-level fallback option.
1620
+
1621
+ ```ts
1622
+ import type { GatewayEvaluationProviderOptions } from '@ai-sdk/gateway';
1623
+ import { experimental_evaluate } from 'ai';
1624
+
1625
+ const questions = {
1626
+ department: {
1627
+ type: 'choice',
1628
+ instructions: 'Which team should handle this?',
1629
+ criteria: { billing: 'Charges and refunds', support: 'Other requests' },
1630
+ },
1631
+ requestsRefund: {
1632
+ type: 'boolean',
1633
+ instructions: 'Is the customer requesting money back?',
1634
+ },
1635
+ } as const;
1636
+
1637
+ const result = await experimental_evaluate({
1638
+ model: 'typesafe-ai/jev',
1639
+ state: 'I was charged twice. Please refund the duplicate.',
1640
+ questions,
1641
+ providerOptions: {
1642
+ gateway: {
1643
+ models: [
1644
+ {
1645
+ model: 'openai/gpt-5.6-sol',
1646
+ when: {
1647
+ any: [
1648
+ { question: 'department', confidenceBelow: 0.6 },
1649
+ {
1650
+ question: 'requestsRefund',
1651
+ probabilityBetween: [0.4, 0.6],
1652
+ },
1653
+ ],
1654
+ },
1655
+ },
1656
+ ],
1657
+ } satisfies GatewayEvaluationProviderOptions<keyof typeof questions>,
1658
+ },
1659
+ });
1660
+
1661
+ // The model that produced the answers, the fallback when the condition matched.
1662
+ console.log(result.response.modelId);
1663
+ console.log(JSON.stringify(result.providerMetadata?.gateway?.routing, null, 2));
1664
+ ```
1665
+
1666
+ When the condition matches, `result.response.modelId` names the fallback model,
1667
+ and `providerMetadata.gateway.routing.modelAttempts` lists the primary and
1668
+ fallback attempts. The successful attempt of each stage carries its own
1669
+ `generationId`, `usage`, and cost fields, and the first fallback attempt lists
1670
+ the questions that triggered it in `triggeredBy`.
1671
+
1484
1672
  #### Zero Data Retention Example
1485
1673
 
1486
1674
  Set `zeroDataRetention` to true to route requests to providers with zero data retention agreements with Vercel for AI Gateway. BYOK credentials are skipped by default, since your provider agreements differ from Vercel's. When this filter is on, AI Gateway routes only to providers Vercel has ZDR agreements with for the model. If you have BYOK keys marked as ZDR, those keys are tried first, then AI Gateway falls back to its system credentials. You are responsible for the accuracy of that marking. Applies to both account-wide and request-level ZDR. The request fails if no ZDR-eligible credentials are available. When `zeroDataRetention` is `false` or not specified, there is no enforcement of restricting routing. Request-level ZDR is only available for Vercel Pro and Enterprise plans.
@@ -1540,7 +1728,7 @@ const { text } = await generateText({
1540
1728
 
1541
1729
  #### Filtering by Model Capability
1542
1730
 
1543
- Set `has` to restrict routing to provider models that have the specified capabilities. This applies to both BYOK and system credentials, since the capability is a property of the model rather than the credential. `'implicit-caching'` limits routing to models that perform automatic prompt caching, `'vision'` limits routing to models that accept image input, `'reasoning'` limits routing to models that support reasoning, and `'tool-use'` limits routing to models that support tool calling. Weight-format conditions (`'quantization:fp8'` to require, `'!quantization:fp8'` to exclude) limit routing by the serving provider's recorded weight format. If no provider model for the requested model satisfies the capabilities, the request fails.
1731
+ Set `has` to restrict routing to provider models that have the specified capabilities. This applies to both BYOK and system credentials, since the capability is a property of the model rather than the credential. `'implicit-caching'` limits routing to models that perform automatic prompt caching, `'vision'` limits routing to models that accept image input, `'reasoning'` limits routing to models that support reasoning, `'structured-output'` limits routing to models that support schema-constrained output, and `'tool-use'` limits routing to models that support tool calling. Weight-format conditions (`'quantization:fp8'` to require, `'!quantization:fp8'` to exclude) limit routing by the serving provider's recorded weight format. If no provider model for the requested model satisfies the capabilities, the request fails.
1544
1732
 
1545
1733
  ```ts
1546
1734
  import type { GatewayProviderOptions } from '@ai-sdk/gateway';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ai-sdk/gateway",
3
3
  "private": false,
4
- "version": "4.0.92",
4
+ "version": "4.0.95",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "sideEffects": false,
@@ -31,11 +31,11 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@ai-sdk/provider": "4.0.18",
34
- "@ai-sdk/provider-utils": "5.0.47",
34
+ "@ai-sdk/provider-utils": "5.0.49",
35
35
  "@vercel/oidc": "3.2.0"
36
36
  },
37
37
  "devDependencies": {
38
- "@ai-sdk/test-server": "2.0.1",
38
+ "@ai-sdk/test-server": "2.0.2",
39
39
  "@types/node": "22.19.19",
40
40
  "@vercel/ai-tsconfig": "0.0.0",
41
41
  "tsup": "^8.5.1",
@@ -8,6 +8,7 @@ import {
8
8
  createJsonResponseHandler,
9
9
  getErrorMessage,
10
10
  lazySchema,
11
+ parseProviderOptions,
11
12
  postJsonToApi,
12
13
  resolve,
13
14
  zodSchema,
@@ -17,6 +18,7 @@ import { z } from './zod';
17
18
  import { asGatewayError } from './errors';
18
19
  import { parseAuthMethod } from './errors/parse-auth-method';
19
20
  import type { GatewayConfig } from './gateway-config';
21
+ import { gatewayEvaluationProviderOptionsSchema } from './gateway-provider-options';
20
22
 
21
23
  export class GatewayEvaluationModel implements EvaluationModelV4 {
22
24
  readonly specificationVersion = 'v4';
@@ -44,6 +46,15 @@ export class GatewayEvaluationModel implements EvaluationModelV4 {
44
46
  }: Parameters<EvaluationModelV4['doEvaluate']>[0]): Promise<
45
47
  Awaited<ReturnType<EvaluationModelV4['doEvaluate']>>
46
48
  > {
49
+ const gatewayOptions = await parseProviderOptions({
50
+ provider: 'gateway',
51
+ providerOptions,
52
+ schema: gatewayEvaluationProviderOptionsSchema,
53
+ });
54
+ const validatedProviderOptions =
55
+ gatewayOptions == null
56
+ ? providerOptions
57
+ : { ...providerOptions, gateway: gatewayOptions };
47
58
  const resolvedHeaders = this.config.headers
48
59
  ? await resolve(this.config.headers)
49
60
  : undefined;
@@ -63,7 +74,9 @@ export class GatewayEvaluationModel implements EvaluationModelV4 {
63
74
  body: {
64
75
  state,
65
76
  questions,
66
- ...(providerOptions ? { providerOptions } : {}),
77
+ ...(validatedProviderOptions
78
+ ? { providerOptions: validatedProviderOptions }
79
+ : {}),
67
80
  },
68
81
  successfulResponseHandler: createJsonResponseHandler(
69
82
  gatewayEvaluationResponseSchema,
@@ -84,7 +97,7 @@ export class GatewayEvaluationModel implements EvaluationModelV4 {
84
97
  providerMetadata:
85
98
  responseBody.providerMetadata as unknown as SharedV4ProviderMetadata,
86
99
  response: {
87
- modelId: this.modelId,
100
+ modelId: responseBody.model ?? this.modelId,
88
101
  headers: responseHeaders,
89
102
  body: rawValue,
90
103
  },
@@ -152,6 +165,7 @@ const gatewayEvaluationResponseSchema = lazySchema(() =>
152
165
  zodSchema(
153
166
  z.object({
154
167
  answers: z.record(z.string(), gatewayEvaluationAnswerSchema),
168
+ model: z.string().optional(),
155
169
  rounding: z
156
170
  .object({
157
171
  probabilityDecimals: z.number().optional(),
@@ -1,4 +1,50 @@
1
+ import { lazySchema, zodSchema } from '@ai-sdk/provider-utils';
2
+ import type { ZodType } from 'zod/v4';
3
+ import { z } from './zod';
4
+
1
5
  // https://vercel.com/docs/ai-gateway/provider-options
6
+ export const EVALUATION_FALLBACK_MAX_CONDITION_DEPTH = 5;
7
+ export const EVALUATION_FALLBACK_MAX_CONDITIONS_PER_LIST = 20;
8
+ export const EVALUATION_FALLBACK_MAX_QUESTION_LENGTH = 256;
9
+ export const EVALUATION_FALLBACK_MAX_MODEL_LENGTH = 256;
10
+
11
+ export const gatewayEvaluationProviderOptionsSchema = lazySchema(() =>
12
+ zodSchema(
13
+ z
14
+ .object({
15
+ models: gatewayModelFallbacksSchema.optional(),
16
+ })
17
+ .catchall(z.unknown()),
18
+ ),
19
+ );
20
+
21
+ /**
22
+ * A condition on the primary model's answers. `QUESTION_ID` narrows
23
+ * `question` to your question IDs. Groups nest at most five levels deep,
24
+ * which the SDK checks at runtime.
25
+ */
26
+ export type EvaluationFallbackCondition<QUESTION_ID extends string = string> =
27
+ | ExclusiveCondition<{ question: QUESTION_ID; confidenceBelow: number }>
28
+ | ExclusiveCondition<{
29
+ question: QUESTION_ID;
30
+ probabilityBetween: [number, number];
31
+ }>
32
+ | ExclusiveCondition<{ any: EvaluationFallbackConditionList<QUESTION_ID> }>
33
+ | ExclusiveCondition<{ all: EvaluationFallbackConditionList<QUESTION_ID> }>
34
+ | ExclusiveCondition<{
35
+ atLeast: {
36
+ count: number;
37
+ conditions: EvaluationFallbackConditionList<QUESTION_ID>;
38
+ };
39
+ }>;
40
+
41
+ export type GatewayModelFallback<QUESTION_ID extends string = string> =
42
+ | string
43
+ | {
44
+ model: string;
45
+ when: EvaluationFallbackCondition<QUESTION_ID>;
46
+ };
47
+
2
48
  export type GatewayProviderOptions = {
3
49
  /**
4
50
  * Service-owned options may be added by the Gateway without requiring an SDK
@@ -19,16 +65,18 @@ export type GatewayProviderOptions = {
19
65
  * Restrict routing to provider models that satisfy every given entry.
20
66
  *
21
67
  * Entries are capability tags (`'implicit-caching'`, `'reasoning'`,
22
- * `'tool-use'`, `'vision'`) or weight-format conditions: `'quantization:fp8'`
23
- * requires the serving provider to report that weight format,
24
- * `'!quantization:fp8'` excludes it (providers with no recorded format still
25
- * pass an exclusion). Format values are an open space but must match
26
- * `[a-zA-Z0-9._-]{1,32}` and compare case-insensitively; unknown capability
27
- * names are rejected by the Gateway with a 400.
68
+ * `'tool-use'`, `'vision'` (image input), `'structured-output'`
69
+ * (schema-constrained output)) or weight-format conditions:
70
+ * `'quantization:fp8'` requires the serving provider to report that weight
71
+ * format, `'!quantization:fp8'` excludes it (providers with no recorded
72
+ * format still pass an exclusion). Format values are an open space but must
73
+ * match `[a-zA-Z0-9._-]{1,32}` and compare case-insensitively. Unknown
74
+ * capability names are rejected by the Gateway with a 400.
28
75
  */
29
76
  has?: Array<
30
77
  | 'implicit-caching'
31
78
  | 'reasoning'
79
+ | 'structured-output'
32
80
  | 'tool-use'
33
81
  | 'vision'
34
82
  | `quantization:${string}`
@@ -41,7 +89,11 @@ export type GatewayProviderOptions = {
41
89
  */
42
90
  idempotencyKey?: string;
43
91
 
44
- /** Array of model slugs specifying fallback models to use in order. */
92
+ /**
93
+ * Array of model slugs specifying fallback models to use in order.
94
+ * Conditional entries are only valid on evaluation requests, see
95
+ * `GatewayEvaluationProviderOptions`.
96
+ */
45
97
  models?: string[];
46
98
 
47
99
  /** Array of provider slugs that are the only ones allowed to be used. */
@@ -73,3 +125,153 @@ export type GatewayProviderOptions = {
73
125
  /** Filter to providers with zero data retention agreements. */
74
126
  zeroDataRetention?: boolean;
75
127
  };
128
+
129
+ /**
130
+ * Gateway provider options for evaluation requests. Same as
131
+ * `GatewayProviderOptions`, except `models` may start with one conditional
132
+ * `{ model, when }` entry followed by string error fallbacks.
133
+ *
134
+ * The SDK validates `models` strictly before sending the request, so new
135
+ * condition shapes need an SDK release. Other keys pass through unchanged.
136
+ */
137
+ export type GatewayEvaluationProviderOptions<
138
+ QUESTION_ID extends string = string,
139
+ > = GatewayProviderOptionsWithoutModels & {
140
+ models?: GatewayModelFallbackList<QUESTION_ID>;
141
+ };
142
+
143
+ type EvaluationFallbackConditionList<QUESTION_ID extends string> = [
144
+ EvaluationFallbackCondition<QUESTION_ID>,
145
+ ...EvaluationFallbackCondition<QUESTION_ID>[],
146
+ ];
147
+
148
+ type ConditionKey =
149
+ | 'question'
150
+ | 'confidenceBelow'
151
+ | 'probabilityBetween'
152
+ | 'any'
153
+ | 'all'
154
+ | 'atLeast';
155
+
156
+ // Rules out the other shapes' keys, so a condition can't mix two shapes.
157
+ type ExclusiveCondition<CONDITION> = CONDITION & {
158
+ [KEY in Exclude<ConditionKey, keyof CONDITION>]?: never;
159
+ };
160
+
161
+ type GatewayProviderOptionsWithoutModels = {
162
+ [KEY in keyof GatewayProviderOptions as KEY extends 'models'
163
+ ? never
164
+ : KEY]: GatewayProviderOptions[KEY];
165
+ };
166
+
167
+ type ConditionalGatewayModelFallback<QUESTION_ID extends string> = Exclude<
168
+ GatewayModelFallback<QUESTION_ID>,
169
+ string
170
+ >;
171
+
172
+ type GatewayModelFallbackList<QUESTION_ID extends string> =
173
+ | string[]
174
+ | [ConditionalGatewayModelFallback<QUESTION_ID>, ...string[]];
175
+
176
+ const probabilitySchema = z.number().finite().min(0).max(1);
177
+ const questionSchema = z
178
+ .string()
179
+ .min(1)
180
+ .max(EVALUATION_FALLBACK_MAX_QUESTION_LENGTH);
181
+ const directConditionSchema = z.union([
182
+ z
183
+ .object({
184
+ question: questionSchema,
185
+ confidenceBelow: probabilitySchema,
186
+ })
187
+ .strict(),
188
+ z
189
+ .object({
190
+ question: questionSchema,
191
+ probabilityBetween: z
192
+ .array(probabilitySchema)
193
+ .length(2)
194
+ .refine(([minimum, maximum]) => minimum <= maximum, {
195
+ message:
196
+ 'probabilityBetween minimum must be less than or equal to maximum',
197
+ }),
198
+ })
199
+ .strict(),
200
+ ]) as ZodType<EvaluationFallbackCondition>;
201
+
202
+ const groupBeyondMaxDepthSchema = z
203
+ .union([
204
+ z.object({ any: z.unknown() }),
205
+ z.object({ all: z.unknown() }),
206
+ z.object({ atLeast: z.unknown() }),
207
+ ])
208
+ .superRefine((_, context) => {
209
+ context.addIssue({
210
+ code: 'custom',
211
+ message: `conditions can be nested at most ${EVALUATION_FALLBACK_MAX_CONDITION_DEPTH} levels deep`,
212
+ });
213
+ });
214
+
215
+ const conditionalModelFallbackSchema = z
216
+ .object({
217
+ model: z.string().min(1).max(EVALUATION_FALLBACK_MAX_MODEL_LENGTH),
218
+ when: conditionSchema(1),
219
+ })
220
+ .strict();
221
+
222
+ const gatewayModelFallbacksSchema = z
223
+ .array(z.union([z.string(), conditionalModelFallbackSchema]))
224
+ .superRefine((entries, context) => {
225
+ const conditionalIndexes = entries.flatMap((entry, index) =>
226
+ typeof entry === 'string' ? [] : [index],
227
+ );
228
+ if (conditionalIndexes.length > 1) {
229
+ context.addIssue({
230
+ code: 'custom',
231
+ message: 'models supports at most one conditional evaluation fallback',
232
+ });
233
+ }
234
+ if (conditionalIndexes[0] !== undefined && conditionalIndexes[0] !== 0) {
235
+ context.addIssue({
236
+ code: 'custom',
237
+ message:
238
+ 'a conditional evaluation fallback must be the first models entry',
239
+ path: [conditionalIndexes[0]],
240
+ });
241
+ }
242
+ });
243
+
244
+ function conditionSchema(depth: number): ZodType<EvaluationFallbackCondition> {
245
+ if (depth === EVALUATION_FALLBACK_MAX_CONDITION_DEPTH) {
246
+ return z.union([
247
+ directConditionSchema,
248
+ groupBeyondMaxDepthSchema,
249
+ ]) as ZodType<EvaluationFallbackCondition>;
250
+ }
251
+
252
+ const childConditionSchema = conditionSchema(depth + 1);
253
+ const conditionListSchema = z
254
+ .array(childConditionSchema)
255
+ .min(1)
256
+ .max(EVALUATION_FALLBACK_MAX_CONDITIONS_PER_LIST);
257
+
258
+ return z.union([
259
+ directConditionSchema,
260
+ z.object({ any: conditionListSchema }).strict(),
261
+ z.object({ all: conditionListSchema }).strict(),
262
+ z
263
+ .object({
264
+ atLeast: z
265
+ .object({
266
+ count: z.number().int().min(1),
267
+ conditions: conditionListSchema,
268
+ })
269
+ .strict()
270
+ .refine(({ count, conditions }) => count <= conditions.length, {
271
+ message: 'atLeast count cannot exceed the number of conditions',
272
+ path: ['count'],
273
+ }),
274
+ })
275
+ .strict(),
276
+ ]) as ZodType<EvaluationFallbackCondition>;
277
+ }
@@ -1,3 +1,5 @@
1
+ import { browserbaseFetch } from './tool/browserbase-fetch';
2
+ import { browserbaseSearch } from './tool/browserbase-search';
1
3
  import { exaSearch } from './tool/exa-search';
2
4
  import { parallelSearch } from './tool/parallel-search';
3
5
  import { perplexitySearch } from './tool/perplexity-search';
@@ -7,6 +9,22 @@ import { takoSearch } from './tool/tako-search';
7
9
  * Gateway-specific provider-defined tools.
8
10
  */
9
11
  export const gatewayTools = {
12
+ /**
13
+ * Fetch page content using Browserbase's lightweight Fetch API.
14
+ *
15
+ * Supports raw, Markdown, and schema-driven JSON output as well as redirects,
16
+ * proxy routing, and TLS controls.
17
+ */
18
+ browserbaseFetch,
19
+
20
+ /**
21
+ * Search the web using Browserbase's Search API for fast, structured results.
22
+ *
23
+ * Returns titles, URLs, and available publication metadata without requiring
24
+ * a browser session.
25
+ */
26
+ browserbaseSearch,
27
+
10
28
  /**
11
29
  * Search the web using Exa for current information and token-efficient
12
30
  * excerpts optimized for agent workflows.
package/src/index.ts CHANGED
@@ -47,6 +47,9 @@ export type {
47
47
  GatewayProviderMetadata,
48
48
  } from './gateway-provider-metadata';
49
49
  export type {
50
+ EvaluationFallbackCondition,
51
+ GatewayEvaluationProviderOptions,
52
+ GatewayModelFallback,
50
53
  GatewayProviderOptions,
51
54
  /** @deprecated Use `GatewayProviderOptions` instead. */
52
55
  GatewayProviderOptions as GatewayLanguageModelOptions,