@ai-sdk/gateway 4.0.0-beta.1 → 4.0.0-beta.108
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 +794 -4
- package/dist/index.d.ts +314 -42
- package/dist/index.js +1369 -397
- package/dist/index.js.map +1 -1
- package/docs/00-ai-gateway.mdx +447 -61
- package/package.json +15 -15
- package/src/errors/as-gateway-error.ts +2 -1
- package/src/errors/create-gateway-error.ts +17 -3
- package/src/errors/gateway-authentication-error.ts +8 -5
- package/src/errors/gateway-error.ts +8 -0
- package/src/errors/gateway-failed-dependency-error.ts +35 -0
- package/src/errors/gateway-forbidden-error.ts +34 -0
- package/src/errors/gateway-response-error.ts +1 -1
- package/src/errors/index.ts +2 -0
- package/src/errors/parse-auth-method.ts +1 -2
- package/src/gateway-config.ts +1 -1
- package/src/gateway-embedding-model-settings.ts +1 -0
- package/src/gateway-embedding-model.ts +62 -15
- package/src/gateway-fetch-metadata.ts +51 -38
- package/src/gateway-generation-info.ts +149 -0
- package/src/gateway-headers.ts +3 -0
- package/src/gateway-image-model-settings.ts +14 -1
- package/src/gateway-image-model.ts +46 -21
- package/src/gateway-language-model-settings.ts +52 -31
- package/src/gateway-language-model.ts +72 -42
- package/src/gateway-model-entry.ts +15 -3
- package/src/gateway-provider-options.ts +50 -78
- package/src/gateway-provider.ts +239 -35
- 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/gateway-reranking-model-settings.ts +7 -0
- package/src/gateway-reranking-model.ts +142 -0
- package/src/gateway-speech-model-settings.ts +1 -0
- package/src/gateway-speech-model.ts +145 -0
- package/src/gateway-spend-report.ts +193 -0
- package/src/gateway-transcription-model-settings.ts +1 -0
- package/src/gateway-transcription-model.ts +155 -0
- package/src/gateway-video-model-settings.ts +4 -0
- package/src/gateway-video-model.ts +29 -19
- package/src/index.ts +30 -5
- package/src/tool/parallel-search.ts +10 -11
- package/src/tool/perplexity-search.ts +10 -11
- package/dist/index.d.mts +0 -602
- package/dist/index.mjs +0 -1539
- package/dist/index.mjs.map +0 -1
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import type {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
LanguageModelV3GenerateResult,
|
|
8
|
-
LanguageModelV3StreamResult,
|
|
2
|
+
LanguageModelV4,
|
|
3
|
+
LanguageModelV4CallOptions,
|
|
4
|
+
LanguageModelV4StreamPart,
|
|
5
|
+
LanguageModelV4GenerateResult,
|
|
6
|
+
LanguageModelV4StreamResult,
|
|
9
7
|
} from '@ai-sdk/provider';
|
|
10
8
|
import {
|
|
11
9
|
combineHeaders,
|
|
@@ -14,6 +12,9 @@ import {
|
|
|
14
12
|
createJsonResponseHandler,
|
|
15
13
|
postJsonToApi,
|
|
16
14
|
resolve,
|
|
15
|
+
serializeModelOptions,
|
|
16
|
+
WORKFLOW_SERIALIZE,
|
|
17
|
+
WORKFLOW_DESERIALIZE,
|
|
17
18
|
type ParseResult,
|
|
18
19
|
type Resolvable,
|
|
19
20
|
} from '@ai-sdk/provider-utils';
|
|
@@ -28,10 +29,24 @@ type GatewayChatConfig = GatewayConfig & {
|
|
|
28
29
|
o11yHeaders: Resolvable<Record<string, string>>;
|
|
29
30
|
};
|
|
30
31
|
|
|
31
|
-
export class GatewayLanguageModel implements
|
|
32
|
-
readonly specificationVersion = '
|
|
32
|
+
export class GatewayLanguageModel implements LanguageModelV4 {
|
|
33
|
+
readonly specificationVersion = 'v4';
|
|
33
34
|
readonly supportedUrls = { '*/*': [/.*/] };
|
|
34
35
|
|
|
36
|
+
static [WORKFLOW_SERIALIZE](model: GatewayLanguageModel) {
|
|
37
|
+
return serializeModelOptions({
|
|
38
|
+
modelId: model.modelId,
|
|
39
|
+
config: model.config,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
static [WORKFLOW_DESERIALIZE](options: {
|
|
44
|
+
modelId: GatewayModelId;
|
|
45
|
+
config: GatewayChatConfig;
|
|
46
|
+
}) {
|
|
47
|
+
return new GatewayLanguageModel(options.modelId, options.config);
|
|
48
|
+
}
|
|
49
|
+
|
|
35
50
|
constructor(
|
|
36
51
|
readonly modelId: GatewayModelId,
|
|
37
52
|
private readonly config: GatewayChatConfig,
|
|
@@ -41,7 +56,7 @@ export class GatewayLanguageModel implements LanguageModelV3 {
|
|
|
41
56
|
return this.config.provider;
|
|
42
57
|
}
|
|
43
58
|
|
|
44
|
-
private async getArgs(options:
|
|
59
|
+
private async getArgs(options: LanguageModelV4CallOptions) {
|
|
45
60
|
const { abortSignal: _abortSignal, ...optionsWithoutSignal } = options;
|
|
46
61
|
|
|
47
62
|
return {
|
|
@@ -51,12 +66,14 @@ export class GatewayLanguageModel implements LanguageModelV3 {
|
|
|
51
66
|
}
|
|
52
67
|
|
|
53
68
|
async doGenerate(
|
|
54
|
-
options:
|
|
55
|
-
): Promise<
|
|
69
|
+
options: LanguageModelV4CallOptions,
|
|
70
|
+
): Promise<LanguageModelV4GenerateResult> {
|
|
56
71
|
const { args, warnings } = await this.getArgs(options);
|
|
57
72
|
const { abortSignal } = options;
|
|
58
73
|
|
|
59
|
-
const resolvedHeaders =
|
|
74
|
+
const resolvedHeaders = this.config.headers
|
|
75
|
+
? await resolve(this.config.headers)
|
|
76
|
+
: undefined;
|
|
60
77
|
|
|
61
78
|
try {
|
|
62
79
|
const {
|
|
@@ -88,17 +105,22 @@ export class GatewayLanguageModel implements LanguageModelV3 {
|
|
|
88
105
|
warnings,
|
|
89
106
|
};
|
|
90
107
|
} catch (error) {
|
|
91
|
-
throw await asGatewayError(
|
|
108
|
+
throw await asGatewayError(
|
|
109
|
+
error,
|
|
110
|
+
await parseAuthMethod(resolvedHeaders ?? {}),
|
|
111
|
+
);
|
|
92
112
|
}
|
|
93
113
|
}
|
|
94
114
|
|
|
95
115
|
async doStream(
|
|
96
|
-
options:
|
|
97
|
-
): Promise<
|
|
116
|
+
options: LanguageModelV4CallOptions,
|
|
117
|
+
): Promise<LanguageModelV4StreamResult> {
|
|
98
118
|
const { args, warnings } = await this.getArgs(options);
|
|
99
119
|
const { abortSignal } = options;
|
|
100
120
|
|
|
101
|
-
const resolvedHeaders =
|
|
121
|
+
const resolvedHeaders = this.config.headers
|
|
122
|
+
? await resolve(this.config.headers)
|
|
123
|
+
: undefined;
|
|
102
124
|
|
|
103
125
|
try {
|
|
104
126
|
const { value: response, responseHeaders } = await postJsonToApi({
|
|
@@ -122,8 +144,8 @@ export class GatewayLanguageModel implements LanguageModelV3 {
|
|
|
122
144
|
return {
|
|
123
145
|
stream: response.pipeThrough(
|
|
124
146
|
new TransformStream<
|
|
125
|
-
ParseResult<
|
|
126
|
-
|
|
147
|
+
ParseResult<LanguageModelV4StreamPart>,
|
|
148
|
+
LanguageModelV4StreamPart
|
|
127
149
|
>({
|
|
128
150
|
start(controller) {
|
|
129
151
|
if (warnings.length > 0) {
|
|
@@ -161,36 +183,34 @@ export class GatewayLanguageModel implements LanguageModelV3 {
|
|
|
161
183
|
response: { headers: responseHeaders },
|
|
162
184
|
};
|
|
163
185
|
} catch (error) {
|
|
164
|
-
throw await asGatewayError(
|
|
186
|
+
throw await asGatewayError(
|
|
187
|
+
error,
|
|
188
|
+
await parseAuthMethod(resolvedHeaders ?? {}),
|
|
189
|
+
);
|
|
165
190
|
}
|
|
166
191
|
}
|
|
167
192
|
|
|
168
|
-
private isFilePart(part: unknown) {
|
|
169
|
-
return (
|
|
170
|
-
part && typeof part === 'object' && 'type' in part && part.type === 'file'
|
|
171
|
-
);
|
|
172
|
-
}
|
|
173
|
-
|
|
174
193
|
/**
|
|
175
|
-
* Encodes
|
|
176
|
-
* instance directly to avoid copying the file data.
|
|
194
|
+
* Encodes inline `Uint8Array` file data to a base64 string in place.
|
|
177
195
|
* @param options - The options to encode.
|
|
178
|
-
* @returns The options with the file
|
|
196
|
+
* @returns The options with the file data encoded.
|
|
179
197
|
*/
|
|
180
|
-
private maybeEncodeFileParts(options:
|
|
198
|
+
private maybeEncodeFileParts(options: LanguageModelV4CallOptions) {
|
|
181
199
|
for (const message of options.prompt) {
|
|
200
|
+
if (!Array.isArray(message.content)) {
|
|
201
|
+
continue;
|
|
202
|
+
}
|
|
182
203
|
for (const part of message.content) {
|
|
183
|
-
if (
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
);
|
|
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
|
+
}
|
|
194
214
|
}
|
|
195
215
|
}
|
|
196
216
|
}
|
|
@@ -204,9 +224,19 @@ export class GatewayLanguageModel implements LanguageModelV3 {
|
|
|
204
224
|
|
|
205
225
|
private getModelConfigHeaders(modelId: string, streaming: boolean) {
|
|
206
226
|
return {
|
|
207
|
-
'ai-language-model-specification-version': '
|
|
227
|
+
'ai-language-model-specification-version': '4',
|
|
208
228
|
'ai-language-model-id': modelId,
|
|
209
229
|
'ai-language-model-streaming': String(streaming),
|
|
210
230
|
};
|
|
211
231
|
}
|
|
212
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,4 +1,16 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { LanguageModelV4 } from '@ai-sdk/provider';
|
|
2
|
+
|
|
3
|
+
export const KNOWN_MODEL_TYPES = [
|
|
4
|
+
'embedding',
|
|
5
|
+
'image',
|
|
6
|
+
'language',
|
|
7
|
+
'reranking',
|
|
8
|
+
'speech',
|
|
9
|
+
'transcription',
|
|
10
|
+
'video',
|
|
11
|
+
] as const;
|
|
12
|
+
|
|
13
|
+
export type KnownModelType = (typeof KNOWN_MODEL_TYPES)[number];
|
|
2
14
|
|
|
3
15
|
export interface GatewayLanguageModelEntry {
|
|
4
16
|
/**
|
|
@@ -49,10 +61,10 @@ export interface GatewayLanguageModelEntry {
|
|
|
49
61
|
/**
|
|
50
62
|
* Optional field to differentiate between model types.
|
|
51
63
|
*/
|
|
52
|
-
modelType?:
|
|
64
|
+
modelType?: KnownModelType | null;
|
|
53
65
|
}
|
|
54
66
|
|
|
55
67
|
export type GatewayLanguageModelSpecification = Pick<
|
|
56
|
-
|
|
68
|
+
LanguageModelV4,
|
|
57
69
|
'specificationVersion' | 'provider' | 'modelId'
|
|
58
70
|
>;
|
|
@@ -1,80 +1,52 @@
|
|
|
1
|
-
import { InferSchema, lazySchema, zodSchema } from '@ai-sdk/provider-utils';
|
|
2
|
-
import { z } from 'zod/v4';
|
|
3
|
-
|
|
4
1
|
// https://vercel.com/docs/ai-gateway/provider-options
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
byok: z
|
|
53
|
-
.record(z.string(), z.array(z.record(z.string(), z.unknown())))
|
|
54
|
-
.optional(),
|
|
55
|
-
/**
|
|
56
|
-
* Whether to filter by only providers that state they have zero data
|
|
57
|
-
* retention with Vercel AI Gateway. When enabled, only providers that
|
|
58
|
-
* have agreements with Vercel AI Gateway for zero data retention will be
|
|
59
|
-
* used.
|
|
60
|
-
*/
|
|
61
|
-
zeroDataRetention: z.boolean().optional(),
|
|
62
|
-
/**
|
|
63
|
-
* Per-provider timeouts for BYOK credentials in milliseconds.
|
|
64
|
-
* Controls how long to wait for a provider to start responding
|
|
65
|
-
* before falling back to the next available provider.
|
|
66
|
-
*
|
|
67
|
-
* Example: `{ byok: { openai: 5000, anthropic: 2000 } }`
|
|
68
|
-
*/
|
|
69
|
-
providerTimeouts: z
|
|
70
|
-
.object({
|
|
71
|
-
byok: z.record(z.string(), z.number().int().min(1000)).optional(),
|
|
72
|
-
})
|
|
73
|
-
.optional(),
|
|
74
|
-
}),
|
|
75
|
-
),
|
|
76
|
-
);
|
|
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;
|
|
77
49
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
50
|
+
/** Filter to providers with zero data retention agreements. */
|
|
51
|
+
zeroDataRetention?: boolean;
|
|
52
|
+
};
|