@tanstack/ai-llmgateway 0.0.0
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/LICENSE +21 -0
- package/README.md +94 -0
- package/dist/esm/adapters/summarize.d.ts +51 -0
- package/dist/esm/adapters/summarize.js +55 -0
- package/dist/esm/adapters/summarize.js.map +1 -0
- package/dist/esm/adapters/text.d.ts +64 -0
- package/dist/esm/adapters/text.js +67 -0
- package/dist/esm/adapters/text.js.map +1 -0
- package/dist/esm/index.d.ts +14 -0
- package/dist/esm/index.js +5 -0
- package/dist/esm/message-types.d.ts +116 -0
- package/dist/esm/model-meta.d.ts +374 -0
- package/dist/esm/model-meta.js +363 -0
- package/dist/esm/model-meta.js.map +1 -0
- package/dist/esm/text/text-provider-options.d.ts +97 -0
- package/dist/esm/utils/client.d.ts +16 -0
- package/dist/esm/utils/client.js +29 -0
- package/dist/esm/utils/client.js.map +1 -0
- package/package.json +74 -0
- package/src/adapters/summarize.ts +79 -0
- package/src/adapters/text.ts +119 -0
- package/src/index.ts +52 -0
- package/src/message-types.ts +130 -0
- package/src/model-meta.ts +516 -0
- package/src/text/text-provider-options.ts +128 -0
- package/src/utils/client.ts +36 -0
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
import type { LLMGatewayTextProviderOptions } from './text/text-provider-options'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Internal metadata structure describing an LLM Gateway model's capabilities
|
|
5
|
+
* and pricing.
|
|
6
|
+
*
|
|
7
|
+
* LLM Gateway routes hundreds of models from many providers through one
|
|
8
|
+
* OpenAI-compatible endpoint. This file curates a set of flagship models
|
|
9
|
+
* with per-model metadata for type safety; any model listed on
|
|
10
|
+
* https://llmgateway.io/models works at runtime — pass its id with a type
|
|
11
|
+
* assertion, or prefer a curated model for full type support. Prices are
|
|
12
|
+
* USD per million tokens and follow the gateway's provider-passthrough
|
|
13
|
+
* pricing (they may drift; the models page is the source of truth).
|
|
14
|
+
*
|
|
15
|
+
* Model ids accept an optional `provider/` prefix (e.g. `openai/gpt-5.5`)
|
|
16
|
+
* to pin routing to a specific provider — the unprefixed ids below let the
|
|
17
|
+
* gateway pick the best available provider.
|
|
18
|
+
*/
|
|
19
|
+
interface ModelMeta<TProviderOptions = unknown> {
|
|
20
|
+
name: string
|
|
21
|
+
context_window?: number
|
|
22
|
+
max_completion_tokens?: number
|
|
23
|
+
pricing: {
|
|
24
|
+
input?: { normal: number; cached?: number }
|
|
25
|
+
output?: { normal: number }
|
|
26
|
+
}
|
|
27
|
+
supports: {
|
|
28
|
+
input: Array<'text' | 'image' | 'audio'>
|
|
29
|
+
output: Array<'text'>
|
|
30
|
+
endpoints: Array<'chat'>
|
|
31
|
+
features: Array<
|
|
32
|
+
| 'streaming'
|
|
33
|
+
| 'tools'
|
|
34
|
+
| 'json_object'
|
|
35
|
+
| 'json_schema'
|
|
36
|
+
| 'reasoning'
|
|
37
|
+
| 'vision'
|
|
38
|
+
>
|
|
39
|
+
tools?: ReadonlyArray<never>
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Type-level description of which provider options this model supports.
|
|
43
|
+
*/
|
|
44
|
+
providerOptions?: TProviderOptions
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
const GPT_5_6_TERRA = {
|
|
48
|
+
name: 'gpt-5.6-terra',
|
|
49
|
+
context_window: 1_050_000,
|
|
50
|
+
max_completion_tokens: 128_000,
|
|
51
|
+
pricing: {
|
|
52
|
+
input: {
|
|
53
|
+
normal: 2.5,
|
|
54
|
+
cached: 0.25,
|
|
55
|
+
},
|
|
56
|
+
output: {
|
|
57
|
+
normal: 15,
|
|
58
|
+
},
|
|
59
|
+
},
|
|
60
|
+
supports: {
|
|
61
|
+
input: ['text', 'image'],
|
|
62
|
+
output: ['text'],
|
|
63
|
+
endpoints: ['chat'],
|
|
64
|
+
features: [
|
|
65
|
+
'streaming',
|
|
66
|
+
'tools',
|
|
67
|
+
'json_object',
|
|
68
|
+
'json_schema',
|
|
69
|
+
'reasoning',
|
|
70
|
+
'vision',
|
|
71
|
+
],
|
|
72
|
+
tools: [] as const,
|
|
73
|
+
},
|
|
74
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
75
|
+
|
|
76
|
+
const GPT_5_5 = {
|
|
77
|
+
name: 'gpt-5.5',
|
|
78
|
+
context_window: 1_050_000,
|
|
79
|
+
max_completion_tokens: 128_000,
|
|
80
|
+
pricing: {
|
|
81
|
+
input: {
|
|
82
|
+
normal: 5,
|
|
83
|
+
cached: 0.5,
|
|
84
|
+
},
|
|
85
|
+
output: {
|
|
86
|
+
normal: 30,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
supports: {
|
|
90
|
+
input: ['text', 'image'],
|
|
91
|
+
output: ['text'],
|
|
92
|
+
endpoints: ['chat'],
|
|
93
|
+
features: [
|
|
94
|
+
'streaming',
|
|
95
|
+
'tools',
|
|
96
|
+
'json_object',
|
|
97
|
+
'json_schema',
|
|
98
|
+
'reasoning',
|
|
99
|
+
'vision',
|
|
100
|
+
],
|
|
101
|
+
tools: [] as const,
|
|
102
|
+
},
|
|
103
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
104
|
+
|
|
105
|
+
const GPT_5_4_MINI = {
|
|
106
|
+
name: 'gpt-5.4-mini',
|
|
107
|
+
context_window: 400_000,
|
|
108
|
+
max_completion_tokens: 128_000,
|
|
109
|
+
pricing: {
|
|
110
|
+
input: {
|
|
111
|
+
normal: 0.75,
|
|
112
|
+
cached: 0.075,
|
|
113
|
+
},
|
|
114
|
+
output: {
|
|
115
|
+
normal: 4.5,
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
supports: {
|
|
119
|
+
input: ['text', 'image'],
|
|
120
|
+
output: ['text'],
|
|
121
|
+
endpoints: ['chat'],
|
|
122
|
+
features: [
|
|
123
|
+
'streaming',
|
|
124
|
+
'tools',
|
|
125
|
+
'json_object',
|
|
126
|
+
'json_schema',
|
|
127
|
+
'reasoning',
|
|
128
|
+
'vision',
|
|
129
|
+
],
|
|
130
|
+
tools: [] as const,
|
|
131
|
+
},
|
|
132
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
133
|
+
|
|
134
|
+
const CLAUDE_OPUS_5 = {
|
|
135
|
+
name: 'claude-opus-5',
|
|
136
|
+
context_window: 1_000_000,
|
|
137
|
+
max_completion_tokens: 128_000,
|
|
138
|
+
pricing: {
|
|
139
|
+
input: {
|
|
140
|
+
normal: 5,
|
|
141
|
+
cached: 0.5,
|
|
142
|
+
},
|
|
143
|
+
output: {
|
|
144
|
+
normal: 25,
|
|
145
|
+
},
|
|
146
|
+
},
|
|
147
|
+
supports: {
|
|
148
|
+
input: ['text', 'image'],
|
|
149
|
+
output: ['text'],
|
|
150
|
+
endpoints: ['chat'],
|
|
151
|
+
features: ['streaming', 'tools', 'reasoning', 'vision'],
|
|
152
|
+
tools: [] as const,
|
|
153
|
+
},
|
|
154
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
155
|
+
|
|
156
|
+
const CLAUDE_SONNET_5 = {
|
|
157
|
+
name: 'claude-sonnet-5',
|
|
158
|
+
context_window: 1_000_000,
|
|
159
|
+
max_completion_tokens: 128_000,
|
|
160
|
+
pricing: {
|
|
161
|
+
input: {
|
|
162
|
+
normal: 2,
|
|
163
|
+
cached: 0.2,
|
|
164
|
+
},
|
|
165
|
+
output: {
|
|
166
|
+
normal: 10,
|
|
167
|
+
},
|
|
168
|
+
},
|
|
169
|
+
supports: {
|
|
170
|
+
input: ['text', 'image'],
|
|
171
|
+
output: ['text'],
|
|
172
|
+
endpoints: ['chat'],
|
|
173
|
+
features: ['streaming', 'tools', 'reasoning', 'vision'],
|
|
174
|
+
tools: [] as const,
|
|
175
|
+
},
|
|
176
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
177
|
+
|
|
178
|
+
const CLAUDE_HAIKU_4_5 = {
|
|
179
|
+
name: 'claude-haiku-4-5',
|
|
180
|
+
context_window: 200_000,
|
|
181
|
+
max_completion_tokens: 64_000,
|
|
182
|
+
pricing: {
|
|
183
|
+
input: {
|
|
184
|
+
normal: 1,
|
|
185
|
+
cached: 0.1,
|
|
186
|
+
},
|
|
187
|
+
output: {
|
|
188
|
+
normal: 5,
|
|
189
|
+
},
|
|
190
|
+
},
|
|
191
|
+
supports: {
|
|
192
|
+
input: ['text', 'image'],
|
|
193
|
+
output: ['text'],
|
|
194
|
+
endpoints: ['chat'],
|
|
195
|
+
features: [
|
|
196
|
+
'streaming',
|
|
197
|
+
'tools',
|
|
198
|
+
'json_object',
|
|
199
|
+
'json_schema',
|
|
200
|
+
'reasoning',
|
|
201
|
+
'vision',
|
|
202
|
+
],
|
|
203
|
+
tools: [] as const,
|
|
204
|
+
},
|
|
205
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
206
|
+
|
|
207
|
+
const GEMINI_PRO_LATEST = {
|
|
208
|
+
name: 'gemini-pro-latest',
|
|
209
|
+
context_window: 1_048_576,
|
|
210
|
+
max_completion_tokens: 65_536,
|
|
211
|
+
pricing: {
|
|
212
|
+
input: {
|
|
213
|
+
normal: 2,
|
|
214
|
+
cached: 0.2,
|
|
215
|
+
},
|
|
216
|
+
output: {
|
|
217
|
+
normal: 12,
|
|
218
|
+
},
|
|
219
|
+
},
|
|
220
|
+
supports: {
|
|
221
|
+
input: ['text', 'image'],
|
|
222
|
+
output: ['text'],
|
|
223
|
+
endpoints: ['chat'],
|
|
224
|
+
features: [
|
|
225
|
+
'streaming',
|
|
226
|
+
'tools',
|
|
227
|
+
'json_object',
|
|
228
|
+
'json_schema',
|
|
229
|
+
'reasoning',
|
|
230
|
+
'vision',
|
|
231
|
+
],
|
|
232
|
+
tools: [] as const,
|
|
233
|
+
},
|
|
234
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
235
|
+
|
|
236
|
+
const GEMINI_3_6_FLASH = {
|
|
237
|
+
name: 'gemini-3.6-flash',
|
|
238
|
+
context_window: 1_048_576,
|
|
239
|
+
max_completion_tokens: 65_536,
|
|
240
|
+
pricing: {
|
|
241
|
+
input: {
|
|
242
|
+
normal: 1.5,
|
|
243
|
+
cached: 0.15,
|
|
244
|
+
},
|
|
245
|
+
output: {
|
|
246
|
+
normal: 7.5,
|
|
247
|
+
},
|
|
248
|
+
},
|
|
249
|
+
supports: {
|
|
250
|
+
input: ['text', 'image'],
|
|
251
|
+
output: ['text'],
|
|
252
|
+
endpoints: ['chat'],
|
|
253
|
+
features: [
|
|
254
|
+
'streaming',
|
|
255
|
+
'tools',
|
|
256
|
+
'json_object',
|
|
257
|
+
'json_schema',
|
|
258
|
+
'reasoning',
|
|
259
|
+
'vision',
|
|
260
|
+
],
|
|
261
|
+
tools: [] as const,
|
|
262
|
+
},
|
|
263
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
264
|
+
|
|
265
|
+
const KIMI_K3 = {
|
|
266
|
+
name: 'kimi-k3',
|
|
267
|
+
context_window: 1_048_576,
|
|
268
|
+
max_completion_tokens: 1_048_576,
|
|
269
|
+
pricing: {
|
|
270
|
+
input: {
|
|
271
|
+
normal: 3,
|
|
272
|
+
cached: 0.3,
|
|
273
|
+
},
|
|
274
|
+
output: {
|
|
275
|
+
normal: 15,
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
supports: {
|
|
279
|
+
input: ['text', 'image'],
|
|
280
|
+
output: ['text'],
|
|
281
|
+
endpoints: ['chat'],
|
|
282
|
+
features: [
|
|
283
|
+
'streaming',
|
|
284
|
+
'tools',
|
|
285
|
+
'json_object',
|
|
286
|
+
'json_schema',
|
|
287
|
+
'reasoning',
|
|
288
|
+
'vision',
|
|
289
|
+
],
|
|
290
|
+
tools: [] as const,
|
|
291
|
+
},
|
|
292
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
293
|
+
|
|
294
|
+
const GLM_5_2 = {
|
|
295
|
+
name: 'glm-5.2',
|
|
296
|
+
context_window: 1_000_000,
|
|
297
|
+
max_completion_tokens: 128_000,
|
|
298
|
+
pricing: {
|
|
299
|
+
input: {
|
|
300
|
+
normal: 1.4,
|
|
301
|
+
cached: 0.26,
|
|
302
|
+
},
|
|
303
|
+
output: {
|
|
304
|
+
normal: 4.4,
|
|
305
|
+
},
|
|
306
|
+
},
|
|
307
|
+
supports: {
|
|
308
|
+
input: ['text'],
|
|
309
|
+
output: ['text'],
|
|
310
|
+
endpoints: ['chat'],
|
|
311
|
+
features: ['streaming', 'tools', 'json_object', 'json_schema', 'reasoning'],
|
|
312
|
+
tools: [] as const,
|
|
313
|
+
},
|
|
314
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
315
|
+
|
|
316
|
+
const DEEPSEEK_V4_PRO = {
|
|
317
|
+
name: 'deepseek-v4-pro',
|
|
318
|
+
context_window: 1_050_000,
|
|
319
|
+
max_completion_tokens: 393_216,
|
|
320
|
+
pricing: {
|
|
321
|
+
input: {
|
|
322
|
+
normal: 0.435,
|
|
323
|
+
},
|
|
324
|
+
output: {
|
|
325
|
+
normal: 0.87,
|
|
326
|
+
},
|
|
327
|
+
},
|
|
328
|
+
supports: {
|
|
329
|
+
input: ['text'],
|
|
330
|
+
output: ['text'],
|
|
331
|
+
endpoints: ['chat'],
|
|
332
|
+
features: ['streaming', 'tools', 'json_object', 'json_schema', 'reasoning'],
|
|
333
|
+
tools: [] as const,
|
|
334
|
+
},
|
|
335
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
336
|
+
|
|
337
|
+
const QWEN_3_7_MAX = {
|
|
338
|
+
name: 'qwen3.7-max',
|
|
339
|
+
context_window: 1_000_000,
|
|
340
|
+
max_completion_tokens: 65_536,
|
|
341
|
+
pricing: {
|
|
342
|
+
input: {
|
|
343
|
+
normal: 2.5,
|
|
344
|
+
cached: 0.5,
|
|
345
|
+
},
|
|
346
|
+
output: {
|
|
347
|
+
normal: 7.5,
|
|
348
|
+
},
|
|
349
|
+
},
|
|
350
|
+
supports: {
|
|
351
|
+
input: ['text'],
|
|
352
|
+
output: ['text'],
|
|
353
|
+
endpoints: ['chat'],
|
|
354
|
+
features: ['streaming', 'tools', 'json_object', 'json_schema', 'reasoning'],
|
|
355
|
+
tools: [] as const,
|
|
356
|
+
},
|
|
357
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
358
|
+
|
|
359
|
+
const MINIMAX_M2_5 = {
|
|
360
|
+
name: 'minimax-m2.5',
|
|
361
|
+
context_window: 204_800,
|
|
362
|
+
max_completion_tokens: 131_100,
|
|
363
|
+
pricing: {
|
|
364
|
+
input: {
|
|
365
|
+
normal: 0.3,
|
|
366
|
+
cached: 0.03,
|
|
367
|
+
},
|
|
368
|
+
output: {
|
|
369
|
+
normal: 1.2,
|
|
370
|
+
},
|
|
371
|
+
},
|
|
372
|
+
supports: {
|
|
373
|
+
input: ['text'],
|
|
374
|
+
output: ['text'],
|
|
375
|
+
endpoints: ['chat'],
|
|
376
|
+
features: ['streaming', 'tools', 'reasoning'],
|
|
377
|
+
tools: [] as const,
|
|
378
|
+
},
|
|
379
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
380
|
+
|
|
381
|
+
const GROK_4_5 = {
|
|
382
|
+
name: 'grok-4-5',
|
|
383
|
+
context_window: 500_000,
|
|
384
|
+
pricing: {
|
|
385
|
+
input: {
|
|
386
|
+
normal: 2,
|
|
387
|
+
cached: 0.5,
|
|
388
|
+
},
|
|
389
|
+
output: {
|
|
390
|
+
normal: 6,
|
|
391
|
+
},
|
|
392
|
+
},
|
|
393
|
+
supports: {
|
|
394
|
+
input: ['text', 'image'],
|
|
395
|
+
output: ['text'],
|
|
396
|
+
endpoints: ['chat'],
|
|
397
|
+
features: [
|
|
398
|
+
'streaming',
|
|
399
|
+
'tools',
|
|
400
|
+
'json_object',
|
|
401
|
+
'json_schema',
|
|
402
|
+
'reasoning',
|
|
403
|
+
'vision',
|
|
404
|
+
],
|
|
405
|
+
tools: [] as const,
|
|
406
|
+
},
|
|
407
|
+
} as const satisfies ModelMeta<LLMGatewayTextProviderOptions>
|
|
408
|
+
|
|
409
|
+
/**
|
|
410
|
+
* Curated LLM Gateway chat model identifiers.
|
|
411
|
+
*
|
|
412
|
+
* Any model on https://llmgateway.io/models works at runtime; these curated
|
|
413
|
+
* entries carry per-model type metadata (input modalities, provider
|
|
414
|
+
* options).
|
|
415
|
+
*/
|
|
416
|
+
export const LLMGATEWAY_CHAT_MODELS = [
|
|
417
|
+
GPT_5_6_TERRA.name,
|
|
418
|
+
GPT_5_5.name,
|
|
419
|
+
GPT_5_4_MINI.name,
|
|
420
|
+
CLAUDE_OPUS_5.name,
|
|
421
|
+
CLAUDE_SONNET_5.name,
|
|
422
|
+
CLAUDE_HAIKU_4_5.name,
|
|
423
|
+
GEMINI_PRO_LATEST.name,
|
|
424
|
+
GEMINI_3_6_FLASH.name,
|
|
425
|
+
KIMI_K3.name,
|
|
426
|
+
GLM_5_2.name,
|
|
427
|
+
DEEPSEEK_V4_PRO.name,
|
|
428
|
+
QWEN_3_7_MAX.name,
|
|
429
|
+
MINIMAX_M2_5.name,
|
|
430
|
+
GROK_4_5.name,
|
|
431
|
+
] as const
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Union type of all curated LLM Gateway chat model names.
|
|
435
|
+
*/
|
|
436
|
+
export type LLMGatewayChatModels = (typeof LLMGATEWAY_CHAT_MODELS)[number]
|
|
437
|
+
|
|
438
|
+
/**
|
|
439
|
+
* Model id accepted by the LLM Gateway adapters: a curated model name (with
|
|
440
|
+
* autocomplete and per-model type metadata) or any other model id from
|
|
441
|
+
* https://llmgateway.io/models, optionally prefixed with `provider/` to pin
|
|
442
|
+
* routing to a specific provider. Uncurated ids fall back to text-only
|
|
443
|
+
* input and the generic provider options.
|
|
444
|
+
*/
|
|
445
|
+
export type LLMGatewayModelId = LLMGatewayChatModels | (string & {})
|
|
446
|
+
|
|
447
|
+
/**
|
|
448
|
+
* Type-only map from LLM Gateway chat model name to its supported input
|
|
449
|
+
* modalities.
|
|
450
|
+
*/
|
|
451
|
+
export type LLMGatewayModelInputModalitiesByName = {
|
|
452
|
+
[GPT_5_6_TERRA.name]: typeof GPT_5_6_TERRA.supports.input
|
|
453
|
+
[GPT_5_5.name]: typeof GPT_5_5.supports.input
|
|
454
|
+
[GPT_5_4_MINI.name]: typeof GPT_5_4_MINI.supports.input
|
|
455
|
+
[CLAUDE_OPUS_5.name]: typeof CLAUDE_OPUS_5.supports.input
|
|
456
|
+
[CLAUDE_SONNET_5.name]: typeof CLAUDE_SONNET_5.supports.input
|
|
457
|
+
[CLAUDE_HAIKU_4_5.name]: typeof CLAUDE_HAIKU_4_5.supports.input
|
|
458
|
+
[GEMINI_PRO_LATEST.name]: typeof GEMINI_PRO_LATEST.supports.input
|
|
459
|
+
[GEMINI_3_6_FLASH.name]: typeof GEMINI_3_6_FLASH.supports.input
|
|
460
|
+
[KIMI_K3.name]: typeof KIMI_K3.supports.input
|
|
461
|
+
[GLM_5_2.name]: typeof GLM_5_2.supports.input
|
|
462
|
+
[DEEPSEEK_V4_PRO.name]: typeof DEEPSEEK_V4_PRO.supports.input
|
|
463
|
+
[QWEN_3_7_MAX.name]: typeof QWEN_3_7_MAX.supports.input
|
|
464
|
+
[MINIMAX_M2_5.name]: typeof MINIMAX_M2_5.supports.input
|
|
465
|
+
[GROK_4_5.name]: typeof GROK_4_5.supports.input
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Type-only map from LLM Gateway chat model name to its provider options
|
|
470
|
+
* type.
|
|
471
|
+
*/
|
|
472
|
+
export type LLMGatewayChatModelProviderOptionsByName = {
|
|
473
|
+
[K in (typeof LLMGATEWAY_CHAT_MODELS)[number]]: LLMGatewayTextProviderOptions
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
/**
|
|
477
|
+
* Type-only map from LLM Gateway chat model name to its supported provider
|
|
478
|
+
* tools. LLM Gateway exposes no provider-specific tool factories, so every
|
|
479
|
+
* model gets an empty tuple. This ensures that passing an Anthropic/OpenAI
|
|
480
|
+
* ProviderTool to an LLM Gateway adapter produces a compile-time type error.
|
|
481
|
+
*/
|
|
482
|
+
export type LLMGatewayChatModelToolCapabilitiesByName = {
|
|
483
|
+
[GPT_5_6_TERRA.name]: typeof GPT_5_6_TERRA.supports.tools
|
|
484
|
+
[GPT_5_5.name]: typeof GPT_5_5.supports.tools
|
|
485
|
+
[GPT_5_4_MINI.name]: typeof GPT_5_4_MINI.supports.tools
|
|
486
|
+
[CLAUDE_OPUS_5.name]: typeof CLAUDE_OPUS_5.supports.tools
|
|
487
|
+
[CLAUDE_SONNET_5.name]: typeof CLAUDE_SONNET_5.supports.tools
|
|
488
|
+
[CLAUDE_HAIKU_4_5.name]: typeof CLAUDE_HAIKU_4_5.supports.tools
|
|
489
|
+
[GEMINI_PRO_LATEST.name]: typeof GEMINI_PRO_LATEST.supports.tools
|
|
490
|
+
[GEMINI_3_6_FLASH.name]: typeof GEMINI_3_6_FLASH.supports.tools
|
|
491
|
+
[KIMI_K3.name]: typeof KIMI_K3.supports.tools
|
|
492
|
+
[GLM_5_2.name]: typeof GLM_5_2.supports.tools
|
|
493
|
+
[DEEPSEEK_V4_PRO.name]: typeof DEEPSEEK_V4_PRO.supports.tools
|
|
494
|
+
[QWEN_3_7_MAX.name]: typeof QWEN_3_7_MAX.supports.tools
|
|
495
|
+
[MINIMAX_M2_5.name]: typeof MINIMAX_M2_5.supports.tools
|
|
496
|
+
[GROK_4_5.name]: typeof GROK_4_5.supports.tools
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
/**
|
|
500
|
+
* Resolves the provider options type for a specific LLM Gateway model.
|
|
501
|
+
* Falls back to the generic options for uncurated model ids.
|
|
502
|
+
*/
|
|
503
|
+
export type ResolveProviderOptions<TModel extends string> =
|
|
504
|
+
TModel extends keyof LLMGatewayChatModelProviderOptionsByName
|
|
505
|
+
? LLMGatewayChatModelProviderOptionsByName[TModel]
|
|
506
|
+
: LLMGatewayTextProviderOptions
|
|
507
|
+
|
|
508
|
+
/**
|
|
509
|
+
* Resolve input modalities for a specific model.
|
|
510
|
+
* If the model has explicit modalities in the map, use those; otherwise use
|
|
511
|
+
* text only.
|
|
512
|
+
*/
|
|
513
|
+
export type ResolveInputModalities<TModel extends string> =
|
|
514
|
+
TModel extends keyof LLMGatewayModelInputModalitiesByName
|
|
515
|
+
? LLMGatewayModelInputModalitiesByName[TModel]
|
|
516
|
+
: readonly ['text']
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
ChatCompletionToolChoiceOption,
|
|
3
|
+
ResponseFormatJsonObject,
|
|
4
|
+
ResponseFormatJsonSchema,
|
|
5
|
+
ResponseFormatText,
|
|
6
|
+
} from '../message-types'
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* LLM Gateway provider options for text/chat models.
|
|
10
|
+
*
|
|
11
|
+
* LLM Gateway exposes the OpenAI Chat Completions wire format and routes
|
|
12
|
+
* each request to the underlying provider, so these are the standard Chat
|
|
13
|
+
* Completions parameters. Parameters a routed provider doesn't support are
|
|
14
|
+
* stripped by the gateway before the request is forwarded upstream.
|
|
15
|
+
*
|
|
16
|
+
* @see https://docs.llmgateway.io
|
|
17
|
+
*/
|
|
18
|
+
export interface LLMGatewayTextProviderOptions {
|
|
19
|
+
/**
|
|
20
|
+
* Number between -2.0 and 2.0. Positive values penalize new tokens based on
|
|
21
|
+
* their existing frequency in the text so far, decreasing the model's
|
|
22
|
+
* likelihood to repeat the same line verbatim.
|
|
23
|
+
*/
|
|
24
|
+
frequency_penalty?: number | null
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The maximum number of tokens that can be generated in the chat
|
|
28
|
+
* completion. Deprecated by OpenAI in favor of `max_completion_tokens`,
|
|
29
|
+
* but still accepted by the gateway and translated per provider.
|
|
30
|
+
*/
|
|
31
|
+
max_tokens?: number | null
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* An upper bound for the number of tokens that can be generated for a
|
|
35
|
+
* completion, including visible output tokens and reasoning tokens.
|
|
36
|
+
*/
|
|
37
|
+
max_completion_tokens?: number | null
|
|
38
|
+
|
|
39
|
+
/** Whether to enable parallel function calling during tool use. */
|
|
40
|
+
parallel_tool_calls?: boolean | null
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Number between -2.0 and 2.0. Positive values penalize new tokens based on
|
|
44
|
+
* whether they appear in the text so far, increasing the model's likelihood
|
|
45
|
+
* to talk about new topics.
|
|
46
|
+
*/
|
|
47
|
+
presence_penalty?: number | null
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Controls reasoning effort for reasoning-capable models.
|
|
51
|
+
*
|
|
52
|
+
* The gateway accepts the extended effort scale in addition to OpenAI's
|
|
53
|
+
* `low` / `medium` / `high`; which tiers a given model honors depends on
|
|
54
|
+
* the model and the provider it is routed to. See the model's page on
|
|
55
|
+
* https://llmgateway.io/models for the tiers it supports.
|
|
56
|
+
*/
|
|
57
|
+
reasoning_effort?:
|
|
58
|
+
| 'none'
|
|
59
|
+
| 'minimal'
|
|
60
|
+
| 'low'
|
|
61
|
+
| 'medium'
|
|
62
|
+
| 'high'
|
|
63
|
+
| 'xhigh'
|
|
64
|
+
| 'max'
|
|
65
|
+
| null
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* An object specifying the format that the model must output.
|
|
69
|
+
*
|
|
70
|
+
* - `json_schema` — enables Structured Outputs (preferred)
|
|
71
|
+
* - `json_object` — enables the older JSON mode
|
|
72
|
+
* - `text` — plain text output (default)
|
|
73
|
+
*/
|
|
74
|
+
response_format?:
|
|
75
|
+
| ResponseFormatText
|
|
76
|
+
| ResponseFormatJsonSchema
|
|
77
|
+
| ResponseFormatJsonObject
|
|
78
|
+
| null
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* If specified, the gateway forwards the seed so providers that support it
|
|
82
|
+
* can sample deterministically. Determinism is not guaranteed.
|
|
83
|
+
*/
|
|
84
|
+
seed?: number | null
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Up to 4 sequences where the API will stop generating further tokens.
|
|
88
|
+
* The returned text will not contain the stop sequence.
|
|
89
|
+
*/
|
|
90
|
+
stop?: string | null | Array<string>
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Sampling temperature between 0 and 2. Higher values like 0.8 make the
|
|
94
|
+
* output more random, while lower values like 0.2 make it more focused and
|
|
95
|
+
* deterministic. We generally recommend altering this or `top_p` but not
|
|
96
|
+
* both.
|
|
97
|
+
*/
|
|
98
|
+
temperature?: number | null
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Controls which (if any) tool is called by the model.
|
|
102
|
+
*
|
|
103
|
+
* - `none` — never call tools
|
|
104
|
+
* - `auto` — model decides (default when tools are present)
|
|
105
|
+
* - `required` — model must call tools
|
|
106
|
+
* - Named choice — forces a specific tool
|
|
107
|
+
*/
|
|
108
|
+
tool_choice?: ChatCompletionToolChoiceOption | null
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* An alternative to sampling with temperature, called nucleus sampling,
|
|
112
|
+
* where the model considers the results of the tokens with top_p
|
|
113
|
+
* probability mass. So 0.1 means only the tokens comprising the top 10%
|
|
114
|
+
* probability mass are considered.
|
|
115
|
+
*/
|
|
116
|
+
top_p?: number | null
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* A unique identifier representing your end-user, which can help monitor
|
|
120
|
+
* and detect abuse.
|
|
121
|
+
*/
|
|
122
|
+
user?: string | null
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* External provider options (what users pass in)
|
|
127
|
+
*/
|
|
128
|
+
export type ExternalTextProviderOptions = LLMGatewayTextProviderOptions
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { getApiKeyFromEnv } from '@tanstack/ai-utils'
|
|
2
|
+
import type { ClientOptions } from 'openai'
|
|
3
|
+
|
|
4
|
+
export interface LLMGatewayClientConfig extends Omit<ClientOptions, 'apiKey'> {
|
|
5
|
+
apiKey: string
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Gets the LLM Gateway API key from environment variables
|
|
10
|
+
* @throws Error if LLM_GATEWAY_API_KEY is not found
|
|
11
|
+
*/
|
|
12
|
+
export function getLLMGatewayApiKeyFromEnv(): string {
|
|
13
|
+
try {
|
|
14
|
+
return getApiKeyFromEnv('LLM_GATEWAY_API_KEY')
|
|
15
|
+
} catch (cause) {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'LLM_GATEWAY_API_KEY is required. Please set it in your environment variables or use the factory function with an explicit API key.',
|
|
18
|
+
{ cause },
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Returns an LLM Gateway client config with the gateway's OpenAI-compatible
|
|
25
|
+
* base URL applied when not already set. LLM Gateway accepts the OpenAI SDK
|
|
26
|
+
* verbatim, so the adapter drives it via the OpenAI SDK with this baseURL.
|
|
27
|
+
* Point `baseURL` at your own deployment when self-hosting.
|
|
28
|
+
*/
|
|
29
|
+
export function withLLMGatewayDefaults(
|
|
30
|
+
config: LLMGatewayClientConfig,
|
|
31
|
+
): LLMGatewayClientConfig {
|
|
32
|
+
return {
|
|
33
|
+
...config,
|
|
34
|
+
baseURL: config.baseURL || 'https://api.llmgateway.io/v1',
|
|
35
|
+
}
|
|
36
|
+
}
|