@juspay/neurolink 12.40.2 → 12.41.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/CHANGELOG.md +3 -3
- package/dist/browser/neurolink.min.js +447 -443
- package/dist/cli/commands/proxy.js +5 -1
- package/dist/proxy/accountLedger.js +3 -0
- package/dist/proxy/codexOutboundCache.d.ts +52 -0
- package/dist/proxy/codexOutboundCache.js +147 -0
- package/dist/proxy/codexOutboundFallback.d.ts +27 -2
- package/dist/proxy/codexOutboundFallback.js +147 -11
- package/dist/proxy/codexResponsesFormat.js +7 -1
- package/dist/proxy/codexToAnthropicFallback.js +6 -0
- package/dist/proxy/proxyAnalysis.js +4 -0
- package/dist/proxy/proxyConfig.js +120 -0
- package/dist/proxy/proxyTokenUsage.d.ts +15 -0
- package/dist/proxy/proxyTokenUsage.js +33 -0
- package/dist/proxy/proxyTracer.d.ts +16 -1
- package/dist/proxy/proxyTracer.js +26 -5
- package/dist/proxy/requestLogger.js +9 -0
- package/dist/proxy/runtimeConfig.js +20 -0
- package/dist/proxy/sseInterceptor.js +9 -0
- package/dist/proxy/vertexAnthropicFallback.js +9 -0
- package/dist/server/routes/claudeProxyRoutes.js +65 -1
- package/dist/server/routes/codexProxyRoutes.d.ts +39 -3
- package/dist/server/routes/codexProxyRoutes.js +792 -8
- package/dist/server/routes/index.d.ts +8 -0
- package/dist/server/routes/index.js +9 -1
- package/dist/types/analytics.d.ts +25 -0
- package/dist/types/codex.d.ts +45 -1
- package/dist/types/proxy.d.ts +40 -2
- package/dist/types/proxyClient.d.ts +2 -0
- package/dist/types/server.d.ts +15 -0
- package/dist/types/subscription.d.ts +22 -0
- package/dist/utils/anthropicCacheBreakpoints.d.ts +2 -2
- package/dist/utils/anthropicCacheBreakpoints.js +14 -3
- package/dist/utils/pricing.js +101 -24
- package/docs-site/static/search-index.json +17 -6
- package/package.json +4 -4
package/dist/utils/pricing.js
CHANGED
|
@@ -78,7 +78,8 @@ const PRICING = {
|
|
|
78
78
|
// Anthropic (direct API) — updated March 2026
|
|
79
79
|
anthropic: {
|
|
80
80
|
// Claude 5 family. Rates from platform.claude.com/docs/en/about-claude/pricing
|
|
81
|
-
// (checked 2026-09-23). A 5-minute cache write is 1.25x base input
|
|
81
|
+
// (checked 2026-09-23). A 5-minute cache write is 1.25x base input and a
|
|
82
|
+
// 1-hour one 2x, on every Claude model below. The cache
|
|
82
83
|
// hit multiplier is 0.1x for most models but 0.05x on Opus 5.5 and 0.025x on
|
|
83
84
|
// Fable/Mythos 5.1, so those three are listed in full rather than left to the
|
|
84
85
|
// longest-prefix fallback — which would silently quote the 5.0 family's rates.
|
|
@@ -87,18 +88,22 @@ const PRICING = {
|
|
|
87
88
|
output: 50.0 / 1_000_000,
|
|
88
89
|
cacheRead: 0.25 / 1_000_000,
|
|
89
90
|
cacheCreation: 12.5 / 1_000_000,
|
|
91
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
90
92
|
},
|
|
91
93
|
"claude-mythos-5-1": {
|
|
92
94
|
input: 10.0 / 1_000_000,
|
|
93
95
|
output: 50.0 / 1_000_000,
|
|
94
96
|
cacheRead: 0.25 / 1_000_000,
|
|
95
97
|
cacheCreation: 12.5 / 1_000_000,
|
|
98
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
96
99
|
},
|
|
97
100
|
"claude-opus-5-5": {
|
|
98
101
|
input: 4.0 / 1_000_000,
|
|
99
102
|
output: 20.0 / 1_000_000,
|
|
100
103
|
cacheRead: 0.2 / 1_000_000,
|
|
101
104
|
cacheCreation: 5.0 / 1_000_000,
|
|
105
|
+
// 1h TTL = 2x base input (platform.claude.com/docs/en/about-claude/pricing, read 2026-09-29).
|
|
106
|
+
cacheCreation1h: 8.0 / 1_000_000,
|
|
102
107
|
},
|
|
103
108
|
// Sonnet 5.5 bills exactly as Sonnet 5 does, cache rates included.
|
|
104
109
|
"claude-sonnet-5-5": {
|
|
@@ -106,36 +111,43 @@ const PRICING = {
|
|
|
106
111
|
output: 10.0 / 1_000_000,
|
|
107
112
|
cacheRead: 0.2 / 1_000_000,
|
|
108
113
|
cacheCreation: 2.5 / 1_000_000,
|
|
114
|
+
// 1h TTL = 2x base input (platform.claude.com/docs/en/about-claude/pricing, read 2026-09-29).
|
|
115
|
+
cacheCreation1h: 4.0 / 1_000_000,
|
|
109
116
|
},
|
|
110
117
|
"claude-fable-5": {
|
|
111
118
|
input: 10.0 / 1_000_000,
|
|
112
119
|
output: 50.0 / 1_000_000,
|
|
113
120
|
cacheRead: 1.0 / 1_000_000,
|
|
114
121
|
cacheCreation: 12.5 / 1_000_000,
|
|
122
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
115
123
|
},
|
|
116
124
|
"claude-mythos-5": {
|
|
117
125
|
input: 10.0 / 1_000_000,
|
|
118
126
|
output: 50.0 / 1_000_000,
|
|
119
127
|
cacheRead: 1.0 / 1_000_000,
|
|
120
128
|
cacheCreation: 12.5 / 1_000_000,
|
|
129
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
121
130
|
},
|
|
122
131
|
"claude-opus-5": {
|
|
123
132
|
input: 5.0 / 1_000_000,
|
|
124
133
|
output: 25.0 / 1_000_000,
|
|
125
134
|
cacheRead: 0.5 / 1_000_000,
|
|
126
135
|
cacheCreation: 6.25 / 1_000_000,
|
|
136
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
127
137
|
},
|
|
128
138
|
"claude-opus-4-8": {
|
|
129
139
|
input: 5.0 / 1_000_000,
|
|
130
140
|
output: 25.0 / 1_000_000,
|
|
131
141
|
cacheRead: 0.5 / 1_000_000,
|
|
132
142
|
cacheCreation: 6.25 / 1_000_000,
|
|
143
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
133
144
|
},
|
|
134
145
|
"claude-opus-4-7": {
|
|
135
146
|
input: 5.0 / 1_000_000,
|
|
136
147
|
output: 25.0 / 1_000_000,
|
|
137
148
|
cacheRead: 0.5 / 1_000_000,
|
|
138
149
|
cacheCreation: 6.25 / 1_000_000,
|
|
150
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
139
151
|
},
|
|
140
152
|
// Sonnet 5's $2/$10 launch pricing became the standard price; the
|
|
141
153
|
// previously scheduled 2026-09-01 rise to $3/$15 was cancelled.
|
|
@@ -144,6 +156,8 @@ const PRICING = {
|
|
|
144
156
|
output: 10.0 / 1_000_000,
|
|
145
157
|
cacheRead: 0.2 / 1_000_000,
|
|
146
158
|
cacheCreation: 2.5 / 1_000_000,
|
|
159
|
+
// 1h TTL = 2x base input (platform.claude.com/docs/en/about-claude/pricing).
|
|
160
|
+
cacheCreation1h: 4.0 / 1_000_000,
|
|
147
161
|
},
|
|
148
162
|
// Claude 4.6 family
|
|
149
163
|
"claude-opus-4-6": {
|
|
@@ -151,12 +165,14 @@ const PRICING = {
|
|
|
151
165
|
output: 25.0 / 1_000_000,
|
|
152
166
|
cacheRead: 0.5 / 1_000_000,
|
|
153
167
|
cacheCreation: 6.25 / 1_000_000,
|
|
168
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
154
169
|
},
|
|
155
170
|
"claude-sonnet-4-6": {
|
|
156
171
|
input: 3.0 / 1_000_000,
|
|
157
172
|
output: 15.0 / 1_000_000,
|
|
158
173
|
cacheRead: 0.3 / 1_000_000,
|
|
159
174
|
cacheCreation: 3.75 / 1_000_000,
|
|
175
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
160
176
|
},
|
|
161
177
|
// Claude 4.5 family
|
|
162
178
|
"claude-sonnet-4-5-20250929": {
|
|
@@ -164,6 +180,7 @@ const PRICING = {
|
|
|
164
180
|
output: 15.0 / 1_000_000,
|
|
165
181
|
cacheRead: 0.3 / 1_000_000,
|
|
166
182
|
cacheCreation: 3.75 / 1_000_000,
|
|
183
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
167
184
|
},
|
|
168
185
|
// Undated aliases for the same models. Clients report the bare name far
|
|
169
186
|
// more often than the dated one, and without these the longest-prefix
|
|
@@ -175,24 +192,28 @@ const PRICING = {
|
|
|
175
192
|
output: 15.0 / 1_000_000,
|
|
176
193
|
cacheRead: 0.3 / 1_000_000,
|
|
177
194
|
cacheCreation: 3.75 / 1_000_000,
|
|
195
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
178
196
|
},
|
|
179
197
|
"claude-opus-4-5": {
|
|
180
198
|
input: 5.0 / 1_000_000,
|
|
181
199
|
output: 25.0 / 1_000_000,
|
|
182
200
|
cacheRead: 0.5 / 1_000_000,
|
|
183
201
|
cacheCreation: 6.25 / 1_000_000,
|
|
202
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
184
203
|
},
|
|
185
204
|
"claude-haiku-4-5-20251001": {
|
|
186
205
|
input: 1.0 / 1_000_000,
|
|
187
206
|
output: 5.0 / 1_000_000,
|
|
188
207
|
cacheRead: 0.1 / 1_000_000,
|
|
189
208
|
cacheCreation: 1.25 / 1_000_000,
|
|
209
|
+
cacheCreation1h: 2.0 / 1_000_000,
|
|
190
210
|
},
|
|
191
211
|
"claude-haiku-4-5": {
|
|
192
212
|
input: 1.0 / 1_000_000,
|
|
193
213
|
output: 5.0 / 1_000_000,
|
|
194
214
|
cacheRead: 0.1 / 1_000_000,
|
|
195
215
|
cacheCreation: 1.25 / 1_000_000,
|
|
216
|
+
cacheCreation1h: 2.0 / 1_000_000,
|
|
196
217
|
},
|
|
197
218
|
// Claude 4.0/4.1 family
|
|
198
219
|
"claude-opus-4-1": {
|
|
@@ -200,18 +221,21 @@ const PRICING = {
|
|
|
200
221
|
output: 75.0 / 1_000_000,
|
|
201
222
|
cacheRead: 1.5 / 1_000_000,
|
|
202
223
|
cacheCreation: 18.75 / 1_000_000,
|
|
224
|
+
cacheCreation1h: 30.0 / 1_000_000,
|
|
203
225
|
},
|
|
204
226
|
"claude-opus-4": {
|
|
205
227
|
input: 15.0 / 1_000_000,
|
|
206
228
|
output: 75.0 / 1_000_000,
|
|
207
229
|
cacheRead: 1.5 / 1_000_000,
|
|
208
230
|
cacheCreation: 18.75 / 1_000_000,
|
|
231
|
+
cacheCreation1h: 30.0 / 1_000_000,
|
|
209
232
|
},
|
|
210
233
|
"claude-sonnet-4": {
|
|
211
234
|
input: 3.0 / 1_000_000,
|
|
212
235
|
output: 15.0 / 1_000_000,
|
|
213
236
|
cacheRead: 0.3 / 1_000_000,
|
|
214
237
|
cacheCreation: 3.75 / 1_000_000,
|
|
238
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
215
239
|
},
|
|
216
240
|
// Claude 3.x family
|
|
217
241
|
"claude-3-7-sonnet": {
|
|
@@ -219,40 +243,47 @@ const PRICING = {
|
|
|
219
243
|
output: 15.0 / 1_000_000,
|
|
220
244
|
cacheRead: 0.3 / 1_000_000,
|
|
221
245
|
cacheCreation: 3.75 / 1_000_000,
|
|
246
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
222
247
|
},
|
|
223
248
|
"claude-3-5-sonnet": {
|
|
224
249
|
input: 3.0 / 1_000_000,
|
|
225
250
|
output: 15.0 / 1_000_000,
|
|
226
251
|
cacheRead: 0.3 / 1_000_000,
|
|
227
252
|
cacheCreation: 3.75 / 1_000_000,
|
|
253
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
228
254
|
},
|
|
229
255
|
"claude-3-5-haiku": {
|
|
230
256
|
input: 0.8 / 1_000_000,
|
|
231
257
|
output: 4.0 / 1_000_000,
|
|
232
258
|
cacheRead: 0.08 / 1_000_000,
|
|
233
259
|
cacheCreation: 1.0 / 1_000_000,
|
|
260
|
+
cacheCreation1h: 1.6 / 1_000_000,
|
|
234
261
|
},
|
|
235
262
|
"claude-3-opus": {
|
|
236
263
|
input: 15.0 / 1_000_000,
|
|
237
264
|
output: 75.0 / 1_000_000,
|
|
238
265
|
cacheRead: 1.5 / 1_000_000,
|
|
239
266
|
cacheCreation: 18.75 / 1_000_000,
|
|
267
|
+
cacheCreation1h: 30.0 / 1_000_000,
|
|
240
268
|
},
|
|
241
269
|
"claude-3-sonnet": {
|
|
242
270
|
input: 3.0 / 1_000_000,
|
|
243
271
|
output: 15.0 / 1_000_000,
|
|
244
272
|
cacheRead: 0.3 / 1_000_000,
|
|
245
273
|
cacheCreation: 3.75 / 1_000_000,
|
|
274
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
246
275
|
},
|
|
247
276
|
"claude-3-haiku": {
|
|
248
277
|
input: 0.25 / 1_000_000,
|
|
249
278
|
output: 1.25 / 1_000_000,
|
|
250
279
|
cacheRead: 0.025 / 1_000_000,
|
|
251
280
|
cacheCreation: 0.3125 / 1_000_000,
|
|
281
|
+
cacheCreation1h: 0.5 / 1_000_000,
|
|
252
282
|
},
|
|
253
283
|
},
|
|
254
284
|
// Google Vertex AI — Claude models on Vertex (same pricing, @ date suffix)
|
|
255
285
|
vertex: {
|
|
286
|
+
// A 1-hour cache write is 2x base input, as on the direct API.
|
|
256
287
|
// Claude 5 family. Absent here until now, so a Vertex leg serving any of
|
|
257
288
|
// them resolved to no rate at all and booked the turn at $0 — on the one
|
|
258
289
|
// provider in the chain that bills in real currency.
|
|
@@ -263,30 +294,36 @@ const PRICING = {
|
|
|
263
294
|
output: 50.0 / 1_000_000,
|
|
264
295
|
cacheRead: 0.25 / 1_000_000,
|
|
265
296
|
cacheCreation: 12.5 / 1_000_000,
|
|
297
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
266
298
|
},
|
|
267
299
|
"claude-mythos-5-1": {
|
|
268
300
|
input: 10.0 / 1_000_000,
|
|
269
301
|
output: 50.0 / 1_000_000,
|
|
270
302
|
cacheRead: 0.25 / 1_000_000,
|
|
271
303
|
cacheCreation: 12.5 / 1_000_000,
|
|
304
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
272
305
|
},
|
|
273
306
|
"claude-fable-5": {
|
|
274
307
|
input: 10.0 / 1_000_000,
|
|
275
308
|
output: 50.0 / 1_000_000,
|
|
276
309
|
cacheRead: 1.0 / 1_000_000,
|
|
277
310
|
cacheCreation: 12.5 / 1_000_000,
|
|
311
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
278
312
|
},
|
|
279
313
|
"claude-mythos-5": {
|
|
280
314
|
input: 10.0 / 1_000_000,
|
|
281
315
|
output: 50.0 / 1_000_000,
|
|
282
316
|
cacheRead: 1.0 / 1_000_000,
|
|
283
317
|
cacheCreation: 12.5 / 1_000_000,
|
|
318
|
+
cacheCreation1h: 20.0 / 1_000_000,
|
|
284
319
|
},
|
|
285
320
|
"claude-opus-5-5": {
|
|
286
321
|
input: 4.0 / 1_000_000,
|
|
287
322
|
output: 20.0 / 1_000_000,
|
|
288
323
|
cacheRead: 0.2 / 1_000_000,
|
|
289
324
|
cacheCreation: 5.0 / 1_000_000,
|
|
325
|
+
// 1h TTL = 2x base input (platform.claude.com/docs/en/about-claude/pricing, read 2026-09-29).
|
|
326
|
+
cacheCreation1h: 8.0 / 1_000_000,
|
|
290
327
|
},
|
|
291
328
|
// Sonnet 5.5 bills exactly as Sonnet 5 does, cache rates included.
|
|
292
329
|
"claude-sonnet-5-5": {
|
|
@@ -294,60 +331,72 @@ const PRICING = {
|
|
|
294
331
|
output: 10.0 / 1_000_000,
|
|
295
332
|
cacheRead: 0.2 / 1_000_000,
|
|
296
333
|
cacheCreation: 2.5 / 1_000_000,
|
|
334
|
+
// 1h TTL = 2x base input (platform.claude.com/docs/en/about-claude/pricing, read 2026-09-29).
|
|
335
|
+
cacheCreation1h: 4.0 / 1_000_000,
|
|
297
336
|
},
|
|
298
337
|
"claude-opus-5": {
|
|
299
338
|
input: 5.0 / 1_000_000,
|
|
300
339
|
output: 25.0 / 1_000_000,
|
|
301
340
|
cacheRead: 0.5 / 1_000_000,
|
|
302
341
|
cacheCreation: 6.25 / 1_000_000,
|
|
342
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
303
343
|
},
|
|
304
344
|
"claude-sonnet-5": {
|
|
305
345
|
input: 2.0 / 1_000_000,
|
|
306
346
|
output: 10.0 / 1_000_000,
|
|
307
347
|
cacheRead: 0.2 / 1_000_000,
|
|
308
348
|
cacheCreation: 2.5 / 1_000_000,
|
|
349
|
+
// 1h TTL = 2x base input (platform.claude.com/docs/en/about-claude/pricing).
|
|
350
|
+
cacheCreation1h: 4.0 / 1_000_000,
|
|
309
351
|
},
|
|
310
352
|
"claude-sonnet-4-6": {
|
|
311
353
|
input: 3.0 / 1_000_000,
|
|
312
354
|
output: 15.0 / 1_000_000,
|
|
313
355
|
cacheRead: 0.3 / 1_000_000,
|
|
314
356
|
cacheCreation: 3.75 / 1_000_000,
|
|
357
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
315
358
|
},
|
|
316
359
|
"claude-opus-4-6": {
|
|
317
360
|
input: 5.0 / 1_000_000,
|
|
318
361
|
output: 25.0 / 1_000_000,
|
|
319
362
|
cacheRead: 0.5 / 1_000_000,
|
|
320
363
|
cacheCreation: 6.25 / 1_000_000,
|
|
364
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
321
365
|
},
|
|
322
366
|
"claude-sonnet-4-5": {
|
|
323
367
|
input: 3.0 / 1_000_000,
|
|
324
368
|
output: 15.0 / 1_000_000,
|
|
325
369
|
cacheRead: 0.3 / 1_000_000,
|
|
326
370
|
cacheCreation: 3.75 / 1_000_000,
|
|
371
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
327
372
|
},
|
|
328
373
|
"claude-opus-4-5": {
|
|
329
374
|
input: 5.0 / 1_000_000,
|
|
330
375
|
output: 25.0 / 1_000_000,
|
|
331
376
|
cacheRead: 0.5 / 1_000_000,
|
|
332
377
|
cacheCreation: 6.25 / 1_000_000,
|
|
378
|
+
cacheCreation1h: 10.0 / 1_000_000,
|
|
333
379
|
},
|
|
334
380
|
"claude-haiku-4-5": {
|
|
335
381
|
input: 1.0 / 1_000_000,
|
|
336
382
|
output: 5.0 / 1_000_000,
|
|
337
383
|
cacheRead: 0.1 / 1_000_000,
|
|
338
384
|
cacheCreation: 1.25 / 1_000_000,
|
|
385
|
+
cacheCreation1h: 2.0 / 1_000_000,
|
|
339
386
|
},
|
|
340
387
|
"claude-3-5-haiku": {
|
|
341
388
|
input: 0.8 / 1_000_000,
|
|
342
389
|
output: 4.0 / 1_000_000,
|
|
343
390
|
cacheRead: 0.08 / 1_000_000,
|
|
344
391
|
cacheCreation: 1.0 / 1_000_000,
|
|
392
|
+
cacheCreation1h: 1.6 / 1_000_000,
|
|
345
393
|
},
|
|
346
394
|
"claude-3-5-sonnet": {
|
|
347
395
|
input: 3.0 / 1_000_000,
|
|
348
396
|
output: 15.0 / 1_000_000,
|
|
349
397
|
cacheRead: 0.3 / 1_000_000,
|
|
350
398
|
cacheCreation: 3.75 / 1_000_000,
|
|
399
|
+
cacheCreation1h: 6.0 / 1_000_000,
|
|
351
400
|
},
|
|
352
401
|
},
|
|
353
402
|
// OpenAI — updated March 2026
|
|
@@ -826,20 +875,37 @@ function isVersionOnlySuffix(model, key) {
|
|
|
826
875
|
return VERSION_SUFFIX_RE.test(model.slice(key.length));
|
|
827
876
|
}
|
|
828
877
|
/**
|
|
829
|
-
*
|
|
830
|
-
*
|
|
878
|
+
* The manifest's canonical id for `model` when the manifest names it by that
|
|
879
|
+
* id or by one of its declared aliases — deliberately excludes
|
|
831
880
|
* resolveManifestEntryExact's longest-prefix fallback. See the call site in
|
|
832
881
|
* findRates for why the prefix path is unsafe to use for pricing precedence.
|
|
833
882
|
*/
|
|
834
|
-
function
|
|
883
|
+
function manifestCanonicalId(provider, model) {
|
|
835
884
|
const manifest = getManifestForProvider(provider);
|
|
836
885
|
if (!manifest) {
|
|
837
|
-
return
|
|
886
|
+
return undefined;
|
|
838
887
|
}
|
|
839
888
|
if (Object.prototype.hasOwnProperty.call(manifest.models, model)) {
|
|
840
|
-
return
|
|
889
|
+
return model;
|
|
841
890
|
}
|
|
842
|
-
return Object.
|
|
891
|
+
return Object.entries(manifest.models).find(([, entry]) => entry.aliases.includes(model))?.[0];
|
|
892
|
+
}
|
|
893
|
+
/**
|
|
894
|
+
* A provider table's entry for `modelKey`: the exact key, else the longest
|
|
895
|
+
* key `modelKey` starts with (never the synthetic "_default"). `exact` is
|
|
896
|
+
* true for a literal key or a version-only suffix of one.
|
|
897
|
+
*/
|
|
898
|
+
function findTableEntry(providerPricing, modelKey) {
|
|
899
|
+
if (providerPricing[modelKey]) {
|
|
900
|
+
return { rates: providerPricing[modelKey], exact: true };
|
|
901
|
+
}
|
|
902
|
+
const sortedKeys = Object.keys(providerPricing)
|
|
903
|
+
.filter((k) => k !== "_default")
|
|
904
|
+
.sort((a, b) => b.length - a.length);
|
|
905
|
+
const key = sortedKeys.find((k) => modelKey.startsWith(k));
|
|
906
|
+
return key
|
|
907
|
+
? { rates: providerPricing[key], exact: isVersionOnlySuffix(modelKey, key) }
|
|
908
|
+
: undefined;
|
|
843
909
|
}
|
|
844
910
|
function findRates(provider, model,
|
|
845
911
|
/**
|
|
@@ -907,12 +973,17 @@ matchKind) {
|
|
|
907
973
|
// claude-sonnet-5 — falls straight through to PRICING's unchanged
|
|
908
974
|
// exact+prefix match below, which is exactly "legacy PRICING as the
|
|
909
975
|
// fallback for entries the manifest lacks."
|
|
910
|
-
|
|
976
|
+
const canonicalId = manifestCanonicalId(normalizedProvider, modelKey);
|
|
977
|
+
if (canonicalId !== undefined) {
|
|
911
978
|
const manifestEntry = resolveManifestEntryExact(normalizedProvider, modelKey);
|
|
912
979
|
if (manifestEntry?.pricingPerMTok) {
|
|
913
980
|
if (matchKind) {
|
|
914
981
|
matchKind.exact = true;
|
|
915
982
|
}
|
|
983
|
+
// The manifest carries no 1-hour cache-write rate; the table entry for
|
|
984
|
+
// the same model does. Without it a 1h write bills at the 5m rate.
|
|
985
|
+
const cacheCreation1h = (findTableEntry(providerPricing, modelKey) ??
|
|
986
|
+
findTableEntry(providerPricing, canonicalId))?.rates.cacheCreation1h;
|
|
916
987
|
return {
|
|
917
988
|
input: manifestEntry.pricingPerMTok.input / 1_000_000,
|
|
918
989
|
output: manifestEntry.pricingPerMTok.output / 1_000_000,
|
|
@@ -922,26 +993,17 @@ matchKind) {
|
|
|
922
993
|
cacheCreation: manifestEntry.pricingPerMTok.cacheWrite !== undefined
|
|
923
994
|
? manifestEntry.pricingPerMTok.cacheWrite / 1_000_000
|
|
924
995
|
: undefined,
|
|
996
|
+
...(cacheCreation1h !== undefined ? { cacheCreation1h } : {}),
|
|
925
997
|
};
|
|
926
998
|
}
|
|
927
999
|
}
|
|
928
|
-
// Exact match
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
}
|
|
933
|
-
return providerPricing[modelKey];
|
|
934
|
-
}
|
|
935
|
-
// Longest-prefix match (skip the synthetic "_default" sentinel below)
|
|
936
|
-
const sortedKeys = Object.keys(providerPricing)
|
|
937
|
-
.filter((k) => k !== "_default")
|
|
938
|
-
.sort((a, b) => b.length - a.length);
|
|
939
|
-
const key = sortedKeys.find((k) => modelKey.startsWith(k));
|
|
940
|
-
if (key) {
|
|
941
|
-
if (matchKind && isVersionOnlySuffix(modelKey, key)) {
|
|
1000
|
+
// Exact match, else longest-prefix match
|
|
1001
|
+
const tableEntry = findTableEntry(providerPricing, modelKey);
|
|
1002
|
+
if (tableEntry) {
|
|
1003
|
+
if (matchKind && tableEntry.exact) {
|
|
942
1004
|
matchKind.exact = true;
|
|
943
1005
|
}
|
|
944
|
-
return
|
|
1006
|
+
return tableEntry.rates;
|
|
945
1007
|
}
|
|
946
1008
|
// Fallback: Vertex hosts both Claude and Gemini models.
|
|
947
1009
|
// If no match found under "vertex", try "google" pricing for Gemini models.
|
|
@@ -997,9 +1059,24 @@ export function calculateCost(provider, model, usage) {
|
|
|
997
1059
|
cost += usage.cacheReadTokens * (rates.cacheRead ?? rates.input);
|
|
998
1060
|
}
|
|
999
1061
|
if (usage.cacheCreationTokens) {
|
|
1062
|
+
// `cacheCreation1hTokens` is a subset of `cacheCreationTokens` (the 1h-TTL
|
|
1063
|
+
// share of the total cache-write count), not additive with it — Anthropic
|
|
1064
|
+
// reports the 1h breakdown inside the same total
|
|
1065
|
+
// (`cache_creation.ephemeral_1h_input_tokens` within
|
|
1066
|
+
// `cache_creation_input_tokens`). Clamp to [0, total] so an inconsistent
|
|
1067
|
+
// or negative count can never bill more tokens than were written, or
|
|
1068
|
+
// subtract cost.
|
|
1069
|
+
const oneHourTokens = Math.max(0, Math.min(usage.cacheCreation1hTokens ?? 0, usage.cacheCreationTokens));
|
|
1070
|
+
const fiveMinTokens = usage.cacheCreationTokens - oneHourTokens;
|
|
1000
1071
|
// Like cache reads, disjoint cache writes must not silently become free
|
|
1001
1072
|
// when a model has no separate creation rate. Preserve explicit zero rates.
|
|
1002
|
-
cost +=
|
|
1073
|
+
cost += fiveMinTokens * (rates.cacheCreation ?? rates.input);
|
|
1074
|
+
// A model without a `cacheCreation1h` rate keeps today's pricing exactly:
|
|
1075
|
+
// it falls back through the 5-minute rate to the input rate, the same
|
|
1076
|
+
// chain the 5-minute share already uses, rather than going unpriced.
|
|
1077
|
+
cost +=
|
|
1078
|
+
oneHourTokens *
|
|
1079
|
+
(rates.cacheCreation1h ?? rates.cacheCreation ?? rates.input);
|
|
1003
1080
|
}
|
|
1004
1081
|
return Math.round(cost * 1_000_000) / 1_000_000; // Round to 6 decimal places
|
|
1005
1082
|
}
|