Documentation
¶
Overview ¶
Package usage keeps the ledger of model spend and prices it.
Every agent step and every utility call (title, risk check, compaction, turn-memory summary, deep-search ranking and synthesis) is written to one table in the global config DB, tagged with the project, session, provider and model it ran on. That is what lets a single view total spend across every project and model: each project keeps its sessions in its own DB, so the sessions alone could never answer "what have I spent this month".
Prices are never stored. A row is priced when it is read, from the provider's own listing or the model catalogue, so a price correction reaches history too.
Index ¶
- Constants
- type Day
- type Ledger
- func (l *Ledger) Backfill(store *session.Store) (steps, utility int, err error)
- func (l *Ledger) DB() *db.DB
- func (l *Ledger) RecordStep(sessionID, messageID, providerID, modelID string, tc session.TokenCounts, ...)
- func (l *Ledger) RecordUtility(sessionID, providerID, modelID string, tc session.TokenCounts, at int64)
- func (l *Ledger) SetHosts(hosts func(providerID string) string)
- type ModelUsage
- type ProjectUsage
- type SessionCost
- type Summary
- type Tokens
- type Totals
Constants ¶
const ( // KindStep is one agent step, keyed by its assistant message id. KindStep = "step" // KindUtility is one utility call made on a session's behalf. KindUtility = "utility" )
Kinds of ledger row.
const ( // BillingMetered is billed per token at a known price. BillingMetered = "metered" // BillingIncluded is a flat plan (Ollama Cloud) or a local model: nothing // is billed per token. OGX meters at the rates its gateway publishes. BillingIncluded = "included" // BillingUnpriced is billed per token at a price nothing publishes. BillingUnpriced = "unpriced" // BillingUnknown is work whose provider was never recorded (sessions from // before ogcode stored one) on a model nothing configured serves today, so // whether it was billed at all cannot be told. It is never counted as a // charge. BillingUnknown = "unknown" )
How a model's tokens are paid for.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Day ¶
type Day struct {
Day string `json:"day"` // YYYY-MM-DD
Input int `json:"input"`
Output int `json:"output"`
Effective int `json:"effective"`
CostUSD float64 `json:"costUsd"`
IncludedListUSD float64 `json:"includedListUsd"`
}
Day is one calendar day of spend, in the server's local time.
type Ledger ¶
type Ledger struct {
// contains filtered or unexported fields
}
Ledger writes model spend to the global config DB for one project. A nil *Ledger records nothing, so a caller without a global DB (tests, one-off tools) needs no guard. Recording never fails a turn: errors are logged.
func NewLedger ¶
NewLedger returns a ledger that records into global under project, the workspace directory the spend happened in. It returns nil when there is no global DB.
func (*Ledger) Backfill ¶
Backfill copies the project's usage from before the ledger existed, once per project: every assistant step that reported usage, at the model its message names or else its session's, and each session's utility total as one row at the session's model (the calls behind it were never itemised). Rows already in the ledger are left alone, so running it twice, or from two servers on the same project at once, adds nothing. Usage from sessions deleted before the ledger existed is gone and stays uncounted.
func (*Ledger) RecordStep ¶
func (l *Ledger) RecordStep(sessionID, messageID, providerID, modelID string, tc session.TokenCounts, at int64)
RecordStep writes one agent step's usage under its assistant message id. A step recorded again replaces its row rather than adding a second one, so a step's final counts are what stays.
func (*Ledger) RecordUtility ¶
func (l *Ledger) RecordUtility(sessionID, providerID, modelID string, tc session.TokenCounts, at int64)
RecordUtility appends one utility call's usage.
type ModelUsage ¶
type ModelUsage struct {
Provider string `json:"provider"`
Model string `json:"model"`
// Name is the catalogue's display name, empty for a model it does not know.
Name string `json:"name,omitempty"`
Billing string `json:"billing"`
// InferredProvider is set when Provider is empty — the work predates
// recorded providers — and a configured provider serves the model today:
// the row is billed as that provider, and says the provider was inferred.
InferredProvider string `json:"inferredProvider,omitempty"`
// Host is the endpoint the calls went to when the provider slot points
// somewhere other than its own default (the OpenAI slot at Z.ai), so the
// row can be named by it; empty on default endpoints. Rows from before
// hosts were recorded take where the provider points today.
Host string `json:"host,omitempty"`
// Calls counts ledger rows: agent steps plus utility calls.
Calls int `json:"calls"`
Sessions int `json:"sessions"`
Tokens
// CostUSD is what was billed per token: 0 for included usage, null when the
// model is billed per token at an unknown price.
CostUSD *float64 `json:"costUsd"`
// ListUSD is included usage priced at the model's list price — what the
// same tokens would cost on the vendor's own API. Null for metered usage,
// which has a real cost, and when the catalogue does not price the model.
ListUSD *float64 `json:"listUsd"`
}
ModelUsage is one provider/model pair's usage and what it cost.
type ProjectUsage ¶
type ProjectUsage struct {
Project string `json:"project"`
Name string `json:"name"`
Tokens
CostUSD float64 `json:"costUsd"`
IncludedListUSD float64 `json:"includedListUsd"`
}
ProjectUsage is one project's share of the spend.
type SessionCost ¶
type SessionCost struct {
Models []ModelUsage `json:"models"`
Totals Totals `json:"totals"`
}
SessionCost is one session's spend by model.
func ForSession ¶
func ForSession(store *session.Store, reg *provider.Registry, id session.SessionID) (*SessionCost, error)
ForSession prices one session from its own messages: each step at the model its message names — or the session's model, for steps from before messages recorded one — and its utility calls at the session's model. Sub-agent work is inside the utility total, folded in when the sub-agent finished.
It reads the session's messages rather than the ledger so it prices exactly the tokens the session's token view counts.
type Summary ¶
type Summary struct {
From int64 `json:"from"`
To int64 `json:"to"`
// Project is the workspace the summary is narrowed to, empty for all.
Project string `json:"project,omitempty"`
// First is when the ledger's oldest row was spent, 0 when it is empty.
First int64 `json:"first"`
Models []ModelUsage `json:"models"`
Projects []ProjectUsage `json:"projects"`
Days []Day `json:"days"`
Totals Totals `json:"totals"`
}
Summary is the ledger totalled over a period.
func Summarize ¶
func Summarize(global *db.DB, reg *provider.Registry, from, to int64, project string) (*Summary, error)
Summarize totals the ledger's spend between from and to (unix ms; to <= 0 means now), by model, by project and by day, pricing each model with reg. project narrows it to one workspace — its own rows and those of the task worktrees inside it; empty means every project.
type Tokens ¶
type Tokens struct {
Input int `json:"input"`
Output int `json:"output"`
Reasoning int `json:"reasoning"`
CacheRead int `json:"cacheRead"`
CacheWrite int `json:"cacheWrite"`
Effective int `json:"effective"`
Total int `json:"total"`
}
Tokens are the counts in one bucket. Effective is everything but cache reads and Total is everything, as session.TokenCounts defines them.
type Totals ¶
type Totals struct {
Tokens
Calls int `json:"calls"`
Sessions int `json:"sessions"`
// CostUSD is everything billed per token at a known price.
CostUSD float64 `json:"costUsd"`
// IncludedListUSD is plan and local usage at list price, the part of the
// work the flat plans covered.
IncludedListUSD float64 `json:"includedListUsd"`
// IncludedEffective is the effective tokens that were not billed per token.
IncludedEffective int `json:"includedEffective"`
// UnpricedEffective is the effective tokens billed per token at a price
// nothing publishes, so CostUSD leaves them out.
UnpricedEffective int `json:"unpricedEffective"`
// UnknownEffective is the effective tokens whose provider was never
// recorded and cannot be inferred, so CostUSD leaves them out too.
UnknownEffective int `json:"unknownEffective"`
}
Totals add up every model in a view.