SPB Git forge

spb/rareindex

Public
54commits 1branches 0releases
7.1 MBsize
maindefault branch
10 days agolast push
TypeScript 61.9% HTML 37.2% SQL 0.7%
2.5 KB · 56 lines typescript
Raw Blame History
1import type { Usage } from './types.js';23/**4 * List prices in USD per 1M tokens (first-party API rates, cached 2026-06). Used only for the5 * cost ledger (§169); billing truth lives with the provider. Update when prices change.6 */7export interface ModelPrice {8  input: number;9  output: number;10  /** cache read multiplier vs input (Anthropic: 0.1) */11  cacheRead: number;12  /** cache write multiplier vs input (Anthropic: 1.25) */13  cacheWrite: number;14}1516export const PRICE_TABLE: Record<string, ModelPrice> = {17  'claude-opus-5': { input: 5, output: 25, cacheRead: 0.1, cacheWrite: 1.25 },18  'claude-opus-4-8': { input: 5, output: 25, cacheRead: 0.1, cacheWrite: 1.25 },19  'claude-sonnet-5': { input: 2, output: 10, cacheRead: 0.1, cacheWrite: 1.25 },20  'claude-sonnet-4-6': { input: 3, output: 15, cacheRead: 0.1, cacheWrite: 1.25 },21  'claude-haiku-4-5': { input: 1, output: 5, cacheRead: 0.1, cacheWrite: 1.25 },22  'claude-fable-5-1': { input: 10, output: 50, cacheRead: 0.1, cacheWrite: 1.25 },23  // OpenAI (approximate list prices; verify before relying on them)24  'gpt-5': { input: 1.25, output: 10, cacheRead: 0.1, cacheWrite: 1 },25  'gpt-5-mini': { input: 0.25, output: 2, cacheRead: 0.1, cacheWrite: 1 },26  'gpt-4o-mini': { input: 0.15, output: 0.6, cacheRead: 0.5, cacheWrite: 1 },27  'text-embedding-3-small': { input: 0.02, output: 0, cacheRead: 1, cacheWrite: 1 },28  'text-embedding-3-large': { input: 0.13, output: 0, cacheRead: 1, cacheWrite: 1 },29};3031/** Local/self-hosted models cost nothing at the API layer. */32export function priceFor(model: string): ModelPrice | null {33  if (PRICE_TABLE[model]) return PRICE_TABLE[model]!;34  const base = Object.keys(PRICE_TABLE).find((k) => model.startsWith(k));35  return base ? PRICE_TABLE[base]! : null;36}3738export function estimateUsd(model: string, usage: Usage): number {39  const p = priceFor(model);40  if (!p) return 0;41  const usd =42    (usage.inputTokens * p.input + usage.outputTokens * p.output + usage.cacheReadTokens * p.input * p.cacheRead + usage.cacheWriteTokens * p.input * p.cacheWrite) / 1_000_000;43  return Math.round(usd * 1e6) / 1e6;44}4546export const ZERO_USAGE: Usage = { inputTokens: 0, outputTokens: 0, cacheReadTokens: 0, cacheWriteTokens: 0 };4748export function addUsage(a: Usage, b: Usage): Usage {49  return {50    inputTokens: a.inputTokens + b.inputTokens,51    outputTokens: a.outputTokens + b.outputTokens,52    cacheReadTokens: a.cacheReadTokens + b.cacheReadTokens,53    cacheWriteTokens: a.cacheWriteTokens + b.cacheWriteTokens,54  };55}56