UNPKG

claude-monitor

Version:

Real-time terminal monitoring tool for Claude AI token usage

111 lines 4.55 kB
import { CostMode } from '../types/index.js'; import { normalizeModelName } from '../types/index.js'; const FALLBACK_PRICING = { opus: { inputPricePerMillion: 15.0, outputPricePerMillion: 75.0, cacheCreationPricePerMillion: 18.75, cacheReadPricePerMillion: 1.5, }, sonnet: { inputPricePerMillion: 3.0, outputPricePerMillion: 15.0, cacheCreationPricePerMillion: 3.75, cacheReadPricePerMillion: 0.3, }, haiku: { inputPricePerMillion: 0.25, outputPricePerMillion: 1.25, cacheCreationPricePerMillion: 0.3, cacheReadPricePerMillion: 0.03, }, }; export class PricingCalculator { pricing; costCache = new Map(); constructor(customPricing) { this.pricing = customPricing || { 'claude-3-opus': FALLBACK_PRICING.opus, 'claude-3-sonnet': FALLBACK_PRICING.sonnet, 'claude-3-haiku': FALLBACK_PRICING.haiku, 'claude-3-5-sonnet': FALLBACK_PRICING.sonnet, 'claude-3-5-haiku': FALLBACK_PRICING.haiku, 'claude-sonnet-4-20250514': FALLBACK_PRICING.sonnet, 'claude-opus-4-20250514': FALLBACK_PRICING.opus, }; } calculateCost(params) { const { model, inputTokens = 0, outputTokens = 0, cacheCreationTokens = 0, cacheReadTokens = 0, tokens, strict = false, } = params; if (model === '<synthetic>') { return 0.0; } const actualInputTokens = tokens?.inputTokens ?? inputTokens; const actualOutputTokens = tokens?.outputTokens ?? outputTokens; const actualCacheCreationTokens = tokens?.cacheCreationTokens ?? cacheCreationTokens; const actualCacheReadTokens = tokens?.cacheReadTokens ?? cacheReadTokens; const cacheKey = `${model}:${actualInputTokens}:${actualOutputTokens}:${actualCacheCreationTokens}:${actualCacheReadTokens}`; const cachedCost = this.costCache.get(cacheKey); if (cachedCost !== undefined) { return cachedCost; } const pricing = this.getPricingForModel(model, strict); const cost = (actualInputTokens / 1_000_000) * pricing.inputPricePerMillion + (actualOutputTokens / 1_000_000) * pricing.outputPricePerMillion + (actualCacheCreationTokens / 1_000_000) * pricing.cacheCreationPricePerMillion + (actualCacheReadTokens / 1_000_000) * pricing.cacheReadPricePerMillion; const roundedCost = Math.round(cost * 1_000_000) / 1_000_000; this.costCache.set(cacheKey, roundedCost); return roundedCost; } getPricingForModel(model, strict) { const normalized = normalizeModelName(model); if (normalized in this.pricing) { return this.pricing[normalized]; } if (model in this.pricing) { return this.pricing[model]; } if (strict) { throw new Error(`Unknown model: ${model}`); } const modelLower = model.toLowerCase(); if (modelLower.includes('opus')) { return FALLBACK_PRICING.opus; } if (modelLower.includes('haiku')) { return FALLBACK_PRICING.haiku; } return FALLBACK_PRICING.sonnet; } calculateCostForEntry(entryData, mode) { if (mode === CostMode.CACHED) { const costValue = entryData.costUSD ?? entryData.cost_usd; if (costValue !== null && costValue !== undefined) { return Number(costValue); } } const model = (entryData.model ?? entryData.Model); if (!model) { throw new Error("Missing 'model' key in entry data"); } const inputTokens = Number(entryData.inputTokens ?? entryData.input_tokens ?? 0); const outputTokens = Number(entryData.outputTokens ?? entryData.output_tokens ?? 0); const cacheCreationTokens = Number(entryData.cacheCreationInputTokens ?? entryData.cache_creation_tokens ?? 0); const cacheReadTokens = Number(entryData.cacheReadInputTokens ?? entryData.cache_read_input_tokens ?? entryData.cache_read_tokens ?? 0); return this.calculateCost({ model, inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, }); } clearCache() { this.costCache.clear(); } } export const defaultPricingCalculator = new PricingCalculator(); //# sourceMappingURL=pricing.js.map