From cfbbb9d6db231811da85d06105086e423c8f06bf Mon Sep 17 00:00:00 2001 From: teernisse Date: Thu, 19 Feb 2026 13:00:45 -0500 Subject: [PATCH] feat: add domain model types for session metrics and statistics MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Define the core data structures that flow through the entire pipeline: - model/session.go: SessionStats (per-session aggregates including token counts across 5 categories — input, output, cache_write_5m, cache_write_1h, cache_read), APICall (deduplicated by message.id, keyed to the final billed usage), and ModelUsage (per-model breakdown within a session). Tracks subagent relationships via IsSubagent/ParentSession fields. - model/metrics.go: Higher-order aggregate types — SummaryStats (top-level totals with per-active-day rates for cost, tokens, sessions, and minutes), DailyStats/HourlyStats/WeeklyStats (time-bucketed views), ModelStats (cross-session model comparison with share percentages), ProjectStats (per-project ranking), and PeriodComparison (current vs previous period for delta display). - model/budget.go: BudgetStats with plan ceiling, custom budget, burn rate, and projected monthly spend for the budget tab. Co-Authored-By: Claude Opus 4.6 --- internal/model/budget.go | 12 +++++ internal/model/metrics.go | 94 +++++++++++++++++++++++++++++++++++++++ internal/model/session.go | 55 +++++++++++++++++++++++ 3 files changed, 161 insertions(+) create mode 100644 internal/model/budget.go create mode 100644 internal/model/metrics.go create mode 100644 internal/model/session.go diff --git a/internal/model/budget.go b/internal/model/budget.go new file mode 100644 index 0000000..0f968e7 --- /dev/null +++ b/internal/model/budget.go @@ -0,0 +1,12 @@ +package model + +// BudgetStats holds budget tracking and forecast data. +type BudgetStats struct { + PlanCeiling float64 + CustomBudget *float64 + CurrentSpend float64 + DailyBurnRate float64 + ProjectedMonthly float64 + DaysRemaining int + BudgetUsedPercent float64 +} diff --git a/internal/model/metrics.go b/internal/model/metrics.go new file mode 100644 index 0000000..5b8ff58 --- /dev/null +++ b/internal/model/metrics.go @@ -0,0 +1,94 @@ +package model + +import "time" + +// SummaryStats holds the top-level aggregate across all sessions. +type SummaryStats struct { + TotalSessions int + TotalPrompts int + TotalAPICalls int + TotalDurationSecs int64 + ActiveDays int + + InputTokens int64 + OutputTokens int64 + CacheCreation5mTokens int64 + CacheCreation1hTokens int64 + CacheReadTokens int64 + TotalBilledTokens int64 + + EstimatedCost float64 + ActualCost *float64 + CacheSavings float64 + CacheHitRate float64 + + CostPerDay float64 + TokensPerDay int64 + SessionsPerDay float64 + PromptsPerDay float64 + MinutesPerDay float64 +} + +// DailyStats holds metrics for a single calendar day. +type DailyStats struct { + Date time.Time + Sessions int + Prompts int + APICalls int + DurationSecs int64 + InputTokens int64 + OutputTokens int64 + CacheCreation5m int64 + CacheCreation1h int64 + CacheReadTokens int64 + EstimatedCost float64 + ActualCost *float64 +} + +// ModelStats holds aggregated metrics for a single model. +type ModelStats struct { + Model string + APICalls int + InputTokens int64 + OutputTokens int64 + CacheCreation5m int64 + CacheCreation1h int64 + CacheReadTokens int64 + EstimatedCost float64 + SharePercent float64 + TrendDirection int // -1, 0, +1 vs previous period +} + +// ProjectStats holds aggregated metrics for a single project. +type ProjectStats struct { + Project string + Sessions int + Prompts int + TotalTokens int64 + EstimatedCost float64 + TrendDirection int +} + +// HourlyStats holds prompt/session counts for one hour of the day. +type HourlyStats struct { + Hour int + Prompts int + Sessions int + Tokens int64 +} + +// WeeklyStats holds metrics for one calendar week. +type WeeklyStats struct { + WeekStart time.Time + Sessions int + Prompts int + TotalTokens int64 + DurationSecs int64 + EstimatedCost float64 +} + +// PeriodComparison holds current and previous period data for delta computation. +type PeriodComparison struct { + Current SummaryStats + Previous SummaryStats +} diff --git a/internal/model/session.go b/internal/model/session.go new file mode 100644 index 0000000..fe079e5 --- /dev/null +++ b/internal/model/session.go @@ -0,0 +1,55 @@ +package model + +import "time" + +// APICall represents one deduplicated API request (final state of a message.id). +type APICall struct { + MessageID string + Model string + Timestamp time.Time + InputTokens int64 + OutputTokens int64 + CacheCreation5mTokens int64 + CacheCreation1hTokens int64 + CacheReadTokens int64 + ServiceTier string + EstimatedCost float64 +} + +// ModelUsage tracks per-model token usage within a session. +type ModelUsage struct { + APICalls int + InputTokens int64 + OutputTokens int64 + CacheCreation5mTokens int64 + CacheCreation1hTokens int64 + CacheReadTokens int64 + EstimatedCost float64 +} + +// SessionStats holds aggregated metrics for a single session file. +type SessionStats struct { + SessionID string + Project string + ProjectPath string + FilePath string + IsSubagent bool + ParentSession string + StartTime time.Time + EndTime time.Time + DurationSecs int64 + + UserMessages int + APICalls int + + InputTokens int64 + OutputTokens int64 + CacheCreation5mTokens int64 + CacheCreation1hTokens int64 + CacheReadTokens int64 + + Models map[string]*ModelUsage + + EstimatedCost float64 + CacheHitRate float64 +}