floe-guard 0.1.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/dist/index.cjs ADDED
@@ -0,0 +1,982 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ BudgetExceeded: () => BudgetExceeded,
24
+ BudgetGuard: () => BudgetGuard,
25
+ FloeGuardError: () => FloeGuardError,
26
+ UnpriceableModelError: () => UnpriceableModelError,
27
+ budgetGuardMiddleware: () => budgetGuardMiddleware,
28
+ priceTokens: () => priceTokens,
29
+ pricing: () => pricing_exports,
30
+ resolvePrice: () => resolvePrice
31
+ });
32
+ module.exports = __toCommonJS(index_exports);
33
+
34
+ // src/errors.ts
35
+ var FloeGuardError = class extends Error {
36
+ constructor(message) {
37
+ super(message);
38
+ this.name = "FloeGuardError";
39
+ Object.setPrototypeOf(this, new.target.prototype);
40
+ }
41
+ };
42
+ var BudgetExceeded = class extends FloeGuardError {
43
+ spentUsd;
44
+ limitUsd;
45
+ constructor(spentUsd, limitUsd) {
46
+ super(
47
+ `BUDGET EXCEEDED \u2014 call blocked (spent $${spentUsd.toFixed(6)} of $${limitUsd.toFixed(6)} ceiling)`
48
+ );
49
+ this.name = "BudgetExceeded";
50
+ this.spentUsd = spentUsd;
51
+ this.limitUsd = limitUsd;
52
+ }
53
+ };
54
+ var UnpriceableModelError = class extends FloeGuardError {
55
+ model;
56
+ constructor(model) {
57
+ super(
58
+ `Cannot price model '${model}': not in the bundled cost map and no manual price was given. The guard cannot enforce a budget on spend it cannot measure. Pass a price override to enable enforcement.`
59
+ );
60
+ this.name = "UnpriceableModelError";
61
+ this.model = model;
62
+ }
63
+ };
64
+
65
+ // src/pricing.ts
66
+ var pricing_exports = {};
67
+ __export(pricing_exports, {
68
+ priceTokens: () => priceTokens,
69
+ resolvePrice: () => resolvePrice
70
+ });
71
+
72
+ // src/cost_map.json
73
+ var cost_map_default = {
74
+ "chatgpt-4o-latest": {
75
+ input_cost_per_token: 5e-6,
76
+ output_cost_per_token: 15e-6,
77
+ litellm_provider: "openai",
78
+ mode: "chat"
79
+ },
80
+ "claude-3-7-sonnet-20250219": {
81
+ input_cost_per_token: 3e-6,
82
+ output_cost_per_token: 15e-6,
83
+ litellm_provider: "anthropic",
84
+ mode: "chat"
85
+ },
86
+ "claude-3-haiku-20240307": {
87
+ input_cost_per_token: 25e-8,
88
+ output_cost_per_token: 125e-8,
89
+ litellm_provider: "anthropic",
90
+ mode: "chat"
91
+ },
92
+ "claude-3-opus-20240229": {
93
+ input_cost_per_token: 15e-6,
94
+ output_cost_per_token: 75e-6,
95
+ litellm_provider: "anthropic",
96
+ mode: "chat"
97
+ },
98
+ "claude-4-opus-20250514": {
99
+ input_cost_per_token: 15e-6,
100
+ output_cost_per_token: 75e-6,
101
+ litellm_provider: "anthropic",
102
+ mode: "chat"
103
+ },
104
+ "claude-4-sonnet-20250514": {
105
+ input_cost_per_token: 3e-6,
106
+ output_cost_per_token: 15e-6,
107
+ litellm_provider: "anthropic",
108
+ mode: "chat"
109
+ },
110
+ "claude-haiku-4-5": {
111
+ input_cost_per_token: 1e-6,
112
+ output_cost_per_token: 5e-6,
113
+ litellm_provider: "anthropic",
114
+ mode: "chat"
115
+ },
116
+ "claude-haiku-4-5-20251001": {
117
+ input_cost_per_token: 1e-6,
118
+ output_cost_per_token: 5e-6,
119
+ litellm_provider: "anthropic",
120
+ mode: "chat"
121
+ },
122
+ "claude-opus-4-1": {
123
+ input_cost_per_token: 15e-6,
124
+ output_cost_per_token: 75e-6,
125
+ litellm_provider: "anthropic",
126
+ mode: "chat"
127
+ },
128
+ "claude-opus-4-1-20250805": {
129
+ input_cost_per_token: 15e-6,
130
+ output_cost_per_token: 75e-6,
131
+ litellm_provider: "anthropic",
132
+ mode: "chat"
133
+ },
134
+ "claude-opus-4-20250514": {
135
+ input_cost_per_token: 15e-6,
136
+ output_cost_per_token: 75e-6,
137
+ litellm_provider: "anthropic",
138
+ mode: "chat"
139
+ },
140
+ "claude-opus-4-5": {
141
+ input_cost_per_token: 5e-6,
142
+ output_cost_per_token: 25e-6,
143
+ litellm_provider: "anthropic",
144
+ mode: "chat"
145
+ },
146
+ "claude-opus-4-5-20251101": {
147
+ input_cost_per_token: 5e-6,
148
+ output_cost_per_token: 25e-6,
149
+ litellm_provider: "anthropic",
150
+ mode: "chat"
151
+ },
152
+ "claude-opus-4-6": {
153
+ input_cost_per_token: 5e-6,
154
+ output_cost_per_token: 25e-6,
155
+ litellm_provider: "anthropic",
156
+ mode: "chat"
157
+ },
158
+ "claude-opus-4-6-20260205": {
159
+ input_cost_per_token: 5e-6,
160
+ output_cost_per_token: 25e-6,
161
+ litellm_provider: "anthropic",
162
+ mode: "chat"
163
+ },
164
+ "claude-opus-4-7": {
165
+ input_cost_per_token: 5e-6,
166
+ output_cost_per_token: 25e-6,
167
+ litellm_provider: "anthropic",
168
+ mode: "chat"
169
+ },
170
+ "claude-opus-4-7-20260416": {
171
+ input_cost_per_token: 5e-6,
172
+ output_cost_per_token: 25e-6,
173
+ litellm_provider: "anthropic",
174
+ mode: "chat"
175
+ },
176
+ "claude-opus-4-8": {
177
+ input_cost_per_token: 5e-6,
178
+ output_cost_per_token: 25e-6,
179
+ litellm_provider: "anthropic",
180
+ mode: "chat"
181
+ },
182
+ "claude-sonnet-4-20250514": {
183
+ input_cost_per_token: 3e-6,
184
+ output_cost_per_token: 15e-6,
185
+ litellm_provider: "anthropic",
186
+ mode: "chat"
187
+ },
188
+ "claude-sonnet-4-5": {
189
+ input_cost_per_token: 3e-6,
190
+ output_cost_per_token: 15e-6,
191
+ litellm_provider: "anthropic",
192
+ mode: "chat"
193
+ },
194
+ "claude-sonnet-4-5-20250929": {
195
+ input_cost_per_token: 3e-6,
196
+ output_cost_per_token: 15e-6,
197
+ litellm_provider: "anthropic",
198
+ mode: "chat"
199
+ },
200
+ "claude-sonnet-4-6": {
201
+ input_cost_per_token: 3e-6,
202
+ output_cost_per_token: 15e-6,
203
+ litellm_provider: "anthropic",
204
+ mode: "chat"
205
+ },
206
+ "ft:gpt-3.5-turbo": {
207
+ input_cost_per_token: 3e-6,
208
+ output_cost_per_token: 6e-6,
209
+ litellm_provider: "openai",
210
+ mode: "chat"
211
+ },
212
+ "ft:gpt-3.5-turbo-0125": {
213
+ input_cost_per_token: 3e-6,
214
+ output_cost_per_token: 6e-6,
215
+ litellm_provider: "openai",
216
+ mode: "chat"
217
+ },
218
+ "ft:gpt-3.5-turbo-0613": {
219
+ input_cost_per_token: 3e-6,
220
+ output_cost_per_token: 6e-6,
221
+ litellm_provider: "openai",
222
+ mode: "chat"
223
+ },
224
+ "ft:gpt-3.5-turbo-1106": {
225
+ input_cost_per_token: 3e-6,
226
+ output_cost_per_token: 6e-6,
227
+ litellm_provider: "openai",
228
+ mode: "chat"
229
+ },
230
+ "ft:gpt-4-0613": {
231
+ input_cost_per_token: 3e-5,
232
+ output_cost_per_token: 6e-5,
233
+ litellm_provider: "openai",
234
+ mode: "chat"
235
+ },
236
+ "ft:gpt-4.1-2025-04-14": {
237
+ input_cost_per_token: 3e-6,
238
+ output_cost_per_token: 12e-6,
239
+ litellm_provider: "openai",
240
+ mode: "chat"
241
+ },
242
+ "ft:gpt-4.1-mini-2025-04-14": {
243
+ input_cost_per_token: 8e-7,
244
+ output_cost_per_token: 32e-7,
245
+ litellm_provider: "openai",
246
+ mode: "chat"
247
+ },
248
+ "ft:gpt-4.1-nano-2025-04-14": {
249
+ input_cost_per_token: 2e-7,
250
+ output_cost_per_token: 8e-7,
251
+ litellm_provider: "openai",
252
+ mode: "chat"
253
+ },
254
+ "ft:gpt-4o-2024-08-06": {
255
+ input_cost_per_token: 375e-8,
256
+ output_cost_per_token: 15e-6,
257
+ litellm_provider: "openai",
258
+ mode: "chat"
259
+ },
260
+ "ft:gpt-4o-2024-11-20": {
261
+ input_cost_per_token: 375e-8,
262
+ output_cost_per_token: 15e-6,
263
+ litellm_provider: "openai",
264
+ mode: "chat"
265
+ },
266
+ "ft:gpt-4o-mini-2024-07-18": {
267
+ input_cost_per_token: 3e-7,
268
+ output_cost_per_token: 12e-7,
269
+ litellm_provider: "openai",
270
+ mode: "chat"
271
+ },
272
+ "ft:o4-mini-2025-04-16": {
273
+ input_cost_per_token: 4e-6,
274
+ output_cost_per_token: 16e-6,
275
+ litellm_provider: "openai",
276
+ mode: "chat"
277
+ },
278
+ "gpt-3.5-turbo": {
279
+ input_cost_per_token: 5e-7,
280
+ output_cost_per_token: 15e-7,
281
+ litellm_provider: "openai",
282
+ mode: "chat"
283
+ },
284
+ "gpt-3.5-turbo-0125": {
285
+ input_cost_per_token: 5e-7,
286
+ output_cost_per_token: 15e-7,
287
+ litellm_provider: "openai",
288
+ mode: "chat"
289
+ },
290
+ "gpt-3.5-turbo-1106": {
291
+ input_cost_per_token: 1e-6,
292
+ output_cost_per_token: 2e-6,
293
+ litellm_provider: "openai",
294
+ mode: "chat"
295
+ },
296
+ "gpt-3.5-turbo-16k": {
297
+ input_cost_per_token: 3e-6,
298
+ output_cost_per_token: 4e-6,
299
+ litellm_provider: "openai",
300
+ mode: "chat"
301
+ },
302
+ "gpt-4": {
303
+ input_cost_per_token: 3e-5,
304
+ output_cost_per_token: 6e-5,
305
+ litellm_provider: "openai",
306
+ mode: "chat"
307
+ },
308
+ "gpt-4-0125-preview": {
309
+ input_cost_per_token: 1e-5,
310
+ output_cost_per_token: 3e-5,
311
+ litellm_provider: "openai",
312
+ mode: "chat"
313
+ },
314
+ "gpt-4-0314": {
315
+ input_cost_per_token: 3e-5,
316
+ output_cost_per_token: 6e-5,
317
+ litellm_provider: "openai",
318
+ mode: "chat"
319
+ },
320
+ "gpt-4-0613": {
321
+ input_cost_per_token: 3e-5,
322
+ output_cost_per_token: 6e-5,
323
+ litellm_provider: "openai",
324
+ mode: "chat"
325
+ },
326
+ "gpt-4-1106-preview": {
327
+ input_cost_per_token: 1e-5,
328
+ output_cost_per_token: 3e-5,
329
+ litellm_provider: "openai",
330
+ mode: "chat"
331
+ },
332
+ "gpt-4-turbo": {
333
+ input_cost_per_token: 1e-5,
334
+ output_cost_per_token: 3e-5,
335
+ litellm_provider: "openai",
336
+ mode: "chat"
337
+ },
338
+ "gpt-4-turbo-2024-04-09": {
339
+ input_cost_per_token: 1e-5,
340
+ output_cost_per_token: 3e-5,
341
+ litellm_provider: "openai",
342
+ mode: "chat"
343
+ },
344
+ "gpt-4-turbo-preview": {
345
+ input_cost_per_token: 1e-5,
346
+ output_cost_per_token: 3e-5,
347
+ litellm_provider: "openai",
348
+ mode: "chat"
349
+ },
350
+ "gpt-4.1": {
351
+ input_cost_per_token: 2e-6,
352
+ output_cost_per_token: 8e-6,
353
+ litellm_provider: "openai",
354
+ mode: "chat"
355
+ },
356
+ "gpt-4.1-2025-04-14": {
357
+ input_cost_per_token: 2e-6,
358
+ output_cost_per_token: 8e-6,
359
+ litellm_provider: "openai",
360
+ mode: "chat"
361
+ },
362
+ "gpt-4.1-mini": {
363
+ input_cost_per_token: 4e-7,
364
+ output_cost_per_token: 16e-7,
365
+ litellm_provider: "openai",
366
+ mode: "chat"
367
+ },
368
+ "gpt-4.1-mini-2025-04-14": {
369
+ input_cost_per_token: 4e-7,
370
+ output_cost_per_token: 16e-7,
371
+ litellm_provider: "openai",
372
+ mode: "chat"
373
+ },
374
+ "gpt-4.1-nano": {
375
+ input_cost_per_token: 1e-7,
376
+ output_cost_per_token: 4e-7,
377
+ litellm_provider: "openai",
378
+ mode: "chat"
379
+ },
380
+ "gpt-4.1-nano-2025-04-14": {
381
+ input_cost_per_token: 1e-7,
382
+ output_cost_per_token: 4e-7,
383
+ litellm_provider: "openai",
384
+ mode: "chat"
385
+ },
386
+ "gpt-4o": {
387
+ input_cost_per_token: 25e-7,
388
+ output_cost_per_token: 1e-5,
389
+ litellm_provider: "openai",
390
+ mode: "chat"
391
+ },
392
+ "gpt-4o-2024-05-13": {
393
+ input_cost_per_token: 5e-6,
394
+ output_cost_per_token: 15e-6,
395
+ litellm_provider: "openai",
396
+ mode: "chat"
397
+ },
398
+ "gpt-4o-2024-08-06": {
399
+ input_cost_per_token: 25e-7,
400
+ output_cost_per_token: 1e-5,
401
+ litellm_provider: "openai",
402
+ mode: "chat"
403
+ },
404
+ "gpt-4o-2024-11-20": {
405
+ input_cost_per_token: 25e-7,
406
+ output_cost_per_token: 1e-5,
407
+ litellm_provider: "openai",
408
+ mode: "chat"
409
+ },
410
+ "gpt-4o-audio-preview": {
411
+ input_cost_per_token: 25e-7,
412
+ output_cost_per_token: 1e-5,
413
+ litellm_provider: "openai",
414
+ mode: "chat"
415
+ },
416
+ "gpt-4o-audio-preview-2024-12-17": {
417
+ input_cost_per_token: 25e-7,
418
+ output_cost_per_token: 1e-5,
419
+ litellm_provider: "openai",
420
+ mode: "chat"
421
+ },
422
+ "gpt-4o-audio-preview-2025-06-03": {
423
+ input_cost_per_token: 25e-7,
424
+ output_cost_per_token: 1e-5,
425
+ litellm_provider: "openai",
426
+ mode: "chat"
427
+ },
428
+ "gpt-4o-mini": {
429
+ input_cost_per_token: 15e-8,
430
+ output_cost_per_token: 6e-7,
431
+ litellm_provider: "openai",
432
+ mode: "chat"
433
+ },
434
+ "gpt-4o-mini-2024-07-18": {
435
+ input_cost_per_token: 15e-8,
436
+ output_cost_per_token: 6e-7,
437
+ litellm_provider: "openai",
438
+ mode: "chat"
439
+ },
440
+ "gpt-4o-mini-audio-preview": {
441
+ input_cost_per_token: 15e-8,
442
+ output_cost_per_token: 6e-7,
443
+ litellm_provider: "openai",
444
+ mode: "chat"
445
+ },
446
+ "gpt-4o-mini-audio-preview-2024-12-17": {
447
+ input_cost_per_token: 15e-8,
448
+ output_cost_per_token: 6e-7,
449
+ litellm_provider: "openai",
450
+ mode: "chat"
451
+ },
452
+ "gpt-4o-mini-realtime-preview": {
453
+ input_cost_per_token: 6e-7,
454
+ output_cost_per_token: 24e-7,
455
+ litellm_provider: "openai",
456
+ mode: "chat"
457
+ },
458
+ "gpt-4o-mini-realtime-preview-2024-12-17": {
459
+ input_cost_per_token: 6e-7,
460
+ output_cost_per_token: 24e-7,
461
+ litellm_provider: "openai",
462
+ mode: "chat"
463
+ },
464
+ "gpt-4o-mini-search-preview": {
465
+ input_cost_per_token: 15e-8,
466
+ output_cost_per_token: 6e-7,
467
+ litellm_provider: "openai",
468
+ mode: "chat"
469
+ },
470
+ "gpt-4o-mini-search-preview-2025-03-11": {
471
+ input_cost_per_token: 15e-8,
472
+ output_cost_per_token: 6e-7,
473
+ litellm_provider: "openai",
474
+ mode: "chat"
475
+ },
476
+ "gpt-4o-realtime-preview": {
477
+ input_cost_per_token: 5e-6,
478
+ output_cost_per_token: 2e-5,
479
+ litellm_provider: "openai",
480
+ mode: "chat"
481
+ },
482
+ "gpt-4o-realtime-preview-2024-12-17": {
483
+ input_cost_per_token: 5e-6,
484
+ output_cost_per_token: 2e-5,
485
+ litellm_provider: "openai",
486
+ mode: "chat"
487
+ },
488
+ "gpt-4o-realtime-preview-2025-06-03": {
489
+ input_cost_per_token: 5e-6,
490
+ output_cost_per_token: 2e-5,
491
+ litellm_provider: "openai",
492
+ mode: "chat"
493
+ },
494
+ "gpt-4o-search-preview": {
495
+ input_cost_per_token: 25e-7,
496
+ output_cost_per_token: 1e-5,
497
+ litellm_provider: "openai",
498
+ mode: "chat"
499
+ },
500
+ "gpt-4o-search-preview-2025-03-11": {
501
+ input_cost_per_token: 25e-7,
502
+ output_cost_per_token: 1e-5,
503
+ litellm_provider: "openai",
504
+ mode: "chat"
505
+ },
506
+ "gpt-5": {
507
+ input_cost_per_token: 125e-8,
508
+ output_cost_per_token: 1e-5,
509
+ litellm_provider: "openai",
510
+ mode: "chat"
511
+ },
512
+ "gpt-5-2025-08-07": {
513
+ input_cost_per_token: 125e-8,
514
+ output_cost_per_token: 1e-5,
515
+ litellm_provider: "openai",
516
+ mode: "chat"
517
+ },
518
+ "gpt-5-chat": {
519
+ input_cost_per_token: 125e-8,
520
+ output_cost_per_token: 1e-5,
521
+ litellm_provider: "openai",
522
+ mode: "chat"
523
+ },
524
+ "gpt-5-chat-latest": {
525
+ input_cost_per_token: 125e-8,
526
+ output_cost_per_token: 1e-5,
527
+ litellm_provider: "openai",
528
+ mode: "chat"
529
+ },
530
+ "gpt-5-mini": {
531
+ input_cost_per_token: 25e-8,
532
+ output_cost_per_token: 2e-6,
533
+ litellm_provider: "openai",
534
+ mode: "chat"
535
+ },
536
+ "gpt-5-mini-2025-08-07": {
537
+ input_cost_per_token: 25e-8,
538
+ output_cost_per_token: 2e-6,
539
+ litellm_provider: "openai",
540
+ mode: "chat"
541
+ },
542
+ "gpt-5-nano": {
543
+ input_cost_per_token: 5e-8,
544
+ output_cost_per_token: 4e-7,
545
+ litellm_provider: "openai",
546
+ mode: "chat"
547
+ },
548
+ "gpt-5-nano-2025-08-07": {
549
+ input_cost_per_token: 5e-8,
550
+ output_cost_per_token: 4e-7,
551
+ litellm_provider: "openai",
552
+ mode: "chat"
553
+ },
554
+ "gpt-5-search-api": {
555
+ input_cost_per_token: 125e-8,
556
+ output_cost_per_token: 1e-5,
557
+ litellm_provider: "openai",
558
+ mode: "chat"
559
+ },
560
+ "gpt-5-search-api-2025-10-14": {
561
+ input_cost_per_token: 125e-8,
562
+ output_cost_per_token: 1e-5,
563
+ litellm_provider: "openai",
564
+ mode: "chat"
565
+ },
566
+ "gpt-5.1": {
567
+ input_cost_per_token: 125e-8,
568
+ output_cost_per_token: 1e-5,
569
+ litellm_provider: "openai",
570
+ mode: "chat"
571
+ },
572
+ "gpt-5.1-2025-11-13": {
573
+ input_cost_per_token: 125e-8,
574
+ output_cost_per_token: 1e-5,
575
+ litellm_provider: "openai",
576
+ mode: "chat"
577
+ },
578
+ "gpt-5.1-chat-latest": {
579
+ input_cost_per_token: 125e-8,
580
+ output_cost_per_token: 1e-5,
581
+ litellm_provider: "openai",
582
+ mode: "chat"
583
+ },
584
+ "gpt-5.2": {
585
+ input_cost_per_token: 175e-8,
586
+ output_cost_per_token: 14e-6,
587
+ litellm_provider: "openai",
588
+ mode: "chat"
589
+ },
590
+ "gpt-5.2-2025-12-11": {
591
+ input_cost_per_token: 175e-8,
592
+ output_cost_per_token: 14e-6,
593
+ litellm_provider: "openai",
594
+ mode: "chat"
595
+ },
596
+ "gpt-5.2-chat-latest": {
597
+ input_cost_per_token: 175e-8,
598
+ output_cost_per_token: 14e-6,
599
+ litellm_provider: "openai",
600
+ mode: "chat"
601
+ },
602
+ "gpt-5.3-chat-latest": {
603
+ input_cost_per_token: 175e-8,
604
+ output_cost_per_token: 14e-6,
605
+ litellm_provider: "openai",
606
+ mode: "chat"
607
+ },
608
+ "gpt-5.4": {
609
+ input_cost_per_token: 25e-7,
610
+ output_cost_per_token: 15e-6,
611
+ litellm_provider: "openai",
612
+ mode: "chat"
613
+ },
614
+ "gpt-5.4-2026-03-05": {
615
+ input_cost_per_token: 25e-7,
616
+ output_cost_per_token: 15e-6,
617
+ litellm_provider: "openai",
618
+ mode: "chat"
619
+ },
620
+ "gpt-5.4-mini": {
621
+ input_cost_per_token: 75e-8,
622
+ output_cost_per_token: 45e-7,
623
+ litellm_provider: "openai",
624
+ mode: "chat"
625
+ },
626
+ "gpt-5.4-mini-2026-03-17": {
627
+ input_cost_per_token: 75e-8,
628
+ output_cost_per_token: 45e-7,
629
+ litellm_provider: "openai",
630
+ mode: "chat"
631
+ },
632
+ "gpt-5.4-nano": {
633
+ input_cost_per_token: 2e-7,
634
+ output_cost_per_token: 125e-8,
635
+ litellm_provider: "openai",
636
+ mode: "chat"
637
+ },
638
+ "gpt-5.4-nano-2026-03-17": {
639
+ input_cost_per_token: 2e-7,
640
+ output_cost_per_token: 125e-8,
641
+ litellm_provider: "openai",
642
+ mode: "chat"
643
+ },
644
+ "gpt-5.5": {
645
+ input_cost_per_token: 5e-6,
646
+ output_cost_per_token: 3e-5,
647
+ litellm_provider: "openai",
648
+ mode: "chat"
649
+ },
650
+ "gpt-5.5-2026-04-23": {
651
+ input_cost_per_token: 5e-6,
652
+ output_cost_per_token: 3e-5,
653
+ litellm_provider: "openai",
654
+ mode: "chat"
655
+ },
656
+ "gpt-audio": {
657
+ input_cost_per_token: 25e-7,
658
+ output_cost_per_token: 1e-5,
659
+ litellm_provider: "openai",
660
+ mode: "chat"
661
+ },
662
+ "gpt-audio-1.5": {
663
+ input_cost_per_token: 25e-7,
664
+ output_cost_per_token: 1e-5,
665
+ litellm_provider: "openai",
666
+ mode: "chat"
667
+ },
668
+ "gpt-audio-2025-08-28": {
669
+ input_cost_per_token: 25e-7,
670
+ output_cost_per_token: 1e-5,
671
+ litellm_provider: "openai",
672
+ mode: "chat"
673
+ },
674
+ "gpt-audio-mini": {
675
+ input_cost_per_token: 6e-7,
676
+ output_cost_per_token: 24e-7,
677
+ litellm_provider: "openai",
678
+ mode: "chat"
679
+ },
680
+ "gpt-audio-mini-2025-10-06": {
681
+ input_cost_per_token: 6e-7,
682
+ output_cost_per_token: 24e-7,
683
+ litellm_provider: "openai",
684
+ mode: "chat"
685
+ },
686
+ "gpt-audio-mini-2025-12-15": {
687
+ input_cost_per_token: 6e-7,
688
+ output_cost_per_token: 24e-7,
689
+ litellm_provider: "openai",
690
+ mode: "chat"
691
+ },
692
+ "gpt-realtime": {
693
+ input_cost_per_token: 4e-6,
694
+ output_cost_per_token: 16e-6,
695
+ litellm_provider: "openai",
696
+ mode: "chat"
697
+ },
698
+ "gpt-realtime-1.5": {
699
+ input_cost_per_token: 4e-6,
700
+ output_cost_per_token: 16e-6,
701
+ litellm_provider: "openai",
702
+ mode: "chat"
703
+ },
704
+ "gpt-realtime-2": {
705
+ input_cost_per_token: 4e-6,
706
+ output_cost_per_token: 16e-6,
707
+ litellm_provider: "openai",
708
+ mode: "chat"
709
+ },
710
+ "gpt-realtime-2025-08-28": {
711
+ input_cost_per_token: 4e-6,
712
+ output_cost_per_token: 16e-6,
713
+ litellm_provider: "openai",
714
+ mode: "chat"
715
+ },
716
+ "gpt-realtime-mini": {
717
+ input_cost_per_token: 6e-7,
718
+ output_cost_per_token: 24e-7,
719
+ litellm_provider: "openai",
720
+ mode: "chat"
721
+ },
722
+ "gpt-realtime-mini-2025-10-06": {
723
+ input_cost_per_token: 6e-7,
724
+ output_cost_per_token: 24e-7,
725
+ litellm_provider: "openai",
726
+ mode: "chat"
727
+ },
728
+ "gpt-realtime-mini-2025-12-15": {
729
+ input_cost_per_token: 6e-7,
730
+ output_cost_per_token: 24e-7,
731
+ litellm_provider: "openai",
732
+ mode: "chat"
733
+ },
734
+ o1: {
735
+ input_cost_per_token: 15e-6,
736
+ output_cost_per_token: 6e-5,
737
+ litellm_provider: "openai",
738
+ mode: "chat"
739
+ },
740
+ "o1-2024-12-17": {
741
+ input_cost_per_token: 15e-6,
742
+ output_cost_per_token: 6e-5,
743
+ litellm_provider: "openai",
744
+ mode: "chat"
745
+ },
746
+ o3: {
747
+ input_cost_per_token: 2e-6,
748
+ output_cost_per_token: 8e-6,
749
+ litellm_provider: "openai",
750
+ mode: "chat"
751
+ },
752
+ "o3-2025-04-16": {
753
+ input_cost_per_token: 2e-6,
754
+ output_cost_per_token: 8e-6,
755
+ litellm_provider: "openai",
756
+ mode: "chat"
757
+ },
758
+ "o3-mini": {
759
+ input_cost_per_token: 11e-7,
760
+ output_cost_per_token: 44e-7,
761
+ litellm_provider: "openai",
762
+ mode: "chat"
763
+ },
764
+ "o3-mini-2025-01-31": {
765
+ input_cost_per_token: 11e-7,
766
+ output_cost_per_token: 44e-7,
767
+ litellm_provider: "openai",
768
+ mode: "chat"
769
+ },
770
+ "o4-mini": {
771
+ input_cost_per_token: 11e-7,
772
+ output_cost_per_token: 44e-7,
773
+ litellm_provider: "openai",
774
+ mode: "chat"
775
+ },
776
+ "o4-mini-2025-04-16": {
777
+ input_cost_per_token: 11e-7,
778
+ output_cost_per_token: 44e-7,
779
+ litellm_provider: "openai",
780
+ mode: "chat"
781
+ },
782
+ "text-embedding-3-large": {
783
+ input_cost_per_token: 13e-8,
784
+ output_cost_per_token: 0,
785
+ litellm_provider: "openai",
786
+ mode: "embedding"
787
+ },
788
+ "text-embedding-3-small": {
789
+ input_cost_per_token: 2e-8,
790
+ output_cost_per_token: 0,
791
+ litellm_provider: "openai",
792
+ mode: "embedding"
793
+ },
794
+ "text-embedding-ada-002": {
795
+ input_cost_per_token: 1e-7,
796
+ output_cost_per_token: 0,
797
+ litellm_provider: "openai",
798
+ mode: "embedding"
799
+ },
800
+ "text-embedding-ada-002-v2": {
801
+ input_cost_per_token: 1e-7,
802
+ output_cost_per_token: 0,
803
+ litellm_provider: "openai",
804
+ mode: "embedding"
805
+ }
806
+ };
807
+
808
+ // src/pricing.ts
809
+ var COST_MAP = cost_map_default;
810
+ function bareModel(model) {
811
+ const m = model.trim();
812
+ const slash = m.lastIndexOf("/");
813
+ return slash === -1 ? m : m.slice(slash + 1);
814
+ }
815
+ function bothFinite(a, b) {
816
+ return typeof a === "number" && typeof b === "number" && Number.isFinite(a) && Number.isFinite(b);
817
+ }
818
+ function resolvePrice(model, overrides) {
819
+ const bare = bareModel(model);
820
+ if (overrides) {
821
+ const ov = overrides[bare] ?? overrides[model.trim()];
822
+ if (ov !== void 0) {
823
+ if (bothFinite(ov.inputCostPerToken, ov.outputCostPerToken)) {
824
+ return {
825
+ inputCostPerToken: ov.inputCostPerToken,
826
+ outputCostPerToken: ov.outputCostPerToken,
827
+ source: "override"
828
+ };
829
+ }
830
+ return null;
831
+ }
832
+ }
833
+ const entry = COST_MAP[bare] ?? COST_MAP[model.trim()];
834
+ if (!entry) return null;
835
+ const input = entry.input_cost_per_token;
836
+ const output = entry.output_cost_per_token;
837
+ if (!bothFinite(input, output)) return null;
838
+ return {
839
+ inputCostPerToken: input,
840
+ outputCostPerToken: output,
841
+ source: "cost_map"
842
+ };
843
+ }
844
+ function priceTokens(priced, promptTokens, completionTokens) {
845
+ const p = Math.max(0, promptTokens);
846
+ const c = Math.max(0, completionTokens);
847
+ const cost = p * priced.inputCostPerToken + c * priced.outputCostPerToken;
848
+ if (!Number.isFinite(cost)) {
849
+ throw new Error("Non-finite LLM cost \u2014 pricing entry is invalid");
850
+ }
851
+ return Math.max(0, cost);
852
+ }
853
+
854
+ // src/guard.ts
855
+ var EPS = 1e-12;
856
+ var BudgetGuard = class {
857
+ limitUsd;
858
+ spentUsd = 0;
859
+ priceOverrides;
860
+ failClosed;
861
+ onBlock;
862
+ /** Cost of the most recent priced call, used to predict the next one. */
863
+ lastCost = 0;
864
+ /**
865
+ * @param limitUsd the spend ceiling, in USD. `0` blocks the very first call.
866
+ */
867
+ constructor(limitUsd, options = {}) {
868
+ if (!Number.isFinite(limitUsd) || limitUsd < 0) {
869
+ throw new RangeError(
870
+ `limitUsd must be a finite, non-negative number, got ${limitUsd}`
871
+ );
872
+ }
873
+ this.limitUsd = limitUsd;
874
+ this.priceOverrides = options.priceOverrides;
875
+ this.failClosed = options.failClosed ?? true;
876
+ this.onBlock = options.onBlock ?? defaultOnBlock;
877
+ }
878
+ /**
879
+ * Throw {@link BudgetExceeded} if the next call would cross the ceiling.
880
+ *
881
+ * Call this immediately before each LLM request. The "next call" is estimated
882
+ * from the last recorded call's cost (override with `estimatedNextCost`); the
883
+ * first call is always allowed unless the ceiling is already met. A check on
884
+ * the running total catches an overshoot if the estimate was too low.
885
+ */
886
+ check(estimatedNextCost) {
887
+ const estimate = estimatedNextCost === void 0 ? this.lastCost : Math.max(0, estimatedNextCost);
888
+ const projected = this.spentUsd + estimate;
889
+ if (this.spentUsd > this.limitUsd - EPS || projected > this.limitUsd + EPS) {
890
+ this.onBlock(this.spentUsd, this.limitUsd);
891
+ throw new BudgetExceeded(this.spentUsd, this.limitUsd);
892
+ }
893
+ }
894
+ /**
895
+ * Price one response's tokens offline and add the cost to the total.
896
+ *
897
+ * Returns the USD cost of this call. If the model is unpriceable and no `price`
898
+ * is given, behaviour depends on `failClosed`: warn + throw (default), or
899
+ * warn + skip accrual.
900
+ */
901
+ record(model, promptTokens, completionTokens, options = {}) {
902
+ let overrides = this.priceOverrides;
903
+ if (options.price !== void 0) {
904
+ overrides = { ...overrides ?? {}, [model]: options.price };
905
+ }
906
+ const priced = resolvePrice(model, overrides);
907
+ if (priced === null) {
908
+ console.warn(
909
+ `Cannot price model '${model}': not in the bundled cost map and no manual price given. The budget guard cannot enforce a ceiling on spend it cannot measure \u2014 pass { price } or set it in priceOverrides.`
910
+ );
911
+ if (this.failClosed) {
912
+ throw new UnpriceableModelError(model);
913
+ }
914
+ return 0;
915
+ }
916
+ const cost = priceTokens(priced, promptTokens, completionTokens);
917
+ this.spentUsd += cost;
918
+ if (this.spentUsd - this.limitUsd > 0 && this.spentUsd - this.limitUsd < EPS) {
919
+ this.spentUsd = this.limitUsd;
920
+ }
921
+ this.lastCost = cost;
922
+ return cost;
923
+ }
924
+ /** USD left before the ceiling (never negative). */
925
+ get remainingUsd() {
926
+ return Math.max(0, this.limitUsd - this.spentUsd);
927
+ }
928
+ };
929
+ function defaultOnBlock(spentUsd, limitUsd) {
930
+ console.error(
931
+ `BUDGET EXCEEDED \u2014 call blocked
932
+ spent so far: $${spentUsd.toFixed(6)} | ceiling: $${limitUsd.toFixed(6)}
933
+ The next call would cross your budget; floe-guard stopped your agent before it ran.`
934
+ );
935
+ }
936
+
937
+ // src/middleware.ts
938
+ function budgetGuardMiddleware(guard) {
939
+ return {
940
+ async wrapGenerate({ doGenerate, model }) {
941
+ guard.check();
942
+ const result = await doGenerate();
943
+ guard.record(
944
+ model.modelId,
945
+ result.usage.promptTokens,
946
+ result.usage.completionTokens
947
+ );
948
+ return result;
949
+ },
950
+ async wrapStream({ doStream, model }) {
951
+ guard.check();
952
+ const { stream, ...rest } = await doStream();
953
+ const guarded = stream.pipeThrough(
954
+ new TransformStream({
955
+ transform(chunk, controller) {
956
+ if (chunk.type === "finish") {
957
+ guard.record(
958
+ model.modelId,
959
+ chunk.usage.promptTokens,
960
+ chunk.usage.completionTokens
961
+ );
962
+ }
963
+ controller.enqueue(chunk);
964
+ }
965
+ })
966
+ );
967
+ return { stream: guarded, ...rest };
968
+ }
969
+ };
970
+ }
971
+ // Annotate the CommonJS export names for ESM import in node:
972
+ 0 && (module.exports = {
973
+ BudgetExceeded,
974
+ BudgetGuard,
975
+ FloeGuardError,
976
+ UnpriceableModelError,
977
+ budgetGuardMiddleware,
978
+ priceTokens,
979
+ pricing,
980
+ resolvePrice
981
+ });
982
+ //# sourceMappingURL=index.cjs.map