import Foundation public enum Provider: String, CaseIterable, Codable, Hashable, Sendable { case claude = "Claude" case codex = "Codex" case gemini = "Gemini" case hermes = "Hermes" case opencode = "OpenCode" } public struct UsageRecord: Identifiable, Hashable, Sendable { public let id: UUID public let provider: Provider public let source: String public let sourcePath: String public let timestamp: Date public let sessionID: String public let model: String public let inputTokens: Int public let outputTokens: Int public let cachedTokens: Int public let reasoningTokens: Int public let toolTokens: Int public let totalTokens: Int public init( id: UUID = UUID(), provider: Provider, source: String, sourcePath: String, timestamp: Date, sessionID: String, model: String, inputTokens: Int, outputTokens: Int, cachedTokens: Int, reasoningTokens: Int, toolTokens: Int, explicitTotal: Int? = nil ) { self.id = id self.provider = provider self.source = source self.sourcePath = sourcePath self.timestamp = timestamp self.sessionID = sessionID self.model = model self.inputTokens = inputTokens self.outputTokens = outputTokens self.cachedTokens = cachedTokens self.reasoningTokens = reasoningTokens self.toolTokens = toolTokens self.totalTokens = explicitTotal ?? inputTokens + outputTokens + cachedTokens + reasoningTokens + toolTokens } } public struct TokenBucket: Hashable, Sendable { public let provider: Provider? public var inputTokens: Int = 0 public var outputTokens: Int = 0 public var cachedTokens: Int = 0 public var reasoningTokens: Int = 0 public var toolTokens: Int = 0 public var totalTokens: Int = 0 public var count: Int = 0 public init(provider: Provider? = nil) { self.provider = provider } public mutating func add(_ record: UsageRecord) { add( inputTokens: record.inputTokens, outputTokens: record.outputTokens, cachedTokens: record.cachedTokens, reasoningTokens: record.reasoningTokens, toolTokens: record.toolTokens, totalTokens: record.totalTokens ) } public mutating func add( inputTokens: Int, outputTokens: Int, cachedTokens: Int, reasoningTokens: Int, toolTokens: Int, totalTokens: Int ) { self.inputTokens += inputTokens self.outputTokens += outputTokens self.cachedTokens += cachedTokens self.reasoningTokens += reasoningTokens self.toolTokens += toolTokens self.totalTokens += totalTokens count += 1 } } public struct SummaryCards: Hashable, Sendable { public let todayTokens: Int public let monthTokens: Int public let totalTokens: Int public let cacheHitRate: Int public let sessionCount: Int } public struct DailyPoint: Identifiable, Hashable, Sendable { public let id = UUID() public let date: Date public let values: [Provider: Int] } public enum TrendMode: String, CaseIterable, Sendable { case daily = "每日" case weekly = "每周" case monthly = "每月" case yearly = "每年" } public struct ToolRow: Identifiable, Hashable, Sendable { public let id = UUID() public let provider: Provider public let inputTokens: Int public let outputTokens: Int public let cachedTokens: Int public let totalTokens: Int public let trendTokens: [Int] } public struct DailyUsageDetail: Identifiable, Hashable, Sendable { public var id: Date { date } public let date: Date public var inputTokens: Int public var outputTokens: Int public var cachedTokens: Int public var totalTokens: Int public var providerTotals: [Provider: Int] public init( date: Date, inputTokens: Int = 0, outputTokens: Int = 0, cachedTokens: Int = 0, totalTokens: Int = 0, providerTotals: [Provider: Int] = [:] ) { self.date = date self.inputTokens = inputTokens self.outputTokens = outputTokens self.cachedTokens = cachedTokens self.totalTokens = totalTokens self.providerTotals = providerTotals } public mutating func add(_ record: UsageRecord) { add( provider: record.provider, inputTokens: record.inputTokens, outputTokens: record.outputTokens, cachedTokens: record.cachedTokens, totalTokens: record.totalTokens ) } public mutating func add( provider: Provider, inputTokens: Int, outputTokens: Int, cachedTokens: Int, totalTokens: Int ) { self.inputTokens += inputTokens self.outputTokens += outputTokens self.cachedTokens += cachedTokens self.totalTokens += totalTokens providerTotals[provider, default: 0] += totalTokens } } public struct Insight: Identifiable, Hashable, Sendable { public enum Tone: String, Sendable { case warning case positive case accent } public let id = UUID() public let tone: Tone public let title: String public let message: String } public struct UsageSummary: Sendable { public let generatedAt: Date public let records: [UsageRecord] public let cards: SummaryCards public let providerTotals: [Provider: TokenBucket] public let todayProviderTotals: [Provider: TokenBucket] public let dailyTrend: [DailyPoint] public let trendPointsByMode: [TrendMode: [DailyPoint]] public let dailyDetails: [DailyUsageDetail] public let toolRows: [ToolRow] public let insights: [Insight] }