// // SessionStats.swift // oAI // // Session statistics tracking // // SPDX-License-Identifier: AGPL-3.0-or-later // Copyright (C) 2026 Rune Olsen // // This file is part of oAI. // // oAI is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // oAI is distributed in the hope that it will be useful, but WITHOUT // ANY WARRANTY; without even the implied warranty of MERCHANTABILITY // or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General // Public License for more details. // // You should have received a copy of the GNU Affero General Public // License along with oAI. If not, see . import Foundation struct SessionStats { var totalInputTokens: Int = 0 var totalOutputTokens: Int = 0 var totalCost: Double = 0.0 var messageCount: Int = 0 var hasCostData: Bool = false var totalTokens: Int { totalInputTokens + totalOutputTokens } var totalTokensDisplay: String { if totalTokens >= 1_000_000 { return String(format: "%.1fM", Double(totalTokens) / 1_000_000) } else if totalTokens >= 1000 { return String(format: "%.1fK", Double(totalTokens) / 1000) } else { return "\(totalTokens)" } } var totalCostDisplay: String { hasCostData ? String(format: "$%.4f", totalCost) : "N/A" } var averageCostPerMessage: Double { guard messageCount > 0 else { return 0.0 } return totalCost / Double(messageCount) } var averageCostDisplay: String { hasCostData ? String(format: "$%.4f", averageCostPerMessage) : "N/A" } mutating func addMessage(inputTokens: Int?, outputTokens: Int?, cost: Double?) { if let input = inputTokens { totalInputTokens += input } if let output = outputTokens { totalOutputTokens += output } if let messageCost = cost { totalCost += messageCost hasCostData = true } messageCount += 1 } mutating func reset() { totalInputTokens = 0 totalOutputTokens = 0 totalCost = 0.0 messageCount = 0 hasCostData = false } }