import { type ResolvedModelPricing } from './model-pricing.js'; import type { CatalogModel } from './model-catalog.js'; export interface ModelPricing { input: number; output: number; } /** * Where a resolved price came from, for the render-side source distinction: * 'user' = the manual pricing.modelPrices entry ("your price"), 'provider' = * served by the provider API, 'catalog' = the live model catalog (dated), * 'fallback' = this module's small built-in safety net. */ export type PricingSourceKind = 'user' | 'provider' | 'catalog' | 'fallback'; /** Result of a pricing lookup: the resolved (possibly zero) price, and whether it's real. */ export interface PricingResult { pricing: ModelPricing; /** False when no source recognized the model, the zero pricing is a placeholder, not a real price. */ priced: boolean; /** Which source priced the model (present only when priced). */ source?: PricingSourceKind; /** ISO date (YYYY-MM-DD) of the catalog/provider snapshot the price came from, when known. */ asOf?: string; } /** Wire (or clear, with null) the live catalog as the primary pricing source. */ export declare function setPricingSource(source: (() => readonly CatalogModel[]) | null): void; /** Wire (or clear, with null) the registry's resolveModelPricing as the primary pricing source. */ export declare function setModelPricingResolver(resolver: ((modelId: string) => ResolvedModelPricing) | null): void; /** * One-call bootstrap wiring: the live catalog as the legacy source AND the * registry's ONE pricing resolver (manual pricing.modelPrices -> registration * -> provider-served -> catalog -> honest unknown) as the primary, so every * cost surface sees a manually-set price immediately and can name its source. */ export declare function wireCostPricing(registry: { getRawCatalogModels(): readonly CatalogModel[]; resolveModelPricing(modelRef: string): ResolvedModelPricing; }): void; /** * resolvePricing, resolve USD-per-1M-token pricing for a model ID, and * whether that pricing is real (vs. an unpriced placeholder). See the module * header for the full resolution order. */ export declare function resolvePricing(modelId: string): PricingResult; /** * The render-side source distinction for a priced model: "your price" for a * manual pricing.modelPrices entry, "catalog price, as of " (or * provider-served/built-in equivalents) otherwise. Null when the model is * unpriced, callers render the explicit "price unknown" marker instead. */ export declare function describePricingSource(modelId: string): string | null; /** * getPricing, resolve USD-per-1M-token pricing for a model ID. * Back-compat wrapper over resolvePricing(); returns zero for both genuinely * free and genuinely unknown models (use resolvePricing/isModelPriced to * distinguish the two). */ export declare function getPricing(modelId: string): ModelPricing; /** True when `modelId` resolves to a real price (free or paid), false when it's an unpriced placeholder. */ export declare function isModelPriced(modelId: string): boolean; /** * calcSessionCost, compute total session cost in USD given raw token counters * and the active model ID. The one formula every cost surface totals with. * * inputTokens , cumulative input tokens * outputTokens , cumulative output tokens * cacheRead , cumulative cache-read tokens * cacheWrite , cumulative cache-write tokens * modelId , registry model identifier * * Unpriced models contribute 0 to the total, only the display layer * distinguishes "genuinely free/priced" from "unpriced". */ export declare function calcSessionCost(inputTokens: number, outputTokens: number, cacheRead: number, cacheWrite: number, modelId: string): number; /** * computeBudgetBreach, the pure predicate a render-time "OVER BUDGET" flag and * a background budget-breach notifier both read, so they agree on exactly one * definition of "over budget". `budgetThreshold <= 0` means no budget is * configured (disabled), which can never be breached. */ export declare function computeBudgetBreach(sessionCost: number, budgetThreshold: number): boolean; /** Read/write access to the `behavior.budgetAlertUsd` host-local config key. * Plain callbacks (rather than a ConfigManager reference) so a caller can pass a * generic-key-cast wrapper and this module keeps no dependency on the config * type layer. */ export interface BudgetAlertConfigAccess { readonly get: (key: string) => unknown; readonly set: (key: string, value: unknown) => void; } /** Default for the `behavior.budgetAlertUsd` synthetic setting: 0 = no budget configured. */ export declare const BUDGET_ALERT_USD_DEFAULT = 0; /** * The dot-path config key backing the session cost-budget alert threshold. * Shared by every reader and writer of the threshold, a cost panel's get/set, * a settings surface's synthetic entry, and readBudgetAlertUsd below, so the * string literal lives in exactly one place. */ export declare const BUDGET_ALERT_USD_CONFIG_KEY = "behavior.budgetAlertUsd"; /** * readBudgetAlertUsd, read the session cost-budget alert threshold (USD) from * config. The single source of truth a cost panel and a background * budget-breach notifier both read, so a threshold set in one is immediately * visible to the other. Falls back to BUDGET_ALERT_USD_DEFAULT (off) when the * key is absent or invalid. */ export declare function readBudgetAlertUsd(configGet: (key: string) => unknown): number; /** * The settings key holding the user's manual per-model prices, the * highest-precedence source in the ONE pricing resolver. Object map of * `provider:model` -> { input, output, cacheRead?, cacheWrite? } in USD per * 1M tokens. */ export declare const MODEL_PRICES_CONFIG_KEY = "pricing.modelPrices"; /** * Persist a manual price for one `provider:model` key into * pricing.modelPrices, preserving every other entry. The registry's resolver * reads the key live per call, so the new price is visible to every cost * surface on the next render, no restart. */ export declare function writeManualModelPrice(config: BudgetAlertConfigAccess, modelKey: string, price: { input: number; output: number; }): void; //# sourceMappingURL=session-cost.d.ts.map