import { POLICY_CAPS } from "../config/defaults.js"; import { derivedRate, estimateCredits, resolveCatalog, usableUsdCost, type UsdModelCost } from "./price-catalog.js"; import type { Policy, PriceCatalog } from "../types.js"; /** The nominal call the budget governor sizes a spawn against: 8k in, 800 out. */ const NOMINAL_INPUT_TOKENS = 8_000; const NOMINAL_OUTPUT_TOKENS = 800; export type PriceCoverageKind = "declared" | "free" | "derived" | "missing"; export interface PriceCoverage { model: string; kind: PriceCoverageKind; creditsPerCall?: number; callsPerTask?: number; } /** * How each declared model gets a price, and what that price buys. * * The calls-per-task column is the point of this: it is what tells someone with a Sonnet-first * roster, at install time, that `balanced` buys them five turns — instead of meeting the number * later as a spawn refusal in the middle of a task. */ export function priceCoverage(tiers: readonly string[], catalog: PriceCatalog, costOf: (model: string) => UsdModelCost | undefined, policy: Policy): PriceCoverage[] { const stopTarget = POLICY_CAPS[policy].internalStopTarget; return tiers.map((model): PriceCoverage => { const declared = catalog.models[model]; const cost = declared ? undefined : costOf(model); const rate = declared ?? (usableUsdCost(cost) ? derivedRate(cost, catalog.creditsPerUsd) : undefined); if (!rate) return { model, kind: "missing" }; const priced = resolveCatalog(catalog, new Map([[model, rate]])); const creditsPerCall = estimateCredits(priced, model, NOMINAL_INPUT_TOKENS, 0, NOMINAL_OUTPUT_TOKENS); const kind: PriceCoverageKind = declared ? (creditsPerCall === 0 ? "free" : "declared") : "derived"; return { model, kind, creditsPerCall, callsPerTask: creditsPerCall > 0 ? Math.floor(stopTarget / creditsPerCall) : undefined }; }); } export function formatPriceCoverage(rows: readonly PriceCoverage[], catalog: PriceCatalog, policy: Policy): string[] { const failed = rows.some((row) => row.kind === "missing"); const width = Math.max(0, ...rows.map((row) => row.model.length)); return [ `price-catalog-coverage=${failed ? "FAIL" : "PASS"} creditsPerUsd=${catalog.creditsPerUsd ?? "unset"} tiers=${rows.length}`, ...rows.map((row) => row.kind === "missing" ? ` ${row.model.padEnd(width)} missing no usable cost in the catalogue or the Pi model registry — add an entry or drop the tier` : ` ${row.model.padEnd(width)} ${row.kind.padEnd(8)} ${row.creditsPerCall!.toFixed(2)} credits/call ${row.callsPerTask === undefined ? "unmetered" : `~${row.callsPerTask} calls at ${policy}`}`), ]; }