cascade-ai 0.48.0 → 0.49.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/README.md +26 -5
- package/dist/cli.cjs +1904 -55
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1904 -55
- package/dist/cli.js.map +1 -1
- package/dist/desktop-core.cjs +1841 -51
- package/dist/index.cjs +1841 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +87 -0
- package/dist/index.d.ts +87 -0
- package/dist/index.js +1841 -51
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -59,11 +59,1688 @@ var __export = (target, all) => {
|
|
|
59
59
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
60
60
|
};
|
|
61
61
|
|
|
62
|
+
// src/core/router/pricing-data.json
|
|
63
|
+
var pricing_data_default;
|
|
64
|
+
var init_pricing_data = __esm({
|
|
65
|
+
"src/core/router/pricing-data.json"() {
|
|
66
|
+
pricing_data_default = {
|
|
67
|
+
schemaVersion: 1,
|
|
68
|
+
generatedAt: "2026-07-27",
|
|
69
|
+
defaultCurrency: "USD",
|
|
70
|
+
note: 'Authoritative offline baseline for model pricing, keyed by model x provider (x region). All token rates are per 1,000,000 tokens in the entry currency. A live source (see live-data.ts) may override an entry when it is fresher; disagreements are recorded rather than silently accepted. Every entry must carry currency, asOf, source and provenance \u2014 a model with NO entry is priced "unknown", never $0. Regenerate with scripts/refresh-pricing.mjs.',
|
|
71
|
+
provenanceLegend: {
|
|
72
|
+
"vendor-pricing-page": "Read directly from the vendor's own published pricing page (see `source`).",
|
|
73
|
+
"litellm-catalog": "From BerriAI/litellm model_prices_and_context_window.json, which cites the vendor page per entry. Used where the vendor page refused automated access.",
|
|
74
|
+
"seed-approximation": "NOT sourced \u2014 an approximation. No entry in this file currently uses this value; it exists so an approximation can never masquerade as a measured price."
|
|
75
|
+
},
|
|
76
|
+
entries: [
|
|
77
|
+
{
|
|
78
|
+
model: "claude-opus-5",
|
|
79
|
+
provider: "anthropic",
|
|
80
|
+
modality: "text",
|
|
81
|
+
currency: "USD",
|
|
82
|
+
asOf: "2026-07-27",
|
|
83
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
84
|
+
provenance: "vendor-pricing-page",
|
|
85
|
+
tiers: [
|
|
86
|
+
{
|
|
87
|
+
inputPer1m: 5,
|
|
88
|
+
outputPer1m: 25,
|
|
89
|
+
cachedInputPer1m: 0.5,
|
|
90
|
+
cacheWritePer1m: 6.25,
|
|
91
|
+
reasoningOutputPer1m: 25
|
|
92
|
+
}
|
|
93
|
+
],
|
|
94
|
+
batchMultiplier: 0.5,
|
|
95
|
+
contextWindow: 1e6
|
|
96
|
+
},
|
|
97
|
+
{
|
|
98
|
+
model: "claude-opus-4-8",
|
|
99
|
+
provider: "anthropic",
|
|
100
|
+
modality: "text",
|
|
101
|
+
currency: "USD",
|
|
102
|
+
asOf: "2026-07-27",
|
|
103
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
104
|
+
provenance: "vendor-pricing-page",
|
|
105
|
+
tiers: [
|
|
106
|
+
{
|
|
107
|
+
inputPer1m: 5,
|
|
108
|
+
outputPer1m: 25,
|
|
109
|
+
cachedInputPer1m: 0.5,
|
|
110
|
+
cacheWritePer1m: 6.25,
|
|
111
|
+
reasoningOutputPer1m: 25
|
|
112
|
+
}
|
|
113
|
+
],
|
|
114
|
+
batchMultiplier: 0.5,
|
|
115
|
+
contextWindow: 1e6
|
|
116
|
+
},
|
|
117
|
+
{
|
|
118
|
+
model: "claude-opus-4-7",
|
|
119
|
+
provider: "anthropic",
|
|
120
|
+
modality: "text",
|
|
121
|
+
currency: "USD",
|
|
122
|
+
asOf: "2026-07-27",
|
|
123
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
124
|
+
provenance: "vendor-pricing-page",
|
|
125
|
+
tiers: [
|
|
126
|
+
{
|
|
127
|
+
inputPer1m: 5,
|
|
128
|
+
outputPer1m: 25,
|
|
129
|
+
cachedInputPer1m: 0.5,
|
|
130
|
+
cacheWritePer1m: 6.25,
|
|
131
|
+
reasoningOutputPer1m: 25
|
|
132
|
+
}
|
|
133
|
+
],
|
|
134
|
+
batchMultiplier: 0.5,
|
|
135
|
+
contextWindow: 1e6
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
model: "claude-opus-4-6",
|
|
139
|
+
provider: "anthropic",
|
|
140
|
+
modality: "text",
|
|
141
|
+
currency: "USD",
|
|
142
|
+
asOf: "2026-07-27",
|
|
143
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
144
|
+
provenance: "vendor-pricing-page",
|
|
145
|
+
tiers: [
|
|
146
|
+
{
|
|
147
|
+
inputPer1m: 5,
|
|
148
|
+
outputPer1m: 25,
|
|
149
|
+
cachedInputPer1m: 0.5,
|
|
150
|
+
cacheWritePer1m: 6.25,
|
|
151
|
+
reasoningOutputPer1m: 25
|
|
152
|
+
}
|
|
153
|
+
],
|
|
154
|
+
batchMultiplier: 0.5,
|
|
155
|
+
contextWindow: 1e6
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
model: "claude-opus-4-5",
|
|
159
|
+
provider: "anthropic",
|
|
160
|
+
modality: "text",
|
|
161
|
+
currency: "USD",
|
|
162
|
+
asOf: "2026-07-27",
|
|
163
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
164
|
+
provenance: "vendor-pricing-page",
|
|
165
|
+
tiers: [
|
|
166
|
+
{
|
|
167
|
+
inputPer1m: 5,
|
|
168
|
+
outputPer1m: 25,
|
|
169
|
+
cachedInputPer1m: 0.5,
|
|
170
|
+
cacheWritePer1m: 6.25,
|
|
171
|
+
reasoningOutputPer1m: 25
|
|
172
|
+
}
|
|
173
|
+
],
|
|
174
|
+
batchMultiplier: 0.5,
|
|
175
|
+
contextWindow: 2e5
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
model: "claude-opus-4-1",
|
|
179
|
+
provider: "anthropic",
|
|
180
|
+
modality: "text",
|
|
181
|
+
currency: "USD",
|
|
182
|
+
asOf: "2026-07-27",
|
|
183
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
184
|
+
provenance: "vendor-pricing-page",
|
|
185
|
+
tiers: [
|
|
186
|
+
{
|
|
187
|
+
inputPer1m: 15,
|
|
188
|
+
outputPer1m: 75,
|
|
189
|
+
cachedInputPer1m: 1.5,
|
|
190
|
+
cacheWritePer1m: 18.75,
|
|
191
|
+
reasoningOutputPer1m: 75
|
|
192
|
+
}
|
|
193
|
+
],
|
|
194
|
+
batchMultiplier: 0.5,
|
|
195
|
+
contextWindow: 2e5,
|
|
196
|
+
notes: "Deprecated by Anthropic; priced for historical/cost-reporting accuracy."
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
model: "claude-opus-4",
|
|
200
|
+
provider: "anthropic",
|
|
201
|
+
modality: "text",
|
|
202
|
+
currency: "USD",
|
|
203
|
+
asOf: "2026-07-27",
|
|
204
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
205
|
+
provenance: "vendor-pricing-page",
|
|
206
|
+
tiers: [
|
|
207
|
+
{
|
|
208
|
+
inputPer1m: 15,
|
|
209
|
+
outputPer1m: 75,
|
|
210
|
+
cachedInputPer1m: 1.5,
|
|
211
|
+
cacheWritePer1m: 18.75,
|
|
212
|
+
reasoningOutputPer1m: 75
|
|
213
|
+
}
|
|
214
|
+
],
|
|
215
|
+
batchMultiplier: 0.5,
|
|
216
|
+
contextWindow: 2e5,
|
|
217
|
+
notes: "Retired except on Google Cloud; priced for historical/cost-reporting accuracy."
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
model: "claude-sonnet-5",
|
|
221
|
+
provider: "anthropic",
|
|
222
|
+
modality: "text",
|
|
223
|
+
currency: "USD",
|
|
224
|
+
asOf: "2026-07-27",
|
|
225
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
226
|
+
provenance: "vendor-pricing-page",
|
|
227
|
+
tiers: [
|
|
228
|
+
{
|
|
229
|
+
inputPer1m: 2,
|
|
230
|
+
outputPer1m: 10,
|
|
231
|
+
cachedInputPer1m: 0.2,
|
|
232
|
+
cacheWritePer1m: 2.5,
|
|
233
|
+
reasoningOutputPer1m: 10
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
batchMultiplier: 0.5,
|
|
237
|
+
contextWindow: 1e6,
|
|
238
|
+
notes: "Introductory pricing through 2026-08-31. Standard pricing of $3/$15 per 1M takes effect 2026-09-01 \u2014 re-check this entry then."
|
|
239
|
+
},
|
|
240
|
+
{
|
|
241
|
+
model: "claude-sonnet-4-6",
|
|
242
|
+
provider: "anthropic",
|
|
243
|
+
modality: "text",
|
|
244
|
+
currency: "USD",
|
|
245
|
+
asOf: "2026-07-27",
|
|
246
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
247
|
+
provenance: "vendor-pricing-page",
|
|
248
|
+
tiers: [
|
|
249
|
+
{
|
|
250
|
+
inputPer1m: 3,
|
|
251
|
+
outputPer1m: 15,
|
|
252
|
+
cachedInputPer1m: 0.3,
|
|
253
|
+
cacheWritePer1m: 3.75,
|
|
254
|
+
reasoningOutputPer1m: 15
|
|
255
|
+
}
|
|
256
|
+
],
|
|
257
|
+
batchMultiplier: 0.5,
|
|
258
|
+
contextWindow: 1e6
|
|
259
|
+
},
|
|
260
|
+
{
|
|
261
|
+
model: "claude-sonnet-4-5",
|
|
262
|
+
provider: "anthropic",
|
|
263
|
+
modality: "text",
|
|
264
|
+
currency: "USD",
|
|
265
|
+
asOf: "2026-07-27",
|
|
266
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
267
|
+
provenance: "vendor-pricing-page",
|
|
268
|
+
tiers: [
|
|
269
|
+
{
|
|
270
|
+
maxInputTokens: 2e5,
|
|
271
|
+
inputPer1m: 3,
|
|
272
|
+
outputPer1m: 15,
|
|
273
|
+
cachedInputPer1m: 0.3,
|
|
274
|
+
cacheWritePer1m: 3.75,
|
|
275
|
+
reasoningOutputPer1m: 15
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
inputPer1m: 6,
|
|
279
|
+
outputPer1m: 22.5,
|
|
280
|
+
cachedInputPer1m: 0.6,
|
|
281
|
+
cacheWritePer1m: 7.5,
|
|
282
|
+
reasoningOutputPer1m: 22.5
|
|
283
|
+
}
|
|
284
|
+
],
|
|
285
|
+
batchMultiplier: 0.5,
|
|
286
|
+
contextWindow: 2e5,
|
|
287
|
+
notes: "Long-context (>200K) premium applies to the 1M-context beta. Base rates from the Anthropic pricing page; the >200K tier from the litellm catalog (Anthropic does not tabulate it on the pricing page)."
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
model: "claude-sonnet-4",
|
|
291
|
+
provider: "anthropic",
|
|
292
|
+
modality: "text",
|
|
293
|
+
currency: "USD",
|
|
294
|
+
asOf: "2026-07-27",
|
|
295
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
296
|
+
provenance: "vendor-pricing-page",
|
|
297
|
+
tiers: [
|
|
298
|
+
{
|
|
299
|
+
inputPer1m: 3,
|
|
300
|
+
outputPer1m: 15,
|
|
301
|
+
cachedInputPer1m: 0.3,
|
|
302
|
+
cacheWritePer1m: 3.75,
|
|
303
|
+
reasoningOutputPer1m: 15
|
|
304
|
+
}
|
|
305
|
+
],
|
|
306
|
+
batchMultiplier: 0.5,
|
|
307
|
+
contextWindow: 2e5
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
model: "claude-haiku-4-5",
|
|
311
|
+
provider: "anthropic",
|
|
312
|
+
modality: "text",
|
|
313
|
+
currency: "USD",
|
|
314
|
+
asOf: "2026-07-27",
|
|
315
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
316
|
+
provenance: "vendor-pricing-page",
|
|
317
|
+
tiers: [
|
|
318
|
+
{
|
|
319
|
+
inputPer1m: 1,
|
|
320
|
+
outputPer1m: 5,
|
|
321
|
+
cachedInputPer1m: 0.1,
|
|
322
|
+
cacheWritePer1m: 1.25,
|
|
323
|
+
reasoningOutputPer1m: 5
|
|
324
|
+
}
|
|
325
|
+
],
|
|
326
|
+
batchMultiplier: 0.5,
|
|
327
|
+
contextWindow: 2e5
|
|
328
|
+
},
|
|
329
|
+
{
|
|
330
|
+
model: "claude-haiku-3-5",
|
|
331
|
+
provider: "anthropic",
|
|
332
|
+
modality: "text",
|
|
333
|
+
currency: "USD",
|
|
334
|
+
asOf: "2026-07-27",
|
|
335
|
+
source: "https://platform.claude.com/docs/en/about-claude/pricing",
|
|
336
|
+
provenance: "vendor-pricing-page",
|
|
337
|
+
tiers: [
|
|
338
|
+
{
|
|
339
|
+
inputPer1m: 0.8,
|
|
340
|
+
outputPer1m: 4,
|
|
341
|
+
cachedInputPer1m: 0.08,
|
|
342
|
+
cacheWritePer1m: 1,
|
|
343
|
+
reasoningOutputPer1m: 4
|
|
344
|
+
}
|
|
345
|
+
],
|
|
346
|
+
batchMultiplier: 0.5,
|
|
347
|
+
contextWindow: 2e5
|
|
348
|
+
},
|
|
349
|
+
{
|
|
350
|
+
model: "gpt-5.6-sol",
|
|
351
|
+
provider: "openai",
|
|
352
|
+
aliases: [
|
|
353
|
+
"gpt-5.6"
|
|
354
|
+
],
|
|
355
|
+
modality: "text",
|
|
356
|
+
currency: "USD",
|
|
357
|
+
asOf: "2026-07-27",
|
|
358
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
359
|
+
provenance: "litellm-catalog",
|
|
360
|
+
tiers: [
|
|
361
|
+
{
|
|
362
|
+
maxInputTokens: 272e3,
|
|
363
|
+
inputPer1m: 5,
|
|
364
|
+
outputPer1m: 30,
|
|
365
|
+
cachedInputPer1m: 0.5,
|
|
366
|
+
cacheWritePer1m: 6.25
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
inputPer1m: 10,
|
|
370
|
+
outputPer1m: 45,
|
|
371
|
+
cachedInputPer1m: 1,
|
|
372
|
+
cacheWritePer1m: 12.5
|
|
373
|
+
}
|
|
374
|
+
],
|
|
375
|
+
batchMultiplier: 0.5,
|
|
376
|
+
contextWindow: 105e4
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
model: "gpt-5.6-terra",
|
|
380
|
+
provider: "openai",
|
|
381
|
+
modality: "text",
|
|
382
|
+
currency: "USD",
|
|
383
|
+
asOf: "2026-07-27",
|
|
384
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
385
|
+
provenance: "litellm-catalog",
|
|
386
|
+
tiers: [
|
|
387
|
+
{
|
|
388
|
+
maxInputTokens: 272e3,
|
|
389
|
+
inputPer1m: 2.5,
|
|
390
|
+
outputPer1m: 15,
|
|
391
|
+
cachedInputPer1m: 0.25,
|
|
392
|
+
cacheWritePer1m: 3.125
|
|
393
|
+
},
|
|
394
|
+
{
|
|
395
|
+
inputPer1m: 5,
|
|
396
|
+
outputPer1m: 22.5,
|
|
397
|
+
cachedInputPer1m: 0.5,
|
|
398
|
+
cacheWritePer1m: 6.25
|
|
399
|
+
}
|
|
400
|
+
],
|
|
401
|
+
batchMultiplier: 0.5,
|
|
402
|
+
contextWindow: 105e4
|
|
403
|
+
},
|
|
404
|
+
{
|
|
405
|
+
model: "gpt-5.6-luna",
|
|
406
|
+
provider: "openai",
|
|
407
|
+
modality: "text",
|
|
408
|
+
currency: "USD",
|
|
409
|
+
asOf: "2026-07-27",
|
|
410
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
411
|
+
provenance: "litellm-catalog",
|
|
412
|
+
tiers: [
|
|
413
|
+
{
|
|
414
|
+
maxInputTokens: 272e3,
|
|
415
|
+
inputPer1m: 1,
|
|
416
|
+
outputPer1m: 6,
|
|
417
|
+
cachedInputPer1m: 0.1,
|
|
418
|
+
cacheWritePer1m: 1.25
|
|
419
|
+
},
|
|
420
|
+
{
|
|
421
|
+
inputPer1m: 2,
|
|
422
|
+
outputPer1m: 9,
|
|
423
|
+
cachedInputPer1m: 0.2,
|
|
424
|
+
cacheWritePer1m: 2.5
|
|
425
|
+
}
|
|
426
|
+
],
|
|
427
|
+
batchMultiplier: 0.5,
|
|
428
|
+
contextWindow: 105e4
|
|
429
|
+
},
|
|
430
|
+
{
|
|
431
|
+
model: "gpt-5.5",
|
|
432
|
+
provider: "openai",
|
|
433
|
+
modality: "text",
|
|
434
|
+
currency: "USD",
|
|
435
|
+
asOf: "2026-07-27",
|
|
436
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
437
|
+
provenance: "litellm-catalog",
|
|
438
|
+
tiers: [
|
|
439
|
+
{
|
|
440
|
+
maxInputTokens: 272e3,
|
|
441
|
+
inputPer1m: 5,
|
|
442
|
+
outputPer1m: 30,
|
|
443
|
+
cachedInputPer1m: 0.5
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
inputPer1m: 10,
|
|
447
|
+
outputPer1m: 45,
|
|
448
|
+
cachedInputPer1m: 1
|
|
449
|
+
}
|
|
450
|
+
],
|
|
451
|
+
batchMultiplier: 0.5,
|
|
452
|
+
contextWindow: 105e4
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
model: "gpt-5.4",
|
|
456
|
+
provider: "openai",
|
|
457
|
+
modality: "text",
|
|
458
|
+
currency: "USD",
|
|
459
|
+
asOf: "2026-07-27",
|
|
460
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
461
|
+
provenance: "litellm-catalog",
|
|
462
|
+
tiers: [
|
|
463
|
+
{
|
|
464
|
+
maxInputTokens: 272e3,
|
|
465
|
+
inputPer1m: 2.5,
|
|
466
|
+
outputPer1m: 15,
|
|
467
|
+
cachedInputPer1m: 0.25
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
inputPer1m: 5,
|
|
471
|
+
outputPer1m: 22.5,
|
|
472
|
+
cachedInputPer1m: 0.5
|
|
473
|
+
}
|
|
474
|
+
],
|
|
475
|
+
batchMultiplier: 0.5,
|
|
476
|
+
contextWindow: 105e4
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
model: "gpt-5.4-mini",
|
|
480
|
+
provider: "openai",
|
|
481
|
+
modality: "text",
|
|
482
|
+
currency: "USD",
|
|
483
|
+
asOf: "2026-07-27",
|
|
484
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
485
|
+
provenance: "litellm-catalog",
|
|
486
|
+
tiers: [
|
|
487
|
+
{
|
|
488
|
+
inputPer1m: 0.75,
|
|
489
|
+
outputPer1m: 4.5,
|
|
490
|
+
cachedInputPer1m: 0.075
|
|
491
|
+
}
|
|
492
|
+
],
|
|
493
|
+
batchMultiplier: 0.5,
|
|
494
|
+
contextWindow: 105e4
|
|
495
|
+
},
|
|
496
|
+
{
|
|
497
|
+
model: "gpt-5",
|
|
498
|
+
provider: "openai",
|
|
499
|
+
modality: "text",
|
|
500
|
+
currency: "USD",
|
|
501
|
+
asOf: "2026-07-27",
|
|
502
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
503
|
+
provenance: "litellm-catalog",
|
|
504
|
+
tiers: [
|
|
505
|
+
{
|
|
506
|
+
inputPer1m: 1.25,
|
|
507
|
+
outputPer1m: 10,
|
|
508
|
+
cachedInputPer1m: 0.125
|
|
509
|
+
}
|
|
510
|
+
],
|
|
511
|
+
contextWindow: 272e3
|
|
512
|
+
},
|
|
513
|
+
{
|
|
514
|
+
model: "gpt-5-mini",
|
|
515
|
+
provider: "openai",
|
|
516
|
+
modality: "text",
|
|
517
|
+
currency: "USD",
|
|
518
|
+
asOf: "2026-07-27",
|
|
519
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
520
|
+
provenance: "litellm-catalog",
|
|
521
|
+
tiers: [
|
|
522
|
+
{
|
|
523
|
+
inputPer1m: 0.25,
|
|
524
|
+
outputPer1m: 2,
|
|
525
|
+
cachedInputPer1m: 0.025
|
|
526
|
+
}
|
|
527
|
+
],
|
|
528
|
+
contextWindow: 272e3
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
model: "gpt-5-nano",
|
|
532
|
+
provider: "openai",
|
|
533
|
+
modality: "text",
|
|
534
|
+
currency: "USD",
|
|
535
|
+
asOf: "2026-07-27",
|
|
536
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
537
|
+
provenance: "litellm-catalog",
|
|
538
|
+
tiers: [
|
|
539
|
+
{
|
|
540
|
+
inputPer1m: 0.05,
|
|
541
|
+
outputPer1m: 0.4,
|
|
542
|
+
cachedInputPer1m: 5e-3
|
|
543
|
+
}
|
|
544
|
+
],
|
|
545
|
+
contextWindow: 272e3
|
|
546
|
+
},
|
|
547
|
+
{
|
|
548
|
+
model: "gpt-4.1",
|
|
549
|
+
provider: "openai",
|
|
550
|
+
modality: "text",
|
|
551
|
+
currency: "USD",
|
|
552
|
+
asOf: "2026-07-27",
|
|
553
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
554
|
+
provenance: "litellm-catalog",
|
|
555
|
+
tiers: [
|
|
556
|
+
{
|
|
557
|
+
inputPer1m: 2,
|
|
558
|
+
outputPer1m: 8,
|
|
559
|
+
cachedInputPer1m: 0.5
|
|
560
|
+
}
|
|
561
|
+
],
|
|
562
|
+
batchMultiplier: 0.5,
|
|
563
|
+
contextWindow: 1047576
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
model: "gpt-4.1-mini",
|
|
567
|
+
provider: "openai",
|
|
568
|
+
modality: "text",
|
|
569
|
+
currency: "USD",
|
|
570
|
+
asOf: "2026-07-27",
|
|
571
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
572
|
+
provenance: "litellm-catalog",
|
|
573
|
+
tiers: [
|
|
574
|
+
{
|
|
575
|
+
inputPer1m: 0.4,
|
|
576
|
+
outputPer1m: 1.6,
|
|
577
|
+
cachedInputPer1m: 0.1
|
|
578
|
+
}
|
|
579
|
+
],
|
|
580
|
+
batchMultiplier: 0.5,
|
|
581
|
+
contextWindow: 1047576
|
|
582
|
+
},
|
|
583
|
+
{
|
|
584
|
+
model: "gpt-4.1-nano",
|
|
585
|
+
provider: "openai",
|
|
586
|
+
modality: "text",
|
|
587
|
+
currency: "USD",
|
|
588
|
+
asOf: "2026-07-27",
|
|
589
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
590
|
+
provenance: "litellm-catalog",
|
|
591
|
+
tiers: [
|
|
592
|
+
{
|
|
593
|
+
inputPer1m: 0.1,
|
|
594
|
+
outputPer1m: 0.4,
|
|
595
|
+
cachedInputPer1m: 0.025
|
|
596
|
+
}
|
|
597
|
+
],
|
|
598
|
+
batchMultiplier: 0.5,
|
|
599
|
+
contextWindow: 1047576
|
|
600
|
+
},
|
|
601
|
+
{
|
|
602
|
+
model: "gpt-4o",
|
|
603
|
+
provider: "openai",
|
|
604
|
+
modality: "text",
|
|
605
|
+
currency: "USD",
|
|
606
|
+
asOf: "2026-07-27",
|
|
607
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
608
|
+
provenance: "litellm-catalog",
|
|
609
|
+
tiers: [
|
|
610
|
+
{
|
|
611
|
+
inputPer1m: 2.5,
|
|
612
|
+
outputPer1m: 10,
|
|
613
|
+
cachedInputPer1m: 1.25
|
|
614
|
+
}
|
|
615
|
+
],
|
|
616
|
+
batchMultiplier: 0.5,
|
|
617
|
+
contextWindow: 128e3
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
model: "gpt-4o-mini",
|
|
621
|
+
provider: "openai",
|
|
622
|
+
modality: "text",
|
|
623
|
+
currency: "USD",
|
|
624
|
+
asOf: "2026-07-27",
|
|
625
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
626
|
+
provenance: "litellm-catalog",
|
|
627
|
+
tiers: [
|
|
628
|
+
{
|
|
629
|
+
inputPer1m: 0.15,
|
|
630
|
+
outputPer1m: 0.6,
|
|
631
|
+
cachedInputPer1m: 0.075
|
|
632
|
+
}
|
|
633
|
+
],
|
|
634
|
+
batchMultiplier: 0.5,
|
|
635
|
+
contextWindow: 128e3
|
|
636
|
+
},
|
|
637
|
+
{
|
|
638
|
+
model: "gpt-5.5",
|
|
639
|
+
provider: "azure",
|
|
640
|
+
region: "global",
|
|
641
|
+
modality: "text",
|
|
642
|
+
currency: "USD",
|
|
643
|
+
asOf: "2026-07-27",
|
|
644
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
645
|
+
provenance: "litellm-catalog",
|
|
646
|
+
tiers: [
|
|
647
|
+
{
|
|
648
|
+
maxInputTokens: 272e3,
|
|
649
|
+
inputPer1m: 5,
|
|
650
|
+
outputPer1m: 30,
|
|
651
|
+
cachedInputPer1m: 0.5
|
|
652
|
+
},
|
|
653
|
+
{
|
|
654
|
+
inputPer1m: 10,
|
|
655
|
+
outputPer1m: 45,
|
|
656
|
+
cachedInputPer1m: 1
|
|
657
|
+
}
|
|
658
|
+
],
|
|
659
|
+
contextWindow: 105e4
|
|
660
|
+
},
|
|
661
|
+
{
|
|
662
|
+
model: "gpt-5.5",
|
|
663
|
+
provider: "azure",
|
|
664
|
+
region: "us",
|
|
665
|
+
modality: "text",
|
|
666
|
+
currency: "USD",
|
|
667
|
+
asOf: "2026-07-27",
|
|
668
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
669
|
+
provenance: "litellm-catalog",
|
|
670
|
+
tiers: [
|
|
671
|
+
{
|
|
672
|
+
maxInputTokens: 272e3,
|
|
673
|
+
inputPer1m: 5.5,
|
|
674
|
+
outputPer1m: 33,
|
|
675
|
+
cachedInputPer1m: 0.55
|
|
676
|
+
},
|
|
677
|
+
{
|
|
678
|
+
inputPer1m: 11,
|
|
679
|
+
outputPer1m: 49.5,
|
|
680
|
+
cachedInputPer1m: 1.1
|
|
681
|
+
}
|
|
682
|
+
],
|
|
683
|
+
contextWindow: 105e4
|
|
684
|
+
},
|
|
685
|
+
{
|
|
686
|
+
model: "gpt-5.5",
|
|
687
|
+
provider: "azure",
|
|
688
|
+
region: "eu",
|
|
689
|
+
modality: "text",
|
|
690
|
+
currency: "USD",
|
|
691
|
+
asOf: "2026-07-27",
|
|
692
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
693
|
+
provenance: "litellm-catalog",
|
|
694
|
+
tiers: [
|
|
695
|
+
{
|
|
696
|
+
maxInputTokens: 272e3,
|
|
697
|
+
inputPer1m: 5.5,
|
|
698
|
+
outputPer1m: 33,
|
|
699
|
+
cachedInputPer1m: 0.55
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
inputPer1m: 11,
|
|
703
|
+
outputPer1m: 49.5,
|
|
704
|
+
cachedInputPer1m: 1.1
|
|
705
|
+
}
|
|
706
|
+
],
|
|
707
|
+
contextWindow: 105e4
|
|
708
|
+
},
|
|
709
|
+
{
|
|
710
|
+
model: "gpt-5.4",
|
|
711
|
+
provider: "azure",
|
|
712
|
+
region: "global",
|
|
713
|
+
modality: "text",
|
|
714
|
+
currency: "USD",
|
|
715
|
+
asOf: "2026-07-27",
|
|
716
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
717
|
+
provenance: "litellm-catalog",
|
|
718
|
+
tiers: [
|
|
719
|
+
{
|
|
720
|
+
maxInputTokens: 272e3,
|
|
721
|
+
inputPer1m: 2.5,
|
|
722
|
+
outputPer1m: 15,
|
|
723
|
+
cachedInputPer1m: 0.25
|
|
724
|
+
},
|
|
725
|
+
{
|
|
726
|
+
inputPer1m: 5,
|
|
727
|
+
outputPer1m: 22.5,
|
|
728
|
+
cachedInputPer1m: 0.5
|
|
729
|
+
}
|
|
730
|
+
],
|
|
731
|
+
contextWindow: 105e4
|
|
732
|
+
},
|
|
733
|
+
{
|
|
734
|
+
model: "gpt-5.4",
|
|
735
|
+
provider: "azure",
|
|
736
|
+
region: "us",
|
|
737
|
+
modality: "text",
|
|
738
|
+
currency: "USD",
|
|
739
|
+
asOf: "2026-07-27",
|
|
740
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
741
|
+
provenance: "litellm-catalog",
|
|
742
|
+
tiers: [
|
|
743
|
+
{
|
|
744
|
+
inputPer1m: 2.75,
|
|
745
|
+
outputPer1m: 16.5,
|
|
746
|
+
cachedInputPer1m: 0.28
|
|
747
|
+
}
|
|
748
|
+
],
|
|
749
|
+
contextWindow: 105e4
|
|
750
|
+
},
|
|
751
|
+
{
|
|
752
|
+
model: "gpt-5.4",
|
|
753
|
+
provider: "azure",
|
|
754
|
+
region: "eu",
|
|
755
|
+
modality: "text",
|
|
756
|
+
currency: "USD",
|
|
757
|
+
asOf: "2026-07-27",
|
|
758
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
759
|
+
provenance: "litellm-catalog",
|
|
760
|
+
tiers: [
|
|
761
|
+
{
|
|
762
|
+
inputPer1m: 2.75,
|
|
763
|
+
outputPer1m: 16.5,
|
|
764
|
+
cachedInputPer1m: 0.28
|
|
765
|
+
}
|
|
766
|
+
],
|
|
767
|
+
contextWindow: 105e4
|
|
768
|
+
},
|
|
769
|
+
{
|
|
770
|
+
model: "gpt-5.6-terra",
|
|
771
|
+
provider: "azure",
|
|
772
|
+
region: "global",
|
|
773
|
+
modality: "text",
|
|
774
|
+
currency: "USD",
|
|
775
|
+
asOf: "2026-07-27",
|
|
776
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
777
|
+
provenance: "litellm-catalog",
|
|
778
|
+
tiers: [
|
|
779
|
+
{
|
|
780
|
+
maxInputTokens: 272e3,
|
|
781
|
+
inputPer1m: 2.5,
|
|
782
|
+
outputPer1m: 15,
|
|
783
|
+
cachedInputPer1m: 0.25
|
|
784
|
+
},
|
|
785
|
+
{
|
|
786
|
+
inputPer1m: 5,
|
|
787
|
+
outputPer1m: 22.5,
|
|
788
|
+
cachedInputPer1m: 0.5
|
|
789
|
+
}
|
|
790
|
+
],
|
|
791
|
+
contextWindow: 105e4
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
model: "gpt-5.6-terra",
|
|
795
|
+
provider: "azure",
|
|
796
|
+
region: "eu",
|
|
797
|
+
modality: "text",
|
|
798
|
+
currency: "USD",
|
|
799
|
+
asOf: "2026-07-27",
|
|
800
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
801
|
+
provenance: "litellm-catalog",
|
|
802
|
+
tiers: [
|
|
803
|
+
{
|
|
804
|
+
maxInputTokens: 272e3,
|
|
805
|
+
inputPer1m: 2.75,
|
|
806
|
+
outputPer1m: 16.5,
|
|
807
|
+
cachedInputPer1m: 0.275
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
inputPer1m: 5.5,
|
|
811
|
+
outputPer1m: 24.75,
|
|
812
|
+
cachedInputPer1m: 0.55
|
|
813
|
+
}
|
|
814
|
+
],
|
|
815
|
+
contextWindow: 105e4
|
|
816
|
+
},
|
|
817
|
+
{
|
|
818
|
+
model: "gpt-5",
|
|
819
|
+
provider: "azure",
|
|
820
|
+
region: "global",
|
|
821
|
+
modality: "text",
|
|
822
|
+
currency: "USD",
|
|
823
|
+
asOf: "2026-07-27",
|
|
824
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
825
|
+
provenance: "litellm-catalog",
|
|
826
|
+
tiers: [
|
|
827
|
+
{
|
|
828
|
+
inputPer1m: 1.25,
|
|
829
|
+
outputPer1m: 10,
|
|
830
|
+
cachedInputPer1m: 0.125
|
|
831
|
+
}
|
|
832
|
+
],
|
|
833
|
+
contextWindow: 272e3
|
|
834
|
+
},
|
|
835
|
+
{
|
|
836
|
+
model: "gpt-5-mini",
|
|
837
|
+
provider: "azure",
|
|
838
|
+
region: "global",
|
|
839
|
+
modality: "text",
|
|
840
|
+
currency: "USD",
|
|
841
|
+
asOf: "2026-07-27",
|
|
842
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
843
|
+
provenance: "litellm-catalog",
|
|
844
|
+
tiers: [
|
|
845
|
+
{
|
|
846
|
+
inputPer1m: 0.25,
|
|
847
|
+
outputPer1m: 2,
|
|
848
|
+
cachedInputPer1m: 0.025
|
|
849
|
+
}
|
|
850
|
+
],
|
|
851
|
+
contextWindow: 272e3
|
|
852
|
+
},
|
|
853
|
+
{
|
|
854
|
+
model: "gpt-5-nano",
|
|
855
|
+
provider: "azure",
|
|
856
|
+
region: "global",
|
|
857
|
+
modality: "text",
|
|
858
|
+
currency: "USD",
|
|
859
|
+
asOf: "2026-07-27",
|
|
860
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
861
|
+
provenance: "litellm-catalog",
|
|
862
|
+
tiers: [
|
|
863
|
+
{
|
|
864
|
+
inputPer1m: 0.05,
|
|
865
|
+
outputPer1m: 0.4,
|
|
866
|
+
cachedInputPer1m: 5e-3
|
|
867
|
+
}
|
|
868
|
+
],
|
|
869
|
+
contextWindow: 272e3
|
|
870
|
+
},
|
|
871
|
+
{
|
|
872
|
+
model: "gpt-4.1",
|
|
873
|
+
provider: "azure",
|
|
874
|
+
region: "global",
|
|
875
|
+
modality: "text",
|
|
876
|
+
currency: "USD",
|
|
877
|
+
asOf: "2026-07-27",
|
|
878
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
879
|
+
provenance: "litellm-catalog",
|
|
880
|
+
tiers: [
|
|
881
|
+
{
|
|
882
|
+
inputPer1m: 2,
|
|
883
|
+
outputPer1m: 8,
|
|
884
|
+
cachedInputPer1m: 0.5
|
|
885
|
+
}
|
|
886
|
+
],
|
|
887
|
+
batchMultiplier: 0.5,
|
|
888
|
+
contextWindow: 1047576
|
|
889
|
+
},
|
|
890
|
+
{
|
|
891
|
+
model: "gpt-4o",
|
|
892
|
+
provider: "azure",
|
|
893
|
+
region: "global",
|
|
894
|
+
modality: "text",
|
|
895
|
+
currency: "USD",
|
|
896
|
+
asOf: "2026-07-27",
|
|
897
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
898
|
+
provenance: "litellm-catalog",
|
|
899
|
+
tiers: [
|
|
900
|
+
{
|
|
901
|
+
inputPer1m: 2.5,
|
|
902
|
+
outputPer1m: 10,
|
|
903
|
+
cachedInputPer1m: 1.25
|
|
904
|
+
}
|
|
905
|
+
],
|
|
906
|
+
contextWindow: 128e3
|
|
907
|
+
},
|
|
908
|
+
{
|
|
909
|
+
model: "gpt-4o-mini",
|
|
910
|
+
provider: "azure",
|
|
911
|
+
region: "global",
|
|
912
|
+
modality: "text",
|
|
913
|
+
currency: "USD",
|
|
914
|
+
asOf: "2026-07-27",
|
|
915
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
916
|
+
provenance: "litellm-catalog",
|
|
917
|
+
tiers: [
|
|
918
|
+
{
|
|
919
|
+
inputPer1m: 0.165,
|
|
920
|
+
outputPer1m: 0.66,
|
|
921
|
+
cachedInputPer1m: 0.075
|
|
922
|
+
}
|
|
923
|
+
],
|
|
924
|
+
contextWindow: 128e3,
|
|
925
|
+
notes: "Azure charges $0.165/$0.66 per 1M for gpt-4o-mini vs $0.15/$0.60 on OpenAI \u2014 same model, different price."
|
|
926
|
+
},
|
|
927
|
+
{
|
|
928
|
+
model: "gemini-3.1-pro",
|
|
929
|
+
provider: "gemini",
|
|
930
|
+
aliases: [
|
|
931
|
+
"gemini-3.1-pro-preview"
|
|
932
|
+
],
|
|
933
|
+
modality: "text",
|
|
934
|
+
currency: "USD",
|
|
935
|
+
asOf: "2026-07-27",
|
|
936
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
937
|
+
provenance: "vendor-pricing-page",
|
|
938
|
+
tiers: [
|
|
939
|
+
{
|
|
940
|
+
maxInputTokens: 2e5,
|
|
941
|
+
inputPer1m: 2,
|
|
942
|
+
outputPer1m: 12,
|
|
943
|
+
cachedInputPer1m: 0.2,
|
|
944
|
+
reasoningOutputPer1m: 12
|
|
945
|
+
},
|
|
946
|
+
{
|
|
947
|
+
inputPer1m: 4,
|
|
948
|
+
outputPer1m: 18,
|
|
949
|
+
cachedInputPer1m: 0.4,
|
|
950
|
+
reasoningOutputPer1m: 18
|
|
951
|
+
}
|
|
952
|
+
],
|
|
953
|
+
batchMultiplier: 0.5,
|
|
954
|
+
contextWindow: 1048576,
|
|
955
|
+
notes: "Long-context tier: $2/$12 per 1M up to 200K prompt tokens, $4/$18 above it."
|
|
956
|
+
},
|
|
957
|
+
{
|
|
958
|
+
model: "gemini-3-pro",
|
|
959
|
+
provider: "gemini",
|
|
960
|
+
aliases: [
|
|
961
|
+
"gemini-3-pro-preview"
|
|
962
|
+
],
|
|
963
|
+
modality: "text",
|
|
964
|
+
currency: "USD",
|
|
965
|
+
asOf: "2026-07-27",
|
|
966
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
967
|
+
provenance: "vendor-pricing-page",
|
|
968
|
+
tiers: [
|
|
969
|
+
{
|
|
970
|
+
maxInputTokens: 2e5,
|
|
971
|
+
inputPer1m: 2,
|
|
972
|
+
outputPer1m: 12,
|
|
973
|
+
cachedInputPer1m: 0.2,
|
|
974
|
+
reasoningOutputPer1m: 12
|
|
975
|
+
},
|
|
976
|
+
{
|
|
977
|
+
inputPer1m: 4,
|
|
978
|
+
outputPer1m: 18,
|
|
979
|
+
cachedInputPer1m: 0.4,
|
|
980
|
+
reasoningOutputPer1m: 18
|
|
981
|
+
}
|
|
982
|
+
],
|
|
983
|
+
batchMultiplier: 0.5,
|
|
984
|
+
contextWindow: 1048576
|
|
985
|
+
},
|
|
986
|
+
{
|
|
987
|
+
model: "gemini-3.6-flash",
|
|
988
|
+
provider: "gemini",
|
|
989
|
+
modality: "text",
|
|
990
|
+
currency: "USD",
|
|
991
|
+
asOf: "2026-07-27",
|
|
992
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
993
|
+
provenance: "vendor-pricing-page",
|
|
994
|
+
tiers: [
|
|
995
|
+
{
|
|
996
|
+
inputPer1m: 1.5,
|
|
997
|
+
outputPer1m: 7.5,
|
|
998
|
+
cachedInputPer1m: 0.15,
|
|
999
|
+
reasoningOutputPer1m: 7.5
|
|
1000
|
+
}
|
|
1001
|
+
],
|
|
1002
|
+
batchMultiplier: 0.5,
|
|
1003
|
+
contextWindow: 1048576,
|
|
1004
|
+
notes: "Released 2026-07-21. Output pricing dropped ~17% from Gemini 3.5 Flash ($9.00 -> $7.50 per 1M); input unchanged."
|
|
1005
|
+
},
|
|
1006
|
+
{
|
|
1007
|
+
model: "gemini-3.5-flash",
|
|
1008
|
+
provider: "gemini",
|
|
1009
|
+
modality: "text",
|
|
1010
|
+
currency: "USD",
|
|
1011
|
+
asOf: "2026-07-27",
|
|
1012
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1013
|
+
provenance: "vendor-pricing-page",
|
|
1014
|
+
tiers: [
|
|
1015
|
+
{
|
|
1016
|
+
inputPer1m: 1.5,
|
|
1017
|
+
outputPer1m: 9,
|
|
1018
|
+
cachedInputPer1m: 0.15,
|
|
1019
|
+
reasoningOutputPer1m: 9
|
|
1020
|
+
}
|
|
1021
|
+
],
|
|
1022
|
+
batchMultiplier: 0.5,
|
|
1023
|
+
contextWindow: 1048576
|
|
1024
|
+
},
|
|
1025
|
+
{
|
|
1026
|
+
model: "gemini-3.5-flash-lite",
|
|
1027
|
+
provider: "gemini",
|
|
1028
|
+
modality: "text",
|
|
1029
|
+
currency: "USD",
|
|
1030
|
+
asOf: "2026-07-27",
|
|
1031
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing",
|
|
1032
|
+
provenance: "litellm-catalog",
|
|
1033
|
+
tiers: [
|
|
1034
|
+
{
|
|
1035
|
+
inputPer1m: 0.3,
|
|
1036
|
+
outputPer1m: 2.5,
|
|
1037
|
+
cachedInputPer1m: 0.03,
|
|
1038
|
+
reasoningOutputPer1m: 2.5
|
|
1039
|
+
}
|
|
1040
|
+
],
|
|
1041
|
+
batchMultiplier: 0.5,
|
|
1042
|
+
contextWindow: 1048576
|
|
1043
|
+
},
|
|
1044
|
+
{
|
|
1045
|
+
model: "gemini-3.1-flash-lite",
|
|
1046
|
+
provider: "gemini",
|
|
1047
|
+
modality: "text",
|
|
1048
|
+
currency: "USD",
|
|
1049
|
+
asOf: "2026-07-27",
|
|
1050
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing#gemini-3.1-flash-lite",
|
|
1051
|
+
provenance: "litellm-catalog",
|
|
1052
|
+
tiers: [
|
|
1053
|
+
{
|
|
1054
|
+
inputPer1m: 0.25,
|
|
1055
|
+
outputPer1m: 1.5,
|
|
1056
|
+
cachedInputPer1m: 0.025,
|
|
1057
|
+
reasoningOutputPer1m: 1.5
|
|
1058
|
+
}
|
|
1059
|
+
],
|
|
1060
|
+
batchMultiplier: 0.5,
|
|
1061
|
+
contextWindow: 1048576
|
|
1062
|
+
},
|
|
1063
|
+
{
|
|
1064
|
+
model: "gemini-3-flash",
|
|
1065
|
+
provider: "gemini",
|
|
1066
|
+
aliases: [
|
|
1067
|
+
"gemini-3-flash-preview"
|
|
1068
|
+
],
|
|
1069
|
+
modality: "text",
|
|
1070
|
+
currency: "USD",
|
|
1071
|
+
asOf: "2026-07-27",
|
|
1072
|
+
source: "https://ai.google.dev/pricing/gemini-3",
|
|
1073
|
+
provenance: "litellm-catalog",
|
|
1074
|
+
tiers: [
|
|
1075
|
+
{
|
|
1076
|
+
inputPer1m: 0.5,
|
|
1077
|
+
outputPer1m: 3,
|
|
1078
|
+
cachedInputPer1m: 0.05,
|
|
1079
|
+
reasoningOutputPer1m: 3
|
|
1080
|
+
}
|
|
1081
|
+
],
|
|
1082
|
+
contextWindow: 1048576
|
|
1083
|
+
},
|
|
1084
|
+
{
|
|
1085
|
+
model: "gemini-2.5-pro",
|
|
1086
|
+
provider: "gemini",
|
|
1087
|
+
modality: "text",
|
|
1088
|
+
currency: "USD",
|
|
1089
|
+
asOf: "2026-07-27",
|
|
1090
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1091
|
+
provenance: "litellm-catalog",
|
|
1092
|
+
tiers: [
|
|
1093
|
+
{
|
|
1094
|
+
maxInputTokens: 2e5,
|
|
1095
|
+
inputPer1m: 1.25,
|
|
1096
|
+
outputPer1m: 10,
|
|
1097
|
+
cachedInputPer1m: 0.125
|
|
1098
|
+
},
|
|
1099
|
+
{
|
|
1100
|
+
inputPer1m: 2.5,
|
|
1101
|
+
outputPer1m: 15,
|
|
1102
|
+
cachedInputPer1m: 0.25
|
|
1103
|
+
}
|
|
1104
|
+
],
|
|
1105
|
+
contextWindow: 1048576
|
|
1106
|
+
},
|
|
1107
|
+
{
|
|
1108
|
+
model: "gemini-2.5-flash",
|
|
1109
|
+
provider: "gemini",
|
|
1110
|
+
modality: "text",
|
|
1111
|
+
currency: "USD",
|
|
1112
|
+
asOf: "2026-07-27",
|
|
1113
|
+
source: "https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash-preview",
|
|
1114
|
+
provenance: "litellm-catalog",
|
|
1115
|
+
tiers: [
|
|
1116
|
+
{
|
|
1117
|
+
inputPer1m: 0.3,
|
|
1118
|
+
outputPer1m: 2.5,
|
|
1119
|
+
cachedInputPer1m: 0.03,
|
|
1120
|
+
reasoningOutputPer1m: 2.5
|
|
1121
|
+
}
|
|
1122
|
+
],
|
|
1123
|
+
contextWindow: 1048576
|
|
1124
|
+
},
|
|
1125
|
+
{
|
|
1126
|
+
model: "gemini-2.5-flash-lite",
|
|
1127
|
+
provider: "gemini",
|
|
1128
|
+
modality: "text",
|
|
1129
|
+
currency: "USD",
|
|
1130
|
+
asOf: "2026-07-27",
|
|
1131
|
+
source: "https://ai.google.dev/gemini-api/docs/models#gemini-2.5-flash-lite",
|
|
1132
|
+
provenance: "litellm-catalog",
|
|
1133
|
+
tiers: [
|
|
1134
|
+
{
|
|
1135
|
+
inputPer1m: 0.1,
|
|
1136
|
+
outputPer1m: 0.4,
|
|
1137
|
+
cachedInputPer1m: 0.01,
|
|
1138
|
+
reasoningOutputPer1m: 0.4
|
|
1139
|
+
}
|
|
1140
|
+
],
|
|
1141
|
+
contextWindow: 1048576
|
|
1142
|
+
},
|
|
1143
|
+
{
|
|
1144
|
+
model: "gemini-2.0-flash",
|
|
1145
|
+
provider: "gemini",
|
|
1146
|
+
modality: "text",
|
|
1147
|
+
currency: "USD",
|
|
1148
|
+
asOf: "2026-07-27",
|
|
1149
|
+
source: "https://ai.google.dev/pricing#2_0flash",
|
|
1150
|
+
provenance: "litellm-catalog",
|
|
1151
|
+
tiers: [
|
|
1152
|
+
{
|
|
1153
|
+
inputPer1m: 0.1,
|
|
1154
|
+
outputPer1m: 0.4,
|
|
1155
|
+
cachedInputPer1m: 0.025
|
|
1156
|
+
}
|
|
1157
|
+
],
|
|
1158
|
+
contextWindow: 1048576,
|
|
1159
|
+
notes: "Gemini Developer API price. Vertex AI lists $0.15/$0.60 per 1M for the same model \u2014 see the vertex entry."
|
|
1160
|
+
},
|
|
1161
|
+
{
|
|
1162
|
+
model: "gemini-2.0-flash-lite",
|
|
1163
|
+
provider: "gemini",
|
|
1164
|
+
modality: "text",
|
|
1165
|
+
currency: "USD",
|
|
1166
|
+
asOf: "2026-07-27",
|
|
1167
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing#gemini-2.0-flash-lite",
|
|
1168
|
+
provenance: "litellm-catalog",
|
|
1169
|
+
tiers: [
|
|
1170
|
+
{
|
|
1171
|
+
inputPer1m: 0.075,
|
|
1172
|
+
outputPer1m: 0.3,
|
|
1173
|
+
cachedInputPer1m: 0.01875
|
|
1174
|
+
}
|
|
1175
|
+
],
|
|
1176
|
+
contextWindow: 1048576
|
|
1177
|
+
},
|
|
1178
|
+
{
|
|
1179
|
+
model: "gemini-2.0-flash",
|
|
1180
|
+
provider: "vertex",
|
|
1181
|
+
modality: "text",
|
|
1182
|
+
currency: "USD",
|
|
1183
|
+
asOf: "2026-07-27",
|
|
1184
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1185
|
+
provenance: "vendor-pricing-page",
|
|
1186
|
+
tiers: [
|
|
1187
|
+
{
|
|
1188
|
+
inputPer1m: 0.15,
|
|
1189
|
+
outputPer1m: 0.6
|
|
1190
|
+
}
|
|
1191
|
+
],
|
|
1192
|
+
batchMultiplier: 0.5,
|
|
1193
|
+
notes: "Vertex AI lists $0.15/$0.60 per 1M; the Gemini Developer API lists $0.10/$0.40 for the same model."
|
|
1194
|
+
},
|
|
1195
|
+
{
|
|
1196
|
+
model: "gemini-3.1-pro",
|
|
1197
|
+
provider: "vertex",
|
|
1198
|
+
aliases: [
|
|
1199
|
+
"gemini-3.1-pro-preview"
|
|
1200
|
+
],
|
|
1201
|
+
modality: "text",
|
|
1202
|
+
currency: "USD",
|
|
1203
|
+
asOf: "2026-07-27",
|
|
1204
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1205
|
+
provenance: "vendor-pricing-page",
|
|
1206
|
+
tiers: [
|
|
1207
|
+
{
|
|
1208
|
+
maxInputTokens: 2e5,
|
|
1209
|
+
inputPer1m: 2,
|
|
1210
|
+
outputPer1m: 12,
|
|
1211
|
+
cachedInputPer1m: 0.2,
|
|
1212
|
+
reasoningOutputPer1m: 12
|
|
1213
|
+
},
|
|
1214
|
+
{
|
|
1215
|
+
inputPer1m: 4,
|
|
1216
|
+
outputPer1m: 18,
|
|
1217
|
+
cachedInputPer1m: 0.4,
|
|
1218
|
+
reasoningOutputPer1m: 18
|
|
1219
|
+
}
|
|
1220
|
+
],
|
|
1221
|
+
batchMultiplier: 0.5,
|
|
1222
|
+
contextWindow: 1048576
|
|
1223
|
+
},
|
|
1224
|
+
{
|
|
1225
|
+
model: "gemini-3.6-flash",
|
|
1226
|
+
provider: "vertex",
|
|
1227
|
+
modality: "text",
|
|
1228
|
+
currency: "USD",
|
|
1229
|
+
asOf: "2026-07-27",
|
|
1230
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1231
|
+
provenance: "vendor-pricing-page",
|
|
1232
|
+
tiers: [
|
|
1233
|
+
{
|
|
1234
|
+
inputPer1m: 1.5,
|
|
1235
|
+
outputPer1m: 7.5,
|
|
1236
|
+
cachedInputPer1m: 0.15,
|
|
1237
|
+
reasoningOutputPer1m: 7.5
|
|
1238
|
+
}
|
|
1239
|
+
],
|
|
1240
|
+
batchMultiplier: 0.5,
|
|
1241
|
+
contextWindow: 1048576
|
|
1242
|
+
},
|
|
1243
|
+
{
|
|
1244
|
+
model: "gemini-2.5-pro",
|
|
1245
|
+
provider: "vertex",
|
|
1246
|
+
modality: "text",
|
|
1247
|
+
currency: "USD",
|
|
1248
|
+
asOf: "2026-07-27",
|
|
1249
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1250
|
+
provenance: "vendor-pricing-page",
|
|
1251
|
+
tiers: [
|
|
1252
|
+
{
|
|
1253
|
+
maxInputTokens: 2e5,
|
|
1254
|
+
inputPer1m: 1.25,
|
|
1255
|
+
outputPer1m: 10,
|
|
1256
|
+
cachedInputPer1m: 0.13
|
|
1257
|
+
},
|
|
1258
|
+
{
|
|
1259
|
+
inputPer1m: 2.5,
|
|
1260
|
+
outputPer1m: 15,
|
|
1261
|
+
cachedInputPer1m: 0.25
|
|
1262
|
+
}
|
|
1263
|
+
],
|
|
1264
|
+
batchMultiplier: 0.5,
|
|
1265
|
+
contextWindow: 1048576
|
|
1266
|
+
},
|
|
1267
|
+
{
|
|
1268
|
+
model: "gemini-2.5-flash",
|
|
1269
|
+
provider: "vertex",
|
|
1270
|
+
modality: "text",
|
|
1271
|
+
currency: "USD",
|
|
1272
|
+
asOf: "2026-07-27",
|
|
1273
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1274
|
+
provenance: "vendor-pricing-page",
|
|
1275
|
+
tiers: [
|
|
1276
|
+
{
|
|
1277
|
+
inputPer1m: 0.3,
|
|
1278
|
+
outputPer1m: 2.5,
|
|
1279
|
+
cachedInputPer1m: 0.03,
|
|
1280
|
+
reasoningOutputPer1m: 2.5
|
|
1281
|
+
}
|
|
1282
|
+
],
|
|
1283
|
+
batchMultiplier: 0.5,
|
|
1284
|
+
contextWindow: 1048576
|
|
1285
|
+
},
|
|
1286
|
+
{
|
|
1287
|
+
model: "claude-sonnet-4-6",
|
|
1288
|
+
provider: "openrouter",
|
|
1289
|
+
modality: "text",
|
|
1290
|
+
currency: "USD",
|
|
1291
|
+
asOf: "2026-07-27",
|
|
1292
|
+
source: "https://openrouter.ai/anthropic/claude-sonnet-4.6",
|
|
1293
|
+
provenance: "litellm-catalog",
|
|
1294
|
+
tiers: [
|
|
1295
|
+
{
|
|
1296
|
+
maxInputTokens: 2e5,
|
|
1297
|
+
inputPer1m: 3,
|
|
1298
|
+
outputPer1m: 15,
|
|
1299
|
+
cachedInputPer1m: 0.3,
|
|
1300
|
+
cacheWritePer1m: 3.75
|
|
1301
|
+
},
|
|
1302
|
+
{
|
|
1303
|
+
inputPer1m: 6,
|
|
1304
|
+
outputPer1m: 22.5,
|
|
1305
|
+
cachedInputPer1m: 0.6,
|
|
1306
|
+
cacheWritePer1m: 7.5
|
|
1307
|
+
}
|
|
1308
|
+
],
|
|
1309
|
+
contextWindow: 1e6
|
|
1310
|
+
},
|
|
1311
|
+
{
|
|
1312
|
+
model: "claude-haiku-4-5",
|
|
1313
|
+
provider: "openrouter",
|
|
1314
|
+
modality: "text",
|
|
1315
|
+
currency: "USD",
|
|
1316
|
+
asOf: "2026-07-27",
|
|
1317
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1318
|
+
provenance: "litellm-catalog",
|
|
1319
|
+
tiers: [
|
|
1320
|
+
{
|
|
1321
|
+
inputPer1m: 1,
|
|
1322
|
+
outputPer1m: 5,
|
|
1323
|
+
cachedInputPer1m: 0.1,
|
|
1324
|
+
cacheWritePer1m: 1.25
|
|
1325
|
+
}
|
|
1326
|
+
],
|
|
1327
|
+
contextWindow: 2e5
|
|
1328
|
+
},
|
|
1329
|
+
{
|
|
1330
|
+
model: "gpt-5",
|
|
1331
|
+
provider: "openrouter",
|
|
1332
|
+
modality: "text",
|
|
1333
|
+
currency: "USD",
|
|
1334
|
+
asOf: "2026-07-27",
|
|
1335
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1336
|
+
provenance: "litellm-catalog",
|
|
1337
|
+
tiers: [
|
|
1338
|
+
{
|
|
1339
|
+
inputPer1m: 1.25,
|
|
1340
|
+
outputPer1m: 10,
|
|
1341
|
+
cachedInputPer1m: 0.125
|
|
1342
|
+
}
|
|
1343
|
+
],
|
|
1344
|
+
contextWindow: 272e3
|
|
1345
|
+
},
|
|
1346
|
+
{
|
|
1347
|
+
model: "gpt-5-mini",
|
|
1348
|
+
provider: "openrouter",
|
|
1349
|
+
modality: "text",
|
|
1350
|
+
currency: "USD",
|
|
1351
|
+
asOf: "2026-07-27",
|
|
1352
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1353
|
+
provenance: "litellm-catalog",
|
|
1354
|
+
tiers: [
|
|
1355
|
+
{
|
|
1356
|
+
inputPer1m: 0.25,
|
|
1357
|
+
outputPer1m: 2,
|
|
1358
|
+
cachedInputPer1m: 0.025
|
|
1359
|
+
}
|
|
1360
|
+
],
|
|
1361
|
+
contextWindow: 272e3
|
|
1362
|
+
},
|
|
1363
|
+
{
|
|
1364
|
+
model: "gemini-3.1-pro",
|
|
1365
|
+
provider: "openrouter",
|
|
1366
|
+
aliases: [
|
|
1367
|
+
"gemini-3.1-pro-preview"
|
|
1368
|
+
],
|
|
1369
|
+
modality: "text",
|
|
1370
|
+
currency: "USD",
|
|
1371
|
+
asOf: "2026-07-27",
|
|
1372
|
+
source: "https://openrouter.ai/google/gemini-3.1-pro-preview",
|
|
1373
|
+
provenance: "litellm-catalog",
|
|
1374
|
+
tiers: [
|
|
1375
|
+
{
|
|
1376
|
+
maxInputTokens: 2e5,
|
|
1377
|
+
inputPer1m: 2,
|
|
1378
|
+
outputPer1m: 12,
|
|
1379
|
+
cachedInputPer1m: 0.2
|
|
1380
|
+
},
|
|
1381
|
+
{
|
|
1382
|
+
inputPer1m: 4,
|
|
1383
|
+
outputPer1m: 18,
|
|
1384
|
+
cachedInputPer1m: 0.4,
|
|
1385
|
+
cacheWritePer1m: 0.25
|
|
1386
|
+
}
|
|
1387
|
+
],
|
|
1388
|
+
contextWindow: 1048576
|
|
1389
|
+
},
|
|
1390
|
+
{
|
|
1391
|
+
model: "text-embedding-3-small",
|
|
1392
|
+
provider: "openai",
|
|
1393
|
+
modality: "embedding",
|
|
1394
|
+
currency: "USD",
|
|
1395
|
+
asOf: "2026-07-27",
|
|
1396
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1397
|
+
provenance: "litellm-catalog",
|
|
1398
|
+
tiers: [
|
|
1399
|
+
{
|
|
1400
|
+
inputPer1m: 0.02,
|
|
1401
|
+
outputPer1m: 0
|
|
1402
|
+
}
|
|
1403
|
+
],
|
|
1404
|
+
batchMultiplier: 0.5,
|
|
1405
|
+
contextWindow: 8191
|
|
1406
|
+
},
|
|
1407
|
+
{
|
|
1408
|
+
model: "text-embedding-3-large",
|
|
1409
|
+
provider: "openai",
|
|
1410
|
+
modality: "embedding",
|
|
1411
|
+
currency: "USD",
|
|
1412
|
+
asOf: "2026-07-27",
|
|
1413
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1414
|
+
provenance: "litellm-catalog",
|
|
1415
|
+
tiers: [
|
|
1416
|
+
{
|
|
1417
|
+
inputPer1m: 0.13,
|
|
1418
|
+
outputPer1m: 0
|
|
1419
|
+
}
|
|
1420
|
+
],
|
|
1421
|
+
batchMultiplier: 0.5,
|
|
1422
|
+
contextWindow: 8191
|
|
1423
|
+
},
|
|
1424
|
+
{
|
|
1425
|
+
model: "gemini-embedding-001",
|
|
1426
|
+
provider: "gemini",
|
|
1427
|
+
modality: "embedding",
|
|
1428
|
+
currency: "USD",
|
|
1429
|
+
asOf: "2026-07-27",
|
|
1430
|
+
source: "https://ai.google.dev/gemini-api/docs/embeddings#model-versions",
|
|
1431
|
+
provenance: "litellm-catalog",
|
|
1432
|
+
tiers: [
|
|
1433
|
+
{
|
|
1434
|
+
inputPer1m: 0.15,
|
|
1435
|
+
outputPer1m: 0
|
|
1436
|
+
}
|
|
1437
|
+
],
|
|
1438
|
+
contextWindow: 2048
|
|
1439
|
+
},
|
|
1440
|
+
{
|
|
1441
|
+
model: "dall-e-3",
|
|
1442
|
+
provider: "openai",
|
|
1443
|
+
modality: "image",
|
|
1444
|
+
currency: "USD",
|
|
1445
|
+
asOf: "2026-07-27",
|
|
1446
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1447
|
+
provenance: "litellm-catalog",
|
|
1448
|
+
rates: [
|
|
1449
|
+
{
|
|
1450
|
+
unit: "per_image",
|
|
1451
|
+
amount: 0.04,
|
|
1452
|
+
variant: "1024x1024 standard"
|
|
1453
|
+
}
|
|
1454
|
+
]
|
|
1455
|
+
},
|
|
1456
|
+
{
|
|
1457
|
+
model: "gemini-3-pro-image",
|
|
1458
|
+
provider: "gemini",
|
|
1459
|
+
modality: "image",
|
|
1460
|
+
currency: "USD",
|
|
1461
|
+
asOf: "2026-07-27",
|
|
1462
|
+
source: "https://ai.google.dev/gemini-api/docs/pricing",
|
|
1463
|
+
provenance: "litellm-catalog",
|
|
1464
|
+
rates: [
|
|
1465
|
+
{
|
|
1466
|
+
unit: "per_image",
|
|
1467
|
+
amount: 0.134,
|
|
1468
|
+
variant: "default output resolution"
|
|
1469
|
+
}
|
|
1470
|
+
],
|
|
1471
|
+
notes: "Google bills image output per output-token ($120 per 1M image output tokens); $0.134/image is that rate applied to one default-resolution image. Cost per image therefore varies with resolution."
|
|
1472
|
+
},
|
|
1473
|
+
{
|
|
1474
|
+
model: "imagen-4.0-generate-001",
|
|
1475
|
+
provider: "vertex",
|
|
1476
|
+
modality: "image",
|
|
1477
|
+
currency: "USD",
|
|
1478
|
+
asOf: "2026-07-27",
|
|
1479
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/pricing",
|
|
1480
|
+
provenance: "litellm-catalog",
|
|
1481
|
+
rates: [
|
|
1482
|
+
{
|
|
1483
|
+
unit: "per_image",
|
|
1484
|
+
amount: 0.04
|
|
1485
|
+
}
|
|
1486
|
+
]
|
|
1487
|
+
},
|
|
1488
|
+
{
|
|
1489
|
+
model: "veo-3.1-generate-001",
|
|
1490
|
+
provider: "gemini",
|
|
1491
|
+
modality: "video",
|
|
1492
|
+
currency: "USD",
|
|
1493
|
+
asOf: "2026-07-27",
|
|
1494
|
+
source: "https://ai.google.dev/gemini-api/docs/video",
|
|
1495
|
+
provenance: "litellm-catalog",
|
|
1496
|
+
rates: [
|
|
1497
|
+
{
|
|
1498
|
+
unit: "per_second",
|
|
1499
|
+
amount: 0.4
|
|
1500
|
+
}
|
|
1501
|
+
]
|
|
1502
|
+
},
|
|
1503
|
+
{
|
|
1504
|
+
model: "veo-3.1-generate-001",
|
|
1505
|
+
provider: "vertex",
|
|
1506
|
+
modality: "video",
|
|
1507
|
+
currency: "USD",
|
|
1508
|
+
asOf: "2026-07-27",
|
|
1509
|
+
source: "https://cloud.google.com/vertex-ai/generative-ai/docs/model-reference/veo",
|
|
1510
|
+
provenance: "litellm-catalog",
|
|
1511
|
+
rates: [
|
|
1512
|
+
{
|
|
1513
|
+
unit: "per_second",
|
|
1514
|
+
amount: 0.4
|
|
1515
|
+
}
|
|
1516
|
+
]
|
|
1517
|
+
},
|
|
1518
|
+
{
|
|
1519
|
+
model: "tts-1",
|
|
1520
|
+
provider: "openai",
|
|
1521
|
+
modality: "speech",
|
|
1522
|
+
currency: "USD",
|
|
1523
|
+
asOf: "2026-07-27",
|
|
1524
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1525
|
+
provenance: "litellm-catalog",
|
|
1526
|
+
rates: [
|
|
1527
|
+
{
|
|
1528
|
+
unit: "per_character",
|
|
1529
|
+
amount: 15e-6
|
|
1530
|
+
}
|
|
1531
|
+
],
|
|
1532
|
+
notes: "$15 per 1M characters."
|
|
1533
|
+
},
|
|
1534
|
+
{
|
|
1535
|
+
model: "tts-1-hd",
|
|
1536
|
+
provider: "openai",
|
|
1537
|
+
modality: "speech",
|
|
1538
|
+
currency: "USD",
|
|
1539
|
+
asOf: "2026-07-27",
|
|
1540
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1541
|
+
provenance: "litellm-catalog",
|
|
1542
|
+
rates: [
|
|
1543
|
+
{
|
|
1544
|
+
unit: "per_character",
|
|
1545
|
+
amount: 3e-5
|
|
1546
|
+
}
|
|
1547
|
+
],
|
|
1548
|
+
notes: "$30 per 1M characters."
|
|
1549
|
+
},
|
|
1550
|
+
{
|
|
1551
|
+
model: "whisper-1",
|
|
1552
|
+
provider: "openai",
|
|
1553
|
+
modality: "transcription",
|
|
1554
|
+
currency: "USD",
|
|
1555
|
+
asOf: "2026-07-27",
|
|
1556
|
+
source: "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json",
|
|
1557
|
+
provenance: "litellm-catalog",
|
|
1558
|
+
rates: [
|
|
1559
|
+
{
|
|
1560
|
+
unit: "per_audio_minute",
|
|
1561
|
+
amount: 6e-3
|
|
1562
|
+
}
|
|
1563
|
+
],
|
|
1564
|
+
notes: "litellm records $0.0001 per audio second; $0.006/minute is that rate x 60."
|
|
1565
|
+
}
|
|
1566
|
+
]
|
|
1567
|
+
};
|
|
1568
|
+
}
|
|
1569
|
+
});
|
|
1570
|
+
|
|
1571
|
+
// src/core/router/pricing.ts
|
|
1572
|
+
function normalizeForPricing(id) {
|
|
1573
|
+
let s = id.trim().toLowerCase();
|
|
1574
|
+
s = s.replace(/^models\//, "");
|
|
1575
|
+
const slash = s.lastIndexOf("/");
|
|
1576
|
+
if (slash !== -1) s = s.slice(slash + 1);
|
|
1577
|
+
const tag = s.search(/[:@]/);
|
|
1578
|
+
if (tag !== -1) s = s.slice(0, tag);
|
|
1579
|
+
s = s.replace(/-latest$/, "");
|
|
1580
|
+
s = s.replace(/-preview(?:-\d{2}-\d{2})?$/, "");
|
|
1581
|
+
s = s.replace(/-\d{4}-\d{2}-\d{2}$/, "");
|
|
1582
|
+
s = s.replace(/-\d{8}$/, "");
|
|
1583
|
+
s = s.replace(/-preview$/, "");
|
|
1584
|
+
return s;
|
|
1585
|
+
}
|
|
1586
|
+
function indexKey(model, provider, region) {
|
|
1587
|
+
return `${provider}|${normalizeForPricing(model)}|${region ?? ""}`;
|
|
1588
|
+
}
|
|
1589
|
+
function findPricing(modelId, provider, opts = {}) {
|
|
1590
|
+
const ids = [modelId, opts.baseModelId].filter((x) => !!x);
|
|
1591
|
+
const providers = [provider, ...opts.fallbackProviders ?? []];
|
|
1592
|
+
for (const p of providers) {
|
|
1593
|
+
for (const id of ids) {
|
|
1594
|
+
const hit = (opts.region ? INDEX.get(indexKey(id, p, opts.region)) : void 0) ?? INDEX.get(indexKey(id, p));
|
|
1595
|
+
if (hit) return { entry: hit, matchedProvider: p, viaFallback: p !== provider };
|
|
1596
|
+
}
|
|
1597
|
+
}
|
|
1598
|
+
return null;
|
|
1599
|
+
}
|
|
1600
|
+
function pricingDatasetMeta() {
|
|
1601
|
+
const { schemaVersion, generatedAt, defaultCurrency } = DATASET;
|
|
1602
|
+
return { schemaVersion, generatedAt, defaultCurrency };
|
|
1603
|
+
}
|
|
1604
|
+
function tierFor(entry, inputTokens = 0) {
|
|
1605
|
+
const tiers = entry.tiers;
|
|
1606
|
+
if (!tiers?.length) return null;
|
|
1607
|
+
for (const t of tiers) {
|
|
1608
|
+
if (t.maxInputTokens === void 0 || inputTokens <= t.maxInputTokens) return t;
|
|
1609
|
+
}
|
|
1610
|
+
return tiers[tiers.length - 1] ?? null;
|
|
1611
|
+
}
|
|
1612
|
+
function tokenRatesPer1k(entry, opts = {}) {
|
|
1613
|
+
const tier = tierFor(entry, opts.inputTokens ?? 0);
|
|
1614
|
+
if (!tier) return null;
|
|
1615
|
+
const mult = (opts.batch ? entry.batchMultiplier ?? 1 : 1) * PER_1M_TO_PER_1K;
|
|
1616
|
+
const out = {
|
|
1617
|
+
input: tier.inputPer1m * mult,
|
|
1618
|
+
output: tier.outputPer1m * mult
|
|
1619
|
+
};
|
|
1620
|
+
if (tier.cachedInputPer1m !== void 0) out.cachedInput = tier.cachedInputPer1m * mult;
|
|
1621
|
+
if (tier.cacheWritePer1m !== void 0) out.cacheWrite = tier.cacheWritePer1m * mult;
|
|
1622
|
+
if (tier.reasoningOutputPer1m !== void 0) out.reasoningOutput = tier.reasoningOutputPer1m * mult;
|
|
1623
|
+
return out;
|
|
1624
|
+
}
|
|
1625
|
+
function isLoopbackOrPrivateHost(url) {
|
|
1626
|
+
if (!url) return false;
|
|
1627
|
+
try {
|
|
1628
|
+
const host = new URL(url).hostname.toLowerCase().replace(/^\[|\]$/g, "");
|
|
1629
|
+
if (LOOPBACK_HOSTS.has(host) || LOOPBACK_HOSTS.has(`[${host}]`)) return true;
|
|
1630
|
+
if (host.endsWith(".local")) return true;
|
|
1631
|
+
if (/^127\./.test(host)) return true;
|
|
1632
|
+
if (/^10\./.test(host)) return true;
|
|
1633
|
+
if (/^192\.168\./.test(host)) return true;
|
|
1634
|
+
if (/^172\.(1[6-9]|2\d|3[01])\./.test(host)) return true;
|
|
1635
|
+
return false;
|
|
1636
|
+
} catch {
|
|
1637
|
+
return false;
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
function isLocalEndpoint(cfg) {
|
|
1641
|
+
if (typeof cfg.local === "boolean") return cfg.local;
|
|
1642
|
+
if (cfg.type === "ollama") return true;
|
|
1643
|
+
if (cfg.type === "openai-compatible") return isLoopbackOrPrivateHost(cfg.baseUrl);
|
|
1644
|
+
return false;
|
|
1645
|
+
}
|
|
1646
|
+
function resolvePricing(model, opts = {}) {
|
|
1647
|
+
if (model.isLocal) return FREE;
|
|
1648
|
+
const fallbackProviders = model.provider === "azure" ? ["openai"] : model.provider === "gemini" ? ["vertex"] : [];
|
|
1649
|
+
const match = findPricing(model.id, model.provider, {
|
|
1650
|
+
region: opts.region,
|
|
1651
|
+
baseModelId: model.baseModelId,
|
|
1652
|
+
fallbackProviders
|
|
1653
|
+
});
|
|
1654
|
+
if (!match) return UNKNOWN;
|
|
1655
|
+
const rates = tokenRatesPer1k(match.entry, { inputTokens: opts.inputTokens, batch: opts.batch });
|
|
1656
|
+
if (!rates) return UNKNOWN;
|
|
1657
|
+
return {
|
|
1658
|
+
input: rates.input,
|
|
1659
|
+
output: rates.output,
|
|
1660
|
+
unknown: false,
|
|
1661
|
+
free: false,
|
|
1662
|
+
entry: match.entry,
|
|
1663
|
+
...match.viaFallback ? { estimatedFromProvider: match.matchedProvider } : {}
|
|
1664
|
+
};
|
|
1665
|
+
}
|
|
1666
|
+
function withResolvedPricing(model, opts = {}) {
|
|
1667
|
+
const p = resolvePricing(model, opts);
|
|
1668
|
+
return {
|
|
1669
|
+
...model,
|
|
1670
|
+
inputCostPer1kTokens: p.input,
|
|
1671
|
+
outputCostPer1kTokens: p.output,
|
|
1672
|
+
...p.unknown ? { pricingUnknown: true } : { pricingUnknown: false }
|
|
1673
|
+
};
|
|
1674
|
+
}
|
|
1675
|
+
function isPricingUnknown(model) {
|
|
1676
|
+
return model.pricingUnknown === true && !model.isLocal;
|
|
1677
|
+
}
|
|
1678
|
+
function blendedCostPer1k(model) {
|
|
1679
|
+
if (isPricingUnknown(model)) return BLENDED_COST_CEILING;
|
|
1680
|
+
return model.inputCostPer1kTokens + model.outputCostPer1kTokens * 2;
|
|
1681
|
+
}
|
|
1682
|
+
function reconcilePrice(model, live) {
|
|
1683
|
+
const baseline = resolvePricing(model);
|
|
1684
|
+
const liveIsZero = !(live.input > 0) && !(live.output > 0);
|
|
1685
|
+
if (liveIsZero && !model.isLocal) {
|
|
1686
|
+
return { input: baseline.input, output: baseline.output, accepted: false };
|
|
1687
|
+
}
|
|
1688
|
+
if (baseline.unknown || !baseline.entry) {
|
|
1689
|
+
return { input: live.input, output: live.output, accepted: true };
|
|
1690
|
+
}
|
|
1691
|
+
const dsBlend = baseline.input + baseline.output * 2;
|
|
1692
|
+
const liveBlend = live.input + live.output * 2;
|
|
1693
|
+
const ratio = dsBlend > 0 ? liveBlend / dsBlend : Number.POSITIVE_INFINITY;
|
|
1694
|
+
const material = dsBlend > 0 && Math.abs(ratio - 1) > DISAGREEMENT_THRESHOLD;
|
|
1695
|
+
return {
|
|
1696
|
+
input: live.input,
|
|
1697
|
+
output: live.output,
|
|
1698
|
+
accepted: true,
|
|
1699
|
+
...material ? {
|
|
1700
|
+
disagreement: {
|
|
1701
|
+
modelId: model.id,
|
|
1702
|
+
provider: model.provider,
|
|
1703
|
+
dataset: { input: baseline.input, output: baseline.output },
|
|
1704
|
+
live: { input: live.input, output: live.output },
|
|
1705
|
+
ratio: Math.round(ratio * 1e3) / 1e3,
|
|
1706
|
+
datasetAsOf: baseline.entry.asOf,
|
|
1707
|
+
datasetSource: baseline.entry.source
|
|
1708
|
+
}
|
|
1709
|
+
} : {}
|
|
1710
|
+
};
|
|
1711
|
+
}
|
|
1712
|
+
var DATASET, INDEX, PER_1M_TO_PER_1K, LOOPBACK_HOSTS, UNKNOWN, FREE, BLENDED_COST_CEILING, DISAGREEMENT_THRESHOLD;
|
|
1713
|
+
var init_pricing = __esm({
|
|
1714
|
+
"src/core/router/pricing.ts"() {
|
|
1715
|
+
init_pricing_data();
|
|
1716
|
+
DATASET = pricing_data_default;
|
|
1717
|
+
INDEX = /* @__PURE__ */ new Map();
|
|
1718
|
+
for (const entry of DATASET.entries) {
|
|
1719
|
+
for (const name of [entry.model, ...entry.aliases ?? []]) {
|
|
1720
|
+
const withRegion = indexKey(name, entry.provider, entry.region);
|
|
1721
|
+
if (!INDEX.has(withRegion)) INDEX.set(withRegion, entry);
|
|
1722
|
+
const bare = indexKey(name, entry.provider);
|
|
1723
|
+
const existing = INDEX.get(bare);
|
|
1724
|
+
if (!existing || existing.region && existing.region !== "global" && entry.region === "global") {
|
|
1725
|
+
INDEX.set(bare, entry);
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
}
|
|
1729
|
+
PER_1M_TO_PER_1K = 1 / 1e3;
|
|
1730
|
+
LOOPBACK_HOSTS = /* @__PURE__ */ new Set(["localhost", "127.0.0.1", "0.0.0.0", "::1", "[::1]"]);
|
|
1731
|
+
UNKNOWN = { input: 0, output: 0, unknown: true, free: false };
|
|
1732
|
+
FREE = { input: 0, output: 0, unknown: false, free: true };
|
|
1733
|
+
BLENDED_COST_CEILING = 0.05;
|
|
1734
|
+
DISAGREEMENT_THRESHOLD = 0.02;
|
|
1735
|
+
}
|
|
1736
|
+
});
|
|
1737
|
+
|
|
62
1738
|
// src/constants.ts
|
|
63
1739
|
var CASCADE_VERSION, CASCADE_CONFIG_FILE, CASCADE_DB_FILE, CASCADE_DASHBOARD_SECRET_FILE, GLOBAL_CONFIG_DIR, GLOBAL_DB_FILE, GLOBAL_KEYSTORE_FILE, GLOBAL_CREDENTIALS_FILE, GLOBAL_RUNTIME_DB_FILE, DEFAULT_DASHBOARD_PORT, DEFAULT_CONTEXT_LIMIT, DEFAULT_AUTO_SUMMARIZE_AT, MODELS, T1_MODEL_PRIORITY, T2_MODEL_PRIORITY, T3_MODEL_PRIORITY, VISION_MODEL_PRIORITY, COMPLEXITY_T2_COUNT, THEME_NAMES, DEFAULT_THEME, OLLAMA_BASE_URL, LM_STUDIO_BASE_URL, AZURE_BASE_URL_TEMPLATE, TOOL_NAMES, DEFAULT_APPROVAL_REQUIRED;
|
|
64
1740
|
var init_constants = __esm({
|
|
65
1741
|
"src/constants.ts"() {
|
|
66
|
-
|
|
1742
|
+
init_pricing();
|
|
1743
|
+
CASCADE_VERSION = "0.49.0";
|
|
67
1744
|
CASCADE_CONFIG_FILE = ".cascade/config.json";
|
|
68
1745
|
CASCADE_DB_FILE = ".cascade/memory.db";
|
|
69
1746
|
CASCADE_DASHBOARD_SECRET_FILE = ".cascade/dashboard-secret";
|
|
@@ -404,6 +2081,13 @@ var init_constants = __esm({
|
|
|
404
2081
|
for (const _m of Object.values(MODELS)) {
|
|
405
2082
|
if (_m.supportsToolUse === void 0) _m.supportsToolUse = !_m.isLocal;
|
|
406
2083
|
}
|
|
2084
|
+
for (const _m of Object.values(MODELS)) {
|
|
2085
|
+
const priced = resolvePricing(_m);
|
|
2086
|
+
if (priced.unknown || priced.free || priced.estimatedFromProvider) continue;
|
|
2087
|
+
_m.inputCostPer1kTokens = priced.input;
|
|
2088
|
+
_m.outputCostPer1kTokens = priced.output;
|
|
2089
|
+
_m.pricingUnknown = false;
|
|
2090
|
+
}
|
|
407
2091
|
T1_MODEL_PRIORITY = [
|
|
408
2092
|
"gpt-5.5",
|
|
409
2093
|
"gpt-5.4",
|
|
@@ -488,24 +2172,53 @@ var init_constants = __esm({
|
|
|
488
2172
|
|
|
489
2173
|
// src/utils/cost.ts
|
|
490
2174
|
function resolveModelPricing(model) {
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
2175
|
+
if (model.isLocal) return { input: 0, output: 0, unknown: false };
|
|
2176
|
+
if (model.inputCostPer1kTokens > 0 || model.outputCostPer1kTokens > 0) {
|
|
2177
|
+
return {
|
|
2178
|
+
input: model.inputCostPer1kTokens,
|
|
2179
|
+
output: model.outputCostPer1kTokens,
|
|
2180
|
+
unknown: false
|
|
2181
|
+
};
|
|
2182
|
+
}
|
|
2183
|
+
const fromDataset = resolvePricing(model);
|
|
2184
|
+
if (!fromDataset.unknown) {
|
|
2185
|
+
return {
|
|
2186
|
+
input: fromDataset.input,
|
|
2187
|
+
output: fromDataset.output,
|
|
2188
|
+
unknown: false,
|
|
2189
|
+
...fromDataset.estimatedFromProvider ? { estimatedFromProvider: fromDataset.estimatedFromProvider } : {}
|
|
2190
|
+
};
|
|
2191
|
+
}
|
|
2192
|
+
if (model.id) {
|
|
494
2193
|
const known = Object.values(MODELS).find((m) => m.id === model.id && !m.isLocal);
|
|
495
|
-
if (known) {
|
|
496
|
-
|
|
497
|
-
|
|
2194
|
+
if (known && (known.inputCostPer1kTokens > 0 || known.outputCostPer1kTokens > 0)) {
|
|
2195
|
+
return {
|
|
2196
|
+
input: known.inputCostPer1kTokens,
|
|
2197
|
+
output: known.outputCostPer1kTokens,
|
|
2198
|
+
unknown: false
|
|
2199
|
+
};
|
|
498
2200
|
}
|
|
499
2201
|
}
|
|
500
|
-
return { input, output };
|
|
2202
|
+
return { input: 0, output: 0, unknown: true };
|
|
501
2203
|
}
|
|
502
2204
|
function calculateCost(inputTokens, outputTokens, model) {
|
|
503
2205
|
const { input, output } = resolveModelPricing(model);
|
|
504
2206
|
return inputTokens / 1e3 * input + outputTokens / 1e3 * output;
|
|
505
2207
|
}
|
|
2208
|
+
function buildTokenUsage(inputTokens, outputTokens, model) {
|
|
2209
|
+
const { input, output, unknown } = resolveModelPricing(model);
|
|
2210
|
+
return {
|
|
2211
|
+
inputTokens,
|
|
2212
|
+
outputTokens,
|
|
2213
|
+
totalTokens: inputTokens + outputTokens,
|
|
2214
|
+
estimatedCostUsd: inputTokens / 1e3 * input + outputTokens / 1e3 * output,
|
|
2215
|
+
...unknown ? { costUnknown: true } : {}
|
|
2216
|
+
};
|
|
2217
|
+
}
|
|
506
2218
|
var init_cost = __esm({
|
|
507
2219
|
"src/utils/cost.ts"() {
|
|
508
2220
|
init_constants();
|
|
2221
|
+
init_pricing();
|
|
509
2222
|
}
|
|
510
2223
|
});
|
|
511
2224
|
|
|
@@ -531,12 +2244,7 @@ var init_base = __esm({
|
|
|
531
2244
|
return calculateCost(inputTokens, outputTokens, this.model);
|
|
532
2245
|
}
|
|
533
2246
|
makeUsage(inputTokens, outputTokens) {
|
|
534
|
-
return
|
|
535
|
-
inputTokens,
|
|
536
|
-
outputTokens,
|
|
537
|
-
totalTokens: inputTokens + outputTokens,
|
|
538
|
-
estimatedCostUsd: this.estimateCost(inputTokens, outputTokens)
|
|
539
|
-
};
|
|
2247
|
+
return buildTokenUsage(inputTokens, outputTokens, this.model);
|
|
540
2248
|
}
|
|
541
2249
|
};
|
|
542
2250
|
}
|
|
@@ -612,6 +2320,7 @@ var init_anthropic = __esm({
|
|
|
612
2320
|
"src/providers/anthropic.ts"() {
|
|
613
2321
|
init_constants();
|
|
614
2322
|
init_base();
|
|
2323
|
+
init_pricing();
|
|
615
2324
|
init_model_filter();
|
|
616
2325
|
AnthropicProvider = class extends BaseProvider {
|
|
617
2326
|
client;
|
|
@@ -722,7 +2431,7 @@ var init_anthropic = __esm({
|
|
|
722
2431
|
return data.data.filter((m) => isChatModel(m.id)).map((m) => {
|
|
723
2432
|
const known = Object.values(MODELS).find((km) => km.id === m.id && km.provider === "anthropic");
|
|
724
2433
|
if (known) return known;
|
|
725
|
-
return {
|
|
2434
|
+
return withResolvedPricing({
|
|
726
2435
|
id: m.id,
|
|
727
2436
|
name: m.display_name || m.id,
|
|
728
2437
|
provider: "anthropic",
|
|
@@ -733,7 +2442,7 @@ var init_anthropic = __esm({
|
|
|
733
2442
|
maxOutputTokens: 8e3,
|
|
734
2443
|
supportsStreaming: true,
|
|
735
2444
|
isLocal: false
|
|
736
|
-
};
|
|
2445
|
+
});
|
|
737
2446
|
});
|
|
738
2447
|
} catch {
|
|
739
2448
|
return Object.values(MODELS).filter((m) => m.provider === "anthropic");
|
|
@@ -828,6 +2537,7 @@ var init_openai = __esm({
|
|
|
828
2537
|
"src/providers/openai.ts"() {
|
|
829
2538
|
init_constants();
|
|
830
2539
|
init_base();
|
|
2540
|
+
init_pricing();
|
|
831
2541
|
init_model_filter();
|
|
832
2542
|
OpenAIProvider = class extends BaseProvider {
|
|
833
2543
|
client;
|
|
@@ -953,7 +2663,7 @@ var init_openai = __esm({
|
|
|
953
2663
|
return response.data.filter((m) => isChatModel(m.id)).map((m) => {
|
|
954
2664
|
const known = Object.values(MODELS).find((km) => km.id === m.id && km.provider === "openai");
|
|
955
2665
|
if (known) return known;
|
|
956
|
-
return {
|
|
2666
|
+
return withResolvedPricing({
|
|
957
2667
|
id: m.id,
|
|
958
2668
|
name: m.id,
|
|
959
2669
|
provider: "openai",
|
|
@@ -964,7 +2674,7 @@ var init_openai = __esm({
|
|
|
964
2674
|
maxOutputTokens: 4e3,
|
|
965
2675
|
supportsStreaming: true,
|
|
966
2676
|
isLocal: false
|
|
967
|
-
};
|
|
2677
|
+
});
|
|
968
2678
|
});
|
|
969
2679
|
} catch {
|
|
970
2680
|
return Object.values(MODELS).filter((m) => m.provider === "openai");
|
|
@@ -1067,6 +2777,10 @@ function azureModelForDeployment(cfg) {
|
|
|
1067
2777
|
const baseModelId = cfg.model?.trim() || inferAzureBaseModel(id) || void 0;
|
|
1068
2778
|
const base = baseModelId ? MODELS[baseModelId] : void 0;
|
|
1069
2779
|
if (base) {
|
|
2780
|
+
const azurePrice = resolvePricing(
|
|
2781
|
+
{ id, provider: "azure", isLocal: false, baseModelId },
|
|
2782
|
+
{ region: cfg.region }
|
|
2783
|
+
);
|
|
1070
2784
|
return {
|
|
1071
2785
|
...base,
|
|
1072
2786
|
id,
|
|
@@ -1075,7 +2789,12 @@ function azureModelForDeployment(cfg) {
|
|
|
1075
2789
|
provider: "azure",
|
|
1076
2790
|
baseModelId,
|
|
1077
2791
|
// real identity for benchmark + live pricing
|
|
1078
|
-
supportsToolUse: base.supportsToolUse ?? true
|
|
2792
|
+
supportsToolUse: base.supportsToolUse ?? true,
|
|
2793
|
+
...azurePrice.unknown ? {} : {
|
|
2794
|
+
inputCostPer1kTokens: azurePrice.input,
|
|
2795
|
+
outputCostPer1kTokens: azurePrice.output,
|
|
2796
|
+
pricingUnknown: false
|
|
2797
|
+
}
|
|
1079
2798
|
};
|
|
1080
2799
|
}
|
|
1081
2800
|
return {
|
|
@@ -1098,6 +2817,7 @@ var init_azure = __esm({
|
|
|
1098
2817
|
"src/providers/azure.ts"() {
|
|
1099
2818
|
init_constants();
|
|
1100
2819
|
init_openai();
|
|
2820
|
+
init_pricing();
|
|
1101
2821
|
DEFAULT_AZURE_API_VERSION = "2024-12-01-preview";
|
|
1102
2822
|
AzureOpenAIProvider = class extends OpenAIProvider {
|
|
1103
2823
|
constructor(config, model) {
|
|
@@ -1158,6 +2878,7 @@ var init_gemini = __esm({
|
|
|
1158
2878
|
"src/providers/gemini.ts"() {
|
|
1159
2879
|
init_constants();
|
|
1160
2880
|
init_base();
|
|
2881
|
+
init_pricing();
|
|
1161
2882
|
init_model_filter();
|
|
1162
2883
|
GeminiProvider = class extends BaseProvider {
|
|
1163
2884
|
client;
|
|
@@ -1258,7 +2979,7 @@ var init_gemini = __esm({
|
|
|
1258
2979
|
(km) => km.id === id && km.provider === "gemini"
|
|
1259
2980
|
);
|
|
1260
2981
|
if (known) return known;
|
|
1261
|
-
return {
|
|
2982
|
+
return withResolvedPricing({
|
|
1262
2983
|
id,
|
|
1263
2984
|
name: m.displayName || id,
|
|
1264
2985
|
provider: "gemini",
|
|
@@ -1269,7 +2990,7 @@ var init_gemini = __esm({
|
|
|
1269
2990
|
maxOutputTokens: m.outputTokenLimit || 8e3,
|
|
1270
2991
|
supportsStreaming: true,
|
|
1271
2992
|
isLocal: false
|
|
1272
|
-
};
|
|
2993
|
+
});
|
|
1273
2994
|
});
|
|
1274
2995
|
} catch {
|
|
1275
2996
|
return Object.values(MODELS).filter((m) => m.provider === "gemini");
|
|
@@ -1475,6 +3196,7 @@ var init_ollama = __esm({
|
|
|
1475
3196
|
init_constants();
|
|
1476
3197
|
init_net();
|
|
1477
3198
|
init_base();
|
|
3199
|
+
init_pricing();
|
|
1478
3200
|
init_model_filter();
|
|
1479
3201
|
TOOL_CAPABLE_FAMILIES = [
|
|
1480
3202
|
"llama3.1",
|
|
@@ -1634,9 +3356,10 @@ var init_ollama = __esm({
|
|
|
1634
3356
|
return supportedKeywords.some((k) => name.includes(k)) && isChatModel(name);
|
|
1635
3357
|
});
|
|
1636
3358
|
const shows = await Promise.all(entries.map((m) => this.showModel(m.name)));
|
|
3359
|
+
const local = isLocalEndpoint({ ...this.config, type: "ollama" });
|
|
1637
3360
|
return entries.map((m, i) => {
|
|
1638
3361
|
const show = shows[i];
|
|
1639
|
-
return {
|
|
3362
|
+
return withResolvedPricing({
|
|
1640
3363
|
id: m.name,
|
|
1641
3364
|
name: m.name,
|
|
1642
3365
|
provider: "ollama",
|
|
@@ -1646,10 +3369,10 @@ var init_ollama = __esm({
|
|
|
1646
3369
|
outputCostPer1kTokens: 0,
|
|
1647
3370
|
maxOutputTokens: 4e3,
|
|
1648
3371
|
supportsStreaming: true,
|
|
1649
|
-
isLocal:
|
|
3372
|
+
isLocal: local,
|
|
1650
3373
|
supportsToolUse: show?.tools ?? isToolCapable(m.name),
|
|
1651
3374
|
minSizeB: this.parseSizeB(m.details?.parameter_size)
|
|
1652
|
-
};
|
|
3375
|
+
});
|
|
1653
3376
|
});
|
|
1654
3377
|
} catch {
|
|
1655
3378
|
return [];
|
|
@@ -1733,6 +3456,7 @@ var init_openai_compatible = __esm({
|
|
|
1733
3456
|
init_openai();
|
|
1734
3457
|
init_model_filter();
|
|
1735
3458
|
init_net();
|
|
3459
|
+
init_pricing();
|
|
1736
3460
|
OpenAICompatibleProvider = class extends OpenAIProvider {
|
|
1737
3461
|
constructor(config, model) {
|
|
1738
3462
|
super({ ...config, apiKey: config.apiKey ?? "not-required" }, model);
|
|
@@ -1766,7 +3490,8 @@ var init_openai_compatible = __esm({
|
|
|
1766
3490
|
}).filter((x) => typeof x === "string" && x.length > 0);
|
|
1767
3491
|
if (ids.length === 0) return [this.model];
|
|
1768
3492
|
const chatIds = ids.filter((id) => isChatModel(id));
|
|
1769
|
-
|
|
3493
|
+
const local = isLocalEndpoint(this.config);
|
|
3494
|
+
return (chatIds.length ? chatIds : ids).map((id) => withResolvedPricing({
|
|
1770
3495
|
id,
|
|
1771
3496
|
name: id,
|
|
1772
3497
|
provider: "openai-compatible",
|
|
@@ -1776,7 +3501,7 @@ var init_openai_compatible = __esm({
|
|
|
1776
3501
|
outputCostPer1kTokens: 0,
|
|
1777
3502
|
maxOutputTokens: 4e3,
|
|
1778
3503
|
supportsStreaming: true,
|
|
1779
|
-
isLocal:
|
|
3504
|
+
isLocal: local
|
|
1780
3505
|
}));
|
|
1781
3506
|
}
|
|
1782
3507
|
async isAvailable() {
|
|
@@ -3098,7 +4823,18 @@ var ProviderConfigSchema = z.object({
|
|
|
3098
4823
|
apiVersion: z.string().optional(),
|
|
3099
4824
|
model: z.string().optional(),
|
|
3100
4825
|
authToken: z.string().optional(),
|
|
3101
|
-
credentialSource: z.string().optional()
|
|
4826
|
+
credentialSource: z.string().optional(),
|
|
4827
|
+
/**
|
|
4828
|
+
* "This endpoint is self-hosted, so inference genuinely costs $0."
|
|
4829
|
+
* Only meaningful for `ollama` and `openai-compatible`. Unset ⇒ inferred:
|
|
4830
|
+
* ollama is local, openai-compatible is local when its baseUrl is
|
|
4831
|
+
* loopback/LAN. Set it explicitly to override — e.g. `false` for an Ollama
|
|
4832
|
+
* instance you rent, `true` for a llama.cpp box on your own LAN reached by
|
|
4833
|
+
* hostname.
|
|
4834
|
+
*/
|
|
4835
|
+
local: z.boolean().optional(),
|
|
4836
|
+
/** Region for providers whose price varies by region (Azure: global | us | eu | …). */
|
|
4837
|
+
region: z.string().optional()
|
|
3102
4838
|
});
|
|
3103
4839
|
var ModelOverridesSchema = z.object({
|
|
3104
4840
|
t1: z.string().optional(),
|
|
@@ -3947,6 +5683,7 @@ init_openai();
|
|
|
3947
5683
|
|
|
3948
5684
|
// src/core/router/selector.ts
|
|
3949
5685
|
init_constants();
|
|
5686
|
+
init_pricing();
|
|
3950
5687
|
function normalizeModelId(id) {
|
|
3951
5688
|
return id.replace(/^models\//, "").toLowerCase();
|
|
3952
5689
|
}
|
|
@@ -4148,7 +5885,7 @@ var ModelSelector = class {
|
|
|
4148
5885
|
else if (this.availableProviders.size === 1) providerStr = Array.from(this.availableProviders)[0];
|
|
4149
5886
|
}
|
|
4150
5887
|
if (providerStr && this.availableProviders.has(providerStr)) {
|
|
4151
|
-
const dynamicModel = {
|
|
5888
|
+
const dynamicModel = withResolvedPricing({
|
|
4152
5889
|
id: actualId,
|
|
4153
5890
|
name: actualId,
|
|
4154
5891
|
provider: providerStr,
|
|
@@ -4159,7 +5896,7 @@ var ModelSelector = class {
|
|
|
4159
5896
|
maxOutputTokens: 8e3,
|
|
4160
5897
|
supportsStreaming: true,
|
|
4161
5898
|
isLocal: providerStr === "ollama"
|
|
4162
|
-
};
|
|
5899
|
+
});
|
|
4163
5900
|
this.addDynamicModel(dynamicModel);
|
|
4164
5901
|
return dynamicModel;
|
|
4165
5902
|
}
|
|
@@ -4529,6 +6266,7 @@ function computeDelegationSavings(stats, t1Model) {
|
|
|
4529
6266
|
|
|
4530
6267
|
// src/core/router/live-data.ts
|
|
4531
6268
|
init_constants();
|
|
6269
|
+
init_pricing();
|
|
4532
6270
|
var DEFAULT_SNAPSHOT_URL = "https://raw.githubusercontent.com/Varun-SV/Cascade-AI/main/src/core/router/benchmark-data.json";
|
|
4533
6271
|
var OPENROUTER_MODELS_URL = "https://openrouter.ai/api/v1/models";
|
|
4534
6272
|
var FETCH_TIMEOUT_MS = 8e3;
|
|
@@ -4546,6 +6284,8 @@ var LiveDataProvider = class {
|
|
|
4546
6284
|
snapshot = null;
|
|
4547
6285
|
prices = /* @__PURE__ */ new Map();
|
|
4548
6286
|
capabilities = /* @__PURE__ */ new Map();
|
|
6287
|
+
/** Dataset-vs-live price mismatches, deduped by `provider:modelId`. */
|
|
6288
|
+
disagreements = /* @__PURE__ */ new Map();
|
|
4549
6289
|
source = "bundled";
|
|
4550
6290
|
fetchedAt = 0;
|
|
4551
6291
|
loaded = false;
|
|
@@ -4699,14 +6439,45 @@ var LiveDataProvider = class {
|
|
|
4699
6439
|
/**
|
|
4700
6440
|
* Returns a price-corrected copy of each model when live pricing is known,
|
|
4701
6441
|
* leaving the original untouched (so the shared catalog is never mutated).
|
|
6442
|
+
*
|
|
6443
|
+
* Reconciliation policy (see reconcilePrice in pricing.ts): the bundled
|
|
6444
|
+
* dataset is the authoritative baseline, and a live quote overrides it
|
|
6445
|
+
* because it is fresher by construction — but the disagreement is RECORDED,
|
|
6446
|
+
* not swallowed. A dataset/live mismatch is the best signal available that
|
|
6447
|
+
* the committed prices have gone stale, so it must be visible rather than
|
|
6448
|
+
* silently resolved in either direction. A live quote of $0 for a non-local
|
|
6449
|
+
* model is rejected outright: that is the very failure mode this change
|
|
6450
|
+
* exists to prevent, and a marketplace's free-tier alias must never zero out
|
|
6451
|
+
* the price of the paid model Cascade is actually calling.
|
|
4702
6452
|
*/
|
|
4703
6453
|
applyLivePricing(models) {
|
|
4704
6454
|
return models.map((m) => {
|
|
4705
6455
|
const p = this.getLivePrice(m.baseModelId ?? m.id);
|
|
4706
6456
|
if (!p) return m;
|
|
4707
|
-
|
|
6457
|
+
const reconciled = reconcilePrice(m, p);
|
|
6458
|
+
if (reconciled.disagreement) this.recordDisagreement(reconciled.disagreement);
|
|
6459
|
+
if (!reconciled.accepted) return m;
|
|
6460
|
+
return {
|
|
6461
|
+
...m,
|
|
6462
|
+
inputCostPer1kTokens: reconciled.input,
|
|
6463
|
+
outputCostPer1kTokens: reconciled.output,
|
|
6464
|
+
pricingUnknown: false
|
|
6465
|
+
};
|
|
4708
6466
|
});
|
|
4709
6467
|
}
|
|
6468
|
+
recordDisagreement(d) {
|
|
6469
|
+
const key = `${d.provider}:${d.modelId}`;
|
|
6470
|
+
if (this.disagreements.has(key)) return;
|
|
6471
|
+
this.disagreements.set(key, d);
|
|
6472
|
+
}
|
|
6473
|
+
/**
|
|
6474
|
+
* Dataset-vs-live price mismatches seen this session, newest-model-first
|
|
6475
|
+
* insertion order. Surfaced by `cascade models --verbose`; a non-empty list
|
|
6476
|
+
* means src/core/router/pricing-data.json is probably due a refresh.
|
|
6477
|
+
*/
|
|
6478
|
+
getPriceDisagreements() {
|
|
6479
|
+
return [...this.disagreements.values()];
|
|
6480
|
+
}
|
|
4710
6481
|
/** Current capability facts for a model id, or null when unknown. */
|
|
4711
6482
|
getCapability(modelId) {
|
|
4712
6483
|
return this.capabilities.get(normalizeModelId2(modelId)) ?? null;
|
|
@@ -4903,7 +6674,9 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
4903
6674
|
tokensByTier: {},
|
|
4904
6675
|
inputTokensByTier: {},
|
|
4905
6676
|
outputTokensByTier: {},
|
|
4906
|
-
costByFeature: {}
|
|
6677
|
+
costByFeature: {},
|
|
6678
|
+
untrackedCostCalls: 0,
|
|
6679
|
+
untrackedCostModels: []
|
|
4907
6680
|
};
|
|
4908
6681
|
tierModels = /* @__PURE__ */ new Map();
|
|
4909
6682
|
/**
|
|
@@ -5253,7 +7026,7 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
5253
7026
|
`Model ${model.id} inference timed out after ${cloudTimeoutMs}ms`
|
|
5254
7027
|
);
|
|
5255
7028
|
}
|
|
5256
|
-
const
|
|
7029
|
+
const corrected = buildTokenUsage(
|
|
5257
7030
|
result.usage.inputTokens,
|
|
5258
7031
|
result.usage.outputTokens,
|
|
5259
7032
|
model
|
|
@@ -5262,7 +7035,8 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
5262
7035
|
...result,
|
|
5263
7036
|
usage: {
|
|
5264
7037
|
...result.usage,
|
|
5265
|
-
estimatedCostUsd:
|
|
7038
|
+
estimatedCostUsd: corrected.estimatedCostUsd,
|
|
7039
|
+
...corrected.costUnknown ? { costUnknown: true } : { costUnknown: void 0 }
|
|
5266
7040
|
}
|
|
5267
7041
|
};
|
|
5268
7042
|
if (!result || typeof result.content !== "string" || !result.usage) {
|
|
@@ -5449,7 +7223,9 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
5449
7223
|
tokensByTier: { ...this.stats.tokensByTier },
|
|
5450
7224
|
inputTokensByTier: { ...this.stats.inputTokensByTier },
|
|
5451
7225
|
outputTokensByTier: { ...this.stats.outputTokensByTier },
|
|
5452
|
-
costByFeature: { ...this.stats.costByFeature }
|
|
7226
|
+
costByFeature: { ...this.stats.costByFeature },
|
|
7227
|
+
untrackedCostCalls: this.stats.untrackedCostCalls,
|
|
7228
|
+
untrackedCostModels: [...this.stats.untrackedCostModels]
|
|
5453
7229
|
};
|
|
5454
7230
|
}
|
|
5455
7231
|
/**
|
|
@@ -5500,7 +7276,9 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
5500
7276
|
tokensByTier: {},
|
|
5501
7277
|
inputTokensByTier: {},
|
|
5502
7278
|
outputTokensByTier: {},
|
|
5503
|
-
costByFeature: {}
|
|
7279
|
+
costByFeature: {},
|
|
7280
|
+
untrackedCostCalls: 0,
|
|
7281
|
+
untrackedCostModels: []
|
|
5504
7282
|
};
|
|
5505
7283
|
this.sessionCostUsd = 0;
|
|
5506
7284
|
this.budgetState = "ok";
|
|
@@ -5685,6 +7463,18 @@ var CascadeRouter = class _CascadeRouter extends EventEmitter {
|
|
|
5685
7463
|
if (featureTag) {
|
|
5686
7464
|
this.stats.costByFeature[featureTag] = (this.stats.costByFeature[featureTag] ?? 0) + usage.estimatedCostUsd;
|
|
5687
7465
|
}
|
|
7466
|
+
if (usage.costUnknown) {
|
|
7467
|
+
this.stats.untrackedCostCalls += 1;
|
|
7468
|
+
if (!this.stats.untrackedCostModels.includes(model.id)) {
|
|
7469
|
+
this.stats.untrackedCostModels.push(model.id);
|
|
7470
|
+
const capped = this.config?.budget?.maxCostPerRunUsd != null || this.config?.budget?.sessionBudgetUsd != null;
|
|
7471
|
+
this.emit("cost:untracked", {
|
|
7472
|
+
modelId: model.id,
|
|
7473
|
+
provider: model.provider,
|
|
7474
|
+
reason: capped ? `No published price for ${model.provider}:${model.id}. Its spend is not counted toward your cost budget \u2014 the token cap still applies. Add it to the pricing dataset, or set the provider's \`local: true\` if this endpoint really is free.` : `No published price for ${model.provider}:${model.id}. Cost for this model is reported as "not tracked" rather than $0.00.`
|
|
7475
|
+
});
|
|
7476
|
+
}
|
|
7477
|
+
}
|
|
5688
7478
|
this.runTokens += usage.totalTokens;
|
|
5689
7479
|
this.runCostUsd += usage.estimatedCostUsd;
|
|
5690
7480
|
this.updateBudgetState();
|
|
@@ -11215,6 +13005,7 @@ var noopTelemetry = {
|
|
|
11215
13005
|
};
|
|
11216
13006
|
|
|
11217
13007
|
// src/core/router/task-analyzer.ts
|
|
13008
|
+
init_pricing();
|
|
11218
13009
|
var CODE_SIGNALS = [
|
|
11219
13010
|
/\b(?:function|class|interface|async|await|import|export|const|let|var|def|return|if|else|for|while|try|catch)\b/,
|
|
11220
13011
|
/\b(?:typescript|javascript|python|rust|go|java|c\+\+|sql|bash|shell|dockerfile|kubernetes|terraform)\b/i,
|
|
@@ -11391,8 +13182,8 @@ var TaskAnalyzer = class {
|
|
|
11391
13182
|
}
|
|
11392
13183
|
costEfficiency(model, complexity) {
|
|
11393
13184
|
if (this.tracker) return this.tracker.costEfficiencyScore(model, complexity);
|
|
11394
|
-
const blended = model
|
|
11395
|
-
const normalised = Math.min(1, blended /
|
|
13185
|
+
const blended = blendedCostPer1k(model);
|
|
13186
|
+
const normalised = Math.min(1, blended / BLENDED_COST_CEILING);
|
|
11396
13187
|
const complexityWeight = (6 - complexity) / 5;
|
|
11397
13188
|
return Math.max(0.1, 1 - normalised * complexityWeight);
|
|
11398
13189
|
}
|
|
@@ -11407,6 +13198,9 @@ var TaskAnalyzer = class {
|
|
|
11407
13198
|
analysisCache.clear();
|
|
11408
13199
|
}
|
|
11409
13200
|
};
|
|
13201
|
+
|
|
13202
|
+
// src/core/router/model-performance-tracker.ts
|
|
13203
|
+
init_pricing();
|
|
11410
13204
|
var DEFAULT_STATS_FILE = path32.join(os10.homedir(), ".cascade", "model-perf.json");
|
|
11411
13205
|
var ModelPerformanceTracker = class {
|
|
11412
13206
|
stats = /* @__PURE__ */ new Map();
|
|
@@ -11527,8 +13321,8 @@ var ModelPerformanceTracker = class {
|
|
|
11527
13321
|
* normalised over $0.05 blended as the "expensive" ceiling.
|
|
11528
13322
|
*/
|
|
11529
13323
|
costEfficiencyScore(model, complexity) {
|
|
11530
|
-
const blended = model
|
|
11531
|
-
const normalised = Math.min(1, blended /
|
|
13324
|
+
const blended = blendedCostPer1k(model);
|
|
13325
|
+
const normalised = Math.min(1, blended / BLENDED_COST_CEILING);
|
|
11532
13326
|
const complexityWeight = (6 - complexity) / 5;
|
|
11533
13327
|
return Math.max(0.1, 1 - normalised * complexityWeight);
|
|
11534
13328
|
}
|
|
@@ -14332,7 +16126,11 @@ _(incomplete: ${reasons.join("; ")})_` : partial;
|
|
|
14332
16126
|
inputTokens: 0,
|
|
14333
16127
|
outputTokens: 0,
|
|
14334
16128
|
totalTokens: stats.totalTokens,
|
|
14335
|
-
estimatedCostUsd: stats.totalCostUsd
|
|
16129
|
+
estimatedCostUsd: stats.totalCostUsd,
|
|
16130
|
+
// At least one call ran on a model with no known price, so its spend is
|
|
16131
|
+
// missing from the total above. Say so rather than letting the caller
|
|
16132
|
+
// present an undercount as the final figure.
|
|
16133
|
+
...stats.untrackedCostCalls > 0 ? { costUnknown: true } : {}
|
|
14336
16134
|
},
|
|
14337
16135
|
t2Results,
|
|
14338
16136
|
durationMs,
|
|
@@ -14402,7 +16200,8 @@ _(incomplete: ${reasons.join("; ")})_` : partial;
|
|
|
14402
16200
|
inputTokens: 0,
|
|
14403
16201
|
outputTokens: 0,
|
|
14404
16202
|
totalTokens: stats2.totalTokens,
|
|
14405
|
-
estimatedCostUsd: stats2.totalCostUsd
|
|
16203
|
+
estimatedCostUsd: stats2.totalCostUsd,
|
|
16204
|
+
...stats2.untrackedCostCalls > 0 ? { costUnknown: true } : {}
|
|
14406
16205
|
},
|
|
14407
16206
|
t2Results: [],
|
|
14408
16207
|
durationMs: Date.now() - startMs,
|
|
@@ -14426,7 +16225,8 @@ _(incomplete: ${reasons.join("; ")})_` : partial;
|
|
|
14426
16225
|
inputTokens: result.usage?.inputTokens ?? 0,
|
|
14427
16226
|
outputTokens: result.usage?.outputTokens ?? 0,
|
|
14428
16227
|
totalTokens: stats.totalTokens,
|
|
14429
|
-
estimatedCostUsd: stats.totalCostUsd
|
|
16228
|
+
estimatedCostUsd: stats.totalCostUsd,
|
|
16229
|
+
...stats.untrackedCostCalls > 0 ? { costUnknown: true } : {}
|
|
14430
16230
|
},
|
|
14431
16231
|
t2Results: [],
|
|
14432
16232
|
durationMs: Date.now() - startMs,
|
|
@@ -14616,12 +16416,19 @@ var CloudClient = class _CloudClient {
|
|
|
14616
16416
|
);
|
|
14617
16417
|
await openUrl(authorizeUrl);
|
|
14618
16418
|
const code = await listener.waitForCode;
|
|
14619
|
-
|
|
14620
|
-
|
|
14621
|
-
|
|
14622
|
-
|
|
14623
|
-
|
|
14624
|
-
|
|
16419
|
+
let res;
|
|
16420
|
+
try {
|
|
16421
|
+
res = await fetch(this.url("/api/native/token"), {
|
|
16422
|
+
method: "POST",
|
|
16423
|
+
headers: { "Content-Type": "application/json" },
|
|
16424
|
+
body: JSON.stringify({ code, code_verifier: verifier })
|
|
16425
|
+
});
|
|
16426
|
+
} catch (err) {
|
|
16427
|
+
throw new Error(
|
|
16428
|
+
`Signed in, but could not reach Cascade at ${this.serverUrl} to finish. Check your connection and that the server URL is correct. (${err instanceof Error ? err.message : String(err)})`
|
|
16429
|
+
);
|
|
16430
|
+
}
|
|
16431
|
+
if (!res.ok) throw new Error(await loginFailureMessage(res, this.serverUrl));
|
|
14625
16432
|
const tokens = await res.json();
|
|
14626
16433
|
return await this.finishLogin(tokens);
|
|
14627
16434
|
} finally {
|
|
@@ -14795,6 +16602,22 @@ function sleep(ms, signal) {
|
|
|
14795
16602
|
}, { once: true });
|
|
14796
16603
|
});
|
|
14797
16604
|
}
|
|
16605
|
+
async function loginFailureMessage(res, serverUrl) {
|
|
16606
|
+
const body = await res.text().catch(() => "");
|
|
16607
|
+
let apiError = "";
|
|
16608
|
+
try {
|
|
16609
|
+
apiError = String(JSON.parse(body).error ?? "");
|
|
16610
|
+
} catch {
|
|
16611
|
+
}
|
|
16612
|
+
if (apiError === "invalid_grant") {
|
|
16613
|
+
return "Sign-in expired before it completed \u2014 the code is single-use and short-lived, and restarting the server during sign-in also invalidates it. Please try again.";
|
|
16614
|
+
}
|
|
16615
|
+
if (apiError) return `Sign-in failed: ${apiError} (HTTP ${res.status}).`;
|
|
16616
|
+
if (res.status === 404 || /<html/i.test(body)) {
|
|
16617
|
+
return `Signed in, but ${serverUrl} did not answer the Cascade API (HTTP ${res.status}). If this host was recently pointed at a new server, DNS may still be propagating.`;
|
|
16618
|
+
}
|
|
16619
|
+
return `Sign-in could not be completed (HTTP ${res.status}). Please try again.`;
|
|
16620
|
+
}
|
|
14798
16621
|
function base64url(buf) {
|
|
14799
16622
|
return buf.toString("base64").replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
|
|
14800
16623
|
}
|
|
@@ -19620,7 +21443,10 @@ var DashboardServer = class {
|
|
|
19620
21443
|
this.socket.broadcast("cost:update", {
|
|
19621
21444
|
sessionId,
|
|
19622
21445
|
totalTokens: result.usage.totalTokens,
|
|
19623
|
-
totalCostUsd: result.usage.estimatedCostUsd
|
|
21446
|
+
totalCostUsd: result.usage.estimatedCostUsd,
|
|
21447
|
+
// True when a model with no known price was used: the total above is
|
|
21448
|
+
// an undercount, and the UI must not present it as the full spend.
|
|
21449
|
+
costUnknown: result.usage.costUnknown === true
|
|
19624
21450
|
});
|
|
19625
21451
|
this.throttledBroadcast("workspace");
|
|
19626
21452
|
} catch (err) {
|
|
@@ -19933,7 +21759,8 @@ var DashboardServer = class {
|
|
|
19933
21759
|
this.socket.broadcast("cost:update", {
|
|
19934
21760
|
sessionId,
|
|
19935
21761
|
totalTokens: result.usage.totalTokens,
|
|
19936
|
-
totalCostUsd: result.usage.estimatedCostUsd
|
|
21762
|
+
totalCostUsd: result.usage.estimatedCostUsd,
|
|
21763
|
+
costUnknown: result.usage.costUnknown === true
|
|
19937
21764
|
});
|
|
19938
21765
|
this.throttledBroadcast("workspace");
|
|
19939
21766
|
} catch (err) {
|
|
@@ -20475,7 +22302,8 @@ ${prompt}`;
|
|
|
20475
22302
|
this.socket.broadcast("cost:update", {
|
|
20476
22303
|
sessionId,
|
|
20477
22304
|
totalTokens: result.usage.totalTokens,
|
|
20478
|
-
totalCostUsd: result.usage.estimatedCostUsd
|
|
22305
|
+
totalCostUsd: result.usage.estimatedCostUsd,
|
|
22306
|
+
costUnknown: result.usage.costUnknown === true
|
|
20479
22307
|
});
|
|
20480
22308
|
this.socket.broadcastToRoom(`session:${sessionId}`, "session:complete", { sessionId, result });
|
|
20481
22309
|
this.throttledBroadcast("workspace");
|
|
@@ -20871,6 +22699,7 @@ function makeIdentityCommand(workspacePath = process.cwd()) {
|
|
|
20871
22699
|
});
|
|
20872
22700
|
return identity;
|
|
20873
22701
|
}
|
|
22702
|
+
init_pricing();
|
|
20874
22703
|
async function modelsCommand(options = {}) {
|
|
20875
22704
|
console.log(chalk7.magenta("\n \u25C8 Cascade Models\n"));
|
|
20876
22705
|
const cm = new ConfigManager(process.cwd());
|
|
@@ -20892,17 +22721,20 @@ async function modelsCommand(options = {}) {
|
|
|
20892
22721
|
{ tier: "T3", label: "T3 Worker", color: chalk7.hex("#2DD4BF") }
|
|
20893
22722
|
];
|
|
20894
22723
|
let anyMissing = false;
|
|
22724
|
+
let anyUnpriced = false;
|
|
20895
22725
|
for (const { tier, label, color } of tiers) {
|
|
20896
22726
|
const model = router.getTierModel(tier);
|
|
20897
22727
|
if (model) {
|
|
20898
|
-
const
|
|
20899
|
-
|
|
22728
|
+
const unpriced = isPricingUnknown(model);
|
|
22729
|
+
if (unpriced) anyUnpriced = true;
|
|
22730
|
+
const costIn = unpriced ? "cost not tracked" : model.inputCostPer1kTokens === 0 ? "free" : `$${model.inputCostPer1kTokens.toFixed(4)}/1K in`;
|
|
22731
|
+
const costOut = unpriced ? "" : model.outputCostPer1kTokens === 0 ? "free" : `, $${model.outputCostPer1kTokens.toFixed(4)}/1K out`;
|
|
20900
22732
|
const ctx = model.contextWindow >= 1e6 ? `${(model.contextWindow / 1e6).toFixed(1)}M ctx` : `${(model.contextWindow / 1e3).toFixed(0)}K ctx`;
|
|
20901
22733
|
const local = model.isLocal ? chalk7.gray(" [local]") : "";
|
|
20902
22734
|
const vision = model.isVisionCapable ? chalk7.gray(" \u{1F441}") : "";
|
|
20903
22735
|
const bench = Math.round(benchmarkScore01(model, "mixed") * 100);
|
|
20904
22736
|
console.log(
|
|
20905
|
-
` ${color.bold(tier)} ${chalk7.white(col(model.name, 24))}${chalk7.gray(col(model.provider, 16))}` + (options.verbose ? `${chalk7.gray(col(ctx, 12))}${chalk7.gray(col(`bench ${bench}/100`, 14))}${chalk7.gray(`${costIn}
|
|
22737
|
+
` ${color.bold(tier)} ${chalk7.white(col(model.name, 24))}${chalk7.gray(col(model.provider, 16))}` + (options.verbose ? `${chalk7.gray(col(ctx, 12))}${chalk7.gray(col(`bench ${bench}/100`, 14))}${chalk7.gray(`${costIn}${costOut}`)}` : `${chalk7.gray(col(ctx, 10))}${chalk7.gray(`bench ${bench}/100`)}`) + local + vision
|
|
20906
22738
|
);
|
|
20907
22739
|
} else {
|
|
20908
22740
|
console.log(` ${color.bold(tier)} ${chalk7.red("No model available")} ${chalk7.gray(`(check provider config for ${label})`)}`);
|
|
@@ -20916,8 +22748,25 @@ async function modelsCommand(options = {}) {
|
|
|
20916
22748
|
const src = liveData.getDataSource();
|
|
20917
22749
|
const gen = liveData.getGeneratedAt();
|
|
20918
22750
|
const srcLabel = src === "live" ? "live (just fetched)" : src === "cache" ? "cached" : "bundled";
|
|
22751
|
+
const pricingMeta = pricingDatasetMeta();
|
|
20919
22752
|
console.log(chalk7.gray(
|
|
20920
|
-
` Benchmark data: ${srcLabel}` + (gen ? ` \xB7 updated ${gen.slice(0, 10)}` : "") + ` \xB7 pricing: ${liveData.hasLivePricing() ? "live (OpenRouter)" : "
|
|
22753
|
+
` Benchmark data: ${srcLabel}` + (gen ? ` \xB7 updated ${gen.slice(0, 10)}` : "") + ` \xB7 pricing: ${liveData.hasLivePricing() ? "live (OpenRouter)" : "dataset"} (baseline ${pricingMeta.generatedAt})`
|
|
22754
|
+
));
|
|
22755
|
+
const drift = liveData.getPriceDisagreements();
|
|
22756
|
+
if (drift.length) {
|
|
22757
|
+
console.log(chalk7.yellow(`
|
|
22758
|
+
${drift.length} model${drift.length === 1 ? "" : "s"} priced differently by the live source than by the bundled dataset:`));
|
|
22759
|
+
for (const d of drift.slice(0, 10)) {
|
|
22760
|
+
console.log(chalk7.gray(
|
|
22761
|
+
` ${d.provider}:${d.modelId} dataset $${d.dataset.input.toFixed(5)}/$${d.dataset.output.toFixed(5)} per 1K (as of ${d.datasetAsOf}) \u2192 live $${d.live.input.toFixed(5)}/$${d.live.output.toFixed(5)} (${d.ratio}\xD7)`
|
|
22762
|
+
));
|
|
22763
|
+
}
|
|
22764
|
+
console.log(chalk7.gray(" Live pricing is used. Refresh src/core/router/pricing-data.json to clear this."));
|
|
22765
|
+
}
|
|
22766
|
+
}
|
|
22767
|
+
if (anyUnpriced) {
|
|
22768
|
+
console.log(chalk7.yellow(
|
|
22769
|
+
'\n Some tiers use a model with no published price \u2014 their spend is reported as "cost not tracked", never $0.00,\n and is not counted toward a cost budget. Add the model to the pricing dataset, or set `local: true` on the\n provider if the endpoint genuinely costs nothing to run.'
|
|
20921
22770
|
));
|
|
20922
22771
|
}
|
|
20923
22772
|
if (options.verbose) {
|