costs

package
v1.3.4 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 7, 2026 License: MIT Imports: 17 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func FormatUSD

func FormatUSD(microdollars int64) string

FormatUSD converts microdollars to a display string.

Types

type BudgetAction

type BudgetAction int
const (
	BudgetActionNone BudgetAction = iota
	BudgetActionWarn
	BudgetActionStop
)

type BudgetChecker

type BudgetChecker struct {
	// contains filtered or unexported fields
}

func NewBudgetChecker

func NewBudgetChecker(cfg BudgetConfig, store *Store) *BudgetChecker

func (*BudgetChecker) Check

func (b *BudgetChecker) Check(sessionID, groupName string) BudgetResult

Check is a convenience for non-transactional checks (e.g., TUI display).

func (*BudgetChecker) CheckTx

func (b *BudgetChecker) CheckTx(tx *sql.Tx, sessionID, groupName string, groupSessionIDs []string) (BudgetResult, error)

CheckTx evaluates all budget limits within a transaction. This must be called within the same transaction as the cost event INSERT.

type BudgetConfig

type BudgetConfig struct {
	DailyLimit    int64
	WeeklyLimit   int64
	MonthlyLimit  int64
	GroupLimits   map[string]int64 // group name -> daily limit in microdollars
	SessionLimits map[string]int64 // session ID -> total lifetime limit in microdollars
	Timezone      *time.Location   // for determining day/week/month boundaries
}

BudgetConfig holds budget limits in microdollars.

type BudgetResult

type BudgetResult struct {
	Action     BudgetAction
	Reason     string
	UsedMicro  int64
	LimitMicro int64
	Percentage float64
}

type ClaudeHookParser

type ClaudeHookParser struct {
	// contains filtered or unexported fields
}

ClaudeHookParser parses Claude Code Stop hook JSON payloads.

func (*ClaudeHookParser) CanParse

func (p *ClaudeHookParser) CanParse(toolType string) bool

func (*ClaudeHookParser) Name

func (p *ClaudeHookParser) Name() string

func (*ClaudeHookParser) Parse

func (p *ClaudeHookParser) Parse(input string) ([]CostEvent, error)

type Collector

type Collector struct {
	// contains filtered or unexported fields
}

Collector routes tool output to the appropriate parser and applies pricing.

func NewCollector

func NewCollector(pricer *Pricer) *Collector

NewCollector creates a Collector with all registered parsers.

func (*Collector) Collect

func (c *Collector) Collect(toolType, sessionID, input string) ([]CostEvent, error)

Collect parses input using the appropriate parser, sets session ID and computes cost.

type CostEvent

type CostEvent struct {
	ID               string
	SessionID        string
	Timestamp        time.Time
	Model            string
	InputTokens      int64
	OutputTokens     int64
	CacheReadTokens  int64
	CacheWriteTokens int64
	CostMicrodollars int64 // 1 USD = 1,000,000 microdollars
}

CostEvent represents a single token usage and cost record.

type CostEventWatcher

type CostEventWatcher struct {
	// contains filtered or unexported fields
}

CostEventWatcher watches a directory for new cost event JSON files.

func NewCostEventWatcher

func NewCostEventWatcher(dir string) (*CostEventWatcher, error)

NewCostEventWatcher creates a watcher for the given directory.

func (*CostEventWatcher) EventCh

func (w *CostEventWatcher) EventCh() <-chan RawCostEvent

EventCh returns the channel that emits parsed cost events.

func (*CostEventWatcher) Start

func (w *CostEventWatcher) Start()

Start begins watching for file events. Blocks until stopped.

func (*CostEventWatcher) Stop

func (w *CostEventWatcher) Stop()

Stop cancels the watcher and closes resources.

type CostPoller

type CostPoller struct {
	// contains filtered or unexported fields
}

CostPoller polls tmux capture-pane for non-hook tools and extracts cost events.

func NewCostPoller

func NewCostPoller(collector *Collector) *CostPoller

NewCostPoller creates a poller with deduplication.

func (*CostPoller) Poll

func (p *CostPoller) Poll(toolType, sessionID, capturedOutput string) ([]CostEvent, error)

Poll processes captured tmux output. Returns new cost events or nil if already seen.

type CostSummary

type CostSummary struct {
	TotalCostMicrodollars int64
	TotalInputTokens      int64
	TotalOutputTokens     int64
	TotalCacheReadTokens  int64
	TotalCacheWriteTokens int64
	EventCount            int
}

CostSummary aggregates cost data.

type DailyCost

type DailyCost struct {
	Date             time.Time
	CostMicrodollars int64
	Group            string
}

DailyCost represents cost for a single day.

type Fetcher

type Fetcher struct {
	CachePath string
	Pricer    *Pricer
	Logger    *slog.Logger
}

func (*Fetcher) CacheAge

func (f *Fetcher) CacheAge() time.Duration

func (*Fetcher) FetchAndCache

func (f *Fetcher) FetchAndCache() error

FetchAndCache writes current known prices to cache. Real HTML scraping is deferred — for now, writes hardcoded defaults.

func (*Fetcher) StartDaily

func (f *Fetcher) StartDaily(ctx context.Context)

StartDaily runs the fetch loop. Blocks until context is cancelled.

type GeminiOutputParser

type GeminiOutputParser struct {
	// contains filtered or unexported fields
}

GeminiOutputParser parses Gemini CLI token usage output.

func (*GeminiOutputParser) CanParse

func (p *GeminiOutputParser) CanParse(toolType string) bool

func (*GeminiOutputParser) Name

func (p *GeminiOutputParser) Name() string

func (*GeminiOutputParser) Parse

func (p *GeminiOutputParser) Parse(input string) ([]CostEvent, error)

type MiniMaxOutputParser added in v1.3.1

type MiniMaxOutputParser struct {
	// contains filtered or unexported fields
}

MiniMaxOutputParser parses MiniMax CLI/tool token usage output.

func (*MiniMaxOutputParser) CanParse added in v1.3.1

func (p *MiniMaxOutputParser) CanParse(toolType string) bool

func (*MiniMaxOutputParser) Name added in v1.3.1

func (p *MiniMaxOutputParser) Name() string

func (*MiniMaxOutputParser) Parse added in v1.3.1

func (p *MiniMaxOutputParser) Parse(input string) ([]CostEvent, error)

type ModelPrice

type ModelPrice struct {
	InputPerMtokMicro      int64
	OutputPerMtokMicro     int64
	CacheReadPerMtokMicro  int64
	CacheWritePerMtokMicro int64
}

ModelPrice holds per-model pricing in microdollars per million tokens.

type OpenAIOutputParser

type OpenAIOutputParser struct {
	// contains filtered or unexported fields
}

OpenAIOutputParser parses OpenAI/Codex CLI token usage output.

func (*OpenAIOutputParser) CanParse

func (p *OpenAIOutputParser) CanParse(toolType string) bool

func (*OpenAIOutputParser) Name

func (p *OpenAIOutputParser) Name() string

func (*OpenAIOutputParser) Parse

func (p *OpenAIOutputParser) Parse(input string) ([]CostEvent, error)

type Parser

type Parser interface {
	Name() string
	CanParse(toolType string) bool
	Parse(input string) ([]CostEvent, error)
}

Parser parses tool output into cost events.

type PriceOverride

type PriceOverride struct {
	InputPerMtok      float64 `toml:"input_per_mtok"`
	OutputPerMtok     float64 `toml:"output_per_mtok"`
	CacheReadPerMtok  float64 `toml:"cache_read_per_mtok"`
	CacheWritePerMtok float64 `toml:"cache_write_per_mtok"`
}

PriceOverride holds user-configured pricing in USD per million tokens.

type Pricer

type Pricer struct {
	// contains filtered or unexported fields
}

Pricer resolves model pricing with fallback: override > cache > hardcoded.

func NewPricer

func NewPricer(cfg PricerConfig) *Pricer

NewPricer creates a Pricer with hardcoded defaults and optional overrides.

func (*Pricer) CacheAge

func (p *Pricer) CacheAge() time.Duration

CacheAge returns the age of the cache, or -1 if no cache is loaded.

func (*Pricer) ComputeCost

func (p *Pricer) ComputeCost(model string, input, output, cacheRead, cacheWrite int64) int64

ComputeCost calculates cost in microdollars for token usage on a model.

func (*Pricer) GetPrice

func (p *Pricer) GetPrice(model string) (ModelPrice, bool)

GetPrice returns the price for a model with fallback: override > cache > hardcoded.

func (*Pricer) LoadCache

func (p *Pricer) LoadCache() error

LoadCache reads pricing.json from CachePath.

func (*Pricer) SaveCache

func (p *Pricer) SaveCache(models map[string]pricingCacheModel) error

SaveCache writes pricing.json to CachePath.

type PricerConfig

type PricerConfig struct {
	CachePath string
	Overrides map[string]PriceOverride
}

PricerConfig configures the Pricer.

type RawCostEvent

type RawCostEvent struct {
	InstanceID       string `json:"instance_id"`
	Model            string `json:"model"`
	InputTokens      int64  `json:"input_tokens"`
	OutputTokens     int64  `json:"output_tokens"`
	CacheReadTokens  int64  `json:"cache_read_tokens"`
	CacheWriteTokens int64  `json:"cache_write_tokens"`
	Timestamp        int64  `json:"ts"`
}

RawCostEvent is the JSON structure written by hook_handler.

type SessionCost

type SessionCost struct {
	SessionID        string
	SessionTitle     string
	Group            string
	CostMicrodollars int64
	EventCount       int
}

SessionCost represents per-session cost totals.

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store persists and queries cost events in SQLite.

func NewStore

func NewStore(db *sql.DB) *Store

NewStore creates a Store using an existing database connection.

func (*Store) CostByModel

func (s *Store) CostByModel() (map[string]int64, error)

CostByModel returns total cost per model.

func (*Store) CostByModelForSession

func (s *Store) CostByModelForSession(sessionID string) (map[string]int64, error)

CostByModelForSession returns cost per model for a specific session.

func (*Store) DB

func (s *Store) DB() *sql.DB

DB returns the underlying database for transactional operations.

func (*Store) DailyBySession

func (s *Store) DailyBySession(sessionID string, from, to time.Time) ([]DailyCost, error)

DailyBySession returns daily costs for a specific session.

func (*Store) GlobalRunningTotal

func (s *Store) GlobalRunningTotal(tx *sql.Tx, since time.Time) (int64, error)

GlobalRunningTotal returns the sum of all costs within a time window (for use in a transaction).

func (*Store) GroupRunningTotal

func (s *Store) GroupRunningTotal(tx *sql.Tx, sessionIDs []string, since time.Time) (int64, error)

GroupRunningTotal returns the sum of costs for a set of sessions within a time window.

func (*Store) ProjectedMonthly

func (s *Store) ProjectedMonthly() (int64, error)

ProjectedMonthly estimates monthly spend based on rolling 7-day average.

func (*Store) PurgeOlderThan

func (s *Store) PurgeOlderThan(days int) (int64, error)

PurgeOlderThan deletes events older than the given number of days. Returns count deleted.

func (*Store) RunningTotal

func (s *Store) RunningTotal(tx *sql.Tx, sessionID string, since time.Time) (int64, error)

RunningTotal returns the sum of costs for a session within a time window (for use in a transaction).

func (*Store) TopSessionsByCost

func (s *Store) TopSessionsByCost(limit int) ([]SessionCost, error)

TopSessionsByCost returns the top N sessions by total cost. Joins with instances table to get session titles and groups.

func (*Store) TotalByDateRange

func (s *Store) TotalByDateRange(from, to time.Time) ([]DailyCost, error)

TotalByDateRange returns daily costs within a date range.

func (*Store) TotalBySession

func (s *Store) TotalBySession(sessionID string) (CostSummary, error)

TotalBySession returns aggregated costs for a session.

func (*Store) TotalThisMonth

func (s *Store) TotalThisMonth() (CostSummary, error)

TotalThisMonth returns this month's total costs.

func (*Store) TotalThisWeek

func (s *Store) TotalThisWeek() (CostSummary, error)

TotalThisWeek returns this week's total costs (Monday start).

func (*Store) TotalToday

func (s *Store) TotalToday() (CostSummary, error)

TotalToday returns today's total costs.

func (*Store) WriteCostEvent

func (s *Store) WriteCostEvent(ev CostEvent) error

WriteCostEvent inserts a cost event.

func (*Store) WriteCostEventTx

func (s *Store) WriteCostEventTx(tx *sql.Tx, ev CostEvent) error

WriteCostEventTx inserts a cost event within a transaction.

type SyncResult

type SyncResult struct {
	SessionsScanned int
	EventsImported  int
	EventsSkipped   int
	Errors          []string
}

SyncResult holds the result of a historical sync operation.

func SyncFromTranscripts

func SyncFromTranscripts(store *Store, pricer *Pricer, sessions []SyncSession) SyncResult

SyncFromTranscripts reads historical usage from Claude transcript files and backfills cost_events for managed sessions.

type SyncSession

type SyncSession struct {
	InstanceID      string
	ClaudeSessionID string
	ProjectPath     string
	Tool            string
}

SyncSession holds the info needed to locate a session's transcript.

type TranscriptEntry

type TranscriptEntry struct {
	Type    string `json:"type"`
	UUID    string `json:"uuid"`
	Message struct {
		Model string `json:"model"`
		Usage struct {
			InputTokens              int64 `json:"input_tokens"`
			OutputTokens             int64 `json:"output_tokens"`
			CacheCreationInputTokens int64 `json:"cache_creation_input_tokens"`
			CacheReadInputTokens     int64 `json:"cache_read_input_tokens"`
		} `json:"usage"`
	} `json:"message"`
	// Progress entries nest usage inside data.message.message
	Data      *progressData `json:"data,omitempty"`
	Timestamp string        `json:"timestamp"` // ISO 8601
}

TranscriptEntry represents one line of a Claude transcript JSONL file. Handles both "assistant" entries (direct usage) and "progress" entries (subagent usage).

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL