@raingor/pi-web-switch 0.4.3 → 0.5.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.
@@ -11,6 +11,10 @@ import type { Model } from "@/types";
11
11
  export interface CatalogEntry {
12
12
  // Match patterns: tried in order, first match wins on id (case-insensitive)
13
13
  patterns: string[];
14
+ // Real, callable API model id used when prefilling the form. Patterns are
15
+ // match prefixes/aliases and are not always a usable id (e.g. "qwen3-"), so
16
+ // entries whose first pattern is not callable must set this explicitly.
17
+ apiId?: string;
14
18
  // Filled-in model meta
15
19
  name?: string;
16
20
  reasoning?: boolean;
@@ -36,79 +40,144 @@ const P = (input: number, output: number, cacheRead = 0, cacheWrite = 0) => ({
36
40
 
37
41
  export const MODEL_CATALOG: CatalogEntry[] = [
38
42
  // ── Anthropic Claude ────────────────────────────────────
43
+ // Source: platform.claude.com/docs/en/about-claude/pricing +
44
+ // .../models/overview. cacheWrite = 5-minute cache write price.
39
45
  {
40
- patterns: ["claude-opus-4-5", "claude-4-5-opus"],
41
- name: "Claude 4.5 Opus",
46
+ patterns: ["claude-fable-5"],
47
+ name: "Claude Fable 5",
42
48
  reasoning: true,
43
49
  input: ["text", "image"],
44
- contextWindow: 200_000,
45
- maxTokens: 32_000,
46
- cost: P(15, 75, 1.5, 18.75),
50
+ contextWindow: 1_048_576,
51
+ maxTokens: 131_072,
52
+ cost: P(10, 50, 1, 12.5),
47
53
  family: "Anthropic",
48
54
  },
49
55
  {
50
- patterns: ["claude-sonnet-4-5", "claude-4-5-sonnet"],
51
- name: "Claude 4.5 Sonnet",
56
+ patterns: ["claude-opus-5"],
57
+ name: "Claude Opus 5",
52
58
  reasoning: true,
53
59
  input: ["text", "image"],
54
- contextWindow: 200_000,
55
- maxTokens: 16_384,
60
+ contextWindow: 1_048_576,
61
+ maxTokens: 131_072,
62
+ cost: P(5, 25, 0.5, 6.25),
63
+ family: "Anthropic",
64
+ },
65
+ {
66
+ patterns: ["claude-sonnet-5"],
67
+ name: "Claude Sonnet 5",
68
+ reasoning: true,
69
+ input: ["text", "image"],
70
+ contextWindow: 1_048_576,
71
+ maxTokens: 131_072,
72
+ cost: P(2, 10, 0.2, 2.5),
73
+ family: "Anthropic",
74
+ },
75
+ {
76
+ patterns: ["claude-opus-4-8", "claude-4-8-opus"],
77
+ name: "Claude Opus 4.8",
78
+ reasoning: true,
79
+ input: ["text", "image"],
80
+ contextWindow: 1_048_576,
81
+ maxTokens: 131_072,
82
+ cost: P(5, 25, 0.5, 6.25),
83
+ family: "Anthropic",
84
+ },
85
+ {
86
+ patterns: ["claude-opus-4-7", "claude-4-7-opus"],
87
+ name: "Claude Opus 4.7",
88
+ reasoning: true,
89
+ input: ["text", "image"],
90
+ contextWindow: 1_048_576,
91
+ maxTokens: 131_072,
92
+ cost: P(5, 25, 0.5, 6.25),
93
+ family: "Anthropic",
94
+ },
95
+ {
96
+ patterns: ["claude-opus-4-6", "claude-4-6-opus"],
97
+ name: "Claude Opus 4.6",
98
+ reasoning: true,
99
+ input: ["text", "image"],
100
+ contextWindow: 1_048_576,
101
+ maxTokens: 131_072,
102
+ cost: P(5, 25, 0.5, 6.25),
103
+ family: "Anthropic",
104
+ },
105
+ {
106
+ patterns: ["claude-sonnet-4-6", "claude-4-6-sonnet"],
107
+ name: "Claude Sonnet 4.6",
108
+ reasoning: true,
109
+ input: ["text", "image"],
110
+ contextWindow: 1_048_576,
111
+ maxTokens: 131_072,
56
112
  cost: P(3, 15, 0.3, 3.75),
57
113
  family: "Anthropic",
58
114
  },
59
115
  {
60
- patterns: ["claude-opus-4", "claude-4-opus"],
61
- name: "Claude 4 Opus",
116
+ patterns: ["claude-opus-4-5", "claude-4-5-opus"],
117
+ name: "Claude Opus 4.5",
62
118
  reasoning: true,
63
119
  input: ["text", "image"],
64
120
  contextWindow: 200_000,
65
- maxTokens: 32_000,
66
- cost: P(15, 75, 1.5, 18.75),
121
+ maxTokens: 65_536,
122
+ cost: P(5, 25, 0.5, 6.25),
67
123
  family: "Anthropic",
68
124
  },
69
125
  {
70
- patterns: ["claude-sonnet-4", "claude-4-sonnet"],
71
- name: "Claude 4 Sonnet",
126
+ patterns: ["claude-sonnet-4-5", "claude-4-5-sonnet"],
127
+ name: "Claude Sonnet 4.5",
72
128
  reasoning: true,
73
129
  input: ["text", "image"],
74
130
  contextWindow: 200_000,
75
- maxTokens: 16_384,
131
+ maxTokens: 65_536,
76
132
  cost: P(3, 15, 0.3, 3.75),
77
133
  family: "Anthropic",
78
134
  },
79
135
  {
80
- patterns: ["claude-3-7-sonnet", "claude-3.7-sonnet"],
81
- name: "Claude 3.7 Sonnet",
136
+ patterns: ["claude-haiku-4-5", "claude-4-5-haiku"],
137
+ name: "Claude Haiku 4.5",
82
138
  reasoning: true,
83
139
  input: ["text", "image"],
84
140
  contextWindow: 200_000,
85
- maxTokens: 64_000,
86
- cost: P(3, 15, 0.3, 3.75),
141
+ maxTokens: 65_536,
142
+ cost: P(1, 5, 0.1, 1.25),
87
143
  family: "Anthropic",
88
144
  },
145
+ // Retired on the first-party API, still reachable on Bedrock / Google Cloud.
89
146
  {
90
- patterns: ["claude-3-5-sonnet", "claude-3.5-sonnet"],
91
- name: "Claude 3.5 Sonnet",
92
- reasoning: false,
147
+ patterns: ["claude-opus-4-1", "claude-opus-4", "claude-4-opus"],
148
+ apiId: "claude-opus-4-1",
149
+ name: "Claude Opus 4.1",
150
+ reasoning: true,
93
151
  input: ["text", "image"],
94
152
  contextWindow: 200_000,
95
- maxTokens: 8192,
153
+ maxTokens: 32_000,
154
+ cost: P(15, 75, 1.5, 18.75),
155
+ family: "Anthropic",
156
+ },
157
+ {
158
+ patterns: ["claude-sonnet-4", "claude-4-sonnet"],
159
+ name: "Claude Sonnet 4",
160
+ reasoning: true,
161
+ input: ["text", "image"],
162
+ contextWindow: 200_000,
163
+ maxTokens: 65_536,
96
164
  cost: P(3, 15, 0.3, 3.75),
97
165
  family: "Anthropic",
98
166
  },
99
167
  {
100
- patterns: ["claude-3-5-haiku", "claude-3.5-haiku"],
101
- name: "Claude 3.5 Haiku",
102
- reasoning: false,
168
+ patterns: ["claude-3-7-sonnet", "claude-3.7-sonnet"],
169
+ name: "Claude Sonnet 3.7",
170
+ reasoning: true,
103
171
  input: ["text", "image"],
104
172
  contextWindow: 200_000,
105
- maxTokens: 8192,
106
- cost: P(0.8, 4, 0.08, 1),
173
+ maxTokens: 65_536,
174
+ cost: P(3, 15, 0.3, 3.75),
107
175
  family: "Anthropic",
108
176
  },
109
177
  {
110
- patterns: ["claude-haiku-3-5"],
111
- name: "Claude 3.5 Haiku",
178
+ patterns: ["claude-haiku-3-5", "claude-3-5-haiku", "claude-3.5-haiku"],
179
+ apiId: "claude-3-5-haiku-latest",
180
+ name: "Claude Haiku 3.5",
112
181
  reasoning: false,
113
182
  input: ["text", "image"],
114
183
  contextWindow: 200_000,
@@ -118,44 +187,57 @@ export const MODEL_CATALOG: CatalogEntry[] = [
118
187
  },
119
188
 
120
189
  // ── OpenAI / GPT ────────────────────────────────────────
190
+ // Source: developers.openai.com/api/docs/pricing (short-context column)
191
+ // and the per-model doc pages for context / max output.
121
192
  {
122
- patterns: ["gpt-5", "gpt5"],
123
- name: "GPT-5",
193
+ patterns: ["gpt-5.6-sol", "gpt-5.6"],
194
+ apiId: "gpt-5.6-sol",
195
+ name: "GPT-5.6 Sol",
124
196
  reasoning: true,
125
197
  input: ["text", "image"],
126
- contextWindow: 256_000,
127
- maxTokens: 65_536,
128
- cost: P(10, 40, 5, 10),
198
+ contextWindow: 1_050_000,
199
+ maxTokens: 128_000,
200
+ cost: P(4, 20, 0.4, 5),
129
201
  family: "OpenAI",
130
202
  },
131
203
  {
132
- patterns: ["gpt-5.1", "gpt-5-1"],
133
- name: "GPT-5.1",
204
+ patterns: ["gpt-5.6-terra"],
205
+ name: "GPT-5.6 Terra",
134
206
  reasoning: true,
135
207
  input: ["text", "image"],
136
- contextWindow: 256_000,
137
- maxTokens: 65_536,
138
- cost: P(10, 40, 5, 10),
208
+ contextWindow: 1_050_000,
209
+ maxTokens: 128_000,
210
+ cost: P(2, 12, 0.2, 2.5),
139
211
  family: "OpenAI",
140
212
  },
141
213
  {
142
- patterns: ["gpt-4o-mini"],
143
- name: "GPT-4o Mini",
144
- reasoning: false,
214
+ patterns: ["gpt-5.6-luna"],
215
+ name: "GPT-5.6 Luna",
216
+ reasoning: true,
145
217
  input: ["text", "image"],
146
- contextWindow: 128_000,
147
- maxTokens: 16_384,
148
- cost: P(0.15, 0.6, 0.075, 0.225),
218
+ contextWindow: 1_050_000,
219
+ maxTokens: 128_000,
220
+ cost: P(0.2, 1.2, 0.02, 0.25),
149
221
  family: "OpenAI",
150
222
  },
151
223
  {
152
- patterns: ["gpt-4o"],
153
- name: "GPT-4o",
154
- reasoning: false,
224
+ patterns: ["gpt-5.1", "gpt-5-1"],
225
+ name: "GPT-5.1",
226
+ reasoning: true,
155
227
  input: ["text", "image"],
156
- contextWindow: 128_000,
157
- maxTokens: 16_384,
158
- cost: P(2.5, 10, 1.25, 3.75),
228
+ contextWindow: 400_000,
229
+ maxTokens: 128_000,
230
+ cost: P(1.25, 10, 0.125, 0),
231
+ family: "OpenAI",
232
+ },
233
+ {
234
+ patterns: ["gpt-5", "gpt5"],
235
+ name: "GPT-5",
236
+ reasoning: true,
237
+ input: ["text", "image"],
238
+ contextWindow: 400_000,
239
+ maxTokens: 128_000,
240
+ cost: P(1.25, 10, 0.125, 0),
159
241
  family: "OpenAI",
160
242
  },
161
243
  {
@@ -163,9 +245,9 @@ export const MODEL_CATALOG: CatalogEntry[] = [
163
245
  name: "GPT-4.1 Mini",
164
246
  reasoning: false,
165
247
  input: ["text", "image"],
166
- contextWindow: 1_048_576,
167
- maxTokens: 65_536,
168
- cost: P(0.4, 1.6, 0.2, 0.4),
248
+ contextWindow: 1_047_576,
249
+ maxTokens: 32_768,
250
+ cost: P(0.4, 1.6, 0.1, 0),
169
251
  family: "OpenAI",
170
252
  },
171
253
  {
@@ -173,9 +255,29 @@ export const MODEL_CATALOG: CatalogEntry[] = [
173
255
  name: "GPT-4.1",
174
256
  reasoning: false,
175
257
  input: ["text", "image"],
176
- contextWindow: 1_048_576,
258
+ contextWindow: 1_047_576,
177
259
  maxTokens: 32_768,
178
- cost: P(2, 8, 0.5, 2),
260
+ cost: P(2, 8, 0.5, 0),
261
+ family: "OpenAI",
262
+ },
263
+ {
264
+ patterns: ["gpt-4o-mini"],
265
+ name: "GPT-4o Mini",
266
+ reasoning: false,
267
+ input: ["text", "image"],
268
+ contextWindow: 128_000,
269
+ maxTokens: 16_384,
270
+ cost: P(0.15, 0.6, 0.075, 0),
271
+ family: "OpenAI",
272
+ },
273
+ {
274
+ patterns: ["gpt-4o"],
275
+ name: "GPT-4o",
276
+ reasoning: false,
277
+ input: ["text", "image"],
278
+ contextWindow: 128_000,
279
+ maxTokens: 16_384,
280
+ cost: P(2.5, 10, 1.25, 0),
179
281
  family: "OpenAI",
180
282
  },
181
283
  {
@@ -185,37 +287,37 @@ export const MODEL_CATALOG: CatalogEntry[] = [
185
287
  input: ["text", "image"],
186
288
  contextWindow: 200_000,
187
289
  maxTokens: 100_000,
188
- cost: P(11, 44),
290
+ cost: P(20, 80),
189
291
  family: "OpenAI",
190
292
  },
191
293
  {
192
- patterns: ["o3"],
193
- name: "o3",
294
+ patterns: ["o3-mini"],
295
+ name: "o3-mini",
194
296
  reasoning: true,
195
- input: ["text", "image"],
297
+ input: ["text"],
196
298
  contextWindow: 200_000,
197
299
  maxTokens: 100_000,
198
- cost: P(2, 8, 1, 2),
300
+ cost: P(1.1, 4.4, 0.55, 0),
199
301
  family: "OpenAI",
200
302
  },
201
303
  {
202
- patterns: ["o4-mini"],
203
- name: "o4-mini",
304
+ patterns: ["o3"],
305
+ name: "o3",
204
306
  reasoning: true,
205
307
  input: ["text", "image"],
206
308
  contextWindow: 200_000,
207
309
  maxTokens: 100_000,
208
- cost: P(1.1, 4.4, 0.55, 1.65),
310
+ cost: P(2, 8, 0.5, 0),
209
311
  family: "OpenAI",
210
312
  },
211
313
  {
212
- patterns: ["o3-mini"],
213
- name: "o3-mini",
314
+ patterns: ["o4-mini"],
315
+ name: "o4-mini",
214
316
  reasoning: true,
215
- input: ["text"],
317
+ input: ["text", "image"],
216
318
  contextWindow: 200_000,
217
319
  maxTokens: 100_000,
218
- cost: P(1.1, 4.4, 0.55, 1.65),
320
+ cost: P(1.1, 4.4, 0.275, 0),
219
321
  family: "OpenAI",
220
322
  },
221
323
  {
@@ -230,14 +332,27 @@ export const MODEL_CATALOG: CatalogEntry[] = [
230
332
  },
231
333
 
232
334
  // ── DeepSeek ────────────────────────────────────────────
335
+ // Source: api-docs.deepseek.com/quick_start/pricing (PEAK rates;
336
+ // off-peak is 50% off). Context 1M, max output 384K for all V4 models.
337
+ {
338
+ patterns: ["deepseek-v4-flash-vision-exp"],
339
+ name: "DeepSeek V4 Flash Vision (Exp)",
340
+ reasoning: true,
341
+ input: ["text", "image"],
342
+ contextWindow: 1_048_576,
343
+ maxTokens: 131_072,
344
+ cost: P(0.44, 1.32, 0.014, 0),
345
+ family: "DeepSeek",
346
+ },
233
347
  {
234
- patterns: ["deepseek-v4", "deepseek-v4-flash", "deepseek-v4-chat"],
348
+ patterns: ["deepseek-v4-flash", "deepseek-v4-chat", "deepseek-v4"],
349
+ apiId: "deepseek-v4-flash",
235
350
  name: "DeepSeek V4 Flash",
236
- reasoning: false,
351
+ reasoning: true,
237
352
  input: ["text"],
238
- contextWindow: 128_000,
239
- maxTokens: 8192,
240
- cost: P(0.3, 0.6, 0.15, 0.3),
353
+ contextWindow: 1_048_576,
354
+ maxTokens: 131_072,
355
+ cost: P(0.44, 1.32, 0.014, 0),
241
356
  family: "DeepSeek",
242
357
  },
243
358
  {
@@ -245,51 +360,125 @@ export const MODEL_CATALOG: CatalogEntry[] = [
245
360
  name: "DeepSeek V4 Pro",
246
361
  reasoning: true,
247
362
  input: ["text"],
248
- contextWindow: 128_000,
249
- maxTokens: 8192,
250
- cost: P(2, 8, 1, 2),
363
+ contextWindow: 1_048_576,
364
+ maxTokens: 131_072,
365
+ cost: P(1.32, 3.96, 0.044, 0),
251
366
  family: "DeepSeek",
252
367
  },
368
+ // deepseek-chat / deepseek-reasoner were retired 2026-07-24; kept so an
369
+ // existing config that still references them shows correct metadata.
253
370
  {
254
371
  patterns: ["deepseek-reasoner", "deepseek-r1"],
255
- name: "DeepSeek R1",
372
+ name: "DeepSeek R1 (retired)",
256
373
  reasoning: true,
257
374
  input: ["text"],
258
- contextWindow: 128_000,
375
+ contextWindow: 131_072,
259
376
  maxTokens: 8192,
260
- cost: P(0.55, 2.19, 0.14, 0.55),
377
+ cost: P(0.55, 2.19, 0.14, 0),
261
378
  family: "DeepSeek",
262
379
  },
263
380
  {
264
381
  patterns: ["deepseek-chat", "deepseek-v3"],
265
- name: "DeepSeek V3",
382
+ name: "DeepSeek V3 (retired)",
266
383
  reasoning: false,
267
384
  input: ["text"],
268
- contextWindow: 128_000,
385
+ contextWindow: 131_072,
269
386
  maxTokens: 8192,
270
- cost: P(0.27, 1.1, 0.07, 0.27),
387
+ cost: P(0.27, 1.1, 0.07, 0),
271
388
  family: "DeepSeek",
272
389
  },
273
390
 
274
391
  // ── Google Gemini ───────────────────────────────────────
392
+ // Source: ai.google.dev/gemini-api/docs/pricing (paid tier, standard,
393
+ // <=200k prompt tier where tiered). Output price includes thinking tokens.
394
+ {
395
+ patterns: ["gemini-3.1-pro"],
396
+ name: "Gemini 3.1 Pro",
397
+ reasoning: true,
398
+ input: ["text", "image", "audio"],
399
+ contextWindow: 1_048_576,
400
+ maxTokens: 65_536,
401
+ cost: P(2, 12, 0.2, 0),
402
+ family: "Google",
403
+ },
404
+ {
405
+ patterns: ["gemini-3.7-flash"],
406
+ name: "Gemini 3.7 Flash",
407
+ reasoning: true,
408
+ input: ["text", "image", "audio"],
409
+ contextWindow: 1_048_576,
410
+ maxTokens: 65_536,
411
+ cost: P(0.75, 3.75, 0, 0),
412
+ family: "Google",
413
+ },
414
+ {
415
+ patterns: ["gemini-3.6-flash"],
416
+ name: "Gemini 3.6 Flash",
417
+ reasoning: true,
418
+ input: ["text", "image", "audio"],
419
+ contextWindow: 1_048_576,
420
+ maxTokens: 65_536,
421
+ cost: P(0.75, 3.75, 0, 0),
422
+ family: "Google",
423
+ },
424
+ {
425
+ patterns: ["gemini-3.5-flash-lite"],
426
+ name: "Gemini 3.5 Flash-Lite",
427
+ reasoning: true,
428
+ input: ["text", "image", "audio"],
429
+ contextWindow: 1_048_576,
430
+ maxTokens: 65_536,
431
+ cost: P(0.3, 2.5, 0, 0),
432
+ family: "Google",
433
+ },
434
+ {
435
+ patterns: ["gemini-3.5-flash"],
436
+ name: "Gemini 3.5 Flash",
437
+ reasoning: true,
438
+ input: ["text", "image", "audio"],
439
+ contextWindow: 1_048_576,
440
+ maxTokens: 65_536,
441
+ cost: P(1.5, 9, 0, 0),
442
+ family: "Google",
443
+ },
444
+ {
445
+ patterns: ["gemini-3.1-flash-lite"],
446
+ name: "Gemini 3.1 Flash-Lite",
447
+ reasoning: true,
448
+ input: ["text", "image", "audio"],
449
+ contextWindow: 1_048_576,
450
+ maxTokens: 65_536,
451
+ cost: P(0.25, 1.5, 0, 0),
452
+ family: "Google",
453
+ },
454
+ {
455
+ patterns: ["gemini-3-flash"],
456
+ name: "Gemini 3 Flash",
457
+ reasoning: true,
458
+ input: ["text", "image", "audio"],
459
+ contextWindow: 1_048_576,
460
+ maxTokens: 65_536,
461
+ cost: P(0.5, 3, 0, 0),
462
+ family: "Google",
463
+ },
275
464
  {
276
465
  patterns: ["gemini-2.5-pro"],
277
466
  name: "Gemini 2.5 Pro",
278
467
  reasoning: true,
279
- input: ["text", "image"],
468
+ input: ["text", "image", "audio"],
280
469
  contextWindow: 1_048_576,
281
470
  maxTokens: 65_536,
282
- cost: P(1.25, 10, 0.625, 1.25),
471
+ cost: P(1.25, 10, 0.125, 0),
283
472
  family: "Google",
284
473
  },
285
474
  {
286
475
  patterns: ["gemini-2.5-flash"],
287
476
  name: "Gemini 2.5 Flash",
288
- reasoning: false,
289
- input: ["text", "image"],
477
+ reasoning: true,
478
+ input: ["text", "image", "audio"],
290
479
  contextWindow: 1_048_576,
291
480
  maxTokens: 65_536,
292
- cost: P(0.15, 0.6, 0.075, 0.15),
481
+ cost: P(0.3, 2.5, 0.03, 0),
293
482
  family: "Google",
294
483
  },
295
484
  {
@@ -299,444 +488,519 @@ export const MODEL_CATALOG: CatalogEntry[] = [
299
488
  input: ["text", "image"],
300
489
  contextWindow: 1_048_576,
301
490
  maxTokens: 8192,
302
- cost: P(0.1, 0.4, 0.025, 0.1),
491
+ cost: P(0.1, 0.4, 0.025, 0),
303
492
  family: "Google",
304
493
  },
305
494
 
306
- // ── Alibaba Qwen (通义千问) ─────────────────────────────
307
- {
308
- patterns: ["qwen3-max", "qwen-3-max", "qwen3.7-max", "qwen-3.7-max"],
309
- name: "Qwen 3 Max",
495
+ // ── Alibaba Qwen ────────────────────────────────────────
496
+ // Source: alibabacloud.com/help/en/model-studio/model-pricing
497
+ // (international endpoint, USD list price) + per-model context pages.
498
+ // Entries without `cost` have no published international list price we
499
+ // could verify — fill the price in the form.
500
+ {
501
+ patterns: ["qwen3.8-max", "qwen-3.8-max"],
502
+ name: "Qwen3.8 Max",
310
503
  reasoning: true,
311
- input: ["text"],
312
- contextWindow: 128_000,
313
- maxTokens: 8192,
314
- cost: P(1.5, 6, 0.75, 1.5),
504
+ input: ["text", "image"],
505
+ contextWindow: 1_000_000,
506
+ maxTokens: 131_072,
507
+ cost: P(2, 6, 0.25, 2.5),
315
508
  family: "Qwen",
316
509
  },
317
510
  {
318
- patterns: ["qwen3-coder"],
319
- name: "Qwen 3 Coder",
511
+ patterns: ["qwen3.7-max", "qwen-3.7-max"],
512
+ name: "Qwen3.7 Max",
320
513
  reasoning: true,
321
514
  input: ["text"],
322
- contextWindow: 256_000,
515
+ contextWindow: 262_144,
323
516
  maxTokens: 65_536,
517
+ cost: P(2.5, 7.5, 0, 0),
324
518
  family: "Qwen",
325
519
  },
326
520
  {
327
- patterns: ["qwen3-vl"],
328
- name: "Qwen 3 VL",
329
- reasoning: false,
330
- input: ["text", "image"],
331
- contextWindow: 128_000,
332
- maxTokens: 8192,
521
+ patterns: ["qwen3-max", "qwen-3-max"],
522
+ name: "Qwen3 Max",
523
+ reasoning: true,
524
+ input: ["text"],
525
+ contextWindow: 262_144,
526
+ maxTokens: 65_536,
527
+ cost: P(1.2, 6, 0.24, 0),
333
528
  family: "Qwen",
334
529
  },
335
530
  {
336
- patterns: ["qwen3-"],
337
- name: "Qwen 3",
531
+ patterns: ["qwen3-coder-plus", "qwen3-coder"],
532
+ apiId: "qwen3-coder-plus",
533
+ name: "Qwen3 Coder Plus",
338
534
  reasoning: true,
339
535
  input: ["text"],
340
- contextWindow: 128_000,
341
- maxTokens: 8192,
536
+ contextWindow: 1_000_000,
537
+ maxTokens: 65_536,
538
+ cost: P(1, 5, 0.1, 0),
342
539
  family: "Qwen",
343
540
  },
344
541
  {
345
- patterns: ["qwen2.5-vl", "qwen-vl-max", "qwen-vl-plus"],
346
- name: "Qwen VL",
347
- reasoning: false,
348
- input: ["text", "image"],
349
- contextWindow: 128_000,
350
- maxTokens: 8192,
542
+ patterns: ["qwen3.7-plus", "qwen-3.7-plus"],
543
+ name: "Qwen3.7 Plus",
544
+ reasoning: true,
545
+ input: ["text"],
546
+ contextWindow: 1_000_000,
547
+ maxTokens: 65_536,
548
+ cost: P(0.4, 1.6, 0, 0),
351
549
  family: "Qwen",
352
550
  },
353
551
  {
354
- patterns: ["qwen-max"],
355
- name: "Qwen Max",
552
+ patterns: ["qwen3-vl-plus", "qwen3-vl"],
553
+ apiId: "qwen3-vl-plus",
554
+ name: "Qwen3 VL Plus",
356
555
  reasoning: false,
357
- input: ["text"],
358
- contextWindow: 32_768,
359
- maxTokens: 8192,
360
- cost: P(1.6, 6.4),
556
+ input: ["text", "image"],
557
+ contextWindow: 131_072,
558
+ maxTokens: 32_768,
559
+ cost: P(0.14, 1.43, 0, 0),
361
560
  family: "Qwen",
362
561
  },
363
562
  {
364
563
  patterns: ["qwen-plus"],
365
564
  name: "Qwen Plus",
366
- reasoning: false,
565
+ reasoning: true,
367
566
  input: ["text"],
368
- contextWindow: 128_000,
369
- maxTokens: 8192,
370
- cost: P(0.8, 2),
567
+ contextWindow: 1_000_000,
568
+ maxTokens: 32_768,
569
+ cost: P(0.4, 1.2, 0, 0),
371
570
  family: "Qwen",
372
571
  },
373
572
  {
374
573
  patterns: ["qwen-turbo"],
375
574
  name: "Qwen Turbo",
376
- reasoning: false,
575
+ reasoning: true,
377
576
  input: ["text"],
378
577
  contextWindow: 1_000_000,
379
- maxTokens: 8192,
380
- cost: P(0.3, 0.6),
578
+ maxTokens: 16_384,
579
+ cost: P(0.05, 0.2, 0, 0),
381
580
  family: "Qwen",
382
581
  },
383
582
  {
384
- patterns: ["qwen2.5-coder", "qwen-coder"],
385
- name: "Qwen 2.5 Coder",
583
+ patterns: ["qwen-max"],
584
+ name: "Qwen Max",
386
585
  reasoning: false,
387
586
  input: ["text"],
388
- contextWindow: 128_000,
587
+ contextWindow: 262_144,
389
588
  maxTokens: 8192,
589
+ cost: P(1.6, 6.4, 0, 0),
390
590
  family: "Qwen",
391
591
  },
592
+
593
+ // ── Zhipu GLM ───────────────────────────────────────────
594
+ // Source: docs.z.ai/guides/overview/pricing (USD) and
595
+ // docs.z.ai/guides/overview/concept-param (max_tokens ceilings).
392
596
  {
393
- patterns: ["qwen2.5-72b"],
394
- name: "Qwen 2.5 72B",
395
- reasoning: false,
597
+ patterns: ["glm-5.3"],
598
+ name: "GLM-5.3",
599
+ reasoning: true,
396
600
  input: ["text"],
397
- contextWindow: 128_000,
398
- maxTokens: 8192,
399
- family: "Qwen",
601
+ contextWindow: 1_048_576,
602
+ maxTokens: 131_072,
603
+ cost: P(1.4, 4.4, 0.26, 0),
604
+ family: "GLM",
400
605
  },
401
606
  {
402
- patterns: ["qwen-long"],
403
- name: "Qwen Long",
404
- reasoning: false,
607
+ patterns: ["glm-5.2"],
608
+ name: "GLM-5.2",
609
+ reasoning: true,
405
610
  input: ["text"],
406
- contextWindow: 10_000_000,
407
- maxTokens: 8192,
408
- cost: P(0.5, 2),
409
- family: "Qwen",
611
+ contextWindow: 1_048_576,
612
+ maxTokens: 131_072,
613
+ cost: P(1.4, 4.4, 0.26, 0),
614
+ family: "GLM",
410
615
  },
411
-
412
- // ── Zhipu GLM (智谱) ────────────────────────────────────
413
616
  {
414
- patterns: ["glm-5.1", "glm-5-plus"],
415
- name: "GLM 5.1",
416
- reasoning: false,
617
+ patterns: ["glm-5.1"],
618
+ name: "GLM-5.1",
619
+ reasoning: true,
417
620
  input: ["text"],
418
- contextWindow: 128_000,
419
- maxTokens: 8192,
420
- cost: P(0.5, 2, 0.25, 0.5),
621
+ contextWindow: 204_800,
622
+ maxTokens: 131_072,
623
+ cost: P(1.4, 4.4, 0.26, 0),
421
624
  family: "GLM",
422
625
  },
423
626
  {
424
- patterns: ["glm-z1", "glm-4.5"],
425
- name: "GLM-Z1 (Reasoning)",
627
+ patterns: ["glm-5-turbo"],
628
+ name: "GLM-5-Turbo",
426
629
  reasoning: true,
427
630
  input: ["text"],
428
- contextWindow: 128_000,
429
- maxTokens: 8192,
631
+ contextWindow: 204_800,
632
+ maxTokens: 131_072,
633
+ cost: P(1.2, 4, 0.24, 0),
430
634
  family: "GLM",
431
635
  },
432
636
  {
433
- patterns: ["glm-4-plus"],
434
- name: "GLM-4 Plus",
435
- reasoning: false,
436
- input: ["text"],
437
- contextWindow: 128_000,
438
- maxTokens: 4096,
439
- cost: P(5, 5),
637
+ patterns: ["glm-5v-turbo"],
638
+ name: "GLM-5V-Turbo",
639
+ reasoning: true,
640
+ input: ["text", "image"],
641
+ contextWindow: 204_800,
642
+ maxTokens: 131_072,
643
+ cost: P(1.2, 4, 0.24, 0),
440
644
  family: "GLM",
441
645
  },
442
646
  {
443
- patterns: ["glm-4-air"],
444
- name: "GLM-4 Air",
445
- reasoning: false,
647
+ patterns: ["glm-5"],
648
+ name: "GLM-5",
649
+ reasoning: true,
446
650
  input: ["text"],
447
- contextWindow: 128_000,
448
- maxTokens: 4096,
449
- cost: P(0.1, 0.1),
651
+ contextWindow: 204_800,
652
+ maxTokens: 131_072,
653
+ cost: P(1, 3.2, 0.2, 0),
450
654
  family: "GLM",
451
655
  },
452
656
  {
453
- patterns: ["glm-4v", "glm-4-vision"],
454
- name: "GLM-4V (Vision)",
455
- reasoning: false,
456
- input: ["text", "image"],
457
- contextWindow: 8192,
458
- maxTokens: 4096,
459
- cost: P(1, 1),
657
+ patterns: ["glm-4.7-flashx"],
658
+ name: "GLM-4.7-FlashX",
659
+ reasoning: true,
660
+ input: ["text"],
661
+ contextWindow: 204_800,
662
+ maxTokens: 131_072,
663
+ cost: P(0.07, 0.4, 0.01, 0),
460
664
  family: "GLM",
461
665
  },
462
666
  {
463
- patterns: ["glm-4-long"],
464
- name: "GLM-4 Long",
465
- reasoning: false,
667
+ patterns: ["glm-4.7-flash"],
668
+ name: "GLM-4.7-Flash (Free)",
669
+ reasoning: true,
466
670
  input: ["text"],
467
- contextWindow: 1_000_000,
468
- maxTokens: 4096,
469
- cost: P(1, 1),
671
+ contextWindow: 204_800,
672
+ maxTokens: 131_072,
673
+ cost: P(0, 0, 0, 0),
470
674
  family: "GLM",
471
675
  },
472
-
473
- // ── Moonshot Kimi (月之暗面) ────────────────────────────
474
676
  {
475
- patterns: ["moonshot-v1-128k", "kimi-128k"],
476
- name: "Kimi 128K",
477
- reasoning: false,
677
+ patterns: ["glm-4.7"],
678
+ name: "GLM-4.7",
679
+ reasoning: true,
478
680
  input: ["text"],
479
- contextWindow: 128_000,
480
- maxTokens: 8192,
481
- cost: P(1.2, 1.2),
482
- family: "Moonshot",
681
+ contextWindow: 204_800,
682
+ maxTokens: 131_072,
683
+ cost: P(0.6, 2.2, 0.11, 0),
684
+ family: "GLM",
483
685
  },
484
686
  {
485
- patterns: ["moonshot-v1-32k", "kimi-32k"],
486
- name: "Kimi 32K",
487
- reasoning: false,
687
+ patterns: ["glm-4.6v"],
688
+ name: "GLM-4.6V (Vision)",
689
+ reasoning: true,
690
+ input: ["text", "image"],
691
+ contextWindow: 65_536,
692
+ maxTokens: 32_768,
693
+ cost: P(0.3, 0.9, 0.05, 0),
694
+ family: "GLM",
695
+ },
696
+ {
697
+ patterns: ["glm-4.6"],
698
+ name: "GLM-4.6",
699
+ reasoning: true,
488
700
  input: ["text"],
489
- contextWindow: 32_768,
490
- maxTokens: 8192,
491
- cost: P(0.6, 0.6),
492
- family: "Moonshot",
701
+ contextWindow: 204_800,
702
+ maxTokens: 131_072,
703
+ cost: P(0.6, 2.2, 0.11, 0),
704
+ family: "GLM",
493
705
  },
494
706
  {
495
- patterns: ["moonshot-v1-8k", "kimi-8k", "moonshot-v1"],
496
- name: "Kimi 8K",
497
- reasoning: false,
707
+ patterns: ["glm-4.5-airx"],
708
+ name: "GLM-4.5-AirX",
709
+ reasoning: true,
498
710
  input: ["text"],
499
- contextWindow: 8192,
500
- maxTokens: 4096,
501
- cost: P(0.3, 0.3),
502
- family: "Moonshot",
711
+ contextWindow: 131_072,
712
+ maxTokens: 65_536,
713
+ cost: P(1.1, 4.5, 0.22, 0),
714
+ family: "GLM",
503
715
  },
504
716
  {
505
- patterns: ["kimi-latest"],
506
- name: "Kimi Latest",
507
- reasoning: false,
717
+ patterns: ["glm-4.5-air"],
718
+ name: "GLM-4.5-Air",
719
+ reasoning: true,
508
720
  input: ["text"],
509
- contextWindow: 256_000,
510
- maxTokens: 8192,
511
- family: "Moonshot",
721
+ contextWindow: 131_072,
722
+ maxTokens: 65_536,
723
+ cost: P(0.2, 1.1, 0.03, 0),
724
+ family: "GLM",
512
725
  },
513
-
514
- // ── ByteDance Doubao (豆包) ─────────────────────────────
515
726
  {
516
- patterns: ["doubao-1.5-pro"],
517
- name: "Doubao 1.5 Pro",
518
- reasoning: false,
727
+ patterns: ["glm-4.5-x"],
728
+ name: "GLM-4.5-X",
729
+ reasoning: true,
519
730
  input: ["text"],
520
- contextWindow: 256_000,
521
- maxTokens: 16_384,
522
- cost: P(0.8, 2),
523
- family: "Doubao",
731
+ contextWindow: 131_072,
732
+ maxTokens: 65_536,
733
+ cost: P(2.2, 8.9, 0.45, 0),
734
+ family: "GLM",
524
735
  },
525
736
  {
526
- patterns: ["doubao-pro"],
527
- name: "Doubao Pro",
528
- reasoning: false,
737
+ patterns: ["glm-4.5-flash"],
738
+ name: "GLM-4.5-Flash (Free)",
739
+ reasoning: true,
529
740
  input: ["text"],
530
- contextWindow: 256_000,
531
- maxTokens: 4096,
532
- cost: P(0.8, 2),
533
- family: "Doubao",
741
+ contextWindow: 131_072,
742
+ maxTokens: 65_536,
743
+ cost: P(0, 0, 0, 0),
744
+ family: "GLM",
534
745
  },
535
746
  {
536
- patterns: ["doubao-lite"],
537
- name: "Doubao Lite",
538
- reasoning: false,
747
+ patterns: ["glm-4.5", "glm-z1"],
748
+ apiId: "glm-4.5",
749
+ name: "GLM-4.5",
750
+ reasoning: true,
539
751
  input: ["text"],
540
- contextWindow: 256_000,
541
- maxTokens: 4096,
542
- cost: P(0.3, 0.6),
543
- family: "Doubao",
752
+ contextWindow: 131_072,
753
+ maxTokens: 65_536,
754
+ cost: P(0.6, 2.2, 0.11, 0),
755
+ family: "GLM",
544
756
  },
757
+
758
+ // ── Moonshot Kimi ───────────────────────────────────────
759
+ // Source: platform.kimi.com/docs/models + /docs/pricing/chat. USD figures
760
+ // follow the vendor's own CNY→USD ratio for K2.6 (¥6.5→$0.95, ¥27→$4.00).
761
+ // kimi-latest retired 2026-01-28; moonshot-v1-* retires 2026-08-31.
545
762
  {
546
- patterns: ["doubao-vision"],
547
- name: "Doubao Vision",
548
- reasoning: false,
763
+ patterns: ["kimi-k3"],
764
+ name: "Kimi K3",
765
+ reasoning: true,
549
766
  input: ["text", "image"],
550
- contextWindow: 32_768,
551
- maxTokens: 4096,
552
- family: "Doubao",
767
+ contextWindow: 1_000_000,
768
+ maxTokens: 131_072,
769
+ cost: P(2.92, 14.8, 0.29, 0),
770
+ family: "Moonshot",
553
771
  },
554
772
  {
555
- patterns: ["seed-1-6", "doubao-seed"],
556
- name: "Doubao Seed 1.6",
773
+ patterns: ["kimi-k2.7-code-highspeed"],
774
+ name: "Kimi K2.7 Code Highspeed",
557
775
  reasoning: true,
558
776
  input: ["text"],
559
- contextWindow: 256_000,
560
- maxTokens: 16_384,
561
- family: "Doubao",
777
+ contextWindow: 262_144,
778
+ maxTokens: 98_304,
779
+ cost: P(0.95, 4, 0.19, 0),
780
+ family: "Moonshot",
562
781
  },
563
-
564
- // ── Baidu ERNIE (文心) ──────────────────────────────────
565
782
  {
566
- patterns: ["ernie-4", "ernie-4.0", "wenxin-4"],
567
- name: "ERNIE 4.0",
568
- reasoning: false,
783
+ patterns: ["kimi-k2.7-code"],
784
+ name: "Kimi K2.7 Code",
785
+ reasoning: true,
569
786
  input: ["text"],
570
- contextWindow: 128_000,
571
- maxTokens: 4096,
572
- cost: P(12, 12),
573
- family: "ERNIE",
787
+ contextWindow: 262_144,
788
+ maxTokens: 98_304,
789
+ cost: P(0.95, 4, 0.19, 0),
790
+ family: "Moonshot",
574
791
  },
575
792
  {
576
- patterns: ["ernie-3.5", "ernie-35"],
577
- name: "ERNIE 3.5",
578
- reasoning: false,
579
- input: ["text"],
580
- contextWindow: 128_000,
581
- maxTokens: 4096,
582
- cost: P(1.2, 1.2),
583
- family: "ERNIE",
793
+ patterns: ["kimi-k2.6-thinking"],
794
+ name: "Kimi K2.6 Thinking",
795
+ reasoning: true,
796
+ input: ["text", "image"],
797
+ contextWindow: 262_144,
798
+ maxTokens: 98_304,
799
+ cost: P(0.95, 4, 0.16, 0),
800
+ family: "Moonshot",
584
801
  },
585
802
  {
586
- patterns: ["ernie-x1"],
587
- name: "ERNIE X1 (Reasoning)",
803
+ patterns: ["kimi-k2.6", "kimi-k2-6"],
804
+ apiId: "kimi-k2.6",
805
+ name: "Kimi K2.6",
588
806
  reasoning: true,
589
- input: ["text"],
590
- contextWindow: 128_000,
591
- maxTokens: 8192,
592
- family: "ERNIE",
807
+ input: ["text", "image"],
808
+ contextWindow: 262_144,
809
+ maxTokens: 98_304,
810
+ cost: P(0.95, 4, 0.16, 0),
811
+ family: "Moonshot",
593
812
  },
594
813
 
595
- // ── SenseNova (商汤) ────────────────────────────────────
814
+ // ── xAI Grok ────────────────────────────────────────────
815
+ // Source: docs.x.ai/developers/models (<200k prompt tier).
596
816
  {
597
- patterns: ["glm-5.2"],
598
- name: "GLM 5.2",
599
- reasoning: false,
600
- input: ["text"],
601
- contextWindow: 128_000,
602
- maxTokens: 8192,
603
- family: "SenseNova",
817
+ patterns: ["grok-4.6"],
818
+ name: "Grok 4.6",
819
+ reasoning: true,
820
+ input: ["text", "image"],
821
+ contextWindow: 500_000,
822
+ maxTokens: 131_072,
823
+ cost: P(2, 6, 0.5, 0),
824
+ family: "Grok",
825
+ },
826
+ {
827
+ patterns: ["grok-4.5"],
828
+ name: "Grok 4.5",
829
+ reasoning: true,
830
+ input: ["text", "image"],
831
+ contextWindow: 500_000,
832
+ maxTokens: 131_072,
833
+ cost: P(2, 6, 0.3, 0),
834
+ family: "Grok",
835
+ },
836
+ {
837
+ patterns: ["grok-4.3"],
838
+ name: "Grok 4.3",
839
+ reasoning: true,
840
+ input: ["text", "image"],
841
+ contextWindow: 1_000_000,
842
+ maxTokens: 131_072,
843
+ cost: P(1.25, 2.5, 0.2, 0),
844
+ family: "Grok",
604
845
  },
605
846
 
606
847
  // ── MiniMax ─────────────────────────────────────────────
848
+ // Source: platform.minimax.io docs (context) + published USD rates.
607
849
  {
608
- patterns: ["minimax-abab6.5", "abab6.5"],
609
- name: "MiniMax abab 6.5",
610
- reasoning: false,
611
- input: ["text"],
612
- contextWindow: 245_760,
613
- maxTokens: 8192,
850
+ patterns: ["minimax-m3", "MiniMax-M3"],
851
+ apiId: "MiniMax-M3",
852
+ name: "MiniMax M3",
853
+ reasoning: true,
854
+ input: ["text", "image"],
855
+ contextWindow: 1_048_576,
856
+ maxTokens: 131_072,
857
+ cost: P(0.3, 1.2, 0.06, 0),
614
858
  family: "MiniMax",
615
859
  },
616
860
  {
617
- patterns: ["minimax-text-01"],
618
- name: "MiniMax Text-01",
619
- reasoning: false,
861
+ patterns: ["minimax-m2.7", "MiniMax-M2.7"],
862
+ apiId: "MiniMax-M2.7",
863
+ name: "MiniMax M2.7",
864
+ reasoning: true,
620
865
  input: ["text"],
621
- contextWindow: 1_000_000,
622
- maxTokens: 8192,
866
+ contextWindow: 262_144,
867
+ maxTokens: 131_072,
868
+ cost: P(0.3, 1.2, 0.06, 0),
623
869
  family: "MiniMax",
624
870
  },
625
-
626
- // ── 01.AI Yi (零一万物) ─────────────────────────────────
627
871
  {
628
- patterns: ["yi-lightning"],
629
- name: "Yi Lightning",
630
- reasoning: false,
872
+ patterns: ["minimax-m2.5", "MiniMax-M2.5"],
873
+ apiId: "MiniMax-M2.5",
874
+ name: "MiniMax M2.5",
875
+ reasoning: true,
631
876
  input: ["text"],
632
- contextWindow: 128_000,
633
- maxTokens: 4096,
634
- family: "Yi",
877
+ contextWindow: 262_144,
878
+ maxTokens: 131_072,
879
+ cost: P(0.3, 1.2, 0.06, 0),
880
+ family: "MiniMax",
635
881
  },
636
882
  {
637
- patterns: ["yi-large"],
638
- name: "Yi Large",
639
- reasoning: false,
883
+ patterns: ["minimax-m2", "MiniMax-M2"],
884
+ apiId: "MiniMax-M2",
885
+ name: "MiniMax M2",
886
+ reasoning: true,
640
887
  input: ["text"],
641
- contextWindow: 32_768,
642
- maxTokens: 4096,
643
- cost: P(1, 2),
644
- family: "Yi",
888
+ contextWindow: 196_608,
889
+ maxTokens: 131_072,
890
+ cost: P(0.3, 1.2, 0.06, 0),
891
+ family: "MiniMax",
645
892
  },
893
+
894
+ // ── ByteDance Doubao ────────────────────────────────────
895
+ // Volcengine Ark. Prices vary by input-length tier; these are the
896
+ // entry-tier rates. Verify in the Ark console for your account.
646
897
  {
647
- patterns: ["yi-vision"],
648
- name: "Yi Vision",
649
- reasoning: false,
898
+ patterns: ["doubao-seed-1-6", "doubao-seed-1.6", "doubao-seed"],
899
+ apiId: "doubao-seed-1-6",
900
+ name: "Doubao Seed 1.6",
901
+ reasoning: true,
650
902
  input: ["text", "image"],
651
- contextWindow: 16_384,
652
- maxTokens: 4096,
653
- family: "Yi",
654
- },
655
- {
656
- patterns: ["yi-34b"],
657
- name: "Yi 34B",
658
- reasoning: false,
659
- input: ["text"],
660
- contextWindow: 4096,
661
- maxTokens: 4096,
662
- family: "Yi",
903
+ contextWindow: 262_144,
904
+ maxTokens: 32_768,
905
+ cost: P(0.113, 1.13, 0.023, 0),
906
+ family: "Doubao",
663
907
  },
664
908
 
665
- // ── MiMo ────────────────────────────────────────────────
909
+ // ── Baidu ERNIE ─────────────────────────────────────────
910
+ // Source: cloud.baidu.com/doc/qianfan-docs (CNY per 1K tokens,
911
+ // converted at 7.1 CNY/USD; entry input tier <=32K).
666
912
  {
667
- patterns: ["mimo-v2.5", "mimo-v2"],
668
- name: "MiMo V2.5",
913
+ patterns: ["ernie-5.1", "ernie-5-1"],
914
+ name: "ERNIE 5.1",
669
915
  reasoning: true,
670
- input: ["text"],
671
- contextWindow: 128_000,
672
- maxTokens: 8192,
673
- cost: P(1.2, 4.8, 0.6, 1.2),
674
- family: "MiMo",
916
+ input: ["text", "image"],
917
+ contextWindow: 131_072,
918
+ maxTokens: 65_536,
919
+ cost: P(0.85, 3.38, 0, 0),
920
+ family: "ERNIE",
675
921
  },
676
-
677
- // ── StepFun (阶跃星辰) ──────────────────────────────────
678
922
  {
679
- patterns: ["step-2"],
680
- name: "Step 2",
923
+ patterns: ["ernie-5.0", "ernie-5"],
924
+ apiId: "ernie-5.0",
925
+ name: "ERNIE 5.0",
681
926
  reasoning: true,
682
- input: ["text"],
683
- contextWindow: 128_000,
684
- maxTokens: 8192,
685
- family: "StepFun",
927
+ input: ["text", "image"],
928
+ contextWindow: 131_072,
929
+ maxTokens: 65_536,
930
+ cost: P(0.85, 3.38, 0, 0),
931
+ family: "ERNIE",
686
932
  },
687
933
  {
688
- patterns: ["step-1v"],
689
- name: "Step 1V (Vision)",
934
+ patterns: ["ernie-4.5-turbo-128k", "ernie-4.5-turbo", "ernie-4.5"],
935
+ apiId: "ernie-4.5-turbo-128k",
936
+ name: "ERNIE 4.5 Turbo 128K",
690
937
  reasoning: false,
691
- input: ["text", "image"],
692
- contextWindow: 8192,
693
- maxTokens: 4096,
694
- family: "StepFun",
938
+ input: ["text"],
939
+ contextWindow: 131_072,
940
+ maxTokens: 16_384,
941
+ cost: P(0.11, 0.45, 0.028, 0),
942
+ family: "ERNIE",
695
943
  },
696
944
 
697
945
  // ── Mistral ─────────────────────────────────────────────
946
+ // Source: docs.mistral.ai/inference/pricing.
698
947
  {
699
- patterns: ["mistral-large"],
700
- name: "Mistral Large",
948
+ patterns: ["mistral-large-3", "mistral-large"],
949
+ apiId: "mistral-large-latest",
950
+ name: "Mistral Large 3",
701
951
  reasoning: false,
702
952
  input: ["text"],
703
- contextWindow: 128_000,
704
- maxTokens: 8192,
705
- cost: P(2, 6, 1, 2),
953
+ contextWindow: 131_072,
954
+ maxTokens: 32_768,
955
+ cost: P(0.5, 1.5, 0.05, 0),
706
956
  family: "Mistral",
707
957
  },
708
958
  {
709
- patterns: ["mistral-medium"],
710
- name: "Mistral Medium",
959
+ patterns: ["mistral-medium-3.5", "mistral-medium"],
960
+ apiId: "mistral-medium-latest",
961
+ name: "Mistral Medium 3.5",
711
962
  reasoning: false,
712
963
  input: ["text"],
713
- contextWindow: 32_000,
714
- maxTokens: 4096,
715
- cost: P(0.4, 2),
964
+ contextWindow: 131_072,
965
+ maxTokens: 32_768,
966
+ cost: P(1.5, 7.5, 0.15, 0),
716
967
  family: "Mistral",
717
968
  },
718
969
  {
719
- patterns: ["mistral-small"],
720
- name: "Mistral Small",
970
+ patterns: ["mistral-small-4", "mistral-small"],
971
+ apiId: "mistral-small-latest",
972
+ name: "Mistral Small 4",
721
973
  reasoning: false,
722
974
  input: ["text"],
723
- contextWindow: 32_000,
724
- maxTokens: 4096,
725
- cost: P(0.2, 0.6),
975
+ contextWindow: 131_072,
976
+ maxTokens: 32_768,
977
+ cost: P(0.15, 0.6, 0.015, 0),
726
978
  family: "Mistral",
727
979
  },
728
980
  {
729
- patterns: ["codestral"],
730
- name: "Codestral",
981
+ patterns: ["ministral-3-14b"],
982
+ name: "Ministral 3 14B",
731
983
  reasoning: false,
732
984
  input: ["text"],
733
- contextWindow: 32_000,
734
- maxTokens: 4096,
735
- cost: P(0.3, 0.9),
985
+ contextWindow: 131_072,
986
+ maxTokens: 32_768,
987
+ cost: P(0.2, 0.2, 0.02, 0),
988
+ family: "Mistral",
989
+ },
990
+ {
991
+ patterns: ["ministral-3-8b"],
992
+ name: "Ministral 3 8B",
993
+ reasoning: false,
994
+ input: ["text"],
995
+ contextWindow: 131_072,
996
+ maxTokens: 32_768,
997
+ cost: P(0.15, 0.15, 0.015, 0),
736
998
  family: "Mistral",
737
999
  },
738
1000
 
739
- // ── Llama (Meta) ────────────────────────────────────────
1001
+ // ── Meta Llama (open weights) ───────────────────────────
1002
+ // Prices are a third-party host's serverless list rate (DeepInfra /
1003
+ // Groq) because Meta does not sell tokens directly. Adjust for your host.
740
1004
  {
741
1005
  patterns: ["llama-4-maverick"],
742
1006
  name: "Llama 4 Maverick",
@@ -744,6 +1008,7 @@ export const MODEL_CATALOG: CatalogEntry[] = [
744
1008
  input: ["text", "image"],
745
1009
  contextWindow: 1_000_000,
746
1010
  maxTokens: 16_384,
1011
+ cost: P(0.17, 0.6, 0, 0),
747
1012
  family: "Llama",
748
1013
  },
749
1014
  {
@@ -751,8 +1016,9 @@ export const MODEL_CATALOG: CatalogEntry[] = [
751
1016
  name: "Llama 4 Scout",
752
1017
  reasoning: false,
753
1018
  input: ["text", "image"],
754
- contextWindow: 10_000_000,
1019
+ contextWindow: 1_000_000,
755
1020
  maxTokens: 16_384,
1021
+ cost: P(0.08, 0.3, 0, 0),
756
1022
  family: "Llama",
757
1023
  },
758
1024
  {
@@ -760,112 +1026,32 @@ export const MODEL_CATALOG: CatalogEntry[] = [
760
1026
  name: "Llama 3.3 70B",
761
1027
  reasoning: false,
762
1028
  input: ["text"],
763
- contextWindow: 128_000,
1029
+ contextWindow: 131_072,
764
1030
  maxTokens: 8192,
765
- cost: P(0.59, 0.79),
1031
+ cost: P(0.59, 0.79, 0, 0),
766
1032
  family: "Llama",
767
1033
  },
768
- {
769
- patterns: ["llama-3.1-405b", "llama-3-1-405b"],
770
- name: "Llama 3.1 405B",
771
- reasoning: false,
772
- input: ["text"],
773
- contextWindow: 128_000,
774
- maxTokens: 4096,
775
- family: "Llama",
776
- },
777
- {
778
- patterns: ["llama-3.1-70b", "llama-3-1-70b"],
779
- name: "Llama 3.1 70B",
780
- reasoning: false,
781
- input: ["text"],
782
- contextWindow: 128_000,
783
- maxTokens: 4096,
784
- family: "Llama",
785
- },
786
- {
787
- patterns: ["llama-3.2-90b-vision", "llama-3-2-90b-vision"],
788
- name: "Llama 3.2 90B Vision",
789
- reasoning: false,
790
- input: ["text", "image"],
791
- contextWindow: 128_000,
792
- maxTokens: 4096,
793
- family: "Llama",
794
- },
795
- {
796
- patterns: ["llama-3.2-11b-vision", "llama-3-2-11b-vision"],
797
- name: "Llama 3.2 11B Vision",
798
- reasoning: false,
799
- input: ["text", "image"],
800
- contextWindow: 128_000,
801
- maxTokens: 4096,
802
- family: "Llama",
803
- },
804
-
805
- // ── Grok (xAI) ─────────────────────────────────────────
806
- {
807
- patterns: ["grok-3-mini"],
808
- name: "Grok 3 Mini",
809
- reasoning: true,
810
- input: ["text"],
811
- contextWindow: 131_072,
812
- maxTokens: 16_384,
813
- cost: P(0.3, 0.5),
814
- family: "Grok",
815
- },
816
- {
817
- patterns: ["grok-3"],
818
- name: "Grok 3",
819
- reasoning: true,
820
- input: ["text"],
821
- contextWindow: 131_072,
822
- maxTokens: 16_384,
823
- cost: P(3, 15),
824
- family: "Grok",
825
- },
826
1034
 
827
- // ── Cohere Command ──────────────────────────────────────
828
- {
829
- patterns: ["command-r-plus"],
830
- name: "Command R Plus",
831
- reasoning: false,
832
- input: ["text"],
833
- contextWindow: 128_000,
834
- maxTokens: 4096,
835
- cost: P(2.5, 10),
836
- family: "Cohere",
837
- },
1035
+ // ── 01.AI Yi ────────────────────────────────────────────
838
1036
  {
839
- patterns: ["command-r"],
840
- name: "Command R",
841
- reasoning: false,
842
- input: ["text"],
843
- contextWindow: 128_000,
844
- maxTokens: 4096,
845
- cost: P(0.15, 0.6),
846
- family: "Cohere",
847
- },
848
-
849
- // ── GitHub Copilot ──────────────────────────────────────
850
- {
851
- patterns: ["copilot-gpt-4o"],
852
- name: "Copilot GPT-4o",
1037
+ patterns: ["yi-lightning"],
1038
+ name: "Yi Lightning",
853
1039
  reasoning: false,
854
1040
  input: ["text"],
855
- contextWindow: 128_000,
1041
+ contextWindow: 16_384,
856
1042
  maxTokens: 4096,
857
- cost: P(0, 0),
858
- family: "GitHub",
1043
+ cost: P(0.14, 0.14, 0, 0),
1044
+ family: "Yi",
859
1045
  },
860
1046
 
861
1047
  // ── OpenCode / free providers ───────────────────────────
862
1048
  {
863
1049
  patterns: ["deepseek-v4-flash-free"],
864
1050
  name: "DeepSeek V4 Flash (Free)",
865
- reasoning: false,
1051
+ reasoning: true,
866
1052
  input: ["text"],
867
- contextWindow: 128_000,
868
- maxTokens: 8192,
1053
+ contextWindow: 1_048_576,
1054
+ maxTokens: 131_072,
869
1055
  cost: P(0, 0, 0, 0),
870
1056
  family: "OpenCode",
871
1057
  },
@@ -894,26 +1080,50 @@ export interface GuessResult {
894
1080
  matched?: string; // pattern that matched
895
1081
  }
896
1082
 
897
- export function guessModelMeta(id: string): GuessResult {
898
- const key = (id ?? "").toLowerCase();
1083
+ function catalogPatternScore(id: string, pattern: string): number {
1084
+ const key = id.trim().toLowerCase();
1085
+ const pat = pattern.trim().toLowerCase();
1086
+ if (!key || !pat) return 0;
1087
+ const tail = key.split("/").pop() ?? key;
1088
+
1089
+ // Exact matches must always beat a broader family prefix. For example,
1090
+ // deepseek-v4-flash-free must match its own entry rather than deepseek-v4.
1091
+ if (key === pat) return 10_000 + pat.length;
1092
+ if (tail === pat) return 9_500 + pat.length;
1093
+ if (key.endsWith("/" + pat)) return 9_000 + pat.length;
1094
+ if (tail.startsWith(pat + "-") || tail.startsWith(pat + ":")) return 7_000 + pat.length;
1095
+ if (key.startsWith(pat + "-") || key.startsWith(pat + ":")) return 6_500 + pat.length;
1096
+ if (key.includes("/" + pat + "-") || key.includes("/" + pat + ":")) return 6_000 + pat.length;
1097
+ return 0;
1098
+ }
899
1099
 
900
- // 1. Exact/prefix/suffix catalog match
1100
+ /** Resolve the single best catalog entry for a full model id. */
1101
+ export function findCatalogEntry(id: string): CatalogEntry | undefined {
1102
+ let best: { entry: CatalogEntry; score: number } | undefined;
901
1103
  for (const entry of MODEL_CATALOG) {
902
- for (const p of entry.patterns) {
903
- const pat = p.toLowerCase();
904
- if (key === pat || key.startsWith(pat + "-") || key.endsWith("/" + pat) ||
905
- key.includes("/" + pat + "-") || key.includes("/" + pat + ":")) {
906
- return {
907
- reasoning: entry.reasoning,
908
- input: entry.input,
909
- contextWindow: entry.contextWindow,
910
- maxTokens: entry.maxTokens,
911
- source: "catalog",
912
- matched: entry.name ?? p,
913
- };
914
- }
1104
+ for (const pattern of entry.patterns) {
1105
+ const score = catalogPatternScore(id, pattern);
1106
+ if (score > 0 && (!best || score > best.score)) best = { entry, score };
915
1107
  }
916
1108
  }
1109
+ return best?.entry;
1110
+ }
1111
+
1112
+ export function guessModelMeta(id: string): GuessResult {
1113
+ const key = (id ?? "").toLowerCase();
1114
+
1115
+ // 1. Best exact/alias/family catalog match.
1116
+ const entry = findCatalogEntry(key);
1117
+ if (entry) {
1118
+ return {
1119
+ reasoning: entry.reasoning,
1120
+ input: entry.input,
1121
+ contextWindow: entry.contextWindow,
1122
+ maxTokens: entry.maxTokens,
1123
+ source: "catalog",
1124
+ matched: entry.name ?? entry.patterns[0],
1125
+ };
1126
+ }
917
1127
 
918
1128
  // 2. Heuristic keyword match
919
1129
  const reasoning = KW_REASONING.test(key);
@@ -940,23 +1150,32 @@ export function guessModelMeta(id: string): GuessResult {
940
1150
 
941
1151
  // ─── Search the catalog for the picker UI ───────────────────
942
1152
 
1153
+ /** The id to prefill / display for a catalog entry. */
1154
+ export function catalogEntryId(e: CatalogEntry): string {
1155
+ return e.apiId ?? e.patterns[0] ?? "";
1156
+ }
1157
+
943
1158
  export function searchCatalog(query: string, limit = 40): CatalogEntry[] {
944
1159
  const q = query.trim().toLowerCase();
945
1160
  if (!q) return MODEL_CATALOG.slice(0, limit);
946
- const out: CatalogEntry[] = [];
947
- for (const e of MODEL_CATALOG) {
948
- const hay = [e.name ?? "", e.family ?? "", ...e.patterns].join(" ").toLowerCase();
949
- if (hay.includes(q)) out.push(e);
950
- if (out.length >= limit) break;
951
- }
952
- return out;
1161
+ return MODEL_CATALOG
1162
+ .map((entry, index) => {
1163
+ const patternScore = Math.max(0, ...entry.patterns.map((pattern) => catalogPatternScore(q, pattern)));
1164
+ const hay = [entry.name ?? "", entry.family ?? "", ...entry.patterns].join(" ").toLowerCase();
1165
+ const textScore = hay.includes(q) ? 1_000 - index : 0;
1166
+ return { entry, score: Math.max(patternScore, textScore) };
1167
+ })
1168
+ .filter((item) => item.score > 0)
1169
+ .sort((a, b) => b.score - a.score)
1170
+ .slice(0, limit)
1171
+ .map((item) => item.entry);
953
1172
  }
954
1173
 
955
1174
  // ─── Convert a catalog entry to a Partial<Model> for prefill ─
956
1175
 
957
1176
  export function catalogToModel(e: CatalogEntry, idOverride?: string): Partial<Model> {
958
1177
  return {
959
- id: idOverride ?? e.patterns[0],
1178
+ id: idOverride ?? catalogEntryId(e),
960
1179
  name: e.name,
961
1180
  reasoning: e.reasoning ?? false,
962
1181
  input: e.input ?? ["text"],