import type { MessageUsage } from '../types.js';
/**
 * The WRITE side of the model pricing table the loop's cost fold prices token usage against. Cost is
 * `null` (not `0`) for an unpriced model, so an app seeds its models' per-1M rates once (and
 * re-`upsert`s when a provider changes prices). An adapter implements this — `LucidPricingStore`
 * (production, over the `agent_model_pricing` table) and `InMemoryPricingStore` (testing) ship. Wire
 * it in `config/agent.ts` via `pricingStore: pricingStores.lucid()`; use {@link seedModelPrices} for a
 * one-shot batch. Mirrors the reference `AgentPricingStore` contract exactly.
 */
/** A per-1M-token price for one model. Cache rates fall back to the input rate when omitted. */
export interface ModelPriceInput {
    modelId: string;
    inputPricePer1m: number;
    outputPricePer1m: number;
    /** Per-1M price for cache-write (prompt-cache) input tokens. Omit → priced at the input rate. */
    cacheWritePricePer1m?: number;
    /** Per-1M price for cache-read (prompt-cache) input tokens. Omit → priced at the input rate. */
    cacheReadPricePer1m?: number;
}
/** A current price row as read back, with the ISO timestamp it took effect. */
export interface CurrentModelPrice extends ModelPriceInput {
    effectiveFrom: string;
}
export interface AgentPricingStore {
    /**
     * Set the current price for a model. Atomic supersede: the model's prior `is_current` row (if any)
     * is retired and this one is inserted as current, effective now — so the cost fold always joins to
     * exactly one live price per model, with no window where two rows race for `is_current`.
     */
    upsertModelPrice(input: ModelPriceInput): Promise<void>;
    /** The current price row per model (`is_current`), fetched ONCE per run for the loop's cost fold. */
    listCurrentPrices(): Promise<CurrentModelPrice[]>;
}
/** Seed (or refresh) a batch of model prices — one `upsertModelPrice` per row, in order. */
export declare function seedModelPrices(store: AgentPricingStore, prices: ModelPriceInput[]): Promise<void>;
/**
 * Token-ledger estimate for one turn against a pricing row: the uncached input at the input rate,
 * cache-write/cache-read tokens at their own rates (falling back to the input rate when unpriced),
 * plus output at the output rate. Reasoning tokens are a subset of output and are billed at the
 * output rate, so they don't change the estimate. Cache token counts are subsets of `inputTokens`,
 * so the uncached remainder is the difference. Pure — the SQL and in-memory adapters share it, so
 * every surface reports identical numbers.
 */
export declare function estimateCost(usage: MessageUsage, price: CurrentModelPrice): number;
/**
 * The forms of a model id we will accept a price under, most specific first.
 *
 * Exists because the ledger and the price table are filled by two different parties. The ledger gets
 * what the PROVIDER reports (`finalStep.response.modelId`), and OpenAI answers a request for
 * `gpt-4o-mini` with the dated snapshot `gpt-4o-mini-2024-07-18`. The price table gets what an
 * OPERATOR typed — and every example in these docs, and every published rate card, uses the alias.
 * Matched by raw equality, those two never meet: the fold misses and the dashboard prints `$0.00`
 * next to a real token count.
 *
 * Only DATE-shaped suffixes are stripped, and only from the end. That is the conservative line: a
 * date suffix is unambiguously a snapshot of the same model, whereas a trailing `-002` or `-v2`
 * could be a genuinely different model with a different price. Mispricing silently is worse than
 * not pricing — so anything we are not sure about stays unpriced and stays visible.
 *
 * The exact id is always tried FIRST, so an operator who deliberately prices one snapshot
 * differently from its alias keeps that.
 */
export declare function modelPriceCandidates(modelId: string): string[];
/**
 * The price to use for `modelId`, or `undefined` when the model is genuinely unpriced.
 *
 * `undefined` is the honest answer for "we don't know", and callers must keep it distinguishable
 * from zero: a run that cost nothing and a run nobody priced are different facts, and collapsing
 * them is what made a whole dashboard read `$0.00` while tokens were being burned.
 */
export declare function resolveModelPrice(pricing: ReadonlyMap<string, CurrentModelPrice>, modelId: string): CurrentModelPrice | undefined;
//# sourceMappingURL=pricing-store.d.ts.map