/** Price for a model, in USD per 1,000,000 tokens. */ export interface ModelPrice { /** Model id or a prefix of one (e.g. "claude-opus-4" matches "claude-opus-4-8"). */ id: string; provider?: string; inputPerMTok: number; outputPerMTok: number; cacheReadPerMTok?: number; cacheWritePerMTok?: number; } /** Token counts for a single model call. */ export interface UsageInput { model: string; inputTokens: number; outputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number; sessionId?: string; label?: string; provider?: string; /** Pre-computed cost in USD; when set, overrides meter's own price table (e.g. pi's own cost). */ costUsd?: number; /** ISO timestamp; defaults to now when recorded. */ ts?: string; } /** A recorded model call with its computed cost. One JSONL line in the ledger. */ export interface UsageEvent { ts: string; model: string; provider?: string; inputTokens: number; outputTokens: number; cacheReadTokens?: number; cacheWriteTokens?: number; costUsd: number; sessionId?: string; label?: string; } export interface Budget { /** USD limits per scope. */ daily?: number; monthly?: number; /** All-time cumulative spend cap. */ total?: number; session?: number; } export interface MeterConfig { /** Soft budget. When exceeded, the pi extension warns and auto-downshifts (see `downshift`). */ budget?: Budget; /** Hard cap. When exceeded, the pi extension blocks new prompts and tool calls until you raise it. */ hardLimit?: Budget; prices?: ModelPrice[]; /** Map of expensive model id -> cheaper model id, used when over the soft budget. */ downshift?: Record; /** Override ledger location; supports a leading "~". */ storePath?: string; } export interface SpendSummary { total: number; today: number; month: number; byModel: Record; bySession: Record; count: number; since?: string; } export type BudgetScope = "daily" | "monthly" | "total" | "session"; export interface BudgetStatus { scope: BudgetScope; limit: number; spent: number; remaining: number; ratio: number; state: "ok" | "warn" | "over"; }