import CodexBarCore import CryptoKit import Foundation struct TokenAccountUsageSnapshot: Identifiable { let id: UUID let account: ProviderTokenAccount let snapshot: UsageSnapshot? let error: String? let sourceLabel: String? let cacheKey: String init( account: ProviderTokenAccount, snapshot: UsageSnapshot?, error: String?, sourceLabel: String?, cacheKey: String) { self.id = account.id self.account = account self.snapshot = snapshot self.error = error self.sourceLabel = sourceLabel self.cacheKey = cacheKey } } struct CodexAccountUsageSnapshot: Identifiable { let id: String let account: CodexVisibleAccount let snapshot: UsageSnapshot? let error: String? let sourceLabel: String? init(account: CodexVisibleAccount, snapshot: UsageSnapshot?, error: String?, sourceLabel: String?) { self.id = account.id self.account = account self.snapshot = snapshot self.error = error self.sourceLabel = sourceLabel } } extension UsageStore { func activateCachedTokenAccountSnapshot(provider: UsageProvider, accountID: UUID) { self.knownLimitsAvailabilityByProvider.removeValue(forKey: provider) self.tokenAccountLiveStateProviders.insert(provider) guard let account = self.uniqueTokenAccount(provider: provider, accountID: accountID), let cached = self.accountSnapshots[provider]?.first(where: { $0.account.id == accountID && $0.cacheKey == self.tokenAccountSnapshotCacheKey( provider: provider, account: account) }) else { self.accountSnapshots[provider]?.removeAll { $0.account.id == accountID } // Never show the previous account's usage under the newly selected account. Segmented layouts only // fetch the active account, so an uncached selection must render as refreshing until its fetch completes. self.clearTokenAccountLiveSnapshot(provider: provider) return } if let snapshot = cached.snapshot { self.snapshots[provider] = snapshot self.lastKnownResetSnapshots[provider] = snapshot } else { self.snapshots.removeValue(forKey: provider) self.lastKnownResetSnapshots.removeValue(forKey: provider) } self.errors[provider] = cached.error if let sourceLabel = cached.sourceLabel { self.lastSourceLabels[provider] = sourceLabel } else { self.lastSourceLabels.removeValue(forKey: provider) } } func cacheTokenAccountSnapshot( provider: UsageProvider, account: ProviderTokenAccount, snapshot: UsageSnapshot, sourceLabel: String?) { let cached = TokenAccountUsageSnapshot( account: account, snapshot: snapshot, error: nil, sourceLabel: sourceLabel, cacheKey: self.tokenAccountSnapshotCacheKey(provider: provider, account: account)) var snapshots = self.accountSnapshots[provider] ?? [] if let index = snapshots.firstIndex(where: { $0.account.id == account.id }) { snapshots[index] = cached } else { snapshots.append(cached) } self.accountSnapshots[provider] = snapshots } func pruneTokenAccountSnapshots(provider: UsageProvider, accounts: [ProviderTokenAccount]) { let retained = self.validTokenAccountSnapshots(provider: provider, accounts: accounts) if retained.isEmpty { self.accountSnapshots.removeValue(forKey: provider) } else { self.accountSnapshots[provider] = retained } } func reconcileSelectedTokenAccountSnapshotBeforeRefresh( provider: UsageProvider, accounts: [ProviderTokenAccount]) { self.pruneTokenAccountSnapshots(provider: provider, accounts: accounts) guard let selectedAccount = self.settings.selectedTokenAccount(for: provider) else { if self.tokenAccountLiveStateProviders.remove(provider) != nil { self.knownLimitsAvailabilityByProvider.removeValue(forKey: provider) self.clearTokenAccountLiveSnapshot(provider: provider) } return } // A Settings edit can invalidate the selected credential or endpoint before its replacement refresh // completes. Reconcile the live card now so a failed/cancelled fetch cannot retain old-account data. self.activateCachedTokenAccountSnapshot(provider: provider, accountID: selectedAccount.id) } private func clearTokenAccountLiveSnapshot(provider: UsageProvider) { self.snapshots.removeValue(forKey: provider) self.errors.removeValue(forKey: provider) self.lastSourceLabels.removeValue(forKey: provider) self.lastKnownResetSnapshots.removeValue(forKey: provider) } func validTokenAccountSnapshots( provider: UsageProvider, accounts: [ProviderTokenAccount]) -> [TokenAccountUsageSnapshot] { let accountsByID = Dictionary(grouping: accounts, by: \.id).compactMapValues { matches in matches.count == 1 ? matches[0] : nil } return (self.accountSnapshots[provider] ?? []).filter { cached in guard let account = accountsByID[cached.account.id] else { return false } return cached.cacheKey == self.tokenAccountSnapshotCacheKey(provider: provider, account: account) } } func tokenAccountSnapshotCacheKey(provider: UsageProvider, account: ProviderTokenAccount) -> String { var config = self.settings.configSnapshot.providerConfig(for: provider) ?? ProviderConfig(id: provider) // Active selection and sibling accounts must not invalidate a valid per-account snapshot. config.tokenAccounts = nil let encoder = JSONEncoder() encoder.outputFormatting = [.sortedKeys] var material = Data(provider.rawValue.utf8) material.append((try? encoder.encode(config)) ?? Data()) material.append((try? encoder.encode(account)) ?? Data()) return SHA256.hash(data: material).map { String(format: "%02x", $0) }.joined() } func uniqueTokenAccount(provider: UsageProvider, accountID: UUID) -> ProviderTokenAccount? { let matches = self.settings.tokenAccounts(for: provider).filter { $0.id == accountID } return matches.count == 1 ? matches[0] : nil } } private struct TokenAccountFetchResult { let index: Int let account: ProviderTokenAccount let outcome: ProviderFetchOutcome } private struct CodexAccountFetchResult { let index: Int let account: CodexVisibleAccount let outcome: ProviderFetchOutcome? let limitResetOwnerKey: CodexLimitResetOwnerKey? } private struct CodexAccountFetchRequest { let index: Int let account: CodexVisibleAccount let previousSnapshot: UsageSnapshot? let missingWindowBackfillSnapshot: UsageSnapshot? let limitResetOwnerKey: CodexLimitResetOwnerKey? let descriptor: ProviderDescriptor let context: ProviderFetchContext } private struct CodexManagedVisibleAccountRuntimeState { let authFingerprint: String? let workspaceAccountID: String? } extension UsageStore { static let tokenAccountMenuSnapshotLimit = 6 func freshCodexVisibleAccountsForSnapshotHydration() -> [CodexVisibleAccount] { self.freshCodexVisibleAccountProjectionForAccountRefresh().visibleAccounts } func tokenAccounts(for provider: UsageProvider) -> [ProviderTokenAccount] { guard TokenAccountSupportCatalog.support(for: provider) != nil else { return [] } return self.settings.tokenAccounts(for: provider) } func shouldFetchAllTokenAccounts(provider: UsageProvider, accounts: [ProviderTokenAccount]) -> Bool { guard TokenAccountSupportCatalog.support(for: provider) != nil else { return false } return self.settings.multiAccountMenuLayout == .stacked && accounts.count > 1 } func shouldFetchAllCodexVisibleAccounts() -> Bool { let projection = self.freshCodexVisibleAccountProjectionForAccountRefresh() return self.settings.multiAccountMenuLayout == .stacked && projection.visibleAccounts.count > 1 } func refreshCodexVisibleAccountsForMenu(generation: UInt64? = nil) async { let projection = self.freshCodexVisibleAccountProjectionForAccountRefresh() let accounts = self.limitedCodexVisibleAccounts( projection.visibleAccounts, snapshots: self.codexAccountSnapshots, activeVisibleAccountID: projection.activeVisibleAccountID) guard accounts.count > 1 else { self.codexAccountSnapshots = [] return } let managedAccountIDsWithReadableAuthAtStart = self.codexManagedAccountIDsWithReadableAuth() let originalVisibleAccountID = projection.activeVisibleAccountID let originalSelectionSource = originalVisibleAccountID.flatMap { projection.source(forVisibleAccountID: $0) } let originalVisibleAccount = originalVisibleAccountID.flatMap { id in accounts.first { $0.id == id } } let priorSnapshots = self.codexAccountSnapshots var snapshots: [CodexAccountUsageSnapshot] = [] var selectedOutcome: ProviderFetchOutcome? var selectedAccount: CodexVisibleAccount? var selectedSnapshot: UsageSnapshot? var selectedSourceLabel: String? var selectedLimitResetOwnerKey: CodexLimitResetOwnerKey? let results = await self.fetchCodexVisibleAccountOutcomes( accounts, allVisibleAccounts: projection.visibleAccounts, priorSnapshots: priorSnapshots, activeVisibleAccountID: originalVisibleAccountID) for result in results { let account = result.account let priorSnapshot = Self.codexPriorAccountSnapshot( matching: account, in: priorSnapshots) guard let outcome = result.outcome else { if let priorSnapshot { snapshots.append(priorSnapshot) } if account.id == originalVisibleAccountID { selectedAccount = account selectedLimitResetOwnerKey = result.limitResetOwnerKey } continue } let resolved = self.resolveCodexAccountOutcome( outcome, account: account, priorSnapshot: priorSnapshot, resetBackfillSnapshots: result.limitResetOwnerKey == nil ? [] : self.codexResetBackfillSnapshots( for: account, priorSnapshot: priorSnapshot, activeVisibleAccountID: originalVisibleAccountID)) if let snapshot = resolved.snapshot { snapshots.append(snapshot) } if account.id == originalVisibleAccountID { selectedOutcome = outcome selectedAccount = account selectedSnapshot = resolved.usage selectedSourceLabel = resolved.sourceLabel selectedLimitResetOwnerKey = result.limitResetOwnerKey } } let currentProjection = self.freshCodexVisibleAccountProjectionForAccountRefresh( requireLiveManagedAuthFor: managedAccountIDsWithReadableAuthAtStart) guard self.isCurrentProviderRefreshGeneration(.codex, generation: generation) else { return } let currentSnapshots = snapshots.compactMap { snapshot -> CodexAccountUsageSnapshot? in guard let currentAccount = Self.currentCodexVisibleAccount( matching: snapshot.account, projection: currentProjection, allowProviderAccountAuthFingerprintMismatch: snapshot.error == nil) else { return nil } guard currentAccount != snapshot.account else { return snapshot } return CodexAccountUsageSnapshot( account: currentAccount, snapshot: Self.codexVisibleAccountSnapshotRelabeledForCurrentProjection( snapshot.snapshot, account: currentAccount), error: snapshot.error, sourceLabel: snapshot.sourceLabel) } self.codexAccountSnapshots = currentSnapshots self.codexAccountUsageSnapshotStore?.store(currentSnapshots) let selectionStillMatches = self.codexVisibleSelectionStillMatches( originalVisibleAccountID: originalVisibleAccountID, originalSelectionSource: originalSelectionSource, originalAccount: originalVisibleAccount, currentProjection: currentProjection) guard let selectedOutcome, let selectedAccount else { if selectionStillMatches, let selectedID = currentProjection.activeVisibleAccountID, let preserved = currentSnapshots.first(where: { $0.id == selectedID }), let snapshot = preserved.snapshot { self.snapshots[.codex] = snapshot self.lastKnownResetSnapshots[.codex] = snapshot let publicationGuard = Self.codexScopedRefreshGuard(for: preserved.account) self.lastCodexUsagePublicationGuard = publicationGuard self.lastCodexAccountScopedRefreshGuard = publicationGuard } else if !selectionStillMatches { self.reconcileCodexAccountStateForUsageOwner(self.freshCodexAccountScopedRefreshGuard()) } return } guard selectionStillMatches else { self.reconcileCodexAccountStateForUsageOwner(self.freshCodexAccountScopedRefreshGuard()) return } let allowSelectedAuthFingerprintMismatch = switch selectedOutcome.result { case .success: true case .failure: false } let currentSelectedAccount = Self.currentCodexVisibleAccount( matching: selectedAccount, projection: currentProjection, allowProviderAccountAuthFingerprintMismatch: allowSelectedAuthFingerprintMismatch) if let currentSelectedAccount { let currentSelectedSnapshot = Self.codexVisibleAccountSnapshotRelabeledForCurrentProjection( selectedSnapshot, account: currentSelectedAccount) if self.shouldApplySelectedCodexVisibleAccountOutcome( selectedOutcome, snapshot: currentSelectedSnapshot) { await self.applySelectedCodexVisibleAccountOutcome( selectedOutcome, account: currentSelectedAccount, snapshot: currentSelectedSnapshot, sourceLabel: selectedSourceLabel, limitResetOwnerKey: selectedLimitResetOwnerKey, generation: generation) } } else { self.reconcileCodexAccountStateForUsageOwner(self.freshCodexAccountScopedRefreshGuard()) } } func codexVisibleSelectionStillMatches( originalVisibleAccountID: String?, originalSelectionSource: CodexActiveSource?, originalAccount: CodexVisibleAccount? = nil, currentProjection: CodexVisibleAccountProjection? = nil) -> Bool { let currentProjection = currentProjection ?? self.settings.codexVisibleAccountProjection let currentActiveAccount = currentProjection.activeVisibleAccountID.flatMap { id in currentProjection.visibleAccounts.first { $0.id == id } } let currentSelectionSource = currentActiveAccount?.selectionSource if currentProjection.activeVisibleAccountID == originalVisibleAccountID, currentSelectionSource == originalSelectionSource { guard let originalAccount else { return true } guard let currentActiveAccount else { return false } return Self.codexVisibleAccountMatchesCurrentProjection( originalAccount, account: currentActiveAccount) } guard let originalAccount, let currentActiveAccount, currentSelectionSource == originalSelectionSource else { return false } return Self.codexVisibleAccountMatchesCurrentProjection(originalAccount, account: currentActiveAccount) } private func freshCodexVisibleAccountProjectionForAccountRefresh( requireLiveManagedAuthFor accountIDs: Set = []) -> CodexVisibleAccountProjection { // Auth files can change while account fetches are in flight, so account refreshes bypass the // short-lived reconciliation cache used for normal menu rendering and stale-result guards. self.settings.invalidateCodexAccountReconciliationSnapshotCache() let snapshot = self.settings.codexAccountReconciliationSnapshot return Self.codexVisibleAccountProjectionWithFreshManagedAuthFingerprints( CodexVisibleAccountProjection.make(from: snapshot), snapshot: snapshot, requireLiveManagedAuthFor: accountIDs) } private func codexManagedAccountIDsWithReadableAuth() -> Set { Set(self.settings.codexAccountReconciliationSnapshot.storedAccounts.compactMap { account in CodexAuthFingerprint.fingerprint(homePath: account.managedHomePath) == nil ? nil : account.id }) } private nonisolated static func codexVisibleAccountProjectionWithFreshManagedAuthFingerprints( _ projection: CodexVisibleAccountProjection, snapshot: CodexAccountReconciliationSnapshot, requireLiveManagedAuthFor accountIDs: Set = []) -> CodexVisibleAccountProjection { let managedRuntimeStates = Dictionary( uniqueKeysWithValues: snapshot.storedAccounts.map { account in let workspaceAccountID: String? = switch snapshot.runtimeIdentity(for: account) { case let .providerAccount(id): id case .emailOnly, .unresolved: nil } let authFingerprint = CodexAuthFingerprint.fingerprint(homePath: account.managedHomePath) let requiresLiveAuth = accountIDs.contains(account.id) return (account.id, CodexManagedVisibleAccountRuntimeState( authFingerprint: authFingerprint ?? (requiresLiveAuth ? nil : account.authFingerprint), workspaceAccountID: authFingerprint == nil && requiresLiveAuth ? nil : (workspaceAccountID ?? account.workspaceAccountID))) }) let visibleAccounts = projection.visibleAccounts.map { account in guard case let .managedAccount(id) = account.selectionSource else { return account } let accountWorkspaceAccountID = account.workspaceAccountID .map(CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID) let runtimeWorkspaceAccountID = managedRuntimeStates[id]?.workspaceAccountID .map(CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID) guard let runtimeState = managedRuntimeStates[id], runtimeState.authFingerprint != account.authFingerprint || runtimeWorkspaceAccountID != accountWorkspaceAccountID else { return account } return CodexVisibleAccount( id: account.id, email: account.email, workspaceLabel: account.workspaceLabel, workspaceAccountID: runtimeState.workspaceAccountID, authFingerprint: runtimeState.authFingerprint, storedAccountID: account.storedAccountID, selectionSource: account.selectionSource, isActive: account.isActive, isLive: account.isLive, canReauthenticate: account.canReauthenticate, canRemove: account.canRemove) } return CodexVisibleAccountProjection( visibleAccounts: visibleAccounts, activeVisibleAccountID: projection.activeVisibleAccountID, liveVisibleAccountID: projection.liveVisibleAccountID, hasUnreadableAddedAccountStore: projection.hasUnreadableAddedAccountStore) } private static func currentCodexVisibleAccount( matching account: CodexVisibleAccount, projection: CodexVisibleAccountProjection, allowProviderAccountAuthFingerprintMismatch: Bool = true) -> CodexVisibleAccount? { if let currentAccount = projection.visibleAccounts.first(where: { $0.id == account.id }), self.codexVisibleAccountMatchesCurrentProjection( account, account: currentAccount, allowProviderAccountAuthFingerprintMismatch: allowProviderAccountAuthFingerprintMismatch) { return currentAccount } return projection.visibleAccounts.first { self.codexVisibleAccountMatchesCurrentProjection( account, account: $0, allowProviderAccountAuthFingerprintMismatch: allowProviderAccountAuthFingerprintMismatch) } } private static func codexVisibleAccountSnapshotRelabeledForCurrentProjection( _ snapshot: UsageSnapshot?, account: CodexVisibleAccount) -> UsageSnapshot? { guard let snapshot else { return nil } let existing = snapshot.identity(for: .codex) return snapshot.withIdentity(ProviderIdentitySnapshot( providerID: .codex, accountEmail: account.email, accountOrganization: existing?.accountOrganization, loginMethod: existing?.loginMethod ?? account.workspaceLabel)) } private static func codexVisibleAccountMatchesCurrentProjection( _ prior: CodexVisibleAccount, account: CodexVisibleAccount, allowProviderAccountAuthFingerprintMismatch: Bool = true) -> Bool { guard prior.selectionSource == account.selectionSource else { return false } guard let priorEmail = CodexIdentityResolver.normalizeEmail(prior.email), let accountEmail = CodexIdentityResolver.normalizeEmail(account.email), priorEmail == accountEmail else { return false } let priorWorkspaceID = self.normalizedCodexVisibleAccountText(prior.workspaceAccountID) .map(CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID) let accountWorkspaceID = self.normalizedCodexVisibleAccountText(account.workspaceAccountID) .map(CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID) if priorWorkspaceID != nil || accountWorkspaceID != nil { guard priorWorkspaceID == accountWorkspaceID else { return false } if !allowProviderAccountAuthFingerprintMismatch { guard self.codexVisibleAccountAuthFingerprintMatches(prior, account: account) else { return false } } return true } let priorAuthFingerprint = CodexAuthFingerprint.normalize(prior.authFingerprint) let accountAuthFingerprint = CodexAuthFingerprint.normalize(account.authFingerprint) if priorAuthFingerprint != nil || accountAuthFingerprint != nil { guard priorAuthFingerprint == accountAuthFingerprint else { return false } } return true } private static func codexVisibleAccountAuthFingerprintMatches( _ prior: CodexVisibleAccount, account: CodexVisibleAccount) -> Bool { let priorAuthFingerprint = CodexAuthFingerprint.normalize(prior.authFingerprint) let accountAuthFingerprint = CodexAuthFingerprint.normalize(account.authFingerprint) if priorAuthFingerprint != nil || accountAuthFingerprint != nil { return priorAuthFingerprint == accountAuthFingerprint } return true } func shouldApplySelectedCodexVisibleAccountOutcome( _ outcome: ProviderFetchOutcome, snapshot: UsageSnapshot?) -> Bool { switch outcome.result { case .success: snapshot != nil case .failure: true } } func refreshTokenAccounts( provider: UsageProvider, accounts: [ProviderTokenAccount], generation: UInt64? = nil) async { let selectedAccount = self.settings.selectedTokenAccount(for: provider) let limitedAccounts = self.limitedTokenAccounts(accounts, selected: selectedAccount) let effectiveSelected = selectedAccount ?? limitedAccounts.first // Capture the prior per-account snapshot state so we can preserve last-good // data when an in-flight refresh is cancelled (e.g. menu tab switches). Without // this, cancellation produces empty/error snapshots and the menu briefly shows // misleading cards for accounts that previously had valid data. let priorSnapshots = await MainActor.run { self.pruneTokenAccountSnapshots(provider: provider, accounts: accounts) if let effectiveSelected { self.activateCachedTokenAccountSnapshot(provider: provider, accountID: effectiveSelected.id) } return self.accountSnapshots[provider] ?? [] } let priorByAccountID = Dictionary(uniqueKeysWithValues: priorSnapshots.map { ($0.account.id, $0) }) var snapshots: [TokenAccountUsageSnapshot] = [] var historySamples: [(account: ProviderTokenAccount, snapshot: UsageSnapshot)] = [] var selectedOutcome: ProviderFetchOutcome? var selectedSnapshot: UsageSnapshot? var sawAnyNonCancellationOutcome = false let results = await self.fetchTokenAccountOutcomes(provider: provider, accounts: limitedAccounts) guard self.isCurrentProviderRefreshGeneration(provider, generation: generation) else { return } for result in results { guard let account = self.uniqueTokenAccount(provider: provider, accountID: result.account.id) else { continue } let outcome = result.outcome let isCancellation = Self.outcomeIsCancellation(outcome) if !isCancellation { sawAnyNonCancellationOutcome = true } let resolved = self.resolveAccountOutcome( outcome, provider: provider, account: account, priorSnapshot: priorByAccountID[account.id]) if let snapshot = resolved.snapshot { snapshots.append(snapshot) } if let usage = resolved.usage { historySamples.append((account: account, snapshot: usage)) } if account.id == effectiveSelected?.id { selectedOutcome = outcome selectedSnapshot = resolved.usage } } // If every fetch was cancelled (e.g. the user closed/reopened the menu mid-flight) // and we have no usable snapshots, leave the prior per-account state alone. // Wiping it would produce a menu of useless "cancelled" placeholders. let shouldPreservePriorState = !sawAnyNonCancellationOutcome && snapshots.allSatisfy { $0.snapshot == nil } if !shouldPreservePriorState { await MainActor.run { self.accountSnapshots[provider] = snapshots } } if let selectedOutcome { await self.applySelectedOutcome( selectedOutcome, provider: provider, account: effectiveSelected, fallbackSnapshot: selectedSnapshot, generation: generation) } guard self.isCurrentProviderRefreshGeneration(provider, generation: generation) else { return } await self.recordFetchedTokenAccountPlanUtilizationHistory( provider: provider, samples: historySamples, selectedAccount: effectiveSelected) } private static func outcomeIsCancellation(_ outcome: ProviderFetchOutcome) -> Bool { if case let .failure(error) = outcome.result, error is CancellationError { return true } if case let .failure(error) = outcome.result { return self.errorIsCancellation(error) } return false } private nonisolated static func codexUsageOutcomeMatchesVisibleAccount( _ outcome: ProviderFetchOutcome, account: CodexVisibleAccount) -> Bool { guard case let .success(result) = outcome.result else { return true } guard let resultEmail = CodexIdentityResolver.normalizeEmail( result.usage.scoped(to: .codex).accountEmail(for: .codex)) else { return true } return resultEmail == CodexIdentityResolver.normalizeEmail(account.email) } nonisolated static func errorIsCancellation(_ error: any Error) -> Bool { if error is CancellationError { return true } if let urlError = error as? URLError, urlError.code == .cancelled { return true } let message = error.localizedDescription .trimmingCharacters(in: .whitespacesAndNewlines) .lowercased() return message == "cancelled" || message.contains("cancellationerror") || message.contains("cancelled") } func limitedTokenAccounts( _ accounts: [ProviderTokenAccount], selected: ProviderTokenAccount?) -> [ProviderTokenAccount] { let limit = Self.tokenAccountMenuSnapshotLimit if accounts.count <= limit { return accounts } var limited = Array(accounts.prefix(limit)) if let selected, !limited.contains(where: { $0.id == selected.id }) { limited.removeLast() limited.append(selected) } return limited } func limitedCodexVisibleAccounts( _ accounts: [CodexVisibleAccount], snapshots: [CodexAccountUsageSnapshot] = [], activeVisibleAccountID: String?) -> [CodexVisibleAccount] { let accounts = CodexAccountPresentationOrdering.orderedAccounts( accounts, snapshots: snapshots, activeVisibleAccountID: activeVisibleAccountID) let limit = Self.tokenAccountMenuSnapshotLimit if accounts.count <= limit { return accounts } var limited = Array(accounts.prefix(limit)) if let activeVisibleAccountID, let active = accounts.first(where: { $0.id == activeVisibleAccountID }), !limited.contains(where: { $0.id == activeVisibleAccountID }) { limited.removeLast() limited.append(active) } return limited } func fetchOutcome( provider: UsageProvider, override: TokenAccountOverride?, codexActiveSourceOverride: CodexActiveSource? = nil) async -> ProviderFetchOutcome { let descriptor = self.providerSpecs[provider]?.descriptor ?? ProviderDescriptorRegistry .descriptor(for: provider) let context = self.makeFetchContext( provider: provider, override: override, codexActiveSourceOverride: codexActiveSourceOverride) let outcome = await descriptor.fetchOutcome(context: context) guard provider == .codex else { return outcome } return await Self.attachingCodexResetCreditsIfNeeded( to: outcome, env: context.env, fetcher: self.codexResetCreditsFetcher()) } private func fetchTokenAccountOutcomes( provider: UsageProvider, accounts: [ProviderTokenAccount]) async -> [TokenAccountFetchResult] { let requests: [( index: Int, account: ProviderTokenAccount, descriptor: ProviderDescriptor, context: ProviderFetchContext)] = accounts.enumerated().map { index, account in let override = TokenAccountOverride(provider: provider, account: account) let descriptor = self.providerSpecs[provider]?.descriptor ?? ProviderDescriptorRegistry .descriptor(for: provider) let context = self.makeFetchContext(provider: provider, override: override) return (index, account, descriptor, context) } return await withTaskGroup( of: TokenAccountFetchResult.self, returning: [TokenAccountFetchResult].self) { group in for request in requests { group.addTask { let outcome = await request.descriptor.fetchOutcome(context: request.context) return TokenAccountFetchResult( index: request.index, account: request.account, outcome: outcome) } } var results: [TokenAccountFetchResult] = [] results.reserveCapacity(requests.count) for await result in group { results.append(result) } return results.sorted { $0.index < $1.index } } } private func fetchCodexVisibleAccountOutcomes( _ accounts: [CodexVisibleAccount], allVisibleAccounts: [CodexVisibleAccount], priorSnapshots: [CodexAccountUsageSnapshot], activeVisibleAccountID: String?) async -> [CodexAccountFetchResult] { let resetCreditsFetcher = self.codexResetCreditsFetcher() let requests: [CodexAccountFetchRequest] = accounts.enumerated().map { index, account in let descriptor = self.providerSpecs[.codex]?.descriptor ?? ProviderDescriptorRegistry .descriptor(for: .codex) let context = self.makeFetchContext( provider: .codex, override: nil, codexActiveSourceOverride: account.selectionSource) let limitResetOwnerKey = self.codexLimitResetOwnerKey( forVisibleAccount: account, visibleAccounts: allVisibleAccounts) let priorSnapshot = Self.codexPriorAccountSnapshot( matching: account, in: priorSnapshots) let trustedBackfillSnapshots = limitResetOwnerKey == nil ? [] : self.codexResetBackfillSnapshots( for: account, priorSnapshot: priorSnapshot, activeVisibleAccountID: activeVisibleAccountID) let missingWindowBackfillSnapshot = Self.codexMergedResetBackfillSnapshot(trustedBackfillSnapshots) return CodexAccountFetchRequest( index: index, account: account, previousSnapshot: limitResetOwnerKey == nil ? nil : priorSnapshot?.snapshot, missingWindowBackfillSnapshot: missingWindowBackfillSnapshot, limitResetOwnerKey: limitResetOwnerKey, descriptor: descriptor, context: context) } return await withTaskGroup( of: CodexAccountFetchResult.self, returning: [CodexAccountFetchResult].self) { group in for request in requests { group.addTask { let fetchOutcome: CodexWeeklyConfirmationFetch = { let baseOutcome = await request.descriptor.fetchOutcome(context: request.context) return await Self.attachingCodexResetCreditsIfNeeded( to: baseOutcome, env: request.context.env, fetcher: resetCreditsFetcher) } let initialOutcome = await fetchOutcome() let outcome: ProviderFetchOutcome? = if Self.codexUsageOutcomeMatchesVisibleAccount( initialOutcome, account: request.account) { if let admitted = await Self.codexOutcomeAdmittedForPublication( initialOutcome: initialOutcome, previousSnapshot: request.previousSnapshot, missingWindowBackfillSnapshot: request.missingWindowBackfillSnapshot, fetchConfirmation: fetchOutcome), Self.codexUsageOutcomeMatchesVisibleAccount(admitted, account: request.account) { admitted } else { nil } } else { nil } return CodexAccountFetchResult( index: request.index, account: request.account, outcome: outcome, limitResetOwnerKey: request.limitResetOwnerKey) } } var results: [CodexAccountFetchResult] = [] results.reserveCapacity(requests.count) for await result in group { results.append(result) } return results.sorted { $0.index < $1.index } } } func makeFetchContext( provider: UsageProvider, override: TokenAccountOverride?, codexActiveSourceOverride: CodexActiveSource? = nil, includeCredits: Bool = false) -> ProviderFetchContext { let account = ProviderTokenAccountSelection.selectedAccount( provider: provider, settings: self.settings, override: override) let sourceMode = self.sourceMode(for: provider) let snapshot = ProviderRegistry.makeSettingsSnapshot( settings: self.settings, tokenOverride: override, codexActiveSourceOverride: codexActiveSourceOverride) let env = ProviderRegistry.makeEnvironment( base: self.environmentBase, provider: provider, settings: self.settings, tokenOverride: override, codexActiveSourceOverride: codexActiveSourceOverride) let fetcher = ProviderRegistry.makeFetcher(base: self.codexFetcher, provider: provider, env: env) let verbose = self.settings.isVerboseLoggingEnabled let contextProvider = provider let publicationGeneration = self.providerRefreshPublicationContexts[provider]?.generation let contextConfigRevision = self.settings.providerConfigRevision(for: provider) let originalAccountToken = account?.token let originalManualToken = provider == .stepfun ? self.settings.stepfunToken : nil return ProviderFetchContext( runtime: .app, sourceMode: sourceMode, includeCredits: includeCredits, includeOptionalUsage: self.settings.showOptionalCreditsAndExtraUsage, webTimeout: 60, webDebugDumpHTML: false, verbose: verbose, env: env, settings: snapshot, fetcher: fetcher, claudeFetcher: self.claudeFetcher, browserDetection: self.browserDetection, selectedTokenAccountID: account?.id, tokenAccountTokenUpdater: { [weak self] provider, accountID, token in await MainActor.run { guard let self, provider == contextProvider, self.settings.tokenAccounts(for: provider) .first(where: { $0.id == accountID })?.token == originalAccountToken else { return } guard self.providerConfigMutationIsCurrent( provider: provider, generation: publicationGeneration, originalConfigRevision: contextConfigRevision) else { return } self.settings.updateTokenAccount( provider: provider, accountID: accountID, token: token) self.advanceProviderRefreshConfigRevision( provider: provider, generation: publicationGeneration) } }, providerManualTokenUpdater: { [weak self] provider, token in await MainActor.run { guard let self, provider == .stepfun, self.settings.stepfunToken == originalManualToken else { return } guard self.providerConfigMutationIsCurrent( provider: provider, generation: publicationGeneration, originalConfigRevision: contextConfigRevision) else { return } self.settings.stepfunToken = token self.advanceProviderRefreshConfigRevision( provider: provider, generation: publicationGeneration) } }, costUsageHistoryDays: self.settings.costUsageHistoryDays, persistsCLISessions: true, persistentCLISessionIdleWindow: ProviderRegistry.persistentCLISessionIdleWindow( refreshInterval: self.normalRefreshIntervalForHeuristics())) } private func providerConfigMutationIsCurrent( provider: UsageProvider, generation: UInt64?, originalConfigRevision: UInt64) -> Bool { guard let generation else { return true } let currentConfigRevision = self.settings.providerConfigRevision(for: provider) guard let publication = self.providerRefreshPublicationContexts[provider] else { return false } if publication.generation == generation { return publication.configRevision == currentConfigRevision } // A replacement waits for its predecessor before capturing fetch inputs. Let the predecessor persist an // authorized refresh token while its original config is unchanged; the replacement will then start from it. return originalConfigRevision == currentConfigRevision } private func advanceProviderRefreshConfigRevision(provider: UsageProvider, generation: UInt64?) { guard let generation, var publication = self.providerRefreshPublicationContexts[provider], publication.generation == generation else { return } publication.configRevision = self.settings.providerConfigRevision(for: provider) self.providerRefreshPublicationContexts[provider] = publication } func sourceMode(for provider: UsageProvider) -> ProviderSourceMode { ProviderCatalog.implementation(for: provider)? .sourceMode(context: ProviderSourceModeContext(provider: provider, settings: self.settings)) ?? .auto } private struct ResolvedAccountOutcome { let snapshot: TokenAccountUsageSnapshot? let usage: UsageSnapshot? } private struct ResolvedCodexAccountOutcome { let snapshot: CodexAccountUsageSnapshot? let usage: UsageSnapshot? let sourceLabel: String? } func tokenAccountErrorMessage(_ error: any Error) -> String? { guard !Self.errorIsCancellation(error) else { return nil } let message = error.localizedDescription.trimmingCharacters(in: .whitespacesAndNewlines) return message.isEmpty ? nil : message } /// Per-account snapshot error text. Cancellation is handled before this path so /// transient menu refresh cancellation does not render as a user-facing error. func tokenAccountSnapshotErrorMessage(_ error: any Error) -> String { let message = error.localizedDescription.trimmingCharacters(in: .whitespacesAndNewlines) return message.isEmpty ? "Refresh failed" : message } private func codexResetBackfillSnapshots( for account: CodexVisibleAccount, priorSnapshot: CodexAccountUsageSnapshot?, activeVisibleAccountID: String?) -> [UsageSnapshot] { var snapshots: [UsageSnapshot] = [] if let priorSnapshot, Self.codexPriorSnapshotAccountMatches(priorSnapshot.account, account: account), let prior = priorSnapshot.snapshot { snapshots.append(prior) } if account.id == activeVisibleAccountID, let lastKnown = self.codexLastKnownResetSnapshot(for: account) { snapshots.append(lastKnown) } // Plan history remains display-only: its legacy provider and email keys cannot prove // the composite publication owner required for quota state. return snapshots } private func codexLastKnownResetSnapshot(for account: CodexVisibleAccount) -> UsageSnapshot? { guard let snapshot = self.lastKnownResetSnapshots[.codex], Self.codexVisibleAccountEmailMatches(snapshot: snapshot, account: account), Self.codexScopedGuard(self.lastCodexUsagePublicationGuard, matches: account) else { return nil } return snapshot } func codexLastKnownResetSnapshot(matching guardValue: CodexAccountScopedRefreshGuard?) -> UsageSnapshot? { guard let guardValue, let lastGuard = self.lastCodexUsagePublicationGuard, Self.codexScopedRefreshGuardAllowsResetBackfill(lastGuard, matching: guardValue) else { return nil } return self.lastKnownResetSnapshots[.codex] } private nonisolated static func codexVisibleAccountEmailMatches( snapshot: UsageSnapshot, account: CodexVisibleAccount) -> Bool { guard let identity = snapshot.identity(for: .codex), let identityEmail = CodexIdentityResolver.normalizeEmail(identity.accountEmail), let accountEmail = CodexIdentityResolver.normalizeEmail(account.email), identityEmail == accountEmail else { return false } return true } nonisolated static func codexPriorSnapshotAccountMatches( _ prior: CodexVisibleAccount, account: CodexVisibleAccount) -> Bool { guard let priorEmail = CodexIdentityResolver.normalizeEmail(prior.email), let accountEmail = CodexIdentityResolver.normalizeEmail(account.email), priorEmail == accountEmail else { return false } let priorWorkspaceID = self.normalizedCodexVisibleAccountText(prior.workspaceAccountID) .map(CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID) let accountWorkspaceID = self.normalizedCodexVisibleAccountText(account.workspaceAccountID) .map(CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID) if priorWorkspaceID != nil || accountWorkspaceID != nil { return priorWorkspaceID == accountWorkspaceID } let priorAuthFingerprint = CodexAuthFingerprint.normalize(prior.authFingerprint) let accountAuthFingerprint = CodexAuthFingerprint.normalize(account.authFingerprint) if priorAuthFingerprint != nil || accountAuthFingerprint != nil { guard priorAuthFingerprint == accountAuthFingerprint else { return false } } if prior.selectionSource == account.selectionSource { switch account.selectionSource { case .managedAccount: return true case .liveSystem: return prior.id == account.id case .profileHome: return true } } guard prior.id != prior.email, account.id != account.email else { return false } return prior.id == account.id } private nonisolated static func codexPriorAccountSnapshot( matching account: CodexVisibleAccount, in snapshots: [CodexAccountUsageSnapshot]) -> CodexAccountUsageSnapshot? { if let exact = snapshots.first(where: { $0.id == account.id }), self.codexPriorSnapshotAccountMatches(exact.account, account: account) { return exact } let matches = snapshots.filter { self.codexPriorSnapshotAccountMatches($0.account, account: account) } guard matches.count == 1 else { return nil } return matches[0] } private nonisolated static func codexScopedGuard( _ guardValue: CodexAccountScopedRefreshGuard?, matches account: CodexVisibleAccount) -> Bool { guard let guardValue, guardValue.source == account.selectionSource else { return false } let guardAuthFingerprint = CodexAuthFingerprint.normalize(guardValue.authFingerprint) let accountAuthFingerprint = CodexAuthFingerprint.normalize(account.authFingerprint) if guardAuthFingerprint != nil || accountAuthFingerprint != nil { guard guardAuthFingerprint == accountAuthFingerprint else { return false } } let identity = self.codexVisibleAccountIdentity(for: account) if identity != .unresolved { return guardValue.identity == identity } guard let accountKey = CodexIdentityResolver.normalizeEmail(account.email) else { return false } return guardValue.accountKey == accountKey } private nonisolated static func codexScopedRefreshGuardAllowsResetBackfill( _ lastGuard: CodexAccountScopedRefreshGuard, matching expectedGuard: CodexAccountScopedRefreshGuard) -> Bool { self.codexScopedRefreshGuardsMatchAccount(lastGuard, expectedGuard) } private nonisolated static func codexScopedRefreshGuard(for account: CodexVisibleAccount) -> CodexAccountScopedRefreshGuard { let accountEmail = CodexIdentityResolver.normalizeEmail(account.email) return CodexAccountScopedRefreshGuard( source: account.selectionSource, identity: self.codexVisibleAccountIdentity(for: account), accountKey: accountEmail, authFingerprint: account.authFingerprint) } private nonisolated static func codexVisibleAccountIdentity(for account: CodexVisibleAccount) -> CodexIdentity { if let workspaceAccountID = self.normalizedCodexVisibleAccountText(account.workspaceAccountID) { return .providerAccount(id: CodexOpenAIWorkspaceIdentity.normalizeWorkspaceAccountID(workspaceAccountID)) } return CodexIdentityResolver.resolve(accountId: nil, email: account.email) } private nonisolated static func normalizedCodexVisibleAccountText(_ text: String?) -> String? { guard let trimmed = text?.trimmingCharacters(in: .whitespacesAndNewlines), !trimmed.isEmpty else { return nil } return trimmed } nonisolated static func codexBackfillingResetWindows( _ snapshot: UsageSnapshot, from cached: UsageSnapshot) -> UsageSnapshot { let primary = self.codexBackfillingResetWindow( CodexConsumerProjection.sourceRateWindow(for: .session, snapshot: snapshot), from: CodexConsumerProjection.sourceRateWindow(for: .session, snapshot: cached)) let secondary = self.codexBackfillingResetWindow( CodexConsumerProjection.sourceRateWindow(for: .weekly, snapshot: snapshot), from: CodexConsumerProjection.sourceRateWindow(for: .weekly, snapshot: cached)) guard primary != snapshot.primary || secondary != snapshot.secondary else { return snapshot } return snapshot.with(primary: primary, secondary: secondary) } nonisolated static func codexMergedResetBackfillSnapshot( _ snapshots: [UsageSnapshot], now: Date = Date()) -> UsageSnapshot? { let primary = self.codexPreferredResetBackfillWindow( snapshots.enumerated().compactMap { index, snapshot in CodexConsumerProjection.sourceRateWindow(for: .session, snapshot: snapshot) .map { (window: $0, updatedAt: snapshot.updatedAt, priority: index) } }, now: now) let secondary = self.codexPreferredResetBackfillWindow( snapshots.enumerated().compactMap { index, snapshot in CodexConsumerProjection.sourceRateWindow(for: .weekly, snapshot: snapshot) .map { (window: $0, updatedAt: snapshot.updatedAt, priority: index) } }, now: now) guard primary != nil || secondary != nil else { return nil } return UsageSnapshot( primary: primary, secondary: secondary, updatedAt: snapshots.map(\.updatedAt).max() ?? now) } private nonisolated static func codexPreferredResetBackfillWindow( _ windows: [(window: RateWindow, updatedAt: Date, priority: Int)], now: Date) -> RateWindow? { windows .filter { ($0.window.resetsAt ?? .distantPast) > now } .max { lhs, rhs in if lhs.updatedAt != rhs.updatedAt { return lhs.updatedAt < rhs.updatedAt } if lhs.priority != rhs.priority { return lhs.priority < rhs.priority } let lhsReset = lhs.window.resetsAt ?? .distantPast let rhsReset = rhs.window.resetsAt ?? .distantPast if lhsReset != rhsReset { return lhsReset < rhsReset } return (lhs.window.windowMinutes ?? 0) < (rhs.window.windowMinutes ?? 0) } .map(\.window) } private nonisolated static func codexBackfillingResetWindow( _ window: RateWindow?, from cached: RateWindow?) -> RateWindow? { guard let cached, let resetsAt = cached.resetsAt, resetsAt > Date() else { return window } if let window { return window.backfillingResetTime(from: cached) } guard let windowMinutes = cached.windowMinutes, windowMinutes > 0 else { return nil } return RateWindow( usedPercent: cached.usedPercent, windowMinutes: windowMinutes, resetsAt: resetsAt, resetDescription: cached.resetDescription) } func recordFetchedTokenAccountPlanUtilizationHistory( provider: UsageProvider, samples: [(account: ProviderTokenAccount, snapshot: UsageSnapshot)], selectedAccount: ProviderTokenAccount?) async { for sample in samples where sample.account.id != selectedAccount?.id { await self.recordPlanUtilizationHistorySample( provider: provider, snapshot: sample.snapshot, account: sample.account, shouldUpdatePreferredAccountKey: false, shouldAdoptUnscopedHistory: false) } } private func resolveAccountOutcome( _ outcome: ProviderFetchOutcome, provider: UsageProvider, account: ProviderTokenAccount, priorSnapshot: TokenAccountUsageSnapshot? = nil) -> ResolvedAccountOutcome { switch outcome.result { case let .success(result): let scoped = result.usage.scoped(to: provider) let labeled = self.applyAccountLabel(scoped, provider: provider, account: account) let snapshot = TokenAccountUsageSnapshot( account: account, snapshot: labeled, error: nil, sourceLabel: result.sourceLabel, cacheKey: self.tokenAccountSnapshotCacheKey(provider: provider, account: account)) return ResolvedAccountOutcome(snapshot: snapshot, usage: labeled) case let .failure(error): // Preserve the last-good snapshot when the refresh was cancelled (e.g. the // user switched menu tabs mid-flight). Without this the per-account list // would briefly render error chips for accounts that already had data. if Self.errorIsCancellation(error) { if let priorSnapshot, priorSnapshot.snapshot != nil { return ResolvedAccountOutcome(snapshot: priorSnapshot, usage: priorSnapshot.snapshot) } // No usable prior data: skip this row entirely. The caller will // either preserve the existing per-account state or fall back to // the single live card. Rendering a "cancelled" placeholder here // produces visually duplicate cards with no useful data. return ResolvedAccountOutcome(snapshot: nil, usage: nil) } let snapshot = TokenAccountUsageSnapshot( account: account, snapshot: nil, error: self.tokenAccountSnapshotErrorMessage(error), sourceLabel: nil, cacheKey: self.tokenAccountSnapshotCacheKey(provider: provider, account: account)) return ResolvedAccountOutcome(snapshot: snapshot, usage: nil) } } private func resolveCodexAccountOutcome( _ outcome: ProviderFetchOutcome, account: CodexVisibleAccount, priorSnapshot: CodexAccountUsageSnapshot? = nil, resetBackfillSnapshots: [UsageSnapshot] = []) -> ResolvedCodexAccountOutcome { switch outcome.result { case let .success(result): let scoped = result.usage.scoped(to: .codex) if let resultEmail = CodexIdentityResolver.normalizeEmail(scoped.accountEmail(for: .codex)), resultEmail != CodexIdentityResolver.normalizeEmail(account.email) { return ResolvedCodexAccountOutcome( snapshot: priorSnapshot, usage: nil, sourceLabel: priorSnapshot?.sourceLabel) } let labeled = self.applyCodexVisibleAccountLabel(scoped, account: account) let backfilled = Self.codexMergedResetBackfillSnapshot(resetBackfillSnapshots) .map { Self.codexBackfillingResetWindows(labeled, from: $0) } ?? labeled let snapshot = CodexAccountUsageSnapshot( account: account, snapshot: backfilled, error: nil, sourceLabel: result.sourceLabel) return ResolvedCodexAccountOutcome( snapshot: snapshot, usage: backfilled, sourceLabel: result.sourceLabel) case let .failure(error): if Self.errorIsCancellation(error) { if let priorSnapshot, priorSnapshot.snapshot != nil { return ResolvedCodexAccountOutcome( snapshot: priorSnapshot, usage: priorSnapshot.snapshot, sourceLabel: priorSnapshot.sourceLabel) } return ResolvedCodexAccountOutcome(snapshot: nil, usage: nil, sourceLabel: nil) } let errorMessage = self.tokenAccountSnapshotErrorMessage(error) if Self.shouldPreserveCodexAccountSnapshotOnFailure(errorMessage), let priorSnapshot, let priorUsage = priorSnapshot.snapshot { let snapshot = CodexAccountUsageSnapshot( account: account, snapshot: priorUsage, error: errorMessage, sourceLabel: priorSnapshot.sourceLabel) return ResolvedCodexAccountOutcome( snapshot: snapshot, usage: priorUsage, sourceLabel: priorSnapshot.sourceLabel) } let snapshot = CodexAccountUsageSnapshot( account: account, snapshot: nil, error: errorMessage, sourceLabel: nil) return ResolvedCodexAccountOutcome(snapshot: snapshot, usage: nil, sourceLabel: nil) } } private static func shouldPreserveCodexAccountSnapshotOnFailure(_ message: String) -> Bool { guard CodexAccountHealth.status(forError: message) == .unavailable else { return false } let normalized = message.lowercased() return normalized.contains("network") || normalized.contains("internet connection") || normalized.contains("offline") || normalized.contains("timed out") || normalized.contains("timeout") || normalized.contains("connection was lost") || normalized.contains("could not connect") || normalized.contains("not connected") || normalized.contains("hostname") || normalized.contains("dns") || normalized.contains("temporarily unavailable") } func applySelectedCodexVisibleAccountOutcome( _ outcome: ProviderFetchOutcome, account: CodexVisibleAccount, snapshot: UsageSnapshot?, sourceLabel: String?, limitResetOwnerKey: CodexLimitResetOwnerKey?, generation: UInt64? = nil) async { guard self.isCurrentProviderRefreshGeneration(.codex, generation: generation) else { return } switch outcome.result { case .success: guard let snapshot else { return } let publicationGuard = Self.codexScopedRefreshGuard(for: account) self.lastFetchAttempts[.codex] = outcome.attempts self.handleCodexResetCreditNotifications(snapshot: snapshot) self.handleSessionQuotaTransition( provider: .codex, snapshot: snapshot, codexOwnerKey: Self.codexSessionQuotaOwnerKey(for: publicationGuard)) self.handlePredictivePaceWarningTransitions(provider: .codex, snapshot: snapshot) self.lastKnownResetSnapshots[.codex] = snapshot self.lastCodexUsagePublicationGuard = publicationGuard self.lastCodexAccountScopedRefreshGuard = publicationGuard self.snapshots[.codex] = snapshot if let sourceLabel { self.lastSourceLabels[.codex] = sourceLabel } self.errors[.codex] = nil self.failureGates[.codex]?.recordSuccess() self.rememberLiveSystemCodexEmailIfNeeded(snapshot.accountEmail(for: .codex)) self.seedCodexAccountScopedRefreshGuard(accountEmail: account.email) await self.recordPlanUtilizationHistorySample( provider: .codex, snapshot: snapshot, codexLimitResetOwnerKey: limitResetOwnerKey) guard self.isCurrentProviderRefreshGeneration(.codex, generation: generation) else { return } self.recordCodexHistoricalSampleIfNeeded(snapshot: snapshot) case let .failure(error): guard let message = self.tokenAccountErrorMessage(error) else { self.errors[.codex] = nil return } let publicationGuard = Self.codexScopedRefreshGuard(for: account) self.lastCodexUsagePublicationGuard = publicationGuard self.lastCodexAccountScopedRefreshGuard = publicationGuard self.lastFetchAttempts[.codex] = outcome.attempts let hadPriorData = self.snapshots[.codex] != nil let shouldSurface = self.failureGates[.codex]? .shouldSurfaceError(onFailureWithPriorData: hadPriorData) ?? true if shouldSurface { self.errors[.codex] = message self.snapshots.removeValue(forKey: .codex) } else { self.errors[.codex] = nil } } } func applySelectedOutcome( _ outcome: ProviderFetchOutcome, provider: UsageProvider, account: ProviderTokenAccount?, fallbackSnapshot: UsageSnapshot?, generation: UInt64? = nil) async { await MainActor.run { guard self.isCurrentProviderRefreshGeneration(provider, generation: generation) else { return } self.lastFetchAttempts[provider] = outcome.attempts } guard self.isCurrentProviderRefreshGeneration(provider, generation: generation) else { return } switch outcome.result { case let .success(result): let scoped = result.usage.scoped(to: provider) let labeled: UsageSnapshot = if let account { self.applyAccountLabel(scoped, provider: provider, account: account) } else { scoped } let backfilled = await MainActor.run { guard self.isCurrentProviderRefreshGeneration(provider, generation: generation) else { return nil as UsageSnapshot? } let backfilled = labeled.backfillingResetTimes(from: self.lastKnownResetSnapshots[provider]) let predictivePaceWarningAccountDiscriminatorOverride: String? = if provider == .claude { Self.predictivePaceWarningTokenAccountDiscriminator(account) } else { nil } self.handleQuotaWarningTransitions(provider: provider, snapshot: backfilled) self.handleSessionQuotaTransition(provider: provider, snapshot: backfilled) self.handlePredictivePaceWarningTransitions( provider: provider, snapshot: backfilled, accountDiscriminatorOverride: predictivePaceWarningAccountDiscriminatorOverride) self.lastKnownResetSnapshots[provider] = backfilled self.snapshots[provider] = backfilled self.lastSourceLabels[provider] = result.sourceLabel self.errors[provider] = nil self.knownLimitsAvailabilityByProvider.removeValue(forKey: provider) self.failureGates[provider]?.recordSuccess() return backfilled } guard let backfilled else { return } await self.recordPlanUtilizationHistorySample( provider: provider, snapshot: backfilled, account: account) case let .failure(error): await MainActor.run { self.knownLimitsAvailabilityByProvider.removeValue(forKey: provider) guard let message = self.tokenAccountErrorMessage(error) else { self.errors[provider] = nil return } let hadPriorData = self.snapshots[provider] != nil || fallbackSnapshot != nil let shouldSurface = self.failureGates[provider]? .shouldSurfaceError(onFailureWithPriorData: hadPriorData) ?? true if shouldSurface { self.errors[provider] = message self.snapshots.removeValue(forKey: provider) } else { self.errors[provider] = nil } } } } func applyAccountLabel( _ snapshot: UsageSnapshot, provider: UsageProvider, account: ProviderTokenAccount) -> UsageSnapshot { let label = account.label.trimmingCharacters(in: .whitespacesAndNewlines) guard !label.isEmpty else { return snapshot } let existing = snapshot.identity(for: provider) let email = existing?.accountEmail?.trimmingCharacters(in: .whitespacesAndNewlines) let resolvedEmail = (email?.isEmpty ?? true) ? label : email let identity = ProviderIdentitySnapshot( providerID: provider, accountEmail: resolvedEmail, accountOrganization: existing?.accountOrganization, loginMethod: existing?.loginMethod) return snapshot.withIdentity(identity) } func applyCodexVisibleAccountLabel(_ snapshot: UsageSnapshot, account: CodexVisibleAccount) -> UsageSnapshot { let existing = snapshot.identity(for: .codex) let email = existing?.accountEmail?.trimmingCharacters(in: .whitespacesAndNewlines) let resolvedEmail = (email?.isEmpty ?? true) ? account.email : email let loginMethod = existing?.loginMethod ?? account.workspaceLabel let identity = ProviderIdentitySnapshot( providerID: .codex, accountEmail: resolvedEmail, accountOrganization: existing?.accountOrganization, loginMethod: loginMethod) return snapshot.withIdentity(identity) } }