@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 +38 -0
- package/dist/index.d.ts +98 -19
- package/dist/index.js +153 -2
- package/dist/index.js.map +1 -1
- package/docs/00-ai-gateway.mdx +70 -0
- package/package.json +3 -3
- package/src/gateway-provider-options.ts +50 -116
- package/src/gateway-provider.ts +56 -0
- package/src/gateway-realtime-auth.ts +126 -0
- package/src/gateway-realtime-model-settings.ts +1 -0
- package/src/gateway-realtime-model.ts +107 -0
- package/src/index.ts +9 -0
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
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
byok?: Record<string, Record<string, unknown
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
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
|
|
596
|
-
}
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
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.
|
|
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
|