/** * Credit Ledger — single source of truth for LLM spend across the ecosystem. * * Tracks per-provider, per-model spend with budgets, rate limits, and * threshold events. Persistence-agnostic: holds state in memory, serializes * via snapshot()/restore() for any storage backend (D1, KV, R2, etc.). */ import type { Logger } from './logger.js'; export type ThresholdTier = 'warning' | 'critical' | 'emergency'; export type DepletionTier = 'depletion_warning' | 'depletion_critical' | 'depletion_emergency'; /** Timestamped spend entry for burn rate calculation. */ export interface SpendEntry { timestamp: number; provider: string; cost: number; } /** Burn rate over a rolling window. */ export interface BurnRate { costPerHour: number; costPerDay: number; windowMs: number; sampleCount: number; } /** Projected depletion estimate for a provider. */ export interface DepletionEstimate { remainingBudget: number; burnRate: BurnRate; projectedDepletionDate: Date | null; daysRemaining: number | null; } /** Windowed spend summary for a provider. */ export interface SpendSummary { provider: string; spend: number; requestCount: number; inputTokens: number; outputTokens: number; windowMs: number; } export interface RateLimitWindow { used: number; limit: number; windowStart: number; } export type RateLimitDimension = 'rpm' | 'rpd' | 'tpm' | 'tpd'; export interface ModelAccumulator { spend: number; inputTokens: number; outputTokens: number; requestCount: number; lastRecordedAt: number; } export interface ProviderAccumulator extends ModelAccumulator { models: Record; budget: number | null; rateLimits: Partial>; } export interface BudgetConfig { provider: string; model?: string; monthlyBudget?: number; rateLimits?: Partial>; } export interface ThresholdConfig { warning: number; critical: number; emergency: number; } export interface ThresholdEvent { type: 'threshold_crossed'; provider: string; model?: string; tier: ThresholdTier; spend: number; budget: number; utilizationPct: number; } export interface DepletionEvent { type: 'depletion_projected'; provider: string; tier: DepletionTier; daysRemaining: number; projectedDepletionDate: Date; burnRate: BurnRate; } export type LedgerEvent = ThresholdEvent | DepletionEvent; export type LedgerListener = (event: LedgerEvent) => void; export interface RateLimitCheck { allowed: boolean; used: number; limit: number; } export interface CreditLedgerSnapshot { version: 1; periodStart: number; providers: Record; rateLimits: Partial>; }>; thresholds: ThresholdConfig; budgets: BudgetConfig[]; exportedAt: number; /** Timestamped spend entries for burn rate calculation. Optional for backward compat. */ spendHistory?: SpendEntry[]; } export declare class CreditLedger { private providers; private thresholds; private budgets; private listeners; private periodStart; private lastFiredTier; private lastFiredDepletionTier; private spendHistory; private ringBufferSize; private logger; constructor(config?: { thresholds?: Partial; budgets?: BudgetConfig[]; ringBufferSize?: number; logger?: Logger; }); record(provider: string, model: string, cost: number, inputTokens: number, outputTokens: number): void; setBudget(config: BudgetConfig): void; removeBudget(provider: string, model?: string): void; remainingBalance(provider: string, model?: string): number | null; utilizationPct(provider: string, model?: string): number; getProviderAccumulator(provider: string): ProviderAccumulator | undefined; getModelAccumulator(provider: string, model: string): ModelAccumulator | undefined; totalSpend(): number; breakdown(): Record; /** * Calculate burn rate for a provider over a rolling window. * Default window: 24 hours. */ getBurnRate(provider: string, windowMs?: number): BurnRate; /** * Project when a provider's budget will be depleted at the current burn rate. * Returns null if the provider has no budget or no spend history. */ getDepletionEstimate(provider: string, windowMs?: number): DepletionEstimate | null; /** * Get windowed spend summary for a provider. */ getSpendSummary(provider: string, windowMs: number): SpendSummary; /** * Get spend breakdown for all providers over a window. */ getSpendBreakdown(windowMs: number): SpendSummary[]; checkRateLimit(provider: string, dimension: RateLimitDimension): RateLimitCheck; snapshot(): CreditLedgerSnapshot; restore(snapshot: CreditLedgerSnapshot): void; resetPeriod(): void; on(listener: LedgerListener): () => void; private getOrCreateProvider; private emit; } //# sourceMappingURL=credit-ledger.d.ts.map