package main // pricing.go centralises model pricing as a per-model table (the LiteLLM pattern) // instead of three hardcoded Grok fields. The spend ledger prices each call by the // model it actually used, so when a second model (Gemini) starts answering some // routes, its cost books correctly against the same global ceiling. // ModelPrice is the per-1M-token USD price for one model, applied to the API's // returned usage so the wallet ceiling tracks real cost even as prices change. type ModelPrice struct { InputPerM float64 // non-cached prompt tokens CachedPerM float64 // prompt tokens served from the provider cache (cheaper) OutputPerM float64 // completion tokens } // CostBreakdown is the per-component USD cost of answering one request. A plain // grok_direct call has only Token; a cascade adds Router (the cheap classifier), // Grounding (Gemini Google-search) and/or WebTool (Grok web search) on top. Settle // books each column separately so the ledger and request_log can attribute spend, // and so a half-finished cascade can book only what it actually spent (§8.1). type CostBreakdown struct { Token float64 Grounding float64 WebTool float64 Router float64 } // Total is the grand total across all components (the number the wallet ceiling and // request_log.total_usd care about). Computed, never stored, so it can't drift. func (c CostBreakdown) Total() float64 { return c.Token + c.Grounding + c.WebTool + c.Router } // priceFor returns the configured price for a model. An unknown model falls back to // the default (final-voice) model's price rather than $0 — a $0 price would silently // blind the global ceiling to that call, the one failure mode we never want. func (c *Config) priceFor(model string) ModelPrice { if p, ok := c.Prices[model]; ok { return p } return c.Prices[c.XAIModel] }