// Shared cost-calculation helper for the provider abstraction. // // Each provider knows two things: // 1. Its pricing table (per-1M-token rates per model). // 2. How to map its native usage shape into the normalized // { inputTokens, outputTokens, thinkingTokens, totalTokens } shape. // // This module then turns (rates, normalized usage) → the cost record // the rest of the app already understands. Same shape gemini-helpers // `calcCost` produces, so dashboards / logs don't care which provider // was used. // Format a normalized usage object against a per-model rate table into // the shared cost record. `rates` is { input, output, thinking? } in // USD per 1M tokens; `usage` is { inputTokens, outputTokens, // thinkingTokens, totalTokens } counts. export function formatCost(rates, usage) { const inputTokens = usage.inputTokens || 0; const outputTokens = usage.outputTokens || 0; const thinkingTokens = usage.thinkingTokens || 0; const thinkingRate = rates.thinking != null ? rates.thinking : rates.output; const inputCost = (inputTokens / 1_000_000) * rates.input; const outputCost = (outputTokens / 1_000_000) * rates.output; const thinkingCost = (thinkingTokens / 1_000_000) * thinkingRate; const totalCost = inputCost + outputCost + thinkingCost; return { inputTokens, outputTokens, thinkingTokens, totalTokens: usage.totalTokens || (inputTokens + outputTokens + thinkingTokens), inputCost: inputCost.toFixed(6), outputCost: outputCost.toFixed(6), thinkingCost: thinkingCost.toFixed(6), totalCost: totalCost.toFixed(6), totalCostDisplay: totalCost < 0.01 ? `$${(totalCost * 100).toFixed(3)}¢` : `$${totalCost.toFixed(4)}`, }; } // Look up rates for a model in a provider's pricing table, falling back // to the table's "default" row. Each provider defines its own table. export function ratesFor(pricingTable, model) { return pricingTable[model] || pricingTable["default"] || { input: 0, output: 0 }; } // Zero-cost record — used by providers that don't charge (Ollama, // local, openai-compatible without a known pricing table). export function zeroCost(usage = {}) { const inputTokens = usage.inputTokens || 0; const outputTokens = usage.outputTokens || 0; const thinkingTokens = usage.thinkingTokens || 0; return { inputTokens, outputTokens, thinkingTokens, totalTokens: usage.totalTokens || (inputTokens + outputTokens + thinkingTokens), inputCost: "0.000000", outputCost: "0.000000", thinkingCost: "0.000000", totalCost: "0.000000", totalCostDisplay: "$0.0000", }; }