@tanstack/ai-vercel-gateway 0.2.12 → 0.2.15
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/dist/esm/adapters/evaluate.d.ts +61 -0
- package/dist/esm/adapters/evaluate.js +288 -0
- package/dist/esm/adapters/evaluate.js.map +1 -0
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/index.js +2 -1
- package/dist/esm/model-meta.d.ts +14 -10
- package/dist/esm/model-meta.js +7 -4
- package/dist/esm/model-meta.js.map +1 -1
- package/package.json +4 -4
- package/src/adapters/evaluate.ts +393 -0
- package/src/index.ts +7 -0
- package/src/model-meta.ts +65 -12
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tanstack/ai-vercel-gateway",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.15",
|
|
4
4
|
"description": "Vercel AI Gateway adapter for TanStack AI chat, embeddings, and image generation.",
|
|
5
5
|
"author": "Tanner Linsley",
|
|
6
6
|
"license": "MIT",
|
|
@@ -56,12 +56,12 @@
|
|
|
56
56
|
"vite": "^8.2.1"
|
|
57
57
|
},
|
|
58
58
|
"peerDependencies": {
|
|
59
|
-
"@tanstack/ai": "^0.
|
|
59
|
+
"@tanstack/ai": "^0.57.0"
|
|
60
60
|
},
|
|
61
61
|
"dependencies": {
|
|
62
62
|
"openai": "^6.41.0",
|
|
63
|
-
"@tanstack/ai-utils": "^0.4.
|
|
64
|
-
"@tanstack/openai-base": "^0.10.
|
|
63
|
+
"@tanstack/ai-utils": "^0.4.1",
|
|
64
|
+
"@tanstack/openai-base": "^0.10.14"
|
|
65
65
|
},
|
|
66
66
|
"scripts": {
|
|
67
67
|
"build": "vite build",
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
import { BaseEvaluateAdapter } from '@tanstack/ai/adapters'
|
|
2
|
+
import { toRunErrorPayload } from '@tanstack/ai/adapter-internals'
|
|
3
|
+
import {
|
|
4
|
+
getVercelGatewayApiKeyFromEnv,
|
|
5
|
+
withVercelGatewayDefaults,
|
|
6
|
+
} from '../utils/client'
|
|
7
|
+
import { mapGatewayModelOptions } from '../utils/map-gateway-options'
|
|
8
|
+
import type {
|
|
9
|
+
EvaluateAdapterResult,
|
|
10
|
+
EvaluateOptions,
|
|
11
|
+
WireAnswer,
|
|
12
|
+
WireQuestion,
|
|
13
|
+
} from '@tanstack/ai/adapters'
|
|
14
|
+
import type { VercelGatewayClientConfig } from '../utils/client'
|
|
15
|
+
import type { VercelGatewayRoutingOptions } from '../text/text-provider-options'
|
|
16
|
+
|
|
17
|
+
export interface VercelGatewayEvaluateConfig extends VercelGatewayClientConfig {}
|
|
18
|
+
|
|
19
|
+
export type VercelGatewayEvaluateModel = 'typesafe-ai/jev'
|
|
20
|
+
|
|
21
|
+
export type VercelGatewayEvaluateProviderOptions = Record<string, unknown> & {
|
|
22
|
+
gateway?: VercelGatewayRoutingOptions
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Documented evaluate URL from Vercel AI SDK `GatewayEvaluationModel.getUrl()`:
|
|
27
|
+
* `${baseURL}/evaluation-model` with default baseURL
|
|
28
|
+
* `https://ai-gateway.vercel.sh/v4/ai`. Not `/v1/chat/completions`.
|
|
29
|
+
* https://github.com/vercel/ai/blob/main/packages/gateway/src/gateway-evaluation-model.ts
|
|
30
|
+
*/
|
|
31
|
+
const EVALUATE_PATH = '/v4/ai/evaluation-model'
|
|
32
|
+
const DEFAULT_EVALUATE_URL = `https://ai-gateway.vercel.sh${EVALUATE_PATH}`
|
|
33
|
+
|
|
34
|
+
/** The gateway rejects the request with 400 when this header is absent. */
|
|
35
|
+
const GATEWAY_PROTOCOL_VERSION = '0.0.1'
|
|
36
|
+
|
|
37
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
38
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function isNumberRecord(value: unknown): value is Record<string, number> {
|
|
42
|
+
if (!isRecord(value)) return false
|
|
43
|
+
const values = Object.values(value)
|
|
44
|
+
for (const item of values) {
|
|
45
|
+
if (typeof item !== 'number') return false
|
|
46
|
+
}
|
|
47
|
+
return true
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function isStringRecord(value: unknown): value is Record<string, string> {
|
|
51
|
+
if (!isRecord(value)) return false
|
|
52
|
+
const values = Object.values(value)
|
|
53
|
+
for (const item of values) {
|
|
54
|
+
if (typeof item !== 'string') return false
|
|
55
|
+
}
|
|
56
|
+
return true
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function extraRequestHeaders(defaultHeaders: unknown) {
|
|
60
|
+
if (defaultHeaders == null) return {}
|
|
61
|
+
if (typeof Headers !== 'undefined' && defaultHeaders instanceof Headers) {
|
|
62
|
+
const headers: Record<string, string> = {}
|
|
63
|
+
const entries = defaultHeaders.entries()
|
|
64
|
+
for (const [key, value] of entries) {
|
|
65
|
+
headers[key] = value
|
|
66
|
+
}
|
|
67
|
+
return headers
|
|
68
|
+
}
|
|
69
|
+
if (Array.isArray(defaultHeaders)) {
|
|
70
|
+
const headers: Record<string, string> = {}
|
|
71
|
+
for (const entry of defaultHeaders) {
|
|
72
|
+
if (!Array.isArray(entry) || entry.length < 2) continue
|
|
73
|
+
const key = entry[0]
|
|
74
|
+
const value = entry[1]
|
|
75
|
+
if (typeof key === 'string' && typeof value === 'string') {
|
|
76
|
+
headers[key] = value
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return headers
|
|
80
|
+
}
|
|
81
|
+
if (!isRecord(defaultHeaders)) return {}
|
|
82
|
+
const headers: Record<string, string> = {}
|
|
83
|
+
const keys = Object.keys(defaultHeaders)
|
|
84
|
+
for (const key of keys) {
|
|
85
|
+
const value = defaultHeaders[key]
|
|
86
|
+
if (typeof value === 'string') headers[key] = value
|
|
87
|
+
}
|
|
88
|
+
return headers
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function resolveEvaluateUrl(baseURL: string | null | undefined) {
|
|
92
|
+
if (!baseURL) return DEFAULT_EVALUATE_URL
|
|
93
|
+
try {
|
|
94
|
+
return `${new URL(baseURL).origin}${EVALUATE_PATH}`
|
|
95
|
+
} catch {
|
|
96
|
+
return DEFAULT_EVALUATE_URL
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function toGatewayQuestion(question: WireQuestion) {
|
|
101
|
+
switch (question.type) {
|
|
102
|
+
case 'noul': {
|
|
103
|
+
if (question.criteria === undefined) {
|
|
104
|
+
return {
|
|
105
|
+
type: 'boolean' as const,
|
|
106
|
+
instructions: question.instructions,
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
type: 'boolean' as const,
|
|
111
|
+
instructions: question.instructions,
|
|
112
|
+
criteria: question.criteria,
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
case 'choice':
|
|
116
|
+
case 'score':
|
|
117
|
+
return question
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function toGatewayQuestions(questions: Record<string, WireQuestion>) {
|
|
122
|
+
const mapped: Record<string, unknown> = {}
|
|
123
|
+
const keys = Object.keys(questions)
|
|
124
|
+
for (const key of keys) {
|
|
125
|
+
const question = questions[key]
|
|
126
|
+
if (question === undefined) continue
|
|
127
|
+
mapped[key] = toGatewayQuestion(question)
|
|
128
|
+
}
|
|
129
|
+
return mapped
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function readCount(candidates: Array<unknown>) {
|
|
133
|
+
for (const candidate of candidates) {
|
|
134
|
+
if (typeof candidate === 'number') return candidate
|
|
135
|
+
}
|
|
136
|
+
return 0
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function toTokenUsage(usage: unknown) {
|
|
140
|
+
if (!isRecord(usage)) {
|
|
141
|
+
return { promptTokens: 0, completionTokens: 0, totalTokens: 0 }
|
|
142
|
+
}
|
|
143
|
+
const promptTokens = readCount([
|
|
144
|
+
usage.inputTokens,
|
|
145
|
+
usage.input_tokens,
|
|
146
|
+
usage.promptTokens,
|
|
147
|
+
usage.prompt_tokens,
|
|
148
|
+
])
|
|
149
|
+
const completionTokens = readCount([
|
|
150
|
+
usage.outputTokens,
|
|
151
|
+
usage.output_tokens,
|
|
152
|
+
usage.completionTokens,
|
|
153
|
+
usage.completion_tokens,
|
|
154
|
+
])
|
|
155
|
+
const totalTokens = readCount([
|
|
156
|
+
usage.totalTokens,
|
|
157
|
+
usage.total_tokens,
|
|
158
|
+
promptTokens + completionTokens,
|
|
159
|
+
])
|
|
160
|
+
return { promptTokens, completionTokens, totalTokens }
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function confidenceMap(providerMetadata: unknown) {
|
|
164
|
+
if (!isRecord(providerMetadata)) return {}
|
|
165
|
+
const typesafe = providerMetadata.typesafe
|
|
166
|
+
if (!isRecord(typesafe)) return {}
|
|
167
|
+
if (!isNumberRecord(typesafe.confidence)) return {}
|
|
168
|
+
return typesafe.confidence
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function confidenceFor(
|
|
172
|
+
key: string,
|
|
173
|
+
answer: Record<string, unknown>,
|
|
174
|
+
byKey: Record<string, number>,
|
|
175
|
+
) {
|
|
176
|
+
if (typeof answer.confidence === 'number') return answer.confidence
|
|
177
|
+
const fromMeta = byKey[key]
|
|
178
|
+
if (typeof fromMeta === 'number') return fromMeta
|
|
179
|
+
return 0
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
function toWireAnswer(answer: Record<string, unknown>, confidence: number) {
|
|
183
|
+
switch (answer.type) {
|
|
184
|
+
case 'boolean': {
|
|
185
|
+
if (typeof answer.probability !== 'number') {
|
|
186
|
+
throw new Error(
|
|
187
|
+
'Vercel Gateway evaluate boolean answer was missing probability',
|
|
188
|
+
)
|
|
189
|
+
}
|
|
190
|
+
return { type: 'noul' as const, noul: answer.probability }
|
|
191
|
+
}
|
|
192
|
+
case 'choice': {
|
|
193
|
+
if (typeof answer.choice !== 'string') {
|
|
194
|
+
throw new Error(
|
|
195
|
+
'Vercel Gateway evaluate choice answer was missing choice',
|
|
196
|
+
)
|
|
197
|
+
}
|
|
198
|
+
return {
|
|
199
|
+
type: 'choice' as const,
|
|
200
|
+
choice: answer.choice,
|
|
201
|
+
probabilities: isNumberRecord(answer.probabilities)
|
|
202
|
+
? answer.probabilities
|
|
203
|
+
: {},
|
|
204
|
+
confidence,
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
case 'score': {
|
|
208
|
+
if (typeof answer.score !== 'number') {
|
|
209
|
+
throw new Error(
|
|
210
|
+
'Vercel Gateway evaluate score answer was missing score',
|
|
211
|
+
)
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
type: 'score' as const,
|
|
215
|
+
score: answer.score,
|
|
216
|
+
legend: isStringRecord(answer.legend) ? answer.legend : {},
|
|
217
|
+
probabilities: isNumberRecord(answer.probabilities)
|
|
218
|
+
? answer.probabilities
|
|
219
|
+
: {},
|
|
220
|
+
confidence,
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
default:
|
|
224
|
+
throw new Error(
|
|
225
|
+
`Vercel Gateway evaluate answer had an unexpected type: ${String(answer.type)}`,
|
|
226
|
+
)
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
function toWireAnswers(answers: unknown, byKey: Record<string, number>) {
|
|
231
|
+
if (!isRecord(answers)) {
|
|
232
|
+
throw new Error('Vercel Gateway evaluate response was missing answers')
|
|
233
|
+
}
|
|
234
|
+
const mapped: Record<string, WireAnswer> = {}
|
|
235
|
+
const keys = Object.keys(answers)
|
|
236
|
+
for (const key of keys) {
|
|
237
|
+
const answer = answers[key]
|
|
238
|
+
if (!isRecord(answer)) {
|
|
239
|
+
throw new Error(
|
|
240
|
+
`Vercel Gateway evaluate answer "${key}" had an unexpected shape`,
|
|
241
|
+
)
|
|
242
|
+
}
|
|
243
|
+
mapped[key] = toWireAnswer(answer, confidenceFor(key, answer, byKey))
|
|
244
|
+
}
|
|
245
|
+
return mapped
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/**
|
|
249
|
+
* Vercel AI Gateway evaluate adapter.
|
|
250
|
+
*
|
|
251
|
+
* Talks to `POST /v4/ai/evaluation-model` with `fetch`. Jev is not a chat
|
|
252
|
+
* model; this adapter does not use `/v1/chat/completions`.
|
|
253
|
+
*/
|
|
254
|
+
export class VercelGatewayEvaluateAdapter<
|
|
255
|
+
TModel extends VercelGatewayEvaluateModel,
|
|
256
|
+
> extends BaseEvaluateAdapter<TModel, VercelGatewayEvaluateProviderOptions> {
|
|
257
|
+
readonly name = 'vercel-gateway' as const
|
|
258
|
+
|
|
259
|
+
private readonly apiKey: string
|
|
260
|
+
private readonly evaluateUrl: string
|
|
261
|
+
private readonly extraHeaders: Record<string, string>
|
|
262
|
+
|
|
263
|
+
constructor(config: VercelGatewayEvaluateConfig, model: TModel) {
|
|
264
|
+
super({}, model)
|
|
265
|
+
const defaults = withVercelGatewayDefaults(config)
|
|
266
|
+
this.apiKey = config.apiKey
|
|
267
|
+
this.evaluateUrl = resolveEvaluateUrl(defaults.baseURL)
|
|
268
|
+
this.extraHeaders = extraRequestHeaders(defaults.defaultHeaders)
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
async evaluate(
|
|
272
|
+
options: EvaluateOptions<VercelGatewayEvaluateProviderOptions>,
|
|
273
|
+
) {
|
|
274
|
+
const { model, state, questions, modelOptions, abortSignal, logger } =
|
|
275
|
+
options
|
|
276
|
+
const mapped = mapGatewayModelOptions(modelOptions)
|
|
277
|
+
|
|
278
|
+
logger.request(`activity=evaluate provider=${this.name} model=${model}`, {
|
|
279
|
+
provider: this.name,
|
|
280
|
+
model,
|
|
281
|
+
})
|
|
282
|
+
|
|
283
|
+
try {
|
|
284
|
+
const response = await fetch(this.evaluateUrl, {
|
|
285
|
+
method: 'POST',
|
|
286
|
+
headers: {
|
|
287
|
+
...this.extraHeaders,
|
|
288
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
289
|
+
'Content-Type': 'application/json',
|
|
290
|
+
'ai-gateway-protocol-version': GATEWAY_PROTOCOL_VERSION,
|
|
291
|
+
'ai-evaluation-model-specification-version': '4',
|
|
292
|
+
'ai-model-id': model,
|
|
293
|
+
},
|
|
294
|
+
body: JSON.stringify({
|
|
295
|
+
...mapped,
|
|
296
|
+
model,
|
|
297
|
+
state,
|
|
298
|
+
questions: toGatewayQuestions(questions),
|
|
299
|
+
}),
|
|
300
|
+
...(abortSignal ? { signal: abortSignal } : {}),
|
|
301
|
+
})
|
|
302
|
+
|
|
303
|
+
if (!response.ok) {
|
|
304
|
+
const detail = await response.text().catch(() => '')
|
|
305
|
+
throw new Error(
|
|
306
|
+
`Vercel Gateway evaluate request failed: ${response.status} ${response.statusText}${
|
|
307
|
+
detail ? ` — ${detail}` : ''
|
|
308
|
+
}`,
|
|
309
|
+
)
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const json: unknown = await response.json()
|
|
313
|
+
if (!isRecord(json)) {
|
|
314
|
+
throw new Error(
|
|
315
|
+
'Vercel Gateway evaluate response had an unexpected shape',
|
|
316
|
+
)
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
const result: EvaluateAdapterResult = {
|
|
320
|
+
model: typeof json.model === 'string' ? json.model : model,
|
|
321
|
+
answers: toWireAnswers(
|
|
322
|
+
json.answers,
|
|
323
|
+
confidenceMap(json.providerMetadata),
|
|
324
|
+
),
|
|
325
|
+
usage: toTokenUsage(json.usage),
|
|
326
|
+
}
|
|
327
|
+
return result
|
|
328
|
+
} catch (error: unknown) {
|
|
329
|
+
logger.errors(`${this.name}.evaluate fatal`, {
|
|
330
|
+
error: toRunErrorPayload(error, `${this.name}.evaluate failed`),
|
|
331
|
+
source: `${this.name}.evaluate`,
|
|
332
|
+
})
|
|
333
|
+
throw error
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Create a Vercel AI Gateway evaluate adapter with an explicit API key.
|
|
340
|
+
*
|
|
341
|
+
* @param model Evaluate model id. Use `typesafe-ai/jev`.
|
|
342
|
+
* @param apiKey Vercel AI Gateway API key.
|
|
343
|
+
* @param config Optional client config (`baseURL`, `httpReferer`, `xTitle`).
|
|
344
|
+
*
|
|
345
|
+
* @example
|
|
346
|
+
* ```ts
|
|
347
|
+
* const adapter = createVercelGatewayDecider('typesafe-ai/jev', 'vck_...')
|
|
348
|
+
* ```
|
|
349
|
+
*/
|
|
350
|
+
export function createVercelGatewayDecider<
|
|
351
|
+
TModel extends VercelGatewayEvaluateModel,
|
|
352
|
+
>(
|
|
353
|
+
model: TModel,
|
|
354
|
+
apiKey: string,
|
|
355
|
+
config?: Omit<VercelGatewayEvaluateConfig, 'apiKey'>,
|
|
356
|
+
) {
|
|
357
|
+
return new VercelGatewayEvaluateAdapter({ apiKey, ...config }, model)
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Create a Vercel AI Gateway evaluate adapter.
|
|
362
|
+
*
|
|
363
|
+
* Reads `AI_GATEWAY_API_KEY`, then `VERCEL_OIDC_TOKEN`.
|
|
364
|
+
*
|
|
365
|
+
* @param model Evaluate model id. Use `typesafe-ai/jev`.
|
|
366
|
+
* @param config Optional client config (`baseURL`, `httpReferer`, `xTitle`).
|
|
367
|
+
*
|
|
368
|
+
* @example
|
|
369
|
+
* ```ts
|
|
370
|
+
* import { decide, boolean } from '@tanstack/ai'
|
|
371
|
+
* import { vercelGatewayDecider } from '@tanstack/ai-vercel-gateway'
|
|
372
|
+
*
|
|
373
|
+
* const result = await decide({
|
|
374
|
+
* adapter: vercelGatewayDecider('typesafe-ai/jev'),
|
|
375
|
+
* state: ticket,
|
|
376
|
+
* questions: {
|
|
377
|
+
* refund: boolean({
|
|
378
|
+
* instructions: 'Is the customer asking for a refund?',
|
|
379
|
+
* }),
|
|
380
|
+
* },
|
|
381
|
+
* })
|
|
382
|
+
* ```
|
|
383
|
+
*/
|
|
384
|
+
export function vercelGatewayDecider<TModel extends VercelGatewayEvaluateModel>(
|
|
385
|
+
model: TModel,
|
|
386
|
+
config?: Omit<VercelGatewayEvaluateConfig, 'apiKey'>,
|
|
387
|
+
) {
|
|
388
|
+
return createVercelGatewayDecider(
|
|
389
|
+
model,
|
|
390
|
+
getVercelGatewayApiKeyFromEnv(),
|
|
391
|
+
config,
|
|
392
|
+
)
|
|
393
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -47,6 +47,13 @@ export {
|
|
|
47
47
|
type VercelGatewayImageConfig,
|
|
48
48
|
} from './adapters/image'
|
|
49
49
|
|
|
50
|
+
export {
|
|
51
|
+
VercelGatewayEvaluateAdapter,
|
|
52
|
+
createVercelGatewayDecider,
|
|
53
|
+
vercelGatewayDecider,
|
|
54
|
+
type VercelGatewayEvaluateConfig,
|
|
55
|
+
} from './adapters/evaluate'
|
|
56
|
+
|
|
50
57
|
export type { VercelGatewayEmbeddingProviderOptions } from './embedding/embedding-provider-options'
|
|
51
58
|
export type { VercelGatewayImageProviderOptions } from './image/image-provider-options'
|
|
52
59
|
export type {
|
package/src/model-meta.ts
CHANGED
|
@@ -44,6 +44,7 @@ export const VERCEL_GATEWAY_CHAT_MODELS = [
|
|
|
44
44
|
'alibaba/qwen3.8-flash',
|
|
45
45
|
'alibaba/qwen3.8-max',
|
|
46
46
|
'alibaba/qwen3.8-max-0902',
|
|
47
|
+
'alibaba/qwen3.8-omni-flash',
|
|
47
48
|
'amazon/nova-2-lite',
|
|
48
49
|
'amazon/nova-lite',
|
|
49
50
|
'amazon/nova-micro',
|
|
@@ -81,13 +82,9 @@ export const VERCEL_GATEWAY_CHAT_MODELS = [
|
|
|
81
82
|
'deepseek/deepseek-v4-pro-0813',
|
|
82
83
|
'deepseek/deepseek-v4.1-flash',
|
|
83
84
|
'fish-audio/s1',
|
|
84
|
-
'fish-audio/s1-free',
|
|
85
85
|
'fish-audio/s2-pro',
|
|
86
|
-
'fish-audio/s2-pro-free',
|
|
87
86
|
'fish-audio/s2.1-pro',
|
|
88
|
-
'fish-audio/s2.1-pro-free',
|
|
89
87
|
'fish-audio/transcribe-1',
|
|
90
|
-
'fish-audio/transcribe-1-free',
|
|
91
88
|
'google/gemini-2.5-flash',
|
|
92
89
|
'google/gemini-2.5-flash-image',
|
|
93
90
|
'google/gemini-2.5-flash-lite',
|
|
@@ -151,6 +148,7 @@ export const VERCEL_GATEWAY_CHAT_MODELS = [
|
|
|
151
148
|
'mistral/mistral-medium-3.5',
|
|
152
149
|
'mistral/mistral-nemo',
|
|
153
150
|
'mistral/mistral-small',
|
|
151
|
+
'mixedbread/toast-1',
|
|
154
152
|
'moonshotai/kimi-k2',
|
|
155
153
|
'moonshotai/kimi-k2-thinking',
|
|
156
154
|
'moonshotai/kimi-k2.5',
|
|
@@ -241,6 +239,8 @@ export const VERCEL_GATEWAY_CHAT_MODELS = [
|
|
|
241
239
|
'perplexity/sonar-reasoning-pro',
|
|
242
240
|
'poolside/laguna-s-2.1',
|
|
243
241
|
'poolside/laguna-s-2.1-free',
|
|
242
|
+
'quiverai/arrow-2',
|
|
243
|
+
'quiverai/arrow-2-telos',
|
|
244
244
|
'sakana/fugu-max',
|
|
245
245
|
'sakana/fugu-ultra',
|
|
246
246
|
'sakana/fugu-ultra-v2',
|
|
@@ -263,6 +263,7 @@ export const VERCEL_GATEWAY_CHAT_MODELS = [
|
|
|
263
263
|
'spacexai/grok-voice-think-fast-2.0',
|
|
264
264
|
'stepfun/step-3.5-flash',
|
|
265
265
|
'stepfun/step-3.7-flash',
|
|
266
|
+
'stepfun/step-5-preview',
|
|
266
267
|
'tencent/hy-mt2-lite',
|
|
267
268
|
'tencent/hy-mt2-plus',
|
|
268
269
|
'tencent/hy-mt2-pro',
|
|
@@ -288,6 +289,7 @@ export const VERCEL_GATEWAY_CHAT_MODELS = [
|
|
|
288
289
|
'zai/glm-5.3',
|
|
289
290
|
'zai/glm-5.3-fast',
|
|
290
291
|
'zai/glm-5.3-flash',
|
|
292
|
+
'zai/glm-5.3-flashx',
|
|
291
293
|
'zai/glm-5v-turbo',
|
|
292
294
|
] as const
|
|
293
295
|
|
|
@@ -312,6 +314,7 @@ export const VERCEL_GATEWAY_PROVIDERS = [
|
|
|
312
314
|
'meta',
|
|
313
315
|
'minimax',
|
|
314
316
|
'mistral',
|
|
317
|
+
'mixedbread',
|
|
315
318
|
'moonshotai',
|
|
316
319
|
'morph',
|
|
317
320
|
'nvidia',
|
|
@@ -682,6 +685,18 @@ export type VercelGatewayChatModelProviderOptionsByName = {
|
|
|
682
685
|
| 'reasoning'
|
|
683
686
|
| 'include_reasoning'
|
|
684
687
|
>
|
|
688
|
+
'alibaba/qwen3.8-omni-flash': VercelGatewayCommonOptions &
|
|
689
|
+
Pick<
|
|
690
|
+
VercelGatewayBaseOptions,
|
|
691
|
+
| 'max_tokens'
|
|
692
|
+
| 'max_output_tokens'
|
|
693
|
+
| 'temperature'
|
|
694
|
+
| 'stop'
|
|
695
|
+
| 'reasoning'
|
|
696
|
+
| 'include_reasoning'
|
|
697
|
+
| 'response_format'
|
|
698
|
+
| 'structured_outputs'
|
|
699
|
+
>
|
|
685
700
|
'amazon/nova-2-lite': VercelGatewayCommonOptions &
|
|
686
701
|
Pick<
|
|
687
702
|
VercelGatewayBaseOptions,
|
|
@@ -1006,13 +1021,9 @@ export type VercelGatewayChatModelProviderOptionsByName = {
|
|
|
1006
1021
|
| 'include_reasoning'
|
|
1007
1022
|
>
|
|
1008
1023
|
'fish-audio/s1': VercelGatewayCommonOptions
|
|
1009
|
-
'fish-audio/s1-free': VercelGatewayCommonOptions
|
|
1010
1024
|
'fish-audio/s2-pro': VercelGatewayCommonOptions
|
|
1011
|
-
'fish-audio/s2-pro-free': VercelGatewayCommonOptions
|
|
1012
1025
|
'fish-audio/s2.1-pro': VercelGatewayCommonOptions
|
|
1013
|
-
'fish-audio/s2.1-pro-free': VercelGatewayCommonOptions
|
|
1014
1026
|
'fish-audio/transcribe-1': VercelGatewayCommonOptions
|
|
1015
|
-
'fish-audio/transcribe-1-free': VercelGatewayCommonOptions
|
|
1016
1027
|
'google/gemini-2.5-flash': VercelGatewayCommonOptions &
|
|
1017
1028
|
Pick<
|
|
1018
1029
|
VercelGatewayBaseOptions,
|
|
@@ -1540,6 +1551,11 @@ export type VercelGatewayChatModelProviderOptionsByName = {
|
|
|
1540
1551
|
VercelGatewayBaseOptions,
|
|
1541
1552
|
'max_tokens' | 'max_output_tokens' | 'temperature' | 'stop'
|
|
1542
1553
|
>
|
|
1554
|
+
'mixedbread/toast-1': VercelGatewayCommonOptions &
|
|
1555
|
+
Pick<
|
|
1556
|
+
VercelGatewayBaseOptions,
|
|
1557
|
+
'max_tokens' | 'max_output_tokens' | 'temperature' | 'stop'
|
|
1558
|
+
>
|
|
1543
1559
|
'moonshotai/kimi-k2': VercelGatewayCommonOptions &
|
|
1544
1560
|
Pick<
|
|
1545
1561
|
VercelGatewayBaseOptions,
|
|
@@ -2257,6 +2273,26 @@ export type VercelGatewayChatModelProviderOptionsByName = {
|
|
|
2257
2273
|
| 'reasoning'
|
|
2258
2274
|
| 'include_reasoning'
|
|
2259
2275
|
>
|
|
2276
|
+
'quiverai/arrow-2': VercelGatewayCommonOptions &
|
|
2277
|
+
Pick<
|
|
2278
|
+
VercelGatewayBaseOptions,
|
|
2279
|
+
| 'max_tokens'
|
|
2280
|
+
| 'max_output_tokens'
|
|
2281
|
+
| 'temperature'
|
|
2282
|
+
| 'stop'
|
|
2283
|
+
| 'reasoning'
|
|
2284
|
+
| 'include_reasoning'
|
|
2285
|
+
>
|
|
2286
|
+
'quiverai/arrow-2-telos': VercelGatewayCommonOptions &
|
|
2287
|
+
Pick<
|
|
2288
|
+
VercelGatewayBaseOptions,
|
|
2289
|
+
| 'max_tokens'
|
|
2290
|
+
| 'max_output_tokens'
|
|
2291
|
+
| 'temperature'
|
|
2292
|
+
| 'stop'
|
|
2293
|
+
| 'reasoning'
|
|
2294
|
+
| 'include_reasoning'
|
|
2295
|
+
>
|
|
2260
2296
|
'sakana/fugu-max': VercelGatewayCommonOptions &
|
|
2261
2297
|
Pick<
|
|
2262
2298
|
VercelGatewayBaseOptions,
|
|
@@ -2440,6 +2476,11 @@ export type VercelGatewayChatModelProviderOptionsByName = {
|
|
|
2440
2476
|
| 'reasoning'
|
|
2441
2477
|
| 'include_reasoning'
|
|
2442
2478
|
>
|
|
2479
|
+
'stepfun/step-5-preview': VercelGatewayCommonOptions &
|
|
2480
|
+
Pick<
|
|
2481
|
+
VercelGatewayBaseOptions,
|
|
2482
|
+
'max_tokens' | 'max_output_tokens' | 'temperature' | 'stop'
|
|
2483
|
+
>
|
|
2443
2484
|
'tencent/hy-mt2-lite': VercelGatewayCommonOptions &
|
|
2444
2485
|
Pick<
|
|
2445
2486
|
VercelGatewayBaseOptions,
|
|
@@ -2666,6 +2707,16 @@ export type VercelGatewayChatModelProviderOptionsByName = {
|
|
|
2666
2707
|
| 'reasoning'
|
|
2667
2708
|
| 'include_reasoning'
|
|
2668
2709
|
>
|
|
2710
|
+
'zai/glm-5.3-flashx': VercelGatewayCommonOptions &
|
|
2711
|
+
Pick<
|
|
2712
|
+
VercelGatewayBaseOptions,
|
|
2713
|
+
| 'max_tokens'
|
|
2714
|
+
| 'max_output_tokens'
|
|
2715
|
+
| 'temperature'
|
|
2716
|
+
| 'stop'
|
|
2717
|
+
| 'reasoning'
|
|
2718
|
+
| 'include_reasoning'
|
|
2719
|
+
>
|
|
2669
2720
|
'zai/glm-5v-turbo': VercelGatewayCommonOptions &
|
|
2670
2721
|
Pick<
|
|
2671
2722
|
VercelGatewayBaseOptions,
|
|
@@ -2709,6 +2760,7 @@ export type VercelGatewayModelInputModalitiesByName = {
|
|
|
2709
2760
|
'alibaba/qwen3.8-flash': readonly ['text', 'image', 'document']
|
|
2710
2761
|
'alibaba/qwen3.8-max': readonly ['text', 'image']
|
|
2711
2762
|
'alibaba/qwen3.8-max-0902': readonly ['text', 'image', 'document']
|
|
2763
|
+
'alibaba/qwen3.8-omni-flash': readonly ['text', 'image']
|
|
2712
2764
|
'amazon/nova-2-lite': readonly ['text', 'image', 'document']
|
|
2713
2765
|
'amazon/nova-lite': readonly ['text', 'image', 'document']
|
|
2714
2766
|
'amazon/nova-micro': readonly ['text']
|
|
@@ -2746,13 +2798,9 @@ export type VercelGatewayModelInputModalitiesByName = {
|
|
|
2746
2798
|
'deepseek/deepseek-v4-pro-0813': readonly ['text']
|
|
2747
2799
|
'deepseek/deepseek-v4.1-flash': readonly ['text', 'image']
|
|
2748
2800
|
'fish-audio/s1': readonly ['text']
|
|
2749
|
-
'fish-audio/s1-free': readonly ['text']
|
|
2750
2801
|
'fish-audio/s2-pro': readonly ['text']
|
|
2751
|
-
'fish-audio/s2-pro-free': readonly ['text']
|
|
2752
2802
|
'fish-audio/s2.1-pro': readonly ['text']
|
|
2753
|
-
'fish-audio/s2.1-pro-free': readonly ['text']
|
|
2754
2803
|
'fish-audio/transcribe-1': readonly ['text', 'audio']
|
|
2755
|
-
'fish-audio/transcribe-1-free': readonly ['text', 'audio']
|
|
2756
2804
|
'google/gemini-2.5-flash': readonly ['text', 'image', 'document']
|
|
2757
2805
|
'google/gemini-2.5-flash-image': readonly ['text', 'image']
|
|
2758
2806
|
'google/gemini-2.5-flash-lite': readonly ['text', 'image', 'document']
|
|
@@ -2826,6 +2874,7 @@ export type VercelGatewayModelInputModalitiesByName = {
|
|
|
2826
2874
|
'mistral/mistral-medium-3.5': readonly ['text', 'image']
|
|
2827
2875
|
'mistral/mistral-nemo': readonly ['text']
|
|
2828
2876
|
'mistral/mistral-small': readonly ['text', 'image']
|
|
2877
|
+
'mixedbread/toast-1': readonly ['text']
|
|
2829
2878
|
'moonshotai/kimi-k2': readonly ['text']
|
|
2830
2879
|
'moonshotai/kimi-k2-thinking': readonly ['text']
|
|
2831
2880
|
'moonshotai/kimi-k2.5': readonly ['text', 'image']
|
|
@@ -2921,6 +2970,8 @@ export type VercelGatewayModelInputModalitiesByName = {
|
|
|
2921
2970
|
'perplexity/sonar-reasoning-pro': readonly ['text', 'image']
|
|
2922
2971
|
'poolside/laguna-s-2.1': readonly ['text']
|
|
2923
2972
|
'poolside/laguna-s-2.1-free': readonly ['text']
|
|
2973
|
+
'quiverai/arrow-2': readonly ['text', 'image']
|
|
2974
|
+
'quiverai/arrow-2-telos': readonly ['text', 'image']
|
|
2924
2975
|
'sakana/fugu-max': readonly ['text', 'image']
|
|
2925
2976
|
'sakana/fugu-ultra': readonly ['text', 'image']
|
|
2926
2977
|
'sakana/fugu-ultra-v2': readonly ['text', 'image']
|
|
@@ -2947,6 +2998,7 @@ export type VercelGatewayModelInputModalitiesByName = {
|
|
|
2947
2998
|
'spacexai/grok-voice-think-fast-2.0': readonly ['text', 'audio']
|
|
2948
2999
|
'stepfun/step-3.5-flash': readonly ['text', 'image']
|
|
2949
3000
|
'stepfun/step-3.7-flash': readonly ['text', 'image']
|
|
3001
|
+
'stepfun/step-5-preview': readonly ['text', 'image']
|
|
2950
3002
|
'tencent/hy-mt2-lite': readonly ['text']
|
|
2951
3003
|
'tencent/hy-mt2-plus': readonly ['text']
|
|
2952
3004
|
'tencent/hy-mt2-pro': readonly ['text']
|
|
@@ -2972,6 +3024,7 @@ export type VercelGatewayModelInputModalitiesByName = {
|
|
|
2972
3024
|
'zai/glm-5.3': readonly ['text']
|
|
2973
3025
|
'zai/glm-5.3-fast': readonly ['text']
|
|
2974
3026
|
'zai/glm-5.3-flash': readonly ['text', 'image']
|
|
3027
|
+
'zai/glm-5.3-flashx': readonly ['text', 'image']
|
|
2975
3028
|
'zai/glm-5v-turbo': readonly ['text', 'image', 'document']
|
|
2976
3029
|
}
|
|
2977
3030
|
|