128 lines · 4.4 KB · Swift
RawDownload
import CodexBarCoreimport Foundation extension UsageStore {    func tokenSnapshot(for provider: UsageProvider) -> CostUsageTokenSnapshot? {        self.tokenSnapshots[provider]    }     func tokenError(for provider: UsageProvider) -> String? {        self.tokenErrors[provider]    }     func tokenLastAttemptAt(for provider: UsageProvider) -> Date? {        self.lastTokenFetchAt[provider]    }     func hydrateCachedTokenSnapshots(now: Date = Date()) {        guard self.settings.costUsageEnabled else { return }        guard self.settings.enabledProvidersOrdered(metadataByProvider: self.providerMetadata).contains(.codex) else {            return        }         let scope = self.tokenCostScope(for: .codex)        let historyDays = self.settings.costUsageHistoryDays        Task { @MainActor [weak self] in            guard let self else { return }            guard self.tokenSnapshots[.codex] == nil else { return }            guard let snapshot = await self.costUsageFetcher.loadCachedCodexTokenSnapshot(                now: now,                codexHomePath: scope.codexHomePath,                historyDays: historyDays)            else {                return            }            guard self.settings.costUsageEnabled,                  self.isEnabled(.codex),                  self.tokenCostScope(for: .codex).signature == scope.signature,                  self.tokenSnapshots[.codex] == nil            else {                return            }            self.tokenSnapshots[.codex] = snapshot            self.tokenErrors[.codex] = nil        }    }     func isTokenRefreshInFlight(for provider: UsageProvider) -> Bool {        self.tokenRefreshInFlight.contains(provider)    }     func tokenCostScope(for provider: UsageProvider) -> (codexHomePath: String?, signature: String) {        guard provider == .codex else {            return (nil, provider.rawValue)        }        let homePath = self.settings.activeManagedCodexRemoteHomePath?            .trimmingCharacters(in: .whitespacesAndNewlines)        guard let homePath, !homePath.isEmpty else {            return (nil, "codex:ambient")        }        return (homePath, "codex:managed:\(homePath)")    }     func tokenSnapshot(        fromProviderSnapshot snapshot: UsageSnapshot?,        provider: UsageProvider)        -> CostUsageTokenSnapshot?    {        switch provider {        case .openai:            snapshot?.openAIAPIUsage?.toCostUsageTokenSnapshot()        case .mistral:            snapshot?.mistralUsage?.toCostUsageTokenSnapshot(historyDays: self.settings.costUsageHistoryDays)        default:            nil        }    }     nonisolated static func tokenCostRequiresProviderSnapshot(_ provider: UsageProvider) -> Bool {        switch provider {        case .mistral, .openai:            true        default:            false        }    }     nonisolated static func costUsageCacheDirectory(        fileManager: FileManager = .default) -> URL    {        let root = fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!        return root            .appendingPathComponent("CodexBar", isDirectory: true)            .appendingPathComponent("cost-usage", isDirectory: true)    }     func clearCostUsageCache() async -> String? {        let errorMessage: String? = await Task.detached(priority: .utility) {            let fm = FileManager.default            let cacheDirs = [                Self.costUsageCacheDirectory(fileManager: fm),            ]             for cacheDir in cacheDirs {                do {                    try fm.removeItem(at: cacheDir)                } catch let error as NSError {                    if error.domain == NSCocoaErrorDomain, error.code == NSFileNoSuchFileError { continue }                    return error.localizedDescription                }            }            return nil        }.value         guard errorMessage == nil else { return errorMessage }         self.tokenSnapshots.removeAll()        self.tokenErrors.removeAll()        self.lastTokenFetchAt.removeAll()        self.lastTokenFetchScope.removeAll()        self.tokenFailureGates[.codex]?.reset()        self.tokenFailureGates[.claude]?.reset()        return nil    }     nonisolated static func tokenCostNoDataMessage(for provider: UsageProvider) -> String {        ProviderDescriptorRegistry.descriptor(for: provider).tokenCost.noDataMessage()    }}