Documentation
¶
Overview ¶
Package cost tracks Anthropic token usage and running dollar cost per PromptZero session, and implements the simple "consecutive errors → offline" heuristic that flips the observability offline banner.
Pricer is a read-only rate table: model name → USD per million tokens (input/output split). PromptZero ships with built-in rates for the current Claude lineup; operators can override or extend the table via config.
Tracker accumulates tokens and stream errors. When three consecutive streams fail within a 60s window, Tracker flips to offline and invokes the Offline hook; a successful stream clears the error run and flips back online. The three-strikes rule keeps transient network hiccups from flipping the banner on every stutter.
Index ¶
- func DefaultRates() map[string]Rate
- type Pricer
- type Rate
- type Snapshot
- type Tracker
- func (t *Tracker) AddUsage(inTokens, outTokens int64)
- func (t *Tracker) AddUsageFull(inTokens, outTokens, cacheReadTokens, cacheCreationTokens int64)
- func (t *Tracker) AddUsageFullForModel(model string, inTokens, outTokens, cacheReadTokens, cacheCreationTokens int64)
- func (t *Tracker) BudgetExceeded() bool
- func (t *Tracker) RecordStreamError()
- func (t *Tracker) SetBudget(usdCap float64, onWarn, onHit func(spent, cap float64))
- func (t *Tracker) SetModel(model string)
- func (t *Tracker) Snapshot() Snapshot
- func (t *Tracker) UpdateBudgetCap(usdCap float64)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DefaultRates ¶
DefaultRates returns a copy of the built-in rate table. Current Claude lineup as of late-2025: Opus 4.7 $15/$75, Sonnet 4.6 $3/$15, Haiku 4.5 $0.80/$4. Values should track Anthropic's public pricing page; adjust via config override when it drifts.
Types ¶
type Pricer ¶
type Pricer struct {
// contains filtered or unexported fields
}
Pricer owns the rate table. Lookup is case-insensitive and falls through on unknown models to (0, 0) so the Tracker still records token counts even when the rate isn't known.
func NewPricer ¶
NewPricer seeds a Pricer with DefaultRates plus any overrides. Keys are normalized (trimmed, lower-cased) so "Claude-Opus-4-7" and "claude-opus-4-7" resolve to the same row.
func (*Pricer) Cost ¶
Cost computes USD for (input, output) token counts against the model's rates. Zero rates produce zero cost.
func (*Pricer) CostWithCache ¶ added in v0.3.0
func (p *Pricer) CostWithCache(model string, inTokens, outTokens, cacheReadTokens, cacheCreationTokens int64) float64
CostWithCache is Cost plus prompt-cache read and creation tokens. Cache reads are billed at 0.1x the normal input rate; cache creations at 1.25x. The multipliers match Anthropic's published pricing as of late 2025; if they drift, this is the only place to update.
type Snapshot ¶
type Snapshot struct {
Model string
InputTokens int64
OutputTokens int64
CacheReadTokens int64
CacheCreationTokens int64
TotalUSD float64
Offline bool
// BudgetUSD is the configured session cap; 0 means no budget.
// /cost and /status render the spent/cap pair when non-zero.
BudgetUSD float64
}
Snapshot is a point-in-time copy of the Tracker's accumulated state.
func (Snapshot) CacheHitRate ¶ added in v0.3.0
CacheHitRate returns the fraction of prompt-cacheable input tokens that landed on an existing cache (vs. paid full-price for cache creation). Returns 0 when neither counter has moved yet so fresh sessions don't render a divide-by-zero. Intended for /stats and dashboard display.
type Tracker ¶
type Tracker struct {
// contains filtered or unexported fields
}
Tracker accumulates token counts, dollar cost, and stream error streaks. It is safe for concurrent use. A zero-value Tracker is NOT usable — call NewTracker.
func NewTracker ¶
NewTracker builds a Tracker bound to a specific model. The offline hook is invoked (with the new state) on every transition — pass nil to disable. Model can be changed later via SetModel when the user picks a new default mid-session.
func (*Tracker) AddUsage ¶
AddUsage records one response's input/output token counts and bumps the running USD total. Any successful usage record also clears the consecutive-error run and flips the tracker back online if it was offline. Prefer AddUsageFull for callers that have cache token counters — this wrapper ignores them.
func (*Tracker) AddUsageFull ¶ added in v0.3.0
AddUsageFull is the complete version of AddUsage that also records prompt-cache read / creation tokens. Cache-read tokens are billed at ~10 % of the normal input rate (Anthropic's current published number); cache-creation tokens are billed at ~125 % to amortise the cache write. Model rates default to uncached input pricing if no cache rate is configured, so the dollar line is always conservative.
Pricing uses the Tracker's configured model. Callers that know the per-call model (e.g. agent.Usage.Model from a tier-routed turn) should use AddUsageFullForModel so persona-defined tier overrides (claude-haiku for the classify tier, etc.) are priced correctly.
func (*Tracker) AddUsageFullForModel ¶ added in v0.195.0
func (t *Tracker) AddUsageFullForModel(model string, inTokens, outTokens, cacheReadTokens, cacheCreationTokens int64)
AddUsageFullForModel is AddUsageFull with an explicit per-call model for pricing. When model is "" the Tracker's configured model is used (matches AddUsageFull behaviour). When model is set, the per-call model wins over t.model for the price calc — token counters and the displayed Snapshot.Model stay tied to the tracker's primary model, so the dashboard shows the user-configured base model while the bill reflects actual tier routing.
Pre-fix, every persona that routed the plan tier to a cheaper model (Haiku for read-only defender personas, Sonnet for plan-tier downshift) silently still got billed at the operator's --model rate, often overstating cost 5x.
func (*Tracker) BudgetExceeded ¶ added in v0.21.0
BudgetExceeded reports whether the session has crossed the configured 100% cap. Returns false when no budget is set. Used by the agent's pre-dispatch check to refuse new turns once the cap is exhausted.
func (*Tracker) RecordStreamError ¶
func (t *Tracker) RecordStreamError()
RecordStreamError notifies the tracker that one Messages.NewStreaming call failed. Three failures inside errRunWindow flip offline.
func (*Tracker) SetBudget ¶ added in v0.21.0
SetBudget configures a session USD cap and the callbacks that fire at the 80%-warn and 100%-cap thresholds. usdCap == 0 disables the budget entirely (default). Either callback may be nil.
The 80% threshold fires once per session; the 100% threshold fires once. Re-entering thresholds after a budget bump (e.g. operator raises the cap with /budget set) requires resetting the flags via SetBudget — passing usdCap >= current spend resets warned/hit automatically.
func (*Tracker) SetModel ¶
SetModel updates the tracker's active model. Past usage stays attributed to the prior model's cost — only future AddUsage calls pick up the new rate.
func (*Tracker) Snapshot ¶
Snapshot returns the current state for the /cost REPL command and the /debug view.
func (*Tracker) UpdateBudgetCap ¶ added in v0.23.0
UpdateBudgetCap changes the configured USD cap without touching the warn/hit callbacks (which were wired once at setup time). When the new cap clears the current spend the warned/hit flags reset so a future re-cross fires a fresh notification — matching SetBudget's "operator bumps the cap" behaviour. Setting cap to 0 disables the budget gate entirely. Used by the /budget REPL command.