/** * Model pricing resolution, ONE resolver for every (provider, model) pair. * * Precedence (first hit wins): * 1. User-set manual price from config (`pricing.modelPrices`, keyed * `provider:model`), always wins when present. Negotiated or * self-hosted rates outrank every catalog. * 2. Registration-supplied price on the model definition (custom * provider/model files, runtime provider registration), also * user-origin: the person who registered the model stated the rate. * 3. The provider's own machine-readable pricing where its API serves one * (OpenRouter's /v1/models today), stamped with the fetch date. * 4. The models.dev catalog entry for that exact provider+model, stamped * with the fetch date. * 5. Honest UNKNOWN, a distinct state, never $0, never inferred-free. * * Subscription-tier surfaces resolve to `subscription` (no fake per-token * price). All rates are USD per 1,000,000 tokens. */ import type { CatalogModel } from './model-catalog.js'; /** User- or registration-supplied rates, USD per 1M tokens. */ export interface ManualModelPrice { readonly input: number; readonly output: number; readonly cacheRead?: number | undefined; readonly cacheWrite?: number | undefined; } /** Where a resolved price came from. */ export type ModelPricingSource = 'user' | 'provider' | 'catalog'; /** Resolved rates, USD per 1M tokens. Cache rates present only when the source carried them. */ export interface ModelPricingRates { readonly inputPerMTok: number; readonly outputPerMTok: number; readonly cacheReadPerMTok?: number | undefined; readonly cacheWritePerMTok?: number | undefined; } /** * The resolved price for one (provider, model) pair. `unknown` is a distinct, * honest state: absent-from-catalog usage must never look free. */ export type ResolvedModelPricing = { readonly status: 'priced'; readonly source: ModelPricingSource; /** ISO date of the source snapshot (catalog/provider fetches); absent for user prices. */ readonly asOf?: string | undefined; readonly rates: ModelPricingRates; } | { readonly status: 'subscription'; } | { readonly status: 'unknown'; }; export declare const UNKNOWN_MODEL_PRICING: ResolvedModelPricing; /** Wire shape of an event-level pricing source stamp. */ export type UsageCostSource = ModelPricingSource | 'subscription' | 'unknown'; export interface UsageTokenCounts { readonly inputTokens: number; readonly outputTokens: number; readonly cacheReadTokens?: number | undefined; readonly cacheWriteTokens?: number | undefined; } /** * usage x resolved price -> USD. Null when the pricing is not `priced` * (unknown/subscription), callers must carry the unpriced state forward, * never coerce to $0. Cache tokens use the source's explicit cache rates when * present, else the published per-provider ratio over the input rate. */ export declare function computeUsageCostUsd(pricing: ResolvedModelPricing, usage: UsageTokenCounts, provider?: string | undefined): number | null; /** As computeUsageCostUsd, in cents (the wire unit on LLM_RESPONSE_RECEIVED). */ export declare function computeUsageCostUsdCents(pricing: ResolvedModelPricing, usage: UsageTokenCounts, provider?: string | undefined): number | null; /** The event-level source stamp for a resolution. */ export declare function usageCostSource(pricing: ResolvedModelPricing): UsageCostSource; /** Validate the whole `pricing.modelPrices` config value (record keyed `provider:model`). */ export declare function validateManualModelPrices(value: unknown): boolean; /** Provider-served machine-readable pricing (USD per single token, OpenRouter shape). */ export interface ProviderServedPricing { readonly prompt: number; readonly completion: number; readonly cacheRead?: number | undefined; readonly cacheWrite?: number | undefined; /** Epoch ms of the fetch that produced this price. */ readonly fetchedAt?: number | undefined; } /** Everything the resolver reads. All lookups are live, no snapshot is taken. */ export interface ModelPricingDeps { /** Manual prices from config, keyed `provider:model`. Read per call so config edits apply live. */ readonly getManualPrices: () => Readonly> | undefined; /** Registration-supplied pricing on the model definition, when the definition exists. */ readonly getRegisteredPrice: (providerId: string | undefined, modelId: string) => ManualModelPrice | null; /** The provider's own machine-readable pricing, when its API serves one. */ readonly getProviderServedPricing: (providerId: string, modelId: string) => ProviderServedPricing | null; /** The models.dev catalog snapshot. */ readonly getCatalog: () => { readonly fetchedAt: number; readonly models: readonly CatalogModel[]; } | null; /** True when an SDK provider id and a catalog provider id name the same provider (alias-aware, e.g. gemini/google). */ readonly providerMatchesCatalogId: (providerId: string, catalogProviderId: string) => boolean; /** True when this provider id names a registered provider (used to parse `provider:model` refs). */ readonly isKnownProviderId: (providerId: string) => boolean; } /** * Resolve the price for a model reference. `modelRef` may be a bare model id * (provider taken from `providerId` when given) or a `provider:model` * registry key (its provider segment wins when it names a known provider). */ export declare function resolveModelPricing(deps: ModelPricingDeps, modelRef: string, providerId?: string | undefined): ResolvedModelPricing; /** Narrow accessors a registry hands the resolver, keeps the registry glue tiny. */ export interface RegistryModelPricingInput { readonly getManualPrices: ModelPricingDeps['getManualPrices']; readonly findModelPricing: (providerId: string | undefined, modelId: string) => ManualModelPrice | null; readonly openRouterPricing: (modelId: string) => ProviderServedPricing | null; readonly gatewayPricing: (providerId: string, modelId: string) => ProviderServedPricing | null; readonly getCatalog: ModelPricingDeps['getCatalog']; readonly providerAliases: Readonly>; readonly isKnownProviderId: (providerId: string) => boolean; } /** Assemble ModelPricingDeps from registry accessors (alias-aware provider matching included). */ export declare function buildRegistryModelPricingDeps(input: RegistryModelPricingInput): ModelPricingDeps; //# sourceMappingURL=model-pricing.d.ts.map