// Author: Simon-Pierre Boucher // Contact: contact@spboucher.ai // Project: chat.spboucher.ai import type { ORModelRaw } from "./schemas"; import type { ModelDefinition } from "./types"; function toNumber(v: string | number | null | undefined): number | undefined { if (v === null || v === undefined) return undefined; const n = typeof v === "number" ? v : parseFloat(v); return Number.isFinite(n) ? n : undefined; } /** Pricing values are USD per token (per request/image where applicable). */ export function derivePricing(raw: ORModelRaw): ModelDefinition["pricing"] { const p = raw.pricing ?? {}; return { prompt: toNumber(p.prompt), completion: toNumber(p.completion), image: toNumber(p.image), request: toNumber(p.request), }; } /** Estimated cost in USD from token counts and per-token prices. */ export function estimateCost( pricing: ModelDefinition["pricing"] | undefined, promptTokens: number | undefined, completionTokens: number | undefined ): number | undefined { if (!pricing) return undefined; const inCost = pricing.prompt !== undefined && promptTokens !== undefined ? pricing.prompt * promptTokens : undefined; const outCost = pricing.completion !== undefined && completionTokens !== undefined ? pricing.completion * completionTokens : undefined; if (inCost === undefined && outCost === undefined) return undefined; return (inCost ?? 0) + (outCost ?? 0); } /** Format a USD amount for display: $0.0042, $0.42, $4.20. */ export function formatUsd(v: number | undefined | null): string { if (v === undefined || v === null) return "—"; if (v === 0) return "$0"; if (v < 0.01) return `$${v.toFixed(4)}`; if (v < 1) return `$${v.toFixed(3)}`; return `$${v.toFixed(2)}`; } /** Price per 1M tokens for the model rail chip. */ export function perMillion(perToken: number | undefined): string { if (perToken === undefined) return "—"; const v = perToken * 1_000_000; if (v === 0) return "free"; if (v < 1) return `$${v.toFixed(2)}/M`; return `$${v.toFixed(v < 10 ? 2 : 0)}/M`; }