100 lines · 3.8 KB · Swift
RawDownload
import Foundation /// Aggregated stats from local `~/.grok/sessions/**/signals.json` files./// Used as a local fallback view when the JSON-RPC billing call is unavailable.public struct GrokLocalSessionSummary: Sendable {    public let sessionCount: Int    public let totalTokens: Int    public let lastSessionAt: Date?    public let primaryModel: String?    public let models: [String]     public init(        sessionCount: Int,        totalTokens: Int,        lastSessionAt: Date?,        primaryModel: String?,        models: [String])    {        self.sessionCount = sessionCount        self.totalTokens = totalTokens        self.lastSessionAt = lastSessionAt        self.primaryModel = primaryModel        self.models = models    }} public enum GrokLocalSessionScanner {    public static let defaultLookbackDays = 30     /// Walk `~/.grok/sessions/<encoded_cwd>/<session_id>/signals.json` and aggregate stats.    public static func summarize(        env: [String: String] = ProcessInfo.processInfo.environment,        fileManager: FileManager = .default,        lookbackDays: Int = defaultLookbackDays,        now: Date = .init()) -> GrokLocalSessionSummary    {        let root = GrokCredentialsStore.grokHomeURL(env: env, fileManager: fileManager)            .appendingPathComponent("sessions", isDirectory: true)        guard let rootEnum = fileManager.enumerator(            at: root,            includingPropertiesForKeys: [.contentModificationDateKey, .isDirectoryKey],            options: [.skipsHiddenFiles])        else {            return GrokLocalSessionSummary(                sessionCount: 0,                totalTokens: 0,                lastSessionAt: nil,                primaryModel: nil,                models: [])        }         let lookbackCutoff = Calendar.current.date(byAdding: .day, value: -lookbackDays, to: now) ?? now        var sessionCount = 0        var totalTokens = 0        var lastSessionAt: Date?        var modelCounts: [String: Int] = [:]         while let url = rootEnum.nextObject() as? URL {            guard url.lastPathComponent == "signals.json" else { continue }            let attrs = try? url.resourceValues(forKeys: [.contentModificationDateKey])            let mtime = attrs?.contentModificationDate ?? Date.distantPast            guard mtime >= lookbackCutoff else { continue }             guard let data = try? Data(contentsOf: url),                  let json = try? JSONSerialization.jsonObject(with: data) as? [String: Any]            else { continue }             sessionCount += 1            let beforeCompaction = (json["totalTokensBeforeCompaction"] as? Int) ?? 0            let contextUsed = (json["contextTokensUsed"] as? Int) ?? 0            totalTokens += beforeCompaction + contextUsed             if mtime > (lastSessionAt ?? Date.distantPast) {                lastSessionAt = mtime            }             if let primary = (json["primaryModelId"] as? String)?.trimmingCharacters(in: .whitespacesAndNewlines),               !primary.isEmpty            {                modelCounts[primary, default: 0] += 1            }            if let models = json["modelsUsed"] as? [String] {                for model in models {                    let trimmed = model.trimmingCharacters(in: .whitespacesAndNewlines)                    if !trimmed.isEmpty {                        modelCounts[trimmed, default: 0] += 1                    }                }            }        }         let sortedModels = modelCounts.sorted { $0.value > $1.value }.map(\.key)        return GrokLocalSessionSummary(            sessionCount: sessionCount,            totalTokens: totalTokens,            lastSessionAt: lastSessionAt,            primaryModel: sortedModels.first,            models: sortedModels)    }}