import type { ClientId, CostBasis } from '../models/usage-record.js'; import { type CommunityPricingState, type LoadedPricing, type PricingMode, type PricingTable } from '../pricing/index.js'; /** * Clients that record no cost of their own, so their collector estimates one * from the pricing table at collection time. * * A stored row from one of these that was `unavailable` -- its model was not * in the table when it was collected -- is what a later table can still price. * Rows from any other client carry the cost the client itself reported, which * no pricing table may overwrite. */ export declare const ESTIMATED_CLIENTS: readonly ClientId[]; /** * Where each client puts reasoning tokens relative to `outputTokens`. * * This is a pricing concern, not a cosmetic one. Claude Code's thinking tokens * are a *detail of* `output_tokens`, so they are already paid for by pricing * output. OpenCode's `reasoning` is a *sibling* of `output` (verified: * `tokens.total === input + output + reasoning + cache.read`), so pricing only * `output` would bill nothing for them. Codex follows OpenAI's convention: * `reasoning_output_tokens` is part of `output_tokens` (verified: `total_tokens * === input_tokens + output_tokens` on every counted request). * * Collection-time estimates never hit this, because only the clients whose * reasoning is inside output are estimated -- OpenCode reports its own cost. * Anything that RE-prices a stored row does hit it, for every client. See * docs/DATA_SOURCES.md. */ export declare const REASONING_PLACEMENT: Record; /** * The output-token count to price for a client, given what it stored. * * Use this instead of passing `outputTokens` straight through whenever you are * re-pricing stored rows; a new client whose reasoning is a sibling will * otherwise be under-billed with nothing to show it. */ export declare function billableOutputTokens(client: ClientId, outputTokens: number, reasoningTokens?: number): number; export interface EstimateInput { model: string; inputTokens: number; outputTokens: number; cacheReadTokens?: number; /** Total cache-write tokens; authoritative even if the TTL split is incomplete. */ cacheWriteTokens?: number; cacheWrite5mTokens?: number; cacheWrite1hTokens?: number; /** `usage.speed` from the transcript: 'fast' bills at premium rates. */ speed?: string; /** * The whole prompt of the ONE request being priced -- see {@link promptTokensOf}. * It picks a model's long-context rate card, so a model that has one cannot be * priced without it: summed tokens from many requests would land every group * in the long tier. */ promptTokens?: number; } /** * A request's prompt length as Anthropic bills it: every input token, cache * reads and cache writes included. */ export declare function promptTokensOf(t: { inputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number; }): number; export interface Estimate { costBasis: CostBasis; estimatedCost?: number; /** Explanation shown to the user when they ask how a number was produced. */ note?: string; } /** * Turns token counts into an *API-equivalent* cost. * * Three rules this class exists to enforce: * 1. A model that is not in the pricing table yields `unavailable`, never a guess. * 2. Cache reads and cache writes are priced from their own multipliers, and the * two cache-write TTLs are priced separately (1.25x vs 2x input). Averaging * them would have understated this machine's real usage, where 55.1M of the * 82.6M cache-write tokens used the 1-hour TTL. * 3. Reasoning/thinking tokens are NOT priced separately for Claude Code or * Codex: they are already inside `output_tokens`. Adding them would * double-charge. */ export declare class CostService { private loaded; /** False when a caller handed the table over, which there is then no disk copy to re-read. */ private readonly fromDisk; /** * `mode` is metadata about how the table was assembled, not an input to any * number, so a caller handing over a table directly may omit it. */ constructor(loaded?: Omit & { mode?: PricingMode; }); /** * Re-reads the pricing in force from disk -- built-in tables, community * prices and override -- and returns whether any price changed. * * A long-running MCP server needs this: the community list it downloads in * the background would otherwise only take effect on the next restart. The * table is replaced whole, and only when it differs, so a caller holding the * old one keeps a consistent table rather than a half-updated one. Throws if * the override on disk has become malformed, leaving the current table in * force. */ reload(): boolean; get table(): PricingTable; get pricingVersion(): string; get overridePath(): string | undefined; /** How the table in force was assembled: built-in, an overlay, or a full replacement. */ get pricingMode(): PricingMode; /** The built-in version an overlay sits on. Absent unless `pricingMode` is 'overlay'. */ get baseVersion(): string | undefined; /** What the community price list contributed. Absent when the table was handed over. */ get community(): CommunityPricingState | undefined; knowsModel(model: string): boolean; /** * Every prompt length at which some model changes rate card, ascending. A * caller pricing aggregates splits its groups at these, so that no group * straddles a tier and each can be priced at its own longest prompt. */ longContextThresholds(): number[]; /** Every model the table can price, so a caller need not hardcode a list. */ pricedModels(): string[]; estimate(input: EstimateInput): Estimate; /** The label that must accompany every estimated figure shown to a user. */ estimatedCostLabel(): string; }