Documentation
¶
Overview ¶
Package accountusage is the pure logic behind `hadron team usage` (cli#1472): read each configured model account's rate-limit snapshot (and optionally a ccusage JSON file the operator produced), validate everything before any record exists, and shape one `account-usage` record per account.
It reads exactly two kinds of file per account and nothing else: the snapshot at <configDir>/hadron-usage/rate-limits.json and the optional ccusage file named in the config. It never runs a subprocess and never reads anything else under a Claude config dir (credentials and transcripts live there). Errors name a path and a reason class, never file contents.
Index ¶
Constants ¶
const ( // Collection is the Hadron object type the records are written under. Collection = "account-usage" // SchemaVersion is the record shape version (golden-pinned). SchemaVersion = 1 // SnapshotRel is where the operator's status line writes the snapshot, // relative to an account's config dir. SnapshotRel = "hadron-usage/rate-limits.json" )
const ActiveWindow = 6 * time.Hour
ActiveWindow bounds how long a ccusage block can keep growing (blocks are 5-hour windows; the margin covers a late final write). A block that started longer before an observation is final, so the checkpoint omits it.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Account ¶
type Account struct {
Label string `yaml:"label"`
ConfigDir string `yaml:"configDir"`
Family string `yaml:"family"`
CcusageFile string `yaml:"ccusageFile"`
Workers []string `yaml:"workers"`
// contains filtered or unexported fields
}
Account is one configured subscription account.
type AccountView ¶
type AccountView struct {
Label string `json:"label"`
Family string `json:"family"`
Host string `json:"host"`
ObservedAt string `json:"observedAt"`
FiveHour WindowView `json:"fiveHour"`
SevenDay WindowView `json:"sevenDay"`
Workers []string `json:"workers"`
// WorkersConfigured is false when the account's workers list was never
// configured: Workers is then empty because it is unknown, not because
// nobody ran on the account.
WorkersConfigured bool `json:"workersConfigured"`
Points int `json:"points"`
}
AccountView is one account's current usage.
func View ¶
func View(objects []json.RawMessage, now time.Time) []AccountView
View builds the per-account view from recorded objects (any order, any number of accounts). A record that does not parse as the documented shape is skipped, not guessed at. now decides which windows are expired.
type Block ¶
Block is one ccusage 5-hour block: only the fields collect uses.
func ReadCcusage ¶
ReadCcusage reads a `ccusage blocks --json` file the operator produced. An empty path means none was configured (nil, nil).
type BlockCheckpoint ¶
type BlockCheckpoint struct {
Start string `json:"start"`
Tokens float64 `json:"tokens"`
Cost float64 `json:"costUsd"`
}
BlockCheckpoint is one still-growing ccusage block's totals.
type Config ¶
type Config struct {
// Memory is where records are written (a memory ref); `-m` overrides it.
Memory string `yaml:"memory"`
// Host labels this host in each record; empty means the hostname.
Host string `yaml:"host"`
Accounts []Account `yaml:"accounts"`
}
Config is the host-local YAML file (`--config`).
func LoadConfig ¶
LoadConfig reads and validates the config file. Unknown keys are refused so a typo cannot silently drop an account.
type Previous ¶
type Previous struct {
ObservedAt time.Time
Blocks *[]BlockCheckpoint
}
Previous is the checkpoint carried by this account's previous record on this host and family: its observation time and recorded blocks (nil when that record carried no checkpoint).
type Record ¶
type Record struct {
Label string `json:"label"`
Family string `json:"family"`
Host string `json:"host"`
ObservedAt string `json:"observedAt"`
FiveHourPct *float64 `json:"fiveHourPct,omitempty"`
FiveHourResetsAt *string `json:"fiveHourResetsAt,omitempty"`
SevenDayPct *float64 `json:"sevenDayPct,omitempty"`
SevenDayResetsAt *string `json:"sevenDayResetsAt,omitempty"`
TokensSinceLast *float64 `json:"tokensSinceLast,omitempty"`
EstCostUsdSinceLast *float64 `json:"estCostUsdSinceLast,omitempty"`
// CcusageBlocks is the checkpoint the next collection differences against:
// the ccusage blocks that could still be growing at observation (started
// within ActiveWindow of it). Present, possibly empty, whenever a ccusage
// file was read.
CcusageBlocks *[]BlockCheckpoint `json:"ccusageBlocks,omitempty"`
Workers []string `json:"workers"`
WorkersConfigured bool `json:"workersConfigured"`
SchemaVersion int `json:"schemaVersion"`
}
Record is the `account-usage` object's fields (schemaVersion 1). Absent values are omitted, never 0. The shape is pinned by a golden test: the portal reads it without the CLI.
func BuildRecord ¶
BuildRecord shapes one record. observedAt is the snapshot's own observation time when there is a snapshot, else now. With a ccusage file the record carries its still-growing blocks as the checkpoint. The since-last fields are the growth of blocks that started within ActiveWindow of the previous observation (a block that started after it counts in full, a known block by its increase; older blocks are final and contribute nothing), so growth inside a running block counts and blocks evicted from a rolling file do not matter. They stay absent when there is no ccusage file or previous checkpoint, or a known block's totals went down: an interval that cannot be measured is unknown, not zero.
type Snapshot ¶
Snapshot is a validated rate-limits.json. A missing file is "no data": Present is false and both windows are nil.
func ReadSnapshot ¶
ReadSnapshot reads one account's snapshot. A file that does not exist yet is no data, not an error; anything unreadable or malformed is refused.
type ValidationError ¶
type ValidationError struct{ Msg string }
ValidationError is a refusal of the operator's input (exit 2): a config, snapshot or ccusage file that is missing, malformed or out of range.
func (*ValidationError) Error ¶
func (e *ValidationError) Error() string
type WindowView ¶
type WindowView struct {
UsedPct *float64 `json:"usedPct"`
// ResetsAt is when the window resets (RFC 3339).
ResetsAt *string `json:"resetsAt"`
// Expired is true when ResetsAt has passed: the percentage describes a
// window that is over, so it is reported but must not be read as current.
Expired bool `json:"expired"`
// BurnPctPerHour is the rise in used percentage per hour across this
// window's recorded points (needs two at different times, same window).
BurnPctPerHour *float64 `json:"burnPctPerHour"`
// ExhaustsAt projects when the window reaches 100% at that burn rate.
ExhaustsAt *string `json:"exhaustsAt"`
// ExhaustsBeforeReset is true when ExhaustsAt falls before ResetsAt.
ExhaustsBeforeReset *bool `json:"exhaustsBeforeReset"`
}
WindowView is one window's current state for `team usage show --json`. Null fields mean unknown, never 0.