@ai-sdk/gateway 4.0.0-canary.99 → 4.0.1

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.
@@ -235,6 +235,98 @@ console.log(ranking);
235
235
 
236
236
  Reranking models are useful for improving search results in retrieval-augmented generation (RAG) pipelines by re-scoring candidate documents after an initial retrieval step.
237
237
 
238
+ ## Realtime Models
239
+
240
+ <Note type="warning">
241
+ Realtime support is experimental and the API may change in patch releases.
242
+ </Note>
243
+
244
+ You can create realtime models for bidirectional audio/text WebSocket sessions using the `experimental_realtime` method on the provider instance. The first argument is the model ID in the format `creator/model-name`:
245
+
246
+ ```ts
247
+ import { gateway } from '@ai-sdk/gateway';
248
+
249
+ const model = gateway.experimental_realtime('openai/gpt-realtime-2');
250
+ ```
251
+
252
+ The Gateway normalizes realtime the same way it normalizes every other modality: your client speaks the [normalized AI SDK realtime protocol](/docs/ai-sdk-core/realtime) and the Gateway translates to and from the upstream provider server-side. This means the same client code works regardless of which provider backs the model.
253
+
254
+ Realtime sessions run in the browser and require a short-lived Gateway client secret created on your server with `gateway.experimental_realtime.getToken()`. The method uses your Gateway credential (`apiKey`, `AI_GATEWAY_API_KEY`, or Vercel OIDC token) to mint a `vcst_` client secret and returns the WebSocket URL for the model.
255
+
256
+ ```ts filename='app/api/realtime/setup/route.ts'
257
+ import { gateway } from 'ai';
258
+
259
+ export async function POST() {
260
+ const token = await gateway.experimental_realtime.getToken({
261
+ model: 'openai/gpt-realtime-2',
262
+ expiresAfterSeconds: 60 * 10,
263
+ });
264
+
265
+ return Response.json(token);
266
+ }
267
+ ```
268
+
269
+ Use the matching Gateway realtime model in the browser. Creating the model is
270
+ safe in browser code; only `getToken()` is server-side.
271
+
272
+ ```tsx filename='app/realtime/page.tsx'
273
+ 'use client';
274
+
275
+ import { experimental_useRealtime } from '@ai-sdk/react';
276
+ import { gateway } from 'ai';
277
+
278
+ export default function RealtimePage() {
279
+ const realtime = experimental_useRealtime({
280
+ model: gateway.experimental_realtime('openai/gpt-realtime-2'),
281
+ api: {
282
+ token: '/api/realtime/setup',
283
+ },
284
+ });
285
+
286
+ // ...
287
+ }
288
+ ```
289
+
290
+ Do not expose your Gateway API key or OIDC token to browser clients. Only return
291
+ the short-lived setup response from `getToken()`.
292
+
293
+ <Note>
294
+ The Gateway WebSocket route transports the short-lived auth token via the
295
+ versioned `Sec-WebSocket-Protocol` subprotocol and the model id via the
296
+ `?ai-model-id=` query - the WebSocket transport of the `Authorization` and
297
+ `ai-model-id` headers the HTTP routes use. Subprotocol values must fit the
298
+ WebSocket token grammar, and the complete `Sec-WebSocket-Protocol` header
299
+ should stay compact (under an 8 KiB safe header budget).
300
+ </Note>
301
+
302
+ ### Provider Options
303
+
304
+ Gateway [provider options](#gateway-provider-options) — `tags`, `user`, `byok`, compliance flags, and so on — are set under `providerOptions.gateway` in the **session configuration**, mirroring how they ride the request body on the non-realtime routes. Include them in the session configuration you send to the Gateway, and the Gateway applies them server-side:
305
+
306
+ ```ts
307
+ import type { GatewayProviderOptions } from '@ai-sdk/gateway';
308
+
309
+ const gatewayOptions: GatewayProviderOptions = {
310
+ tags: ['cooking-coach', 'v2'],
311
+ user: 'user-123',
312
+ };
313
+
314
+ const sessionConfig = {
315
+ instructions: 'You are a concise voice assistant.',
316
+ providerOptions: { gateway: gatewayOptions },
317
+ };
318
+ ```
319
+
320
+ The `GatewayProviderOptions` type is exported from `@ai-sdk/gateway` for stable client-facing fields. The type also accepts service-owned option keys so the Gateway service can add or change server-side options without requiring an SDK release for every schema change. Runtime validation is owned by the Gateway service.
321
+
322
+ <Note>
323
+ Provider options are sent in the initial session update after the socket
324
+ opens, so connect-time options such as `byok` and quota selection require a
325
+ Gateway that resolves them from that update. Routing knobs like `order` /
326
+ `only` do not apply to realtime, where the Gateway selects the
327
+ WebSocket-capable provider.
328
+ </Note>
329
+
238
330
  ## Available Models
239
331
 
240
332
  The AI Gateway supports models from OpenAI, Anthropic, Google, Meta, xAI, Mistral, DeepSeek, Amazon Bedrock, Cohere, Perplexity, Alibaba, and other providers.
@@ -563,6 +655,93 @@ for await (const part of result.stream) {
563
655
  }
564
656
  ```
565
657
 
658
+ #### Exa Search
659
+
660
+ The Exa Search tool enables models to search the web using [Exa's Search API](https://exa.ai/docs/reference/search-api-guide-for-coding-agents). This tool is executed by the AI Gateway and returns token-efficient web excerpts for agent workflows.
661
+
662
+ ```ts
663
+ import { gateway, generateText } from 'ai';
664
+
665
+ const result = await generateText({
666
+ model: 'openai/gpt-5.4-nano',
667
+ prompt:
668
+ 'Find the latest AI regulation updates and summarize the key changes.',
669
+ tools: {
670
+ exa_search: gateway.tools.exaSearch(),
671
+ },
672
+ });
673
+
674
+ console.log(result.text);
675
+ console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2));
676
+ console.log('Tool results:', JSON.stringify(result.toolResults, null, 2));
677
+ ```
678
+
679
+ You can also configure the search with optional parameters:
680
+
681
+ ```ts
682
+ import { gateway, generateText } from 'ai';
683
+
684
+ const result = await generateText({
685
+ model: 'openai/gpt-5.4-nano',
686
+ prompt: 'Find recent AI regulation news from trusted sources.',
687
+ tools: {
688
+ exa_search: gateway.tools.exaSearch({
689
+ type: 'fast',
690
+ numResults: 5,
691
+ category: 'news',
692
+ includeDomains: ['reuters.com', 'bbc.com', 'nytimes.com'],
693
+ contents: {
694
+ highlights: true,
695
+ maxAgeHours: 24,
696
+ },
697
+ }),
698
+ },
699
+ });
700
+
701
+ console.log(result.text);
702
+ console.log('Tool calls:', JSON.stringify(result.toolCalls, null, 2));
703
+ console.log('Tool results:', JSON.stringify(result.toolResults, null, 2));
704
+ ```
705
+
706
+ The Exa Search tool supports the following optional configuration options:
707
+
708
+ - **type** _'auto' | 'fast' | 'instant'_
709
+
710
+ Search mode. `'auto'` is the default balance of speed and quality.
711
+
712
+ - **numResults** _number_
713
+
714
+ Maximum number of results to return (1-100, default: 10).
715
+
716
+ - **category** _'company' | 'people' | 'research paper' | 'news' | 'personal site' | 'financial report'_
717
+
718
+ Focus results on a specific content type.
719
+
720
+ - **includeDomains** / **excludeDomains** _string[]_
721
+
722
+ Restrict or exclude search results by domain.
723
+
724
+ - **startPublishedDate** / **endPublishedDate** _string_
725
+
726
+ Filter results by ISO 8601 publication date.
727
+
728
+ - **contents** _object_
729
+
730
+ Control result extraction and freshness:
731
+ - `text` - Return full page text, optionally capped with `maxCharacters`
732
+ - `highlights` - Return token-efficient excerpts
733
+ - `maxAgeHours` - Control cached content freshness
734
+ - `livecrawlTimeout` - Livecrawl timeout in milliseconds
735
+ - `subpages` / `subpageTarget` - Crawl related subpages
736
+ - `extras.links` / `extras.imageLinks` - Extract links from pages
737
+
738
+ The tool works with both `generateText` and `streamText`.
739
+
740
+ This initial Gateway integration supports Exa's plain Search modes and
741
+ token-efficient content controls. Deep synthesis modes and generated summaries
742
+ are intentionally not exposed yet because they have separate pricing from
743
+ standard Search.
744
+
566
745
  #### Parallel Search
567
746
 
568
747
  The Parallel Search tool enables models to search the web using [Parallel AI's Search API](https://docs.parallel.ai/api-reference/search-beta/search). This tool is optimized for LLM consumption, returning relevant excerpts from web pages that can replace multiple keyword searches with a single call.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@ai-sdk/gateway",
3
3
  "private": false,
4
- "version": "4.0.0-canary.99",
4
+ "version": "4.0.1",
5
5
  "type": "module",
6
6
  "license": "Apache-2.0",
7
7
  "sideEffects": false,
@@ -31,8 +31,8 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@vercel/oidc": "3.2.0",
34
- "@ai-sdk/provider": "4.0.0-canary.18",
35
- "@ai-sdk/provider-utils": "5.0.0-canary.46"
34
+ "@ai-sdk/provider": "4.0.0",
35
+ "@ai-sdk/provider-utils": "5.0.0"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@types/node": "22.19.19",
@@ -40,8 +40,8 @@
40
40
  "tsx": "4.19.2",
41
41
  "typescript": "5.8.3",
42
42
  "zod": "3.25.76",
43
- "@vercel/ai-tsconfig": "0.0.0",
44
- "@ai-sdk/test-server": "2.0.0-canary.6"
43
+ "@ai-sdk/test-server": "2.0.0",
44
+ "@vercel/ai-tsconfig": "0.0.0"
45
45
  },
46
46
  "peerDependencies": {
47
47
  "zod": "^3.25.76 || ^4.1.8"
@@ -8,6 +8,8 @@ import {
8
8
  modelNotFoundParamSchema,
9
9
  } from './gateway-model-not-found-error';
10
10
  import { GatewayInternalServerError } from './gateway-internal-server-error';
11
+ import { GatewayFailedDependencyError } from './gateway-failed-dependency-error';
12
+ import { GatewayForbiddenError } from './gateway-forbidden-error';
11
13
  import { GatewayResponseError } from './gateway-response-error';
12
14
  import {
13
15
  lazySchema,
@@ -101,6 +103,20 @@ export async function createGatewayErrorFromResponse({
101
103
  cause,
102
104
  generationId,
103
105
  });
106
+ case 'failed_dependency':
107
+ return new GatewayFailedDependencyError({
108
+ message,
109
+ statusCode,
110
+ cause,
111
+ generationId,
112
+ });
113
+ case 'forbidden':
114
+ return new GatewayForbiddenError({
115
+ message,
116
+ statusCode,
117
+ cause,
118
+ generationId,
119
+ });
104
120
  default:
105
121
  return new GatewayInternalServerError({
106
122
  message,
@@ -0,0 +1,35 @@
1
+ import { GatewayError } from './gateway-error';
2
+
3
+ const name = 'GatewayFailedDependencyError';
4
+ const marker = `vercel.ai.gateway.error.${name}`;
5
+ const symbol = Symbol.for(marker);
6
+
7
+ /**
8
+ * The request could not be fulfilled because a dependency it relied on was not
9
+ * available on the credentials or provider used to serve it (HTTP 424). Not
10
+ * retryable — the caller must change the request.
11
+ */
12
+ export class GatewayFailedDependencyError extends GatewayError {
13
+ private readonly [symbol] = true; // used in isInstance
14
+
15
+ readonly name = name;
16
+ readonly type = 'failed_dependency';
17
+
18
+ constructor({
19
+ message = 'Failed dependency',
20
+ statusCode = 424,
21
+ cause,
22
+ generationId,
23
+ }: {
24
+ message?: string;
25
+ statusCode?: number;
26
+ cause?: unknown;
27
+ generationId?: string;
28
+ } = {}) {
29
+ super({ message, statusCode, cause, generationId });
30
+ }
31
+
32
+ static isInstance(error: unknown): error is GatewayFailedDependencyError {
33
+ return GatewayError.hasMarker(error) && symbol in error;
34
+ }
35
+ }
@@ -0,0 +1,34 @@
1
+ import { GatewayError } from './gateway-error';
2
+
3
+ const name = 'GatewayForbiddenError';
4
+ const marker = `vercel.ai.gateway.error.${name}`;
5
+ const symbol = Symbol.for(marker);
6
+
7
+ /**
8
+ * Forbidden - the request was rejected by policy (e.g. a routing rule),
9
+ * not an authentication failure.
10
+ */
11
+ export class GatewayForbiddenError extends GatewayError {
12
+ private readonly [symbol] = true; // used in isInstance
13
+
14
+ readonly name = name;
15
+ readonly type = 'forbidden';
16
+
17
+ constructor({
18
+ message = 'Forbidden',
19
+ statusCode = 403,
20
+ cause,
21
+ generationId,
22
+ }: {
23
+ message?: string;
24
+ statusCode?: number;
25
+ cause?: unknown;
26
+ generationId?: string;
27
+ } = {}) {
28
+ super({ message, statusCode, cause, generationId });
29
+ }
30
+
31
+ static isInstance(error: unknown): error is GatewayForbiddenError {
32
+ return GatewayError.hasMarker(error) && symbol in error;
33
+ }
34
+ }
@@ -6,6 +6,8 @@ export {
6
6
  export { extractApiCallResponse } from './extract-api-call-response';
7
7
  export { GatewayError } from './gateway-error';
8
8
  export { GatewayAuthenticationError } from './gateway-authentication-error';
9
+ export { GatewayFailedDependencyError } from './gateway-failed-dependency-error';
10
+ export { GatewayForbiddenError } from './gateway-forbidden-error';
9
11
  export { GatewayInternalServerError } from './gateway-internal-server-error';
10
12
  export { GatewayInvalidRequestError } from './gateway-invalid-request-error';
11
13
  export {
@@ -98,7 +98,7 @@ export class GatewayEmbeddingModel implements EmbeddingModelV4 {
98
98
  providerMetadata:
99
99
  responseBody.providerMetadata as unknown as SharedV4ProviderMetadata,
100
100
  response: { headers: responseHeaders, body: rawValue },
101
- warnings: [],
101
+ warnings: responseBody.warnings ?? [],
102
102
  };
103
103
  } catch (error) {
104
104
  throw await asGatewayError(
@@ -120,11 +120,34 @@ export class GatewayEmbeddingModel implements EmbeddingModelV4 {
120
120
  }
121
121
  }
122
122
 
123
+ const gatewayEmbeddingWarningSchema = z.discriminatedUnion('type', [
124
+ z.object({
125
+ type: z.literal('unsupported'),
126
+ feature: z.string(),
127
+ details: z.string().optional(),
128
+ }),
129
+ z.object({
130
+ type: z.literal('compatibility'),
131
+ feature: z.string(),
132
+ details: z.string().optional(),
133
+ }),
134
+ z.object({
135
+ type: z.literal('deprecated'),
136
+ setting: z.string(),
137
+ message: z.string(),
138
+ }),
139
+ z.object({
140
+ type: z.literal('other'),
141
+ message: z.string(),
142
+ }),
143
+ ]);
144
+
123
145
  const gatewayEmbeddingResponseSchema = lazySchema(() =>
124
146
  zodSchema(
125
147
  z.object({
126
148
  embeddings: z.array(z.array(z.number())),
127
149
  usage: z.object({ tokens: z.number() }).nullish(),
150
+ warnings: z.array(gatewayEmbeddingWarningSchema).optional(),
128
151
  providerMetadata: z
129
152
  .record(z.string(), z.record(z.string(), z.unknown()))
130
153
  .optional(),
@@ -167,6 +167,11 @@ const gatewayImageWarningSchema = z.discriminatedUnion('type', [
167
167
  feature: z.string(),
168
168
  details: z.string().optional(),
169
169
  }),
170
+ z.object({
171
+ type: z.literal('deprecated'),
172
+ setting: z.string(),
173
+ message: z.string(),
174
+ }),
170
175
  z.object({
171
176
  type: z.literal('other'),
172
177
  message: z.string(),
@@ -53,8 +53,6 @@ export type GatewayModelId =
53
53
  | 'deepseek/deepseek-v3.2-thinking'
54
54
  | 'deepseek/deepseek-v4-flash'
55
55
  | 'deepseek/deepseek-v4-pro'
56
- | 'google/gemini-2.0-flash'
57
- | 'google/gemini-2.0-flash-lite'
58
56
  | 'google/gemini-2.5-flash'
59
57
  | 'google/gemini-2.5-flash-image'
60
58
  | 'google/gemini-2.5-flash-lite'
@@ -112,10 +110,10 @@ export type GatewayModelId =
112
110
  | 'mistral/pixtral-large'
113
111
  | 'moonshotai/kimi-k2'
114
112
  | 'moonshotai/kimi-k2-thinking'
115
- | 'moonshotai/kimi-k2-thinking-turbo'
116
- | 'moonshotai/kimi-k2-turbo'
117
113
  | 'moonshotai/kimi-k2.5'
118
114
  | 'moonshotai/kimi-k2.6'
115
+ | 'moonshotai/kimi-k2.7-code'
116
+ | 'moonshotai/kimi-k2.7-code-highspeed'
119
117
  | 'morph/morph-v3-fast'
120
118
  | 'morph/morph-v3-large'
121
119
  | 'nvidia/nemotron-3-nano-30b-a3b'
@@ -167,6 +165,7 @@ export type GatewayModelId =
167
165
  | 'perplexity/sonar'
168
166
  | 'perplexity/sonar-pro'
169
167
  | 'perplexity/sonar-reasoning-pro'
168
+ | 'sakana/fugu-ultra'
170
169
  | 'stepfun/step-3.5-flash'
171
170
  | 'stepfun/step-3.7-flash'
172
171
  | 'xai/grok-4.1-fast-non-reasoning'
@@ -195,5 +194,7 @@ export type GatewayModelId =
195
194
  | 'zai/glm-5'
196
195
  | 'zai/glm-5-turbo'
197
196
  | 'zai/glm-5.1'
197
+ | 'zai/glm-5.2'
198
+ | 'zai/glm-5.2-fast'
198
199
  | 'zai/glm-5v-turbo'
199
200
  | (string & {});
@@ -1,7 +1,6 @@
1
1
  import type {
2
2
  LanguageModelV4,
3
3
  LanguageModelV4CallOptions,
4
- LanguageModelV4FilePart,
5
4
  LanguageModelV4StreamPart,
6
5
  LanguageModelV4GenerateResult,
7
6
  LanguageModelV4StreamResult,
@@ -191,30 +190,27 @@ export class GatewayLanguageModel implements LanguageModelV4 {
191
190
  }
192
191
  }
193
192
 
194
- private isFilePart(part: unknown) {
195
- return (
196
- part && typeof part === 'object' && 'type' in part && part.type === 'file'
197
- );
198
- }
199
-
200
193
  /**
201
- * Encodes inline `Uint8Array` file part data to a base64 string in place.
194
+ * Encodes inline `Uint8Array` file data to a base64 string in place.
202
195
  * @param options - The options to encode.
203
- * @returns The options with the file parts encoded.
196
+ * @returns The options with the file data encoded.
204
197
  */
205
198
  private maybeEncodeFileParts(options: LanguageModelV4CallOptions) {
206
199
  for (const message of options.prompt) {
200
+ if (!Array.isArray(message.content)) {
201
+ continue;
202
+ }
207
203
  for (const part of message.content) {
208
- if (this.isFilePart(part)) {
209
- const filePart = part as LanguageModelV4FilePart;
210
- if (
211
- filePart.data.type === 'data' &&
212
- filePart.data.data instanceof Uint8Array
213
- ) {
214
- filePart.data = {
215
- type: 'data',
216
- data: Buffer.from(filePart.data.data).toString('base64'),
217
- };
204
+ if (part.type === 'file' || part.type === 'reasoning-file') {
205
+ part.data = maybeBase64EncodeFileData(part.data);
206
+ } else if (
207
+ part.type === 'tool-result' &&
208
+ part.output.type === 'content'
209
+ ) {
210
+ for (const contentPart of part.output.value) {
211
+ if (contentPart.type === 'file') {
212
+ contentPart.data = maybeBase64EncodeFileData(contentPart.data);
213
+ }
218
214
  }
219
215
  }
220
216
  }
@@ -234,3 +230,13 @@ export class GatewayLanguageModel implements LanguageModelV4 {
234
230
  };
235
231
  }
236
232
  }
233
+
234
+ function maybeBase64EncodeFileData<T extends { type: string }>(data: T): T {
235
+ if (data.type === 'data') {
236
+ const bytes = (data as { data?: unknown }).data;
237
+ if (bytes instanceof Uint8Array) {
238
+ return { ...data, data: Buffer.from(bytes).toString('base64') } as T;
239
+ }
240
+ }
241
+ return data;
242
+ }
@@ -1,118 +1,52 @@
1
- import {
2
- lazySchema,
3
- zodSchema,
4
- type InferSchema,
5
- } from '@ai-sdk/provider-utils';
6
- import { z } from 'zod/v4';
7
-
8
1
  // https://vercel.com/docs/ai-gateway/provider-options
9
- const gatewayProviderOptions = lazySchema(() =>
10
- zodSchema(
11
- z.object({
12
- /**
13
- * Array of provider slugs that are the only ones allowed to be used.
14
- *
15
- * Example: `['azure', 'openai']` will only allow Azure and OpenAI to be used.
16
- */
17
- only: z.array(z.string()).optional(),
18
- /**
19
- * Array of provider slugs that specifies the sequence in which providers should be attempted.
20
- *
21
- * Example: `['bedrock', 'anthropic']` will try Amazon Bedrock first, then Anthropic as fallback.
22
- */
23
- order: z.array(z.string()).optional(),
24
- /**
25
- * Sort providers by a performance or cost metric before routing.
26
- *
27
- * - `'cost'`: lowest cost first
28
- * - `'ttft'`: lowest time-to-first-token first
29
- * - `'tps'`: highest tokens-per-second first
30
- */
31
- sort: z.enum(['cost', 'ttft', 'tps']).optional(),
32
- /**
33
- * The unique identifier for the end user on behalf of whom the request was made.
34
- *
35
- * Used for spend tracking and attribution purposes.
36
- */
37
- user: z.string().optional(),
38
- /**
39
- * User-specified tags for use in reporting and filtering usage.
40
- *
41
- * For example, spend tracking reporting by feature or prompt version.
42
- *
43
- * Example: `['chat', 'v2']`
44
- */
45
- tags: z.array(z.string()).optional(),
46
- /**
47
- * Array of model slugs specifying fallback models to use in order.
48
- *
49
- * Example: `['openai/gpt-5-nano', 'zai/glm-4.6']` will try `openai/gpt-5-nano` first, then `zai/glm-4.6` as fallback.
50
- */
51
- models: z.array(z.string()).optional(),
52
- /**
53
- * Request-scoped BYOK credentials to use instead of cached credentials.
54
- *
55
- * When provided, cached BYOK credentials are ignored entirely.
56
- *
57
- * Each provider can have multiple credentials (tried in order).
58
- *
59
- * Examples:
60
- * - Simple: `{ 'anthropic': [{ apiKey: 'sk-ant-...' }] }`
61
- * - Multiple: `{ 'vertex': [{ projectId: 'proj-1', privateKey: '...' }, { projectId: 'proj-2', privateKey: '...' }] }`
62
- * - Multi-provider: `{ 'anthropic': [{ apiKey: '...' }], 'bedrock': [{ accessKeyId: '...', secretAccessKey: '...' }] }`
63
- */
64
- byok: z
65
- .record(z.string(), z.array(z.record(z.string(), z.unknown())))
66
- .optional(),
67
- /**
68
- * Whether to filter by only providers that have zero data retention
69
- * agreements with Vercel for AI Gateway. When using BYOK credentials,
70
- * this filter is not applied. If BYOK credentials fail and the request
71
- * falls back to system credentials, only providers with zero data
72
- * retention agreements will be used.
73
- */
74
- zeroDataRetention: z.boolean().optional(),
75
- /**
76
- * Whether to filter by only providers that do not train on prompt data.
77
- * When using BYOK credentials, this filter is not applied. If BYOK
78
- * credentials fail and the request falls back to system credentials,
79
- * only providers that have agreements with Vercel for AI Gateway to not
80
- * use prompts for model training will be used.
81
- */
82
- disallowPromptTraining: z.boolean().optional(),
83
- /**
84
- * Whether to filter by only providers that are HIPAA compliant with
85
- * Vercel AI Gateway. When enabled, only providers that have agreements
86
- * with Vercel AI Gateway for HIPAA compliance will be used.
87
- */
88
- hipaaCompliant: z.boolean().optional(),
89
- /**
90
- * The unique identifier for the entity against which quota is tracked.
91
- *
92
- * Used for quota management and enforcement purposes.
93
- */
94
- quotaEntityId: z.string().optional(),
95
- /**
96
- * Per-provider timeouts for BYOK credentials in milliseconds.
97
- * Controls how long to wait for a provider to start responding
98
- * before falling back to the next available provider.
99
- *
100
- * Example: `{ byok: { openai: 5000, anthropic: 2000 } }`
101
- */
102
- providerTimeouts: z
103
- .object({
104
- byok: z.record(z.string(), z.number().int().min(1000)).optional(),
105
- })
106
- .optional(),
107
- /**
108
- * Unified service tier intent. Translated by the gateway into the
109
- * per-provider option each provider expects, and overrides any tier
110
- * also set in the per-provider options. Leave unset for provider
111
- * default.
112
- */
113
- serviceTier: z.enum(['flex', 'priority']).optional(),
114
- }),
115
- ),
116
- );
2
+ export type GatewayProviderOptions = {
3
+ /**
4
+ * Service-owned options may be added by the Gateway without requiring an SDK
5
+ * release. The Gateway service validates and applies the runtime schema.
6
+ */
7
+ [key: string]: unknown;
8
+
9
+ /** Request-scoped BYOK credentials to use instead of cached credentials. */
10
+ byok?: Record<string, Array<Record<string, unknown>>>;
11
+
12
+ /** Enables automatic caching behavior when supported by the Gateway. */
13
+ caching?: 'auto';
14
+
15
+ /** Filter to providers that do not train on prompt data. */
16
+ disallowPromptTraining?: boolean;
17
+
18
+ /** Filter to providers that are HIPAA compliant with Vercel AI Gateway. */
19
+ hipaaCompliant?: boolean;
20
+
21
+ /** Array of model slugs specifying fallback models to use in order. */
22
+ models?: string[];
23
+
24
+ /** Array of provider slugs that are the only ones allowed to be used. */
25
+ only?: string[];
26
+
27
+ /** Array of provider slugs specifying the provider attempt order. */
28
+ order?: string[];
29
+
30
+ /** Per-provider timeouts for BYOK credentials in milliseconds. */
31
+ providerTimeouts?: {
32
+ byok?: Record<string, number>;
33
+ };
34
+
35
+ /** Entity identifier against which quota is tracked. */
36
+ quotaEntityId?: string;
37
+
38
+ /** Unified service tier intent. */
39
+ serviceTier?: 'flex' | 'priority';
40
+
41
+ /** Sort providers by a performance or cost metric before routing. */
42
+ sort?: 'cost' | 'tps' | 'ttft';
43
+
44
+ /** User-specified tags for reporting and filtering usage. */
45
+ tags?: string[];
46
+
47
+ /** End-user identifier for spend tracking and attribution. */
48
+ user?: string;
117
49
 
118
- export type GatewayProviderOptions = InferSchema<typeof gatewayProviderOptions>;
50
+ /** Filter to providers with zero data retention agreements. */
51
+ zeroDataRetention?: boolean;
52
+ };