@ai-sdk/gateway 4.0.0-canary.101 → 4.0.0-canary.103

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/CHANGELOG.md CHANGED
@@ -1,5 +1,43 @@
1
1
  # @ai-sdk/gateway
2
2
 
3
+ ## 4.0.0-canary.103
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [bae5e2b]
8
+ - @ai-sdk/provider-utils@5.0.0-canary.47
9
+
10
+ ## 4.0.0-canary.102
11
+
12
+ ### Patch Changes
13
+
14
+ - a3bb04a: feat(gateway): add experimental realtime model support
15
+
16
+ Adds `gateway.experimental_realtime()` for bidirectional audio/text realtime
17
+ sessions routed through the AI Gateway. Like every other Gateway modality, the
18
+ client speaks the normalized AI SDK realtime protocol and the Gateway
19
+ translates to/from the upstream provider server-side, so `GatewayRealtimeModel`
20
+ is a thin identity codec. Gateway realtime is server-side only for v0 and throws
21
+ if used in a browser because it returns the resolved Gateway auth token rather
22
+ than a minted ephemeral client secret. Because the browser `WebSocket` API
23
+ cannot set request headers, the Gateway auth token is carried via the
24
+ `Sec-WebSocket-Protocol` subprotocol (the same workaround used for OpenAI) and
25
+ the model id rides the `?ai-model-id=` query — the WS transport of the
26
+ `ai-model-id` header used by the HTTP routes. The model id is passed through
27
+ verbatim; the Gateway owns resolution. Provider options (including BYOK) flow
28
+ through the normalized `session.update`, exactly as they ride the request body
29
+ on the non-realtime routes.
30
+
31
+ The versioned subprotocol auth contract is centralized so the client and the
32
+ Gateway server share one definition: `getGatewayRealtimeProtocols` (client
33
+ encode) and `getGatewayRealtimeAuthToken` (server decode), plus the
34
+ `GATEWAY_REALTIME_SUBPROTOCOL` / `GATEWAY_AUTH_SUBPROTOCOL_PREFIX` constants.
35
+
36
+ `GatewayProviderOptions` documents the stable client-facing option fields while
37
+ remaining open to service-owned options. Runtime validation lives in the Gateway
38
+ service so the server can evolve without requiring an SDK release for every new
39
+ option.
40
+
3
41
  ## 4.0.0-canary.101
4
42
 
5
43
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -1,9 +1,64 @@
1
- import { LanguageModelV4, ProviderV4, EmbeddingModelV4, ImageModelV4, Experimental_VideoModelV4, RerankingModelV4, SpeechModelV4, TranscriptionModelV4, TypeValidationError } from '@ai-sdk/provider';
1
+ import { LanguageModelV4, ProviderV4, EmbeddingModelV4, ImageModelV4, Experimental_VideoModelV4, RerankingModelV4, SpeechModelV4, TranscriptionModelV4, Experimental_RealtimeFactoryV4, TypeValidationError } from '@ai-sdk/provider';
2
2
  import * as _ai_sdk_provider_utils from '@ai-sdk/provider-utils';
3
3
  import { FetchFunction, InferSchema } from '@ai-sdk/provider-utils';
4
4
 
5
5
  type GatewayModelId = 'alibaba/qwen-3-14b' | 'alibaba/qwen-3-235b' | 'alibaba/qwen-3-30b' | 'alibaba/qwen-3-32b' | 'alibaba/qwen-3.6-max-preview' | 'alibaba/qwen3-235b-a22b-thinking' | 'alibaba/qwen3-coder' | 'alibaba/qwen3-coder-30b-a3b' | 'alibaba/qwen3-coder-next' | 'alibaba/qwen3-coder-plus' | 'alibaba/qwen3-max' | 'alibaba/qwen3-max-preview' | 'alibaba/qwen3-max-thinking' | 'alibaba/qwen3-next-80b-a3b-instruct' | 'alibaba/qwen3-next-80b-a3b-thinking' | 'alibaba/qwen3-vl-235b-a22b-instruct' | 'alibaba/qwen3-vl-instruct' | 'alibaba/qwen3-vl-thinking' | 'alibaba/qwen3.5-flash' | 'alibaba/qwen3.5-plus' | 'alibaba/qwen3.6-27b' | 'alibaba/qwen3.6-plus' | 'alibaba/qwen3.7-max' | 'alibaba/qwen3.7-plus' | 'amazon/nova-2-lite' | 'amazon/nova-lite' | 'amazon/nova-micro' | 'amazon/nova-pro' | 'anthropic/claude-3-haiku' | 'anthropic/claude-3.5-haiku' | 'anthropic/claude-fable-5' | 'anthropic/claude-haiku-4.5' | 'anthropic/claude-opus-4' | 'anthropic/claude-opus-4.1' | 'anthropic/claude-opus-4.5' | 'anthropic/claude-opus-4.6' | 'anthropic/claude-opus-4.7' | 'anthropic/claude-opus-4.8' | 'anthropic/claude-sonnet-4' | 'anthropic/claude-sonnet-4.5' | 'anthropic/claude-sonnet-4.6' | 'arcee-ai/trinity-large-preview' | 'arcee-ai/trinity-large-thinking' | 'arcee-ai/trinity-mini' | 'bytedance/seed-1.6' | 'bytedance/seed-1.8' | 'cohere/command-a' | 'deepseek/deepseek-r1' | 'deepseek/deepseek-v3' | 'deepseek/deepseek-v3.1' | 'deepseek/deepseek-v3.1-terminus' | 'deepseek/deepseek-v3.2' | 'deepseek/deepseek-v3.2-thinking' | 'deepseek/deepseek-v4-flash' | 'deepseek/deepseek-v4-pro' | 'google/gemini-2.5-flash' | 'google/gemini-2.5-flash-image' | 'google/gemini-2.5-flash-lite' | 'google/gemini-2.5-pro' | 'google/gemini-3-flash' | 'google/gemini-3-pro-image' | 'google/gemini-3-pro-preview' | 'google/gemini-3.1-flash-image' | 'google/gemini-3.1-flash-image-preview' | 'google/gemini-3.1-flash-lite' | 'google/gemini-3.1-flash-lite-preview' | 'google/gemini-3.1-pro-preview' | 'google/gemini-3.5-flash' | 'google/gemma-4-26b-a4b-it' | 'google/gemma-4-31b-it' | 'inception/mercury-2' | 'inception/mercury-coder-small' | 'interfaze/interfaze-beta' | 'kwaipilot/kat-coder-pro-v1' | 'kwaipilot/kat-coder-pro-v2' | 'meituan/longcat-flash-chat' | 'meituan/longcat-flash-thinking-2601' | 'meta/llama-3.1-70b' | 'meta/llama-3.1-8b' | 'meta/llama-3.2-11b' | 'meta/llama-3.2-1b' | 'meta/llama-3.2-3b' | 'meta/llama-3.2-90b' | 'meta/llama-3.3-70b' | 'meta/llama-4-maverick' | 'meta/llama-4-scout' | 'minimax/minimax-m2' | 'minimax/minimax-m2.1' | 'minimax/minimax-m2.1-lightning' | 'minimax/minimax-m2.5' | 'minimax/minimax-m2.5-highspeed' | 'minimax/minimax-m2.7' | 'minimax/minimax-m2.7-highspeed' | 'minimax/minimax-m3' | 'mistral/codestral' | 'mistral/devstral-2' | 'mistral/devstral-small' | 'mistral/devstral-small-2' | 'mistral/magistral-medium' | 'mistral/magistral-small' | 'mistral/ministral-14b' | 'mistral/ministral-3b' | 'mistral/ministral-8b' | 'mistral/mistral-large-3' | 'mistral/mistral-medium' | 'mistral/mistral-medium-3.5' | 'mistral/mistral-nemo' | 'mistral/mistral-small' | 'mistral/pixtral-12b' | 'mistral/pixtral-large' | 'moonshotai/kimi-k2' | 'moonshotai/kimi-k2-thinking' | 'moonshotai/kimi-k2-thinking-turbo' | 'moonshotai/kimi-k2-turbo' | 'moonshotai/kimi-k2.5' | 'moonshotai/kimi-k2.6' | 'morph/morph-v3-fast' | 'morph/morph-v3-large' | 'nvidia/nemotron-3-nano-30b-a3b' | 'nvidia/nemotron-3-super-120b-a12b' | 'nvidia/nemotron-3-ultra-550b-a55b' | 'nvidia/nemotron-nano-12b-v2-vl' | 'nvidia/nemotron-nano-9b-v2' | 'openai/gpt-3.5-turbo' | 'openai/gpt-3.5-turbo-instruct' | 'openai/gpt-4-turbo' | 'openai/gpt-4.1' | 'openai/gpt-4.1-mini' | 'openai/gpt-4.1-nano' | 'openai/gpt-4o' | 'openai/gpt-4o-mini' | 'openai/gpt-4o-mini-search-preview' | 'openai/gpt-5' | 'openai/gpt-5-chat' | 'openai/gpt-5-codex' | 'openai/gpt-5-mini' | 'openai/gpt-5-nano' | 'openai/gpt-5-pro' | 'openai/gpt-5.1-codex' | 'openai/gpt-5.1-codex-max' | 'openai/gpt-5.1-codex-mini' | 'openai/gpt-5.1-instant' | 'openai/gpt-5.1-thinking' | 'openai/gpt-5.2' | 'openai/gpt-5.2-chat' | 'openai/gpt-5.2-codex' | 'openai/gpt-5.2-pro' | 'openai/gpt-5.3-chat' | 'openai/gpt-5.3-codex' | 'openai/gpt-5.4' | 'openai/gpt-5.4-mini' | 'openai/gpt-5.4-nano' | 'openai/gpt-5.4-pro' | 'openai/gpt-5.5' | 'openai/gpt-5.5-pro' | 'openai/gpt-oss-120b' | 'openai/gpt-oss-20b' | 'openai/gpt-oss-safeguard-20b' | 'openai/o1' | 'openai/o3' | 'openai/o3-deep-research' | 'openai/o3-mini' | 'openai/o3-pro' | 'openai/o4-mini' | 'perplexity/sonar' | 'perplexity/sonar-pro' | 'perplexity/sonar-reasoning-pro' | 'stepfun/step-3.5-flash' | 'stepfun/step-3.7-flash' | 'xai/grok-4.1-fast-non-reasoning' | 'xai/grok-4.1-fast-reasoning' | 'xai/grok-4.20-multi-agent' | 'xai/grok-4.20-multi-agent-beta' | 'xai/grok-4.20-non-reasoning' | 'xai/grok-4.20-non-reasoning-beta' | 'xai/grok-4.20-reasoning' | 'xai/grok-4.20-reasoning-beta' | 'xai/grok-4.3' | 'xai/grok-build-0.1' | 'xiaomi/mimo-v2-flash' | 'xiaomi/mimo-v2-pro' | 'xiaomi/mimo-v2.5' | 'xiaomi/mimo-v2.5-pro' | 'zai/glm-4.5' | 'zai/glm-4.5-air' | 'zai/glm-4.5v' | 'zai/glm-4.6' | 'zai/glm-4.6v' | 'zai/glm-4.6v-flash' | 'zai/glm-4.7' | 'zai/glm-4.7-flash' | 'zai/glm-4.7-flashx' | 'zai/glm-5' | 'zai/glm-5-turbo' | 'zai/glm-5.1' | 'zai/glm-5v-turbo' | (string & {});
6
6
 
7
+ /**
8
+ * Shared WebSocket subprotocol contract for AI Gateway realtime auth.
9
+ *
10
+ * The browser `WebSocket` API cannot set request headers, so the Gateway auth
11
+ * (bearer) token is carried through the `Sec-WebSocket-Protocol` handshake
12
+ * instead of an `Authorization` header — the same workaround OpenAI uses for
13
+ * `openai-insecure-api-key.<token>`.
14
+ *
15
+ * This module is the single source of truth for that contract so the client and
16
+ * the Gateway server can't drift: the client encodes values with
17
+ * `getGatewayRealtimeProtocols`, and the Gateway server decodes them with
18
+ * `getGatewayRealtimeAuthToken` / `getGatewayRealtimeTeamIdOrSlug`.
19
+ *
20
+ * WebSocket subprotocol values must fit the RFC token grammar. The auth token is
21
+ * sent as-is, so callers must use tokens that are valid subprotocol tokens; the
22
+ * optional team scope is base64url-encoded by this module. Keep the complete
23
+ * `Sec-WebSocket-Protocol` header compact (target under an 8 KiB safe header
24
+ * budget) because intermediaries may reject large upgrade headers.
25
+ */
26
+ /**
27
+ * Marker subprotocol offered on every handshake so the Gateway can echo a
28
+ * negotiated subprotocol on the 101 response (some clients require the server to
29
+ * select one of the offered subprotocols).
30
+ */
31
+ declare const GATEWAY_REALTIME_SUBPROTOCOL = "ai-gateway-realtime.v1";
32
+ /** Subprotocol prefix that carries the Gateway auth (bearer) token. */
33
+ declare const GATEWAY_AUTH_SUBPROTOCOL_PREFIX = "ai-gateway-auth.";
34
+ /** Subprotocol prefix that carries optional Vercel team scoping. */
35
+ declare const GATEWAY_TEAM_SUBPROTOCOL_PREFIX = "ai-gateway-team.";
36
+ /**
37
+ * Client-side: build the WebSocket subprotocols that carry `token` to the
38
+ * Gateway. Pass the result as the second argument to `new WebSocket(url, ...)`.
39
+ */
40
+ declare function getGatewayRealtimeProtocols(token: string, options?: {
41
+ teamIdOrSlug?: string;
42
+ }): string[];
43
+ /**
44
+ * Server-side: extract the Gateway auth (bearer) token from a
45
+ * `Sec-WebSocket-Protocol` header value, or `undefined` when it is absent or
46
+ * empty. The Gateway upgrade handler turns this into an
47
+ * `Authorization: Bearer <token>` before its normal auth path.
48
+ *
49
+ * Accepts the raw header value (subprotocols are comma-separated and may carry
50
+ * surrounding whitespace).
51
+ */
52
+ declare function getGatewayRealtimeAuthToken(secWebSocketProtocol: string | null | undefined): string | undefined;
53
+ /**
54
+ * Server-side: extract the optional Vercel team ID or slug from the
55
+ * `Sec-WebSocket-Protocol` header value. Team scoping is base64url-encoded so
56
+ * arbitrary team slugs stay within the WebSocket subprotocol token grammar.
57
+ */
58
+ declare function getGatewayRealtimeTeamIdOrSlug(secWebSocketProtocol: string | null | undefined): string | undefined;
59
+
60
+ type GatewayRealtimeModelId = string & {};
61
+
7
62
  type GatewayRerankingModelId = 'cohere/rerank-v3.5' | 'cohere/rerank-v4-fast' | 'cohere/rerank-v4-pro' | 'voyage/rerank-2.5' | 'voyage/rerank-2.5-lite' | (string & {});
8
63
 
9
64
  type GatewaySpeechModelId = string & {};
@@ -539,6 +594,11 @@ interface GatewayProvider extends ProviderV4 {
539
594
  * Creates a model for audio transcription.
540
595
  */
541
596
  transcriptionModel(modelId: GatewayTranscriptionModelId): TranscriptionModelV4;
597
+ /**
598
+ * Creates an experimental realtime model for bidirectional audio/text
599
+ * communication over WebSocket, normalized through the AI Gateway.
600
+ */
601
+ experimental_realtime: Experimental_RealtimeFactoryV4;
542
602
  /**
543
603
  * Gateway-specific tools executed server-side.
544
604
  */
@@ -579,24 +639,43 @@ interface GatewayProviderSettings {
579
639
  declare function createGateway(options?: GatewayProviderSettings): GatewayProvider;
580
640
  declare const gateway: GatewayProvider;
581
641
 
582
- declare const gatewayProviderOptions: _ai_sdk_provider_utils.LazySchema<{
583
- only?: string[] | undefined;
584
- order?: string[] | undefined;
585
- sort?: "cost" | "ttft" | "tps" | undefined;
586
- user?: string | undefined;
587
- tags?: string[] | undefined;
588
- models?: string[] | undefined;
589
- byok?: Record<string, Record<string, unknown>[]> | undefined;
590
- zeroDataRetention?: boolean | undefined;
591
- disallowPromptTraining?: boolean | undefined;
592
- hipaaCompliant?: boolean | undefined;
593
- quotaEntityId?: string | undefined;
642
+ type GatewayProviderOptions = {
643
+ /**
644
+ * Service-owned options may be added by the Gateway without requiring an SDK
645
+ * release. The Gateway service validates and applies the runtime schema.
646
+ */
647
+ [key: string]: unknown;
648
+ /** Request-scoped BYOK credentials to use instead of cached credentials. */
649
+ byok?: Record<string, Array<Record<string, unknown>>>;
650
+ /** Enables automatic caching behavior when supported by the Gateway. */
651
+ caching?: 'auto';
652
+ /** Filter to providers that do not train on prompt data. */
653
+ disallowPromptTraining?: boolean;
654
+ /** Filter to providers that are HIPAA compliant with Vercel AI Gateway. */
655
+ hipaaCompliant?: boolean;
656
+ /** Array of model slugs specifying fallback models to use in order. */
657
+ models?: string[];
658
+ /** Array of provider slugs that are the only ones allowed to be used. */
659
+ only?: string[];
660
+ /** Array of provider slugs specifying the provider attempt order. */
661
+ order?: string[];
662
+ /** Per-provider timeouts for BYOK credentials in milliseconds. */
594
663
  providerTimeouts?: {
595
- byok?: Record<string, number> | undefined;
596
- } | undefined;
597
- serviceTier?: "flex" | "priority" | undefined;
598
- }>;
599
- type GatewayProviderOptions = InferSchema<typeof gatewayProviderOptions>;
664
+ byok?: Record<string, number>;
665
+ };
666
+ /** Entity identifier against which quota is tracked. */
667
+ quotaEntityId?: string;
668
+ /** Unified service tier intent. */
669
+ serviceTier?: 'flex' | 'priority';
670
+ /** Sort providers by a performance or cost metric before routing. */
671
+ sort?: 'cost' | 'tps' | 'ttft';
672
+ /** User-specified tags for reporting and filtering usage. */
673
+ tags?: string[];
674
+ /** End-user identifier for spend tracking and attribution. */
675
+ user?: string;
676
+ /** Filter to providers with zero data retention agreements. */
677
+ zeroDataRetention?: boolean;
678
+ };
600
679
 
601
680
  declare const symbol$7: unique symbol;
602
681
  declare abstract class GatewayError extends Error {
@@ -774,4 +853,4 @@ declare class GatewayResponseError extends GatewayError {
774
853
 
775
854
  declare const VERSION: string;
776
855
 
777
- export { GatewayAuthenticationError, type GatewayCreditsResponse, GatewayError, type GatewayErrorResponse, GatewayFailedDependencyError, type GatewayGenerationInfo, type GatewayGenerationInfoParams, GatewayInternalServerError, GatewayInvalidRequestError, type GatewayLanguageModelEntry, type GatewayProviderOptions as GatewayLanguageModelOptions, type GatewayLanguageModelSpecification, type GatewayLanguageModelEntry as GatewayModelEntry, type GatewayModelId, GatewayModelNotFoundError, type GatewayProvider, type GatewayProviderOptions, type GatewayProviderSettings, GatewayRateLimitError, type GatewayRerankingModelId, GatewayResponseError, type GatewaySpeechModelId, type GatewaySpendReportParams, type GatewaySpendReportResponse, type GatewaySpendReportRow, type GatewayTranscriptionModelId, type GatewayVideoModelId, VERSION, createGateway, createGateway as createGatewayProvider, gateway };
856
+ export { GATEWAY_AUTH_SUBPROTOCOL_PREFIX, GATEWAY_REALTIME_SUBPROTOCOL, GATEWAY_TEAM_SUBPROTOCOL_PREFIX, GatewayAuthenticationError, type GatewayCreditsResponse, GatewayError, type GatewayErrorResponse, GatewayFailedDependencyError, type GatewayGenerationInfo, type GatewayGenerationInfoParams, GatewayInternalServerError, GatewayInvalidRequestError, type GatewayLanguageModelEntry, type GatewayProviderOptions as GatewayLanguageModelOptions, type GatewayLanguageModelSpecification, type GatewayLanguageModelEntry as GatewayModelEntry, type GatewayModelId, GatewayModelNotFoundError, type GatewayProvider, type GatewayProviderOptions, type GatewayProviderSettings, GatewayRateLimitError, type GatewayRealtimeModelId, type GatewayRerankingModelId, GatewayResponseError, type GatewaySpeechModelId, type GatewaySpendReportParams, type GatewaySpendReportResponse, type GatewaySpendReportRow, type GatewayTranscriptionModelId, type GatewayVideoModelId, VERSION, createGateway, createGateway as createGatewayProvider, gateway, getGatewayRealtimeAuthToken, getGatewayRealtimeProtocols, getGatewayRealtimeTeamIdOrSlug };
package/dist/index.js CHANGED
@@ -1,3 +1,57 @@
1
+ // src/gateway-realtime-auth.ts
2
+ var GATEWAY_REALTIME_SUBPROTOCOL = "ai-gateway-realtime.v1";
3
+ var GATEWAY_AUTH_SUBPROTOCOL_PREFIX = "ai-gateway-auth.";
4
+ var GATEWAY_TEAM_SUBPROTOCOL_PREFIX = "ai-gateway-team.";
5
+ function getGatewayRealtimeProtocols(token, options) {
6
+ const protocols = [
7
+ GATEWAY_REALTIME_SUBPROTOCOL,
8
+ `${GATEWAY_AUTH_SUBPROTOCOL_PREFIX}${token}`
9
+ ];
10
+ if (options == null ? void 0 : options.teamIdOrSlug) {
11
+ protocols.push(
12
+ `${GATEWAY_TEAM_SUBPROTOCOL_PREFIX}${encodeSubprotocolValue(options.teamIdOrSlug)}`
13
+ );
14
+ }
15
+ return protocols;
16
+ }
17
+ function getGatewayRealtimeAuthToken(secWebSocketProtocol) {
18
+ var _a10;
19
+ return ((_a10 = findProtocol(secWebSocketProtocol, GATEWAY_AUTH_SUBPROTOCOL_PREFIX)) == null ? void 0 : _a10.slice(
20
+ GATEWAY_AUTH_SUBPROTOCOL_PREFIX.length
21
+ )) || void 0;
22
+ }
23
+ function getGatewayRealtimeTeamIdOrSlug(secWebSocketProtocol) {
24
+ var _a10;
25
+ const encoded = (_a10 = findProtocol(
26
+ secWebSocketProtocol,
27
+ GATEWAY_TEAM_SUBPROTOCOL_PREFIX
28
+ )) == null ? void 0 : _a10.slice(GATEWAY_TEAM_SUBPROTOCOL_PREFIX.length);
29
+ if (!encoded) return void 0;
30
+ try {
31
+ return decodeSubprotocolValue(encoded) || void 0;
32
+ } catch (e) {
33
+ return void 0;
34
+ }
35
+ }
36
+ function findProtocol(secWebSocketProtocol, prefix) {
37
+ return secWebSocketProtocol == null ? void 0 : secWebSocketProtocol.split(",").map((protocol) => protocol.trim()).find((protocol) => protocol.startsWith(prefix));
38
+ }
39
+ function encodeSubprotocolValue(value) {
40
+ const bytes = new TextEncoder().encode(value);
41
+ let binary = "";
42
+ for (const byte of bytes) {
43
+ binary += String.fromCharCode(byte);
44
+ }
45
+ return btoa(binary).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/u, "");
46
+ }
47
+ function decodeSubprotocolValue(value) {
48
+ const base64 = value.replace(/-/g, "+").replace(/_/g, "/");
49
+ const padding = "=".repeat((4 - base64.length % 4) % 4);
50
+ const binary = atob(`${base64}${padding}`);
51
+ const bytes = Uint8Array.from(binary, (char) => char.charCodeAt(0));
52
+ return new TextDecoder().decode(bytes);
53
+ }
54
+
1
55
  // src/gateway-provider.ts
2
56
  import {
3
57
  loadOptionalSetting,
@@ -1801,6 +1855,55 @@ var gatewayTranscriptionResponseSchema = z13.object({
1801
1855
  providerMetadata: z13.record(z13.string(), providerMetadataEntrySchema4).optional()
1802
1856
  });
1803
1857
 
1858
+ // src/gateway-realtime-model.ts
1859
+ var GatewayRealtimeModel = class {
1860
+ constructor(modelId, config) {
1861
+ this.specificationVersion = "v4";
1862
+ this.modelId = modelId;
1863
+ this.provider = config.provider;
1864
+ this.config = config;
1865
+ }
1866
+ /**
1867
+ * Unlike providers with a dedicated ephemeral-secret endpoint (e.g. OpenAI),
1868
+ * the Gateway v0 realtime path does not mint a new client secret. The returned
1869
+ * token is the Gateway credential resolved by the provider (`apiKey`,
1870
+ * `AI_GATEWAY_API_KEY`, or Vercel OIDC token) and the WebSocket upgrade is
1871
+ * authenticated directly with that credential. The
1872
+ * `RealtimeModelV4ClientSecretOptions` are therefore intentionally unused:
1873
+ * `sessionConfig` is applied later via the normalized `session-update` event,
1874
+ * and `expiresAfterSeconds` has no Gateway-side equivalent.
1875
+ */
1876
+ async doCreateClientSecret() {
1877
+ const { token } = await this.config.getAuthToken();
1878
+ return {
1879
+ token,
1880
+ url: toGatewayRealtimeUrl(this.config.baseURL, this.modelId)
1881
+ };
1882
+ }
1883
+ getWebSocketConfig(options) {
1884
+ return {
1885
+ url: options.url,
1886
+ protocols: getGatewayRealtimeProtocols(options.token, {
1887
+ teamIdOrSlug: this.config.teamIdOrSlug
1888
+ })
1889
+ };
1890
+ }
1891
+ parseServerEvent(raw) {
1892
+ return raw;
1893
+ }
1894
+ serializeClientEvent(event) {
1895
+ return event;
1896
+ }
1897
+ buildSessionConfig(config) {
1898
+ return config;
1899
+ }
1900
+ };
1901
+ function toGatewayRealtimeUrl(baseURL, modelId) {
1902
+ const url = new URL(`${baseURL.replace(/^http/, "ws")}/realtime-model`);
1903
+ url.searchParams.set("ai-model-id", modelId);
1904
+ return url.toString();
1905
+ }
1906
+
1804
1907
  // src/tool/parallel-search.ts
1805
1908
  import {
1806
1909
  createProviderExecutedToolFactory,
@@ -2000,7 +2103,7 @@ async function getVercelRequestId() {
2000
2103
  }
2001
2104
 
2002
2105
  // src/version.ts
2003
- var VERSION = true ? "4.0.0-canary.101" : "0.0.0-test";
2106
+ var VERSION = true ? "4.0.0-canary.103" : "0.0.0-test";
2004
2107
 
2005
2108
  // src/gateway-provider.ts
2006
2109
  var AI_GATEWAY_PROTOCOL_VERSION = "0.0.1";
@@ -2033,6 +2136,18 @@ function createGateway(options = {}) {
2033
2136
  });
2034
2137
  }
2035
2138
  };
2139
+ const getRealtimeAuthToken = async () => {
2140
+ try {
2141
+ return await getGatewayAuthToken(options);
2142
+ } catch (error) {
2143
+ throw GatewayAuthenticationError.createContextualError({
2144
+ apiKeyProvided: false,
2145
+ oidcTokenProvided: false,
2146
+ statusCode: 401,
2147
+ cause: error
2148
+ });
2149
+ }
2150
+ };
2036
2151
  const createO11yHeaders = () => {
2037
2152
  const deploymentId = loadOptionalSetting({
2038
2153
  settingValue: void 0,
@@ -2203,6 +2318,29 @@ function createGateway(options = {}) {
2203
2318
  };
2204
2319
  provider.transcriptionModel = createTranscriptionModel;
2205
2320
  provider.transcription = createTranscriptionModel;
2321
+ const createRealtimeModel = (modelId) => {
2322
+ assertGatewayRealtimeServerEnvironment();
2323
+ return new GatewayRealtimeModel(modelId, {
2324
+ provider: "gateway.realtime",
2325
+ baseURL,
2326
+ teamIdOrSlug: options.teamIdOrSlug,
2327
+ getAuthToken: getRealtimeAuthToken
2328
+ });
2329
+ };
2330
+ provider.experimental_realtime = Object.assign(
2331
+ (modelId) => createRealtimeModel(modelId),
2332
+ {
2333
+ getToken: async (tokenOptions) => {
2334
+ const model = createRealtimeModel(tokenOptions.model);
2335
+ const secret = await model.doCreateClientSecret();
2336
+ return {
2337
+ token: secret.token,
2338
+ url: secret.url,
2339
+ ...secret.expiresAt != null && { expiresAt: secret.expiresAt }
2340
+ };
2341
+ }
2342
+ }
2343
+ );
2206
2344
  provider.chat = provider.languageModel;
2207
2345
  provider.embedding = provider.embeddingModel;
2208
2346
  provider.image = provider.imageModel;
@@ -2228,7 +2366,17 @@ async function getGatewayAuthToken(options) {
2228
2366
  authMethod: "oidc"
2229
2367
  };
2230
2368
  }
2369
+ function assertGatewayRealtimeServerEnvironment() {
2370
+ if (typeof globalThis.window !== "undefined") {
2371
+ throw new Error(
2372
+ "AI Gateway realtime models cannot be used in browsers yet. Use gateway.experimental_realtime from server-side code only."
2373
+ );
2374
+ }
2375
+ }
2231
2376
  export {
2377
+ GATEWAY_AUTH_SUBPROTOCOL_PREFIX,
2378
+ GATEWAY_REALTIME_SUBPROTOCOL,
2379
+ GATEWAY_TEAM_SUBPROTOCOL_PREFIX,
2232
2380
  GatewayAuthenticationError,
2233
2381
  GatewayError,
2234
2382
  GatewayFailedDependencyError,
@@ -2240,6 +2388,9 @@ export {
2240
2388
  VERSION,
2241
2389
  createGateway,
2242
2390
  createGateway as createGatewayProvider,
2243
- gateway
2391
+ gateway,
2392
+ getGatewayRealtimeAuthToken,
2393
+ getGatewayRealtimeProtocols,
2394
+ getGatewayRealtimeTeamIdOrSlug
2244
2395
  };
2245
2396
  //# sourceMappingURL=index.js.map