@stackbilt/llm-providers 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/README.md +261 -0
- package/dist/errors.d.ts +79 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +183 -0
- package/dist/errors.js.map +1 -0
- package/dist/factory.d.ts +95 -0
- package/dist/factory.d.ts.map +1 -0
- package/dist/factory.js +418 -0
- package/dist/factory.js.map +1 -0
- package/dist/index.d.ts +137 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +263 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/anthropic.d.ts +38 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +378 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/base.d.ts +107 -0
- package/dist/providers/base.d.ts.map +1 -0
- package/dist/providers/base.js +230 -0
- package/dist/providers/base.js.map +1 -0
- package/dist/providers/cerebras.d.ts +30 -0
- package/dist/providers/cerebras.d.ts.map +1 -0
- package/dist/providers/cerebras.js +292 -0
- package/dist/providers/cerebras.js.map +1 -0
- package/dist/providers/cloudflare.d.ts +47 -0
- package/dist/providers/cloudflare.d.ts.map +1 -0
- package/dist/providers/cloudflare.js +544 -0
- package/dist/providers/cloudflare.js.map +1 -0
- package/dist/providers/groq.d.ts +30 -0
- package/dist/providers/groq.d.ts.map +1 -0
- package/dist/providers/groq.js +222 -0
- package/dist/providers/groq.js.map +1 -0
- package/dist/providers/openai.d.ts +36 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +331 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/types.d.ts +238 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/circuit-breaker.d.ts +111 -0
- package/dist/utils/circuit-breaker.d.ts.map +1 -0
- package/dist/utils/circuit-breaker.js +365 -0
- package/dist/utils/circuit-breaker.js.map +1 -0
- package/dist/utils/cost-tracker.d.ts +130 -0
- package/dist/utils/cost-tracker.d.ts.map +1 -0
- package/dist/utils/cost-tracker.js +272 -0
- package/dist/utils/cost-tracker.js.map +1 -0
- package/dist/utils/credit-ledger.d.ts +161 -0
- package/dist/utils/credit-ledger.d.ts.map +1 -0
- package/dist/utils/credit-ledger.js +463 -0
- package/dist/utils/credit-ledger.js.map +1 -0
- package/dist/utils/retry.d.ts +46 -0
- package/dist/utils/retry.d.ts.map +1 -0
- package/dist/utils/retry.js +125 -0
- package/dist/utils/retry.js.map +1 -0
- package/package.json +57 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cost Tracker
|
|
3
|
+
* Tracks and optimizes LLM usage costs across providers
|
|
4
|
+
*/
|
|
5
|
+
export class CostTracker {
|
|
6
|
+
providers = new Map();
|
|
7
|
+
config;
|
|
8
|
+
ledger;
|
|
9
|
+
constructor(config = {}, ledger) {
|
|
10
|
+
this.config = {
|
|
11
|
+
inputTokenCost: config.inputTokenCost ?? 0.001, // $0.001 per 1k tokens default
|
|
12
|
+
outputTokenCost: config.outputTokenCost ?? 0.002, // $0.002 per 1k tokens default
|
|
13
|
+
maxMonthlyCost: config.maxMonthlyCost,
|
|
14
|
+
alertThreshold: config.alertThreshold ?? 0.8 // 80% of max cost
|
|
15
|
+
};
|
|
16
|
+
this.ledger = ledger;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Calculate cost for a request
|
|
20
|
+
*/
|
|
21
|
+
calculateRequestCost(request, capabilities) {
|
|
22
|
+
const estimatedInputTokens = this.estimateInputTokens(request);
|
|
23
|
+
const estimatedOutputTokens = request.maxTokens || 1000;
|
|
24
|
+
const inputCost = (estimatedInputTokens / 1000) * capabilities.inputTokenCost;
|
|
25
|
+
const outputCost = (estimatedOutputTokens / 1000) * capabilities.outputTokenCost;
|
|
26
|
+
return inputCost + outputCost;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Track actual cost from response
|
|
30
|
+
*/
|
|
31
|
+
trackCost(provider, response) {
|
|
32
|
+
if (!response.usage)
|
|
33
|
+
return;
|
|
34
|
+
// Delegate to CreditLedger when present
|
|
35
|
+
if (this.ledger) {
|
|
36
|
+
this.ledger.record(provider, response.model || 'unknown', response.usage.cost || 0, response.usage.inputTokens, response.usage.outputTokens);
|
|
37
|
+
}
|
|
38
|
+
const entry = this.providers.get(provider) || this.createProviderEntry();
|
|
39
|
+
entry.totalCost += response.usage.cost || 0;
|
|
40
|
+
entry.requestCount++;
|
|
41
|
+
entry.inputTokens += response.usage.inputTokens;
|
|
42
|
+
entry.outputTokens += response.usage.outputTokens;
|
|
43
|
+
entry.lastRecordedAt = Date.now();
|
|
44
|
+
this.providers.set(provider, entry);
|
|
45
|
+
// Check cost alerts
|
|
46
|
+
this.checkCostAlerts(provider);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Get the attached CreditLedger (if any)
|
|
50
|
+
*/
|
|
51
|
+
getLedger() {
|
|
52
|
+
return this.ledger;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Get total cost across all providers
|
|
56
|
+
*/
|
|
57
|
+
getTotalCost() {
|
|
58
|
+
return this.total();
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get cost for specific provider
|
|
62
|
+
*/
|
|
63
|
+
getProviderCost(provider) {
|
|
64
|
+
return this.providers.get(provider)?.totalCost || 0;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get cost breakdown by provider
|
|
68
|
+
*/
|
|
69
|
+
getCostBreakdown() {
|
|
70
|
+
const breakdown = {};
|
|
71
|
+
for (const [provider, entry] of this.providers) {
|
|
72
|
+
breakdown[provider] = {
|
|
73
|
+
...entry,
|
|
74
|
+
cost: entry.totalCost,
|
|
75
|
+
requests: entry.requestCount,
|
|
76
|
+
tokens: {
|
|
77
|
+
input: entry.inputTokens,
|
|
78
|
+
output: entry.outputTokens
|
|
79
|
+
},
|
|
80
|
+
averageCostPerRequest: entry.requestCount > 0 ? entry.totalCost / entry.requestCount : 0
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
return breakdown;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Get a provider snapshot aligned with Workers usage reporting.
|
|
87
|
+
*/
|
|
88
|
+
breakdown() {
|
|
89
|
+
const snapshot = {};
|
|
90
|
+
for (const [provider, entry] of this.providers) {
|
|
91
|
+
snapshot[provider] = { ...entry };
|
|
92
|
+
}
|
|
93
|
+
return snapshot;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Get total cost across all providers.
|
|
97
|
+
*/
|
|
98
|
+
total() {
|
|
99
|
+
let sum = 0;
|
|
100
|
+
for (const entry of this.providers.values()) {
|
|
101
|
+
sum += entry.totalCost;
|
|
102
|
+
}
|
|
103
|
+
return sum;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Get most cost-effective provider for a request
|
|
107
|
+
*/
|
|
108
|
+
getMostCostEffectiveProvider(providers, request) {
|
|
109
|
+
let minCost = Infinity;
|
|
110
|
+
let bestProvider = '';
|
|
111
|
+
for (const [provider, capabilities] of Object.entries(providers)) {
|
|
112
|
+
const cost = this.calculateRequestCost(request, capabilities);
|
|
113
|
+
if (cost < minCost) {
|
|
114
|
+
minCost = cost;
|
|
115
|
+
bestProvider = provider;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return bestProvider;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Check if we're approaching cost limits
|
|
122
|
+
*/
|
|
123
|
+
shouldRouteBasedOnCost(provider) {
|
|
124
|
+
if (!this.config.maxMonthlyCost)
|
|
125
|
+
return false;
|
|
126
|
+
const currentCost = this.getProviderCost(provider);
|
|
127
|
+
const threshold = this.config.maxMonthlyCost * (this.config.alertThreshold || 0.8);
|
|
128
|
+
return currentCost >= threshold;
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Reset cost tracking (e.g., monthly reset)
|
|
132
|
+
*/
|
|
133
|
+
reset() {
|
|
134
|
+
this.providers.clear();
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Reset tracking for specific provider
|
|
138
|
+
*/
|
|
139
|
+
resetProvider(provider) {
|
|
140
|
+
this.providers.delete(provider);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Drain and reset provider tracking for periodic reporting.
|
|
144
|
+
*/
|
|
145
|
+
drain() {
|
|
146
|
+
const snapshot = this.breakdown();
|
|
147
|
+
this.providers.clear();
|
|
148
|
+
return snapshot;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Export cost data for analytics
|
|
152
|
+
*/
|
|
153
|
+
exportData() {
|
|
154
|
+
return {
|
|
155
|
+
totalCost: this.getTotalCost(),
|
|
156
|
+
breakdown: this.getCostBreakdown(),
|
|
157
|
+
period: {
|
|
158
|
+
start: Date.now() - 30 * 24 * 60 * 60 * 1000, // 30 days ago
|
|
159
|
+
end: Date.now()
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Estimate input tokens from request
|
|
165
|
+
*/
|
|
166
|
+
estimateInputTokens(request) {
|
|
167
|
+
// Rough estimation: 1 token ≈ 0.75 words ≈ 4 characters
|
|
168
|
+
let totalChars = 0;
|
|
169
|
+
// Count characters in messages
|
|
170
|
+
for (const message of request.messages) {
|
|
171
|
+
totalChars += message.content.length;
|
|
172
|
+
}
|
|
173
|
+
// Add system prompt if present
|
|
174
|
+
if (request.systemPrompt) {
|
|
175
|
+
totalChars += request.systemPrompt.length;
|
|
176
|
+
}
|
|
177
|
+
// Convert to tokens (rough approximation)
|
|
178
|
+
return Math.ceil(totalChars / 4);
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Check for cost alerts
|
|
182
|
+
*/
|
|
183
|
+
checkCostAlerts(provider) {
|
|
184
|
+
if (!this.config.maxMonthlyCost || !this.config.alertThreshold)
|
|
185
|
+
return;
|
|
186
|
+
const currentCost = this.getProviderCost(provider);
|
|
187
|
+
const alertThreshold = this.config.maxMonthlyCost * this.config.alertThreshold;
|
|
188
|
+
if (currentCost >= alertThreshold) {
|
|
189
|
+
console.warn(`[CostTracker] Cost alert for ${provider}: $${currentCost.toFixed(4)} (${((currentCost / this.config.maxMonthlyCost) * 100).toFixed(1)}% of limit)`);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
/**
|
|
193
|
+
* Update cost configuration
|
|
194
|
+
*/
|
|
195
|
+
updateConfig(config) {
|
|
196
|
+
this.config = { ...this.config, ...config };
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Get current configuration
|
|
200
|
+
*/
|
|
201
|
+
getConfig() {
|
|
202
|
+
return { ...this.config };
|
|
203
|
+
}
|
|
204
|
+
createProviderEntry() {
|
|
205
|
+
return {
|
|
206
|
+
totalCost: 0,
|
|
207
|
+
requestCount: 0,
|
|
208
|
+
inputTokens: 0,
|
|
209
|
+
outputTokens: 0,
|
|
210
|
+
lastRecordedAt: 0
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Default cost tracker instance
|
|
216
|
+
*/
|
|
217
|
+
export const defaultCostTracker = new CostTracker();
|
|
218
|
+
/**
|
|
219
|
+
* Cost optimization utilities
|
|
220
|
+
*/
|
|
221
|
+
export class CostOptimizer {
|
|
222
|
+
/**
|
|
223
|
+
* Choose optimal provider based on cost and performance
|
|
224
|
+
*/
|
|
225
|
+
static chooseOptimalProvider(providers, request, costTracker, performanceWeights = { cost: 0.5, latency: 0.3, quality: 0.2 }) {
|
|
226
|
+
let bestScore = -Infinity;
|
|
227
|
+
let bestProvider = '';
|
|
228
|
+
for (const [provider, capabilities] of Object.entries(providers)) {
|
|
229
|
+
const cost = costTracker.calculateRequestCost(request, capabilities);
|
|
230
|
+
// Normalize cost (lower is better)
|
|
231
|
+
const costScore = 1 / (1 + cost * 1000); // Scale cost for scoring
|
|
232
|
+
// Simple quality score based on model capabilities
|
|
233
|
+
const qualityScore = capabilities.maxContextLength / 100000; // Normalize context length
|
|
234
|
+
// Assume latency score (would be tracked from actual usage)
|
|
235
|
+
const latencyScore = 0.5; // Placeholder
|
|
236
|
+
const totalScore = costScore * performanceWeights.cost +
|
|
237
|
+
latencyScore * performanceWeights.latency +
|
|
238
|
+
qualityScore * performanceWeights.quality;
|
|
239
|
+
if (totalScore > bestScore) {
|
|
240
|
+
bestScore = totalScore;
|
|
241
|
+
bestProvider = provider;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return bestProvider;
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Suggest cost reduction strategies
|
|
248
|
+
*/
|
|
249
|
+
static suggestOptimizations(costBreakdown) {
|
|
250
|
+
const suggestions = [];
|
|
251
|
+
const totalCost = Object.values(costBreakdown).reduce((sum, p) => sum + p.cost, 0);
|
|
252
|
+
// Find most expensive provider
|
|
253
|
+
const mostExpensive = Object.entries(costBreakdown)
|
|
254
|
+
.sort(([, a], [, b]) => b.cost - a.cost)[0];
|
|
255
|
+
if (mostExpensive && mostExpensive[1].cost > totalCost * 0.5) {
|
|
256
|
+
suggestions.push(`Consider reducing usage of ${mostExpensive[0]} (${((mostExpensive[1].cost / totalCost) * 100).toFixed(1)}% of total cost)`);
|
|
257
|
+
}
|
|
258
|
+
// Check for high per-request costs
|
|
259
|
+
for (const [provider, data] of Object.entries(costBreakdown)) {
|
|
260
|
+
if (data.averageCostPerRequest > 0.01) { // $0.01 per request
|
|
261
|
+
suggestions.push(`${provider} has high per-request cost ($${(data.averageCostPerRequest).toFixed(4)}). Consider using smaller models or reducing max_tokens.`);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
// Suggest batch processing if many small requests
|
|
265
|
+
const totalRequests = Object.values(costBreakdown).reduce((sum, p) => sum + p.requests, 0);
|
|
266
|
+
if (totalRequests > 1000 && totalCost / totalRequests < 0.001) {
|
|
267
|
+
suggestions.push('Consider batch processing for small requests to reduce overhead costs.');
|
|
268
|
+
}
|
|
269
|
+
return suggestions;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
//# sourceMappingURL=cost-tracker.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cost-tracker.js","sourceRoot":"","sources":["../../src/utils/cost-tracker.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Credit Ledger — single source of truth for LLM spend across the ecosystem.
|
|
3
|
+
*
|
|
4
|
+
* Tracks per-provider, per-model spend with budgets, rate limits, and
|
|
5
|
+
* threshold events. Persistence-agnostic: holds state in memory, serializes
|
|
6
|
+
* via snapshot()/restore() for any storage backend (D1, KV, R2, etc.).
|
|
7
|
+
*/
|
|
8
|
+
export type ThresholdTier = 'warning' | 'critical' | 'emergency';
|
|
9
|
+
export type DepletionTier = 'depletion_warning' | 'depletion_critical' | 'depletion_emergency';
|
|
10
|
+
/** Timestamped spend entry for burn rate calculation. */
|
|
11
|
+
export interface SpendEntry {
|
|
12
|
+
timestamp: number;
|
|
13
|
+
provider: string;
|
|
14
|
+
cost: number;
|
|
15
|
+
}
|
|
16
|
+
/** Burn rate over a rolling window. */
|
|
17
|
+
export interface BurnRate {
|
|
18
|
+
costPerHour: number;
|
|
19
|
+
costPerDay: number;
|
|
20
|
+
windowMs: number;
|
|
21
|
+
sampleCount: number;
|
|
22
|
+
}
|
|
23
|
+
/** Projected depletion estimate for a provider. */
|
|
24
|
+
export interface DepletionEstimate {
|
|
25
|
+
remainingBudget: number;
|
|
26
|
+
burnRate: BurnRate;
|
|
27
|
+
projectedDepletionDate: Date | null;
|
|
28
|
+
daysRemaining: number | null;
|
|
29
|
+
}
|
|
30
|
+
/** Windowed spend summary for a provider. */
|
|
31
|
+
export interface SpendSummary {
|
|
32
|
+
provider: string;
|
|
33
|
+
spend: number;
|
|
34
|
+
requestCount: number;
|
|
35
|
+
inputTokens: number;
|
|
36
|
+
outputTokens: number;
|
|
37
|
+
windowMs: number;
|
|
38
|
+
}
|
|
39
|
+
export interface RateLimitWindow {
|
|
40
|
+
used: number;
|
|
41
|
+
limit: number;
|
|
42
|
+
windowStart: number;
|
|
43
|
+
}
|
|
44
|
+
export type RateLimitDimension = 'rpm' | 'rpd' | 'tpm' | 'tpd';
|
|
45
|
+
export interface ModelAccumulator {
|
|
46
|
+
spend: number;
|
|
47
|
+
inputTokens: number;
|
|
48
|
+
outputTokens: number;
|
|
49
|
+
requestCount: number;
|
|
50
|
+
lastRecordedAt: number;
|
|
51
|
+
}
|
|
52
|
+
export interface ProviderAccumulator extends ModelAccumulator {
|
|
53
|
+
models: Record<string, ModelAccumulator>;
|
|
54
|
+
budget: number | null;
|
|
55
|
+
rateLimits: Partial<Record<RateLimitDimension, RateLimitWindow>>;
|
|
56
|
+
}
|
|
57
|
+
export interface BudgetConfig {
|
|
58
|
+
provider: string;
|
|
59
|
+
model?: string;
|
|
60
|
+
monthlyBudget?: number;
|
|
61
|
+
rateLimits?: Partial<Record<RateLimitDimension, number>>;
|
|
62
|
+
}
|
|
63
|
+
export interface ThresholdConfig {
|
|
64
|
+
warning: number;
|
|
65
|
+
critical: number;
|
|
66
|
+
emergency: number;
|
|
67
|
+
}
|
|
68
|
+
export interface ThresholdEvent {
|
|
69
|
+
type: 'threshold_crossed';
|
|
70
|
+
provider: string;
|
|
71
|
+
model?: string;
|
|
72
|
+
tier: ThresholdTier;
|
|
73
|
+
spend: number;
|
|
74
|
+
budget: number;
|
|
75
|
+
utilizationPct: number;
|
|
76
|
+
}
|
|
77
|
+
export interface DepletionEvent {
|
|
78
|
+
type: 'depletion_projected';
|
|
79
|
+
provider: string;
|
|
80
|
+
tier: DepletionTier;
|
|
81
|
+
daysRemaining: number;
|
|
82
|
+
projectedDepletionDate: Date;
|
|
83
|
+
burnRate: BurnRate;
|
|
84
|
+
}
|
|
85
|
+
export type LedgerEvent = ThresholdEvent | DepletionEvent;
|
|
86
|
+
export type LedgerListener = (event: LedgerEvent) => void;
|
|
87
|
+
export interface RateLimitCheck {
|
|
88
|
+
allowed: boolean;
|
|
89
|
+
used: number;
|
|
90
|
+
limit: number;
|
|
91
|
+
}
|
|
92
|
+
export interface CreditLedgerSnapshot {
|
|
93
|
+
version: 1;
|
|
94
|
+
periodStart: number;
|
|
95
|
+
providers: Record<string, {
|
|
96
|
+
spend: number;
|
|
97
|
+
inputTokens: number;
|
|
98
|
+
outputTokens: number;
|
|
99
|
+
requestCount: number;
|
|
100
|
+
lastRecordedAt: number;
|
|
101
|
+
budget: number | null;
|
|
102
|
+
models: Record<string, ModelAccumulator>;
|
|
103
|
+
rateLimits: Partial<Record<RateLimitDimension, RateLimitWindow>>;
|
|
104
|
+
}>;
|
|
105
|
+
thresholds: ThresholdConfig;
|
|
106
|
+
budgets: BudgetConfig[];
|
|
107
|
+
exportedAt: number;
|
|
108
|
+
/** Timestamped spend entries for burn rate calculation. Optional for backward compat. */
|
|
109
|
+
spendHistory?: SpendEntry[];
|
|
110
|
+
}
|
|
111
|
+
export declare class CreditLedger {
|
|
112
|
+
private providers;
|
|
113
|
+
private thresholds;
|
|
114
|
+
private budgets;
|
|
115
|
+
private listeners;
|
|
116
|
+
private periodStart;
|
|
117
|
+
private lastFiredTier;
|
|
118
|
+
private lastFiredDepletionTier;
|
|
119
|
+
private spendHistory;
|
|
120
|
+
private ringBufferSize;
|
|
121
|
+
constructor(config?: {
|
|
122
|
+
thresholds?: Partial<ThresholdConfig>;
|
|
123
|
+
budgets?: BudgetConfig[];
|
|
124
|
+
ringBufferSize?: number;
|
|
125
|
+
});
|
|
126
|
+
record(provider: string, model: string, cost: number, inputTokens: number, outputTokens: number): void;
|
|
127
|
+
setBudget(config: BudgetConfig): void;
|
|
128
|
+
removeBudget(provider: string, model?: string): void;
|
|
129
|
+
remainingBalance(provider: string, model?: string): number | null;
|
|
130
|
+
utilizationPct(provider: string, model?: string): number;
|
|
131
|
+
getProviderAccumulator(provider: string): ProviderAccumulator | undefined;
|
|
132
|
+
getModelAccumulator(provider: string, model: string): ModelAccumulator | undefined;
|
|
133
|
+
totalSpend(): number;
|
|
134
|
+
breakdown(): Record<string, ProviderAccumulator>;
|
|
135
|
+
/**
|
|
136
|
+
* Calculate burn rate for a provider over a rolling window.
|
|
137
|
+
* Default window: 24 hours.
|
|
138
|
+
*/
|
|
139
|
+
getBurnRate(provider: string, windowMs?: number): BurnRate;
|
|
140
|
+
/**
|
|
141
|
+
* Project when a provider's budget will be depleted at the current burn rate.
|
|
142
|
+
* Returns null if the provider has no budget or no spend history.
|
|
143
|
+
*/
|
|
144
|
+
getDepletionEstimate(provider: string, windowMs?: number): DepletionEstimate | null;
|
|
145
|
+
/**
|
|
146
|
+
* Get windowed spend summary for a provider.
|
|
147
|
+
*/
|
|
148
|
+
getSpendSummary(provider: string, windowMs: number): SpendSummary;
|
|
149
|
+
/**
|
|
150
|
+
* Get spend breakdown for all providers over a window.
|
|
151
|
+
*/
|
|
152
|
+
getSpendBreakdown(windowMs: number): SpendSummary[];
|
|
153
|
+
checkRateLimit(provider: string, dimension: RateLimitDimension): RateLimitCheck;
|
|
154
|
+
snapshot(): CreditLedgerSnapshot;
|
|
155
|
+
restore(snapshot: CreditLedgerSnapshot): void;
|
|
156
|
+
resetPeriod(): void;
|
|
157
|
+
on(listener: LedgerListener): () => void;
|
|
158
|
+
private getOrCreateProvider;
|
|
159
|
+
private emit;
|
|
160
|
+
}
|
|
161
|
+
//# sourceMappingURL=credit-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"credit-ledger.d.ts","sourceRoot":"","sources":["../../src/utils/credit-ledger.ts"],"names":[],"mappings":"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"}
|