import Foundation private final class PiSessionISO8601FormatterBox: @unchecked Sendable { let lock = NSLock() let withFractional: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] return formatter }() let plain: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime] return formatter }()} enum PiSessionCostScanner { struct Options { var piSessionsRoot: URL? var ompSessionsRoot: URL? var cacheRoot: URL? var refreshMinIntervalSeconds: TimeInterval = 60 var forceRescan: Bool = false init( piSessionsRoot: URL? = nil, ompSessionsRoot: URL? = nil, cacheRoot: URL? = nil, refreshMinIntervalSeconds: TimeInterval = 60, forceRescan: Bool = false) { self.piSessionsRoot = piSessionsRoot self.ompSessionsRoot = ompSessionsRoot self.cacheRoot = cacheRoot self.refreshMinIntervalSeconds = refreshMinIntervalSeconds self.forceRescan = forceRescan } } private struct ParseResult { let contributions: [String: [String: [String: PiPackedUsage]]] let unkeyedContributions: [String: [String: [String: PiPackedUsage]]] let entryUsages: [String: PiSessionEntryUsage] let parsedBytes: Int64 let sessionID: String? let lastModelContext: PiModelContext? } private struct SessionFileCandidate { let url: URL let rootIndex: Int } private struct AssistantIdentity { let provider: UsageProvider let modelName: String } private struct ModelsDevPricingContext { let catalog: ModelsDevCatalog? let cacheRoot: URL? let pricingKey: String } private struct ScanContext { let range: CostUsageScanner.CostUsageDayRange let forceRescan: Bool let pricingContext: ModelsDevPricingContext let checkCancellation: CostUsageScanner.CancellationCheck? } private static let costScale = 1_000_000_000.0 /// Bump for Pi-only cost formula changes not represented by the parser or pricing fingerprints. private static let costFormulaVersion = 1 private static let maxLineBytes = 16 * 1024 * 1024 private static let maxSafeRoundedInt = Double(Int.max) - 1 private static let sessionStartFilenameRegex = try? NSRegularExpression( pattern: "^(\\d{4}-\\d{2}-\\d{2})T(\\d{2})-(\\d{2})-(\\d{2})-(\\d{3})Z_") private static let isoFormatterBox = PiSessionISO8601FormatterBox() static func loadDailyReport( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), options: Options = Options()) -> CostUsageDailyReport { ( try? self.loadDailyReportCancellable( provider: provider, since: since, until: until, now: now, options: options, checkCancellation: nil)) ?? CostUsageDailyReport(data: [], summary: nil) } static func loadDailyReportCancellable( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), options: Options = Options(), checkCancellation: CostUsageScanner.CancellationCheck?) throws -> CostUsageDailyReport { guard provider == .codex || provider == .claude else { return CostUsageDailyReport(data: [], summary: nil) } let range = CostUsageScanner.CostUsageDayRange(since: since, until: until) var cache = PiSessionCostCacheIO.load(cacheRoot: options.cacheRoot) let nowMs = Int64(now.timeIntervalSince1970 * 1000) let refreshMs = Int64(max(0, options.refreshMinIntervalSeconds) * 1000) let pricingContext = self.pricingContext(now: now, cacheRoot: options.cacheRoot) let windowExpanded = self.requestedWindowExpandsCache(range: range, cache: cache) let pricingChanged = cache.pricingKey != pricingContext.pricingKey let shouldRefresh = options.forceRescan || windowExpanded || pricingChanged || refreshMs == 0 || cache.lastScanUnixMs == 0 || nowMs - cache.lastScanUnixMs > refreshMs if shouldRefresh { try checkCancellation?() let roots = self.defaultSessionRoots(options: options) let startCutoff = self.dateFromDayKey(range.scanSinceKey) ?? since var files: [SessionFileCandidate] = [] for (rootIndex, root) in roots.enumerated() { for url in self.listPiSessionFiles(root: root, startCutoffLocal: startCutoff) { files.append(SessionFileCandidate(url: url, rootIndex: rootIndex)) } } files.sort { lhs, rhs in lhs.rootIndex == rhs.rootIndex ? lhs.url.path < rhs.url.path : lhs.rootIndex < rhs.rootIndex } let filePathsInScan = Set(files.map(\.url.path)) for file in files { try self.scanPiSessionFile( fileURL: file.url, cache: &cache, context: ScanContext( range: range, forceRescan: options.forceRescan || windowExpanded || pricingChanged, pricingContext: pricingContext, checkCancellation: checkCancellation)) } try checkCancellation?() for key in cache.files.keys where !filePathsInScan.contains(key) { if let old = cache.files[key] { self.applyContributions( daysByProvider: &cache.daysByProvider, contributions: old.contributions, sign: -1) } cache.files.removeValue(forKey: key) } try self.rebuildDailyUsage(cache: &cache, files: files, checkCancellation: checkCancellation) cache.scanSinceKey = range.scanSinceKey cache.scanUntilKey = range.scanUntilKey cache.pricingKey = pricingContext.pricingKey cache.lastScanUnixMs = nowMs try checkCancellation?() PiSessionCostCacheIO.save(cache: cache, cacheRoot: options.cacheRoot) } return self.buildReport( provider: provider, cache: cache, range: range, pricingContext: pricingContext) } struct CachedDailyReportResult { let report: CostUsageDailyReport let lastScanAt: Date? } static func loadCachedDailyReport( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), cacheRoot: URL? = nil) -> CostUsageDailyReport? { self.loadCachedDailyReportResult( provider: provider, since: since, until: until, now: now, cacheRoot: cacheRoot)?.report } static func loadCachedDailyReportResult( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), cacheRoot: URL? = nil) -> CachedDailyReportResult? { guard provider == .codex || provider == .claude else { return nil } let range = CostUsageScanner.CostUsageDayRange(since: since, until: until) let cache = PiSessionCostCacheIO.load(cacheRoot: cacheRoot) guard !cache.daysByProvider.isEmpty else { return nil } guard !self.requestedWindowExpandsCache(range: range, cache: cache) else { return nil } let pricingContext = self.pricingContext(now: now, cacheRoot: cacheRoot) guard cache.pricingKey == pricingContext.pricingKey else { return nil } let report = self.buildReport( provider: provider, cache: cache, range: range, pricingContext: pricingContext) guard !report.data.isEmpty else { return nil } let lastScanAt = cache.lastScanUnixMs > 0 ? Date(timeIntervalSince1970: TimeInterval(cache.lastScanUnixMs) / 1000) : nil return CachedDailyReportResult(report: report, lastScanAt: lastScanAt) } private static func pricingContext(now: Date, cacheRoot: URL?) -> ModelsDevPricingContext { let modelsDevArtifact = ModelsDevCache.load(now: now, cacheRoot: cacheRoot).artifact return ModelsDevPricingContext( catalog: modelsDevArtifact?.catalog, cacheRoot: cacheRoot, pricingKey: CostUsagePricingKey.codex( modelsDevArtifact: modelsDevArtifact, formulaVersion: Self.costFormulaVersion, parserHash: CodexParserHash.value, modelsDevProviderIDs: ["anthropic", "openai"])) } private static func requestedWindowExpandsCache( range: CostUsageScanner.CostUsageDayRange, cache: PiSessionCostCache) -> Bool { guard let cachedSince = cache.scanSinceKey, let cachedUntil = cache.scanUntilKey else { return true } if range.scanSinceKey < cachedSince { return true } if range.scanUntilKey > cachedUntil { return true } return false } private static func defaultSessionRoots(options: Options) -> [URL] { if options.piSessionsRoot != nil || options.ompSessionsRoot != nil { return [options.piSessionsRoot, options.ompSessionsRoot].compactMap(\.self) } let home = FileManager.default.homeDirectoryForCurrentUser return [".pi", ".omp"].map { directory in home .appendingPathComponent(directory, isDirectory: true) .appendingPathComponent("agent", isDirectory: true) .appendingPathComponent("sessions", isDirectory: true) } } private static func listPiSessionFiles(root: URL, startCutoffLocal: Date) -> [URL] { guard FileManager.default.fileExists(atPath: root.path) else { return [] } let keys: Set<URLResourceKey> = [.isRegularFileKey, .contentModificationDateKey] guard let enumerator = FileManager.default.enumerator( at: root, includingPropertiesForKeys: Array(keys), options: [.skipsHiddenFiles]) else { return [] } var output: [URL] = [] while let item = enumerator.nextObject() as? URL { guard item.pathExtension.lowercased() == "jsonl" else { continue } let values = try? item.resourceValues(forKeys: keys) guard values?.isRegularFile == true else { continue } let startedAt = self.parseSessionStartFromFilename(item.lastPathComponent) let modifiedAt = values?.contentModificationDate if self .shouldIncludeFile(startedAt: startedAt, modifiedAt: modifiedAt, startCutoffLocal: startCutoffLocal) { output.append(item) } } return output.sorted(by: { $0.path < $1.path }) } private static func shouldIncludeFile( startedAt: Date?, modifiedAt: Date?, startCutoffLocal: Date) -> Bool { if let modifiedAt, self.localMidnight(modifiedAt) >= startCutoffLocal { return true } if let startedAt, self.localMidnight(startedAt) >= startCutoffLocal { return true } return false } private static func scanPiSessionFile( fileURL: URL, cache: inout PiSessionCostCache, context: ScanContext) throws { try context.checkCancellation?() let path = fileURL.path let attrs = (try? FileManager.default.attributesOfItem(atPath: path)) ?? [:] let mtime = (attrs[.modificationDate] as? Date)?.timeIntervalSince1970 ?? 0 let size = (attrs[.size] as? NSNumber)?.int64Value ?? 0 let mtimeMs = Int64(mtime * 1000) func storeFileUsage(_ usage: PiSessionFileUsage) { cache.files[path] = usage } let cached = cache.files[path] if !context.forceRescan, let cached, cached.mtimeUnixMs == mtimeMs, cached.size == size { return } if !context.forceRescan, let cached, size > cached.size, cached.parsedBytes > 0, cached.parsedBytes <= size { let delta = try self.parsePiSessionFile( fileURL: fileURL, range: context.range, startOffset: cached.parsedBytes, initialSessionID: cached.sessionID, initialModelContext: cached.lastModelContext, pricingContext: context.pricingContext, checkCancellation: context.checkCancellation) if !delta.contributions.isEmpty { self.applyContributions( daysByProvider: &cache.daysByProvider, contributions: delta.contributions, sign: 1) } let merged = self.mergedContributions(existing: cached.contributions, delta: delta.contributions) let mergedUnkeyed = self.mergedContributions( existing: cached.unkeyedContributions, delta: delta.unkeyedContributions) let mergedEntryUsages = cached.entryUsages.merging(delta.entryUsages) { _, appended in appended } storeFileUsage(PiSessionFileUsage( mtimeUnixMs: mtimeMs, size: size, parsedBytes: delta.parsedBytes, sessionID: delta.sessionID ?? cached.sessionID, lastModelContext: delta.lastModelContext, contributions: merged, unkeyedContributions: mergedUnkeyed, entryUsages: mergedEntryUsages)) return } if let cached { self.applyContributions( daysByProvider: &cache.daysByProvider, contributions: cached.contributions, sign: -1) } let parsed = try self.parsePiSessionFile( fileURL: fileURL, range: context.range, pricingContext: context.pricingContext, checkCancellation: context.checkCancellation) if !parsed.contributions.isEmpty { self.applyContributions(daysByProvider: &cache.daysByProvider, contributions: parsed.contributions, sign: 1) } storeFileUsage(PiSessionFileUsage( mtimeUnixMs: mtimeMs, size: size, parsedBytes: parsed.parsedBytes, sessionID: parsed.sessionID, lastModelContext: parsed.lastModelContext, contributions: parsed.contributions, unkeyedContributions: parsed.unkeyedContributions, entryUsages: parsed.entryUsages)) } private static func parsePiSessionFile( fileURL: URL, range: CostUsageScanner.CostUsageDayRange, startOffset: Int64 = 0, initialSessionID: String? = nil, initialModelContext: PiModelContext? = nil, pricingContext: ModelsDevPricingContext? = nil, checkCancellation: CostUsageScanner.CancellationCheck? = nil) throws -> ParseResult { var sessionID = initialSessionID var currentModelContext = initialModelContext var contributions: [String: [String: [String: PiPackedUsage]]] = [:] var unkeyedContributions: [String: [String: [String: PiPackedUsage]]] = [:] var entryUsages: [String: PiSessionEntryUsage] = [:] func add( provider: UsageProvider, dayKey: String, modelName: String, usage: PiPackedUsage, entryID: String?) { guard !usage.isZero else { return } guard CostUsageScanner.CostUsageDayRange.isInRange( dayKey: dayKey, since: range.scanSinceKey, until: range.scanUntilKey) else { return } let providerKey = provider.rawValue var providerDays = contributions[providerKey] ?? [:] var dayModels = providerDays[dayKey] ?? [:] let merged = self.addPacked(a: dayModels[modelName] ?? PiPackedUsage(), b: usage, sign: 1) if merged.isZero { dayModels.removeValue(forKey: modelName) } else { dayModels[modelName] = merged } if dayModels.isEmpty { providerDays.removeValue(forKey: dayKey) } else { providerDays[dayKey] = dayModels } if providerDays.isEmpty { contributions.removeValue(forKey: providerKey) } else { contributions[providerKey] = providerDays } if let entryID { entryUsages[entryID] = PiSessionEntryUsage( providerRawValue: providerKey, dayKey: dayKey, modelName: modelName, usage: usage) } else { var providerDays = unkeyedContributions[providerKey] ?? [:] var dayModels = providerDays[dayKey] ?? [:] dayModels[modelName] = self.addPacked( a: dayModels[modelName] ?? PiPackedUsage(), b: usage, sign: 1) providerDays[dayKey] = dayModels unkeyedContributions[providerKey] = providerDays } } let parsedBytes: Int64 do { parsedBytes = try CostUsageJsonl.scan( fileURL: fileURL, offset: startOffset, maxLineBytes: Self.maxLineBytes, prefixBytes: Self.maxLineBytes, checkCancellation: checkCancellation, onLine: { line in guard !line.bytes.isEmpty, !line.wasTruncated else { return } autoreleasepool { guard let object = (try? JSONSerialization.jsonObject(with: line.bytes)) as? [String: Any] else { return } guard let type = object["type"] as? String else { return } if type == "session" { sessionID = sessionID ?? self.sessionIdentifier(from: object) return } if type == "model_change" { currentModelContext = self.modelContext(from: object) return }Lines 1–500 of 1083. Load more
import Foundation private final class PiSessionISO8601FormatterBox: @unchecked Sendable { let lock = NSLock() let withFractional: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime, .withFractionalSeconds] return formatter }() let plain: ISO8601DateFormatter = { let formatter = ISO8601DateFormatter() formatter.formatOptions = [.withInternetDateTime] return formatter }() } enum PiSessionCostScanner { struct Options { var piSessionsRoot: URL? var ompSessionsRoot: URL? var cacheRoot: URL? var refreshMinIntervalSeconds: TimeInterval = 60 var forceRescan: Bool = false init( piSessionsRoot: URL? = nil, ompSessionsRoot: URL? = nil, cacheRoot: URL? = nil, refreshMinIntervalSeconds: TimeInterval = 60, forceRescan: Bool = false) { self.piSessionsRoot = piSessionsRoot self.ompSessionsRoot = ompSessionsRoot self.cacheRoot = cacheRoot self.refreshMinIntervalSeconds = refreshMinIntervalSeconds self.forceRescan = forceRescan } } private struct ParseResult { let contributions: [String: [String: [String: PiPackedUsage]]] let unkeyedContributions: [String: [String: [String: PiPackedUsage]]] let entryUsages: [String: PiSessionEntryUsage] let parsedBytes: Int64 let sessionID: String? let lastModelContext: PiModelContext? } private struct SessionFileCandidate { let url: URL let rootIndex: Int } private struct AssistantIdentity { let provider: UsageProvider let modelName: String } private struct ModelsDevPricingContext { let catalog: ModelsDevCatalog? let cacheRoot: URL? let pricingKey: String } private struct ScanContext { let range: CostUsageScanner.CostUsageDayRange let forceRescan: Bool let pricingContext: ModelsDevPricingContext let checkCancellation: CostUsageScanner.CancellationCheck? } private static let costScale = 1_000_000_000.0 /// Bump for Pi-only cost formula changes not represented by the parser or pricing fingerprints. private static let costFormulaVersion = 1 private static let maxLineBytes = 16 * 1024 * 1024 private static let maxSafeRoundedInt = Double(Int.max) - 1 private static let sessionStartFilenameRegex = try? NSRegularExpression( pattern: "^(\\d{4}-\\d{2}-\\d{2})T(\\d{2})-(\\d{2})-(\\d{2})-(\\d{3})Z_") private static let isoFormatterBox = PiSessionISO8601FormatterBox() static func loadDailyReport( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), options: Options = Options()) -> CostUsageDailyReport { ( try? self.loadDailyReportCancellable( provider: provider, since: since, until: until, now: now, options: options, checkCancellation: nil)) ?? CostUsageDailyReport(data: [], summary: nil) } static func loadDailyReportCancellable( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), options: Options = Options(), checkCancellation: CostUsageScanner.CancellationCheck?) throws -> CostUsageDailyReport { guard provider == .codex || provider == .claude else { return CostUsageDailyReport(data: [], summary: nil) } let range = CostUsageScanner.CostUsageDayRange(since: since, until: until) var cache = PiSessionCostCacheIO.load(cacheRoot: options.cacheRoot) let nowMs = Int64(now.timeIntervalSince1970 * 1000) let refreshMs = Int64(max(0, options.refreshMinIntervalSeconds) * 1000) let pricingContext = self.pricingContext(now: now, cacheRoot: options.cacheRoot) let windowExpanded = self.requestedWindowExpandsCache(range: range, cache: cache) let pricingChanged = cache.pricingKey != pricingContext.pricingKey let shouldRefresh = options.forceRescan || windowExpanded || pricingChanged || refreshMs == 0 || cache.lastScanUnixMs == 0 || nowMs - cache.lastScanUnixMs > refreshMs if shouldRefresh { try checkCancellation?() let roots = self.defaultSessionRoots(options: options) let startCutoff = self.dateFromDayKey(range.scanSinceKey) ?? since var files: [SessionFileCandidate] = [] for (rootIndex, root) in roots.enumerated() { for url in self.listPiSessionFiles(root: root, startCutoffLocal: startCutoff) { files.append(SessionFileCandidate(url: url, rootIndex: rootIndex)) } } files.sort { lhs, rhs in lhs.rootIndex == rhs.rootIndex ? lhs.url.path < rhs.url.path : lhs.rootIndex < rhs.rootIndex } let filePathsInScan = Set(files.map(\.url.path)) for file in files { try self.scanPiSessionFile( fileURL: file.url, cache: &cache, context: ScanContext( range: range, forceRescan: options.forceRescan || windowExpanded || pricingChanged, pricingContext: pricingContext, checkCancellation: checkCancellation)) } try checkCancellation?() for key in cache.files.keys where !filePathsInScan.contains(key) { if let old = cache.files[key] { self.applyContributions( daysByProvider: &cache.daysByProvider, contributions: old.contributions, sign: -1) } cache.files.removeValue(forKey: key) } try self.rebuildDailyUsage(cache: &cache, files: files, checkCancellation: checkCancellation) cache.scanSinceKey = range.scanSinceKey cache.scanUntilKey = range.scanUntilKey cache.pricingKey = pricingContext.pricingKey cache.lastScanUnixMs = nowMs try checkCancellation?() PiSessionCostCacheIO.save(cache: cache, cacheRoot: options.cacheRoot) } return self.buildReport( provider: provider, cache: cache, range: range, pricingContext: pricingContext) } struct CachedDailyReportResult { let report: CostUsageDailyReport let lastScanAt: Date? } static func loadCachedDailyReport( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), cacheRoot: URL? = nil) -> CostUsageDailyReport? { self.loadCachedDailyReportResult( provider: provider, since: since, until: until, now: now, cacheRoot: cacheRoot)?.report } static func loadCachedDailyReportResult( provider: UsageProvider, since: Date, until: Date, now: Date = Date(), cacheRoot: URL? = nil) -> CachedDailyReportResult? { guard provider == .codex || provider == .claude else { return nil } let range = CostUsageScanner.CostUsageDayRange(since: since, until: until) let cache = PiSessionCostCacheIO.load(cacheRoot: cacheRoot) guard !cache.daysByProvider.isEmpty else { return nil } guard !self.requestedWindowExpandsCache(range: range, cache: cache) else { return nil } let pricingContext = self.pricingContext(now: now, cacheRoot: cacheRoot) guard cache.pricingKey == pricingContext.pricingKey else { return nil } let report = self.buildReport( provider: provider, cache: cache, range: range, pricingContext: pricingContext) guard !report.data.isEmpty else { return nil } let lastScanAt = cache.lastScanUnixMs > 0 ? Date(timeIntervalSince1970: TimeInterval(cache.lastScanUnixMs) / 1000) : nil return CachedDailyReportResult(report: report, lastScanAt: lastScanAt) } private static func pricingContext(now: Date, cacheRoot: URL?) -> ModelsDevPricingContext { let modelsDevArtifact = ModelsDevCache.load(now: now, cacheRoot: cacheRoot).artifact return ModelsDevPricingContext( catalog: modelsDevArtifact?.catalog, cacheRoot: cacheRoot, pricingKey: CostUsagePricingKey.codex( modelsDevArtifact: modelsDevArtifact, formulaVersion: Self.costFormulaVersion, parserHash: CodexParserHash.value, modelsDevProviderIDs: ["anthropic", "openai"])) } private static func requestedWindowExpandsCache( range: CostUsageScanner.CostUsageDayRange, cache: PiSessionCostCache) -> Bool { guard let cachedSince = cache.scanSinceKey, let cachedUntil = cache.scanUntilKey else { return true } if range.scanSinceKey < cachedSince { return true } if range.scanUntilKey > cachedUntil { return true } return false } private static func defaultSessionRoots(options: Options) -> [URL] { if options.piSessionsRoot != nil || options.ompSessionsRoot != nil { return [options.piSessionsRoot, options.ompSessionsRoot].compactMap(\.self) } let home = FileManager.default.homeDirectoryForCurrentUser return [".pi", ".omp"].map { directory in home .appendingPathComponent(directory, isDirectory: true) .appendingPathComponent("agent", isDirectory: true) .appendingPathComponent("sessions", isDirectory: true) } } private static func listPiSessionFiles(root: URL, startCutoffLocal: Date) -> [URL] { guard FileManager.default.fileExists(atPath: root.path) else { return [] } let keys: Set<URLResourceKey> = [.isRegularFileKey, .contentModificationDateKey] guard let enumerator = FileManager.default.enumerator( at: root, includingPropertiesForKeys: Array(keys), options: [.skipsHiddenFiles]) else { return [] } var output: [URL] = [] while let item = enumerator.nextObject() as? URL { guard item.pathExtension.lowercased() == "jsonl" else { continue } let values = try? item.resourceValues(forKeys: keys) guard values?.isRegularFile == true else { continue } let startedAt = self.parseSessionStartFromFilename(item.lastPathComponent) let modifiedAt = values?.contentModificationDate if self .shouldIncludeFile(startedAt: startedAt, modifiedAt: modifiedAt, startCutoffLocal: startCutoffLocal) { output.append(item) } } return output.sorted(by: { $0.path < $1.path }) } private static func shouldIncludeFile( startedAt: Date?, modifiedAt: Date?, startCutoffLocal: Date) -> Bool { if let modifiedAt, self.localMidnight(modifiedAt) >= startCutoffLocal { return true } if let startedAt, self.localMidnight(startedAt) >= startCutoffLocal { return true } return false } private static func scanPiSessionFile( fileURL: URL, cache: inout PiSessionCostCache, context: ScanContext) throws { try context.checkCancellation?() let path = fileURL.path let attrs = (try? FileManager.default.attributesOfItem(atPath: path)) ?? [:] let mtime = (attrs[.modificationDate] as? Date)?.timeIntervalSince1970 ?? 0 let size = (attrs[.size] as? NSNumber)?.int64Value ?? 0 let mtimeMs = Int64(mtime * 1000) func storeFileUsage(_ usage: PiSessionFileUsage) { cache.files[path] = usage } let cached = cache.files[path] if !context.forceRescan, let cached, cached.mtimeUnixMs == mtimeMs, cached.size == size { return } if !context.forceRescan, let cached, size > cached.size, cached.parsedBytes > 0, cached.parsedBytes <= size { let delta = try self.parsePiSessionFile( fileURL: fileURL, range: context.range, startOffset: cached.parsedBytes, initialSessionID: cached.sessionID, initialModelContext: cached.lastModelContext, pricingContext: context.pricingContext, checkCancellation: context.checkCancellation) if !delta.contributions.isEmpty { self.applyContributions( daysByProvider: &cache.daysByProvider, contributions: delta.contributions, sign: 1) } let merged = self.mergedContributions(existing: cached.contributions, delta: delta.contributions) let mergedUnkeyed = self.mergedContributions( existing: cached.unkeyedContributions, delta: delta.unkeyedContributions) let mergedEntryUsages = cached.entryUsages.merging(delta.entryUsages) { _, appended in appended } storeFileUsage(PiSessionFileUsage( mtimeUnixMs: mtimeMs, size: size, parsedBytes: delta.parsedBytes, sessionID: delta.sessionID ?? cached.sessionID, lastModelContext: delta.lastModelContext, contributions: merged, unkeyedContributions: mergedUnkeyed, entryUsages: mergedEntryUsages)) return } if let cached { self.applyContributions( daysByProvider: &cache.daysByProvider, contributions: cached.contributions, sign: -1) } let parsed = try self.parsePiSessionFile( fileURL: fileURL, range: context.range, pricingContext: context.pricingContext, checkCancellation: context.checkCancellation) if !parsed.contributions.isEmpty { self.applyContributions(daysByProvider: &cache.daysByProvider, contributions: parsed.contributions, sign: 1) } storeFileUsage(PiSessionFileUsage( mtimeUnixMs: mtimeMs, size: size, parsedBytes: parsed.parsedBytes, sessionID: parsed.sessionID, lastModelContext: parsed.lastModelContext, contributions: parsed.contributions, unkeyedContributions: parsed.unkeyedContributions, entryUsages: parsed.entryUsages)) } private static func parsePiSessionFile( fileURL: URL, range: CostUsageScanner.CostUsageDayRange, startOffset: Int64 = 0, initialSessionID: String? = nil, initialModelContext: PiModelContext? = nil, pricingContext: ModelsDevPricingContext? = nil, checkCancellation: CostUsageScanner.CancellationCheck? = nil) throws -> ParseResult { var sessionID = initialSessionID var currentModelContext = initialModelContext var contributions: [String: [String: [String: PiPackedUsage]]] = [:] var unkeyedContributions: [String: [String: [String: PiPackedUsage]]] = [:] var entryUsages: [String: PiSessionEntryUsage] = [:] func add( provider: UsageProvider, dayKey: String, modelName: String, usage: PiPackedUsage, entryID: String?) { guard !usage.isZero else { return } guard CostUsageScanner.CostUsageDayRange.isInRange( dayKey: dayKey, since: range.scanSinceKey, until: range.scanUntilKey) else { return } let providerKey = provider.rawValue var providerDays = contributions[providerKey] ?? [:] var dayModels = providerDays[dayKey] ?? [:] let merged = self.addPacked(a: dayModels[modelName] ?? PiPackedUsage(), b: usage, sign: 1) if merged.isZero { dayModels.removeValue(forKey: modelName) } else { dayModels[modelName] = merged } if dayModels.isEmpty { providerDays.removeValue(forKey: dayKey) } else { providerDays[dayKey] = dayModels } if providerDays.isEmpty { contributions.removeValue(forKey: providerKey) } else { contributions[providerKey] = providerDays } if let entryID { entryUsages[entryID] = PiSessionEntryUsage( providerRawValue: providerKey, dayKey: dayKey, modelName: modelName, usage: usage) } else { var providerDays = unkeyedContributions[providerKey] ?? [:] var dayModels = providerDays[dayKey] ?? [:] dayModels[modelName] = self.addPacked( a: dayModels[modelName] ?? PiPackedUsage(), b: usage, sign: 1) providerDays[dayKey] = dayModels unkeyedContributions[providerKey] = providerDays } } let parsedBytes: Int64 do { parsedBytes = try CostUsageJsonl.scan( fileURL: fileURL, offset: startOffset, maxLineBytes: Self.maxLineBytes, prefixBytes: Self.maxLineBytes, checkCancellation: checkCancellation, onLine: { line in guard !line.bytes.isEmpty, !line.wasTruncated else { return } autoreleasepool { guard let object = (try? JSONSerialization.jsonObject(with: line.bytes)) as? [String: Any] else { return } guard let type = object["type"] as? String else { return } if type == "session" { sessionID = sessionID ?? self.sessionIdentifier(from: object) return } if type == "model_change" { currentModelContext = self.modelContext(from: object) return }