import AppKitimport CodexBarCore extension StatusItemController { /// Identifies which manual refresh a task belongs to, so per-provider refreshes stay independent /// of each other and of the all-providers refresh. enum ManualRefreshScope: Hashable { case global case provider(UsageProvider) }} enum LoginNotificationLogic { static func notificationCopy(providerName: String) -> (title: String, body: String) { ( L("login_success_notification_title", providerName), L("login_success_notification_body")) }} extension StatusItemController: StatusItemMenuPersistentActionDelegate { // MARK: - Actions reachable from menus func refreshStore( forceTokenUsage: Bool, refreshOpenMenusWhenComplete: Bool = true, interaction: ProviderInteraction = .userInitiated) { Task { await self.performStoreRefresh( forceTokenUsage: forceTokenUsage, refreshOpenMenusWhenComplete: refreshOpenMenusWhenComplete, interaction: interaction) } } func performStoreRefresh( forceTokenUsage: Bool, refreshOpenMenusWhenComplete: Bool, interaction: ProviderInteraction) async { await self.withProviderInteraction(interaction) { await self.store.refresh(forceTokenUsage: forceTokenUsage) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } self.store.scheduleStorageFootprintRefreshForOverview(force: true) if refreshOpenMenusWhenComplete { self.refreshOpenMenusAfterExplicitStoreAction() } else { self.invalidateMenus() } } } func performStoreRefresh( enrichmentMode: UsageStore.RefreshEnrichmentMode, refreshOpenMenusWhenComplete: Bool, interaction: ProviderInteraction) async { await self.withProviderInteraction(interaction) { await self.store.refresh(enrichmentMode: enrichmentMode) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } self.store.scheduleStorageFootprintRefreshForOverview(force: true) if refreshOpenMenusWhenComplete { self.refreshOpenMenusAfterExplicitStoreAction() } else { self.invalidateMenus() } } } func performStoreRefresh( for provider: UsageProvider, refreshOpenMenusWhenComplete: Bool, interaction: ProviderInteraction) async { await self.withProviderInteraction(interaction) { await self.store.awaitForcedRefreshEnrichment() guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } let refreshStartedAt = Date() await self.store.refreshProvider(provider) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshProviderStatus(provider) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshTokenUsageNow(for: provider, force: true) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } if provider == .codex { await self.store.refreshCreditsNow(minimumSnapshotUpdatedAt: refreshStartedAt) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshOpenAIDashboardIfNeeded( force: true, expectedGuard: self.store.freshCodexOpenAIWebRefreshGuard(), bypassCoalescing: true) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } if self.store.openAIDashboardRequiresLogin { await self.store.refreshProvider(.codex) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshCreditsNow(minimumSnapshotUpdatedAt: refreshStartedAt) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } } } self.store.scheduleStorageFootprintRefresh(for: [provider], force: true) self.store.persistWidgetSnapshot(reason: "provider-refresh") if refreshOpenMenusWhenComplete { self.refreshOpenMenusAfterExplicitStoreAction() } else { self.invalidateMenus() } } } private func withProviderInteraction( _ interaction: ProviderInteraction, operation: () async -> Void) async { if interaction == .userInitiated { await BrowserCookieAccessGate.withExplicitRetry { await ProviderInteractionContext.$current.withValue(interaction) { await operation() } } } else { await ProviderInteractionContext.$current.withValue(interaction) { await operation() } } } func refreshOpenMenusAfterExplicitStoreAction() { self.invalidateMenus( refreshOpenMenus: true, deferOpenParentMenuRebuild: true) } @objc func refreshNow() { self.startManualRefresh( for: nil, originatingMenuID: nil, originatingMenuInteractionGeneration: nil) } @objc func refreshMenuItem(_ sender: NSMenuItem) { self.refreshMenuProviderNow(in: sender.menu) } func refreshMenuProviderNow(in menu: NSMenu?) { let originatingMenuID = menu.map(ObjectIdentifier.init) let originatingMenuInteractionGeneration = originatingMenuID.flatMap { self.menuSession.menuInteractionGeneration(for: $0) } self.startManualRefresh( for: self.manualRefreshProvider(for: menu), originatingMenuID: originatingMenuID, originatingMenuInteractionGeneration: originatingMenuInteractionGeneration) } private func refreshMenuProviderNow( menuID: ObjectIdentifier, originatingMenuInteractionGeneration: Int) { let menu = self.openMenus[menuID] ?? self.mergedMenu.flatMap { ObjectIdentifier($0) == menuID ? $0 : nil } let provider = menu.flatMap { self.manualRefreshProvider(for: $0) } ?? self.menuProviders[menuID] self.startManualRefresh( for: provider, originatingMenuID: menuID, originatingMenuInteractionGeneration: originatingMenuInteractionGeneration) } private func startManualRefresh( for provider: UsageProvider?, originatingMenuID: ObjectIdentifier?, originatingMenuInteractionGeneration: Int?) { let scope: ManualRefreshScope = provider.map(ManualRefreshScope.provider) ?? .global let scopedRefreshInFlight = provider.map { self.store.refreshingProviders.contains($0) } ?? !self.store.refreshingProviders.isEmpty // Two different providers may refresh concurrently, but an all-providers (.global) refresh must // not overlap a per-provider one (or vice versa) — that would duplicate the shared fetch work. let conflictsWithOtherScope = scope == .global ? self.manualRefreshTasks.contains { $0.key != .global } : self.manualRefreshTasks[.global] != nil guard !self.hasPreparedForAppShutdown, self.manualRefreshTasks[scope] == nil, !conflictsWithOtherScope, !self.store.hasForcedRefreshEnrichmentInFlight, !self.store.isRefreshing, !scopedRefreshInFlight else { return } let frozenModels = self.frozenManualRefreshMenuCardModels() let viewportRestoreRequests = self.armManualRefreshViewportRestoreRequests( originatingMenuID: originatingMenuID, originatingMenuInteractionGeneration: originatingMenuInteractionGeneration) let task = Task { @MainActor [weak self] in guard let self else { return } var completed = false defer { self.manualRefreshTasks[scope] = nil self.menuCardRefreshMonitor.endManualRefresh(for: provider) self.updatePersistentRefreshItemsEnabled() if completed { self.scheduleCompletedManualRefreshViewportRestore(viewportRestoreRequests) } else { self.cancelManualRefreshViewportRestoreRequests(viewportRestoreRequests) } self.completeParentMenuRebuildAfterHostedSubviewCloseIfNeeded() self.prepareAttachedClosedMenusIfNeeded() } guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } #if DEBUG if let operation = self._test_manualRefreshOperation { await operation() guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } completed = true return } #endif if let provider { await self.performStoreRefresh( for: provider, refreshOpenMenusWhenComplete: true, interaction: .userInitiated) } else { await self.performStoreRefresh( enrichmentMode: .forcedBackground, refreshOpenMenusWhenComplete: true, interaction: .userInitiated) } guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } completed = true } self.manualRefreshTasks[scope] = task self.menuCardRefreshMonitor.beginManualRefresh(frozenModels: frozenModels, provider: provider) self.updatePersistentRefreshItemsEnabled() } private func manualRefreshProvider(for menu: NSMenu?) -> UsageProvider? { guard let menu else { return nil } if self.shouldMergeIcons { guard self.mergedMenu == nil || menu === self.mergedMenu else { return nil } guard !self.isMergedOverviewSelected(in: menu) else { return nil } return self.resolvedMenuProvider() } return self.menuProviders[ObjectIdentifier(menu)] } private func frozenManualRefreshMenuCardModels() -> [UsageProvider: UsageMenuCardView.Model] { var providers = self.store.enabledProvidersForDisplay() if let lastMenuProvider, !providers.contains(lastMenuProvider) { providers.append(lastMenuProvider) } if providers.isEmpty, let defaultProvider = self.settings.orderedProviders().first ?? UsageProvider.allCases.first { providers.append(defaultProvider) } var models: [UsageProvider: UsageMenuCardView.Model] = [:] for provider in providers { models[provider] = self.menuCardModel(for: provider) } return models } func performPersistentRefreshAction(in menuID: ObjectIdentifier) { guard let menuInteractionGeneration = self.menuSession.menuInteractionGeneration(for: menuID) else { return } self.performPersistentRefreshAction( in: menuID, menuInteractionGeneration: menuInteractionGeneration) } nonisolated func performPersistentRefreshAction( in menuID: ObjectIdentifier, menuInteractionGeneration: Int) { Task { @MainActor [weak self] in guard let self else { return } self.refreshMenuProviderNow( menuID: menuID, originatingMenuInteractionGeneration: menuInteractionGeneration) } } nonisolated func performPersistentSettingsAction() { Task { @MainActor [weak self] in guard let self else { return } self.closeOpenMenusFromShortcutIfNeeded() self.showSettingsGeneral() } } nonisolated func performPersistentQuitAction() { Task { @MainActor [weak self] in guard let self else { return } self.closeOpenMenusFromShortcutIfNeeded() self.quit() } } nonisolated func performProviderNavigation(_ direction: StatusItemMenuProviderNavigationDirection) { Task { @MainActor [weak self] in self?.navigateProviderSwitcher(direction) } } @objc func refreshAugmentSession() { Task { await self.store.forceRefreshAugmentSession() // Also trigger a full refresh to update the menu and clear any stale errors await ProviderInteractionContext.$current.withValue(.userInitiated) { await self.store.refresh(forceTokenUsage: false) } self.refreshOpenMenusAfterExplicitStoreAction() } } @objc func installUpdate() { self.updater.installUpdate() } @objc func openDashboard() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) let provider = preferred ?? .codex guard let url = self.dashboardURL(for: provider) else { return } NSWorkspace.shared.open(url) } func dashboardURL( for provider: UsageProvider, environment: [String: String] = ProcessInfo.processInfo.environment) -> URL? { if provider == .alibaba { return self.settings.alibabaCodingPlanAPIRegion.dashboardURL } if provider == .alibabatokenplan { return AlibabaTokenPlanUsageFetcher.dashboardURL( region: self.settings.alibabaTokenPlanAPIRegion, environment: environment) } if provider == .minimax { return self.settings.minimaxAPIRegion.dashboardURL } if provider == .opencodego { return self.settings.opencodegoDashboardURL } if provider == .wayfinder { return WayfinderProviderImplementation.dashboardURL( settings: self.settings, environment: environment) } if provider == .zai { return ZaiUsageFetcher.resolveDashboardURL( region: self.settings.zaiAPIRegion, environment: environment, usageScope: self.settings.zaiEffectiveUsageScope()) } if provider == .qoder { return QoderProviderDescriptor.dashboardURL( settings: self.settings.qoderSettingsSnapshot(tokenOverride: nil), sourceLabel: self.store.sourceLabel(for: .qoder)) } let meta = self.store.metadata(for: provider) let urlString: String? = if provider == .claude, self.store.isClaudeSubscription() { meta.subscriptionDashboardURL ?? meta.dashboardURL } else { meta.dashboardURL } guard let urlString else { return nil } return URL(string: urlString) } @objc func openCreditsPurchase() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) let provider = preferred ?? .codex guard provider == .codex else { return } let dashboardURL = self.store.metadata(for: .codex).dashboardURL let purchaseURL = Self.sanitizedCreditsPurchaseURL(self.store.openAIDashboard?.creditsPurchaseURL) let urlString = purchaseURL ?? dashboardURL guard let urlString, let url = URL(string: urlString) else { return } let autoStart = true let accountEmail = self.store.codexAccountEmailForOpenAIDashboard() let cacheScope = self.store.codexCookieCacheScopeForOpenAIWeb() guard OpenAICreditsPurchaseWindowController.canOpenPurchaseWindow( accountEmail: accountEmail, cacheScope: cacheScope) else { self.creditsPurchaseWindow?.close() self.creditsPurchaseWindow = nil return } let controller = self.creditsPurchaseWindow ?? OpenAICreditsPurchaseWindowController() controller.show( purchaseURL: url, accountEmail: accountEmail, cacheScope: cacheScope, autoStartPurchase: autoStart) self.creditsPurchaseWindow = controller } static func sanitizedCreditsPurchaseURL(_ raw: String?) -> String? { guard let raw, let url = URL(string: raw) else { return nil } guard Self.isAllowedChatGPTPurchaseHost(url) else { return nil } let pathComponents = url.pathComponents.map { $0.lowercased() } let allowed = ["settings", "usage", "billing", "credits"] guard pathComponents.contains(where: { allowed.contains($0) }) else { return nil } var components = URLComponents(url: url, resolvingAgainstBaseURL: false) components?.query = nil components?.fragment = nil return components?.url?.absoluteString ?? url.absoluteString } private static func isAllowedChatGPTPurchaseHost(_ url: URL) -> Bool { guard url.scheme?.lowercased() == "https" else { return false } guard let host = url.host?.lowercased() else { return false } return host == "chatgpt.com" || host.hasSuffix(".chatgpt.com") } @objc func openStatusPage() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) self.openStatusPage(for: preferred ?? .codex) } @objc func openStatusPageFromMenuItem(_ sender: NSMenuItem) { let provider = (sender.identifier?.rawValue).flatMap(UsageProvider.init(rawValue:)) ?? self.lastMenuProvider ?? .codex self.openStatusPage(for: provider) } private func openStatusPage(for provider: UsageProvider) { let meta = self.store.metadata(for: provider) let urlString = meta.statusPageURL ?? meta.statusLinkURL guard let urlString, let url = URL(string: urlString) else { return } NSWorkspace.shared.open(url) } @objc func openChangelog() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) let provider = preferred ?? .codex let meta = self.store.metadata(for: provider) guard let urlString = meta.changelogURL, let url = URL(string: urlString) else { return } NSWorkspace.shared.open(url) } @objc func openTerminalCommand(_ sender: NSMenuItem) { let command = sender.representedObject as? String ?? "claude" self.openTerminal(command: command) } @objc func openLoginToProvider(_ sender: NSMenuItem) { guard let urlString = sender.representedObject as? String, let url = URL(string: urlString) else { return } NSWorkspace.shared.open(url) } @objc func addManagedCodexAccountFromMenu(_: NSMenuItem) { guard self.codexAccountPromotionCoordinator.isInteractionBlocked() == false else { self.loginLogger.info("Add Account tap ignored: Codex account change already in-flight") return } guard self.settings.hasUnreadableManagedCodexAccountStore == false else { self.presentLoginAlert( title: L("Managed Codex accounts unavailable"), message: L( "CodexBar could not read managed account storage. " + "Recover the store before adding another account.")) return } Task { @MainActor [weak self] in guard let self else { return } do { let account = try await self.managedCodexAccountCoordinator.authenticateManagedAccount() self.settings.selectAuthenticatedManagedCodexAccount(account) await ProviderInteractionContext.$current.withValue(.userInitiated) { await self.store.refreshCodexAccountScopedState(allowDisabled: true) } } catch { self.presentManagedCodexAccountError(error) } }Lines 1–500 of 889. Load more
import AppKit import CodexBarCore extension StatusItemController { /// Identifies which manual refresh a task belongs to, so per-provider refreshes stay independent /// of each other and of the all-providers refresh. enum ManualRefreshScope: Hashable { case global case provider(UsageProvider) } } enum LoginNotificationLogic { static func notificationCopy(providerName: String) -> (title: String, body: String) { ( L("login_success_notification_title", providerName), L("login_success_notification_body")) } } extension StatusItemController: StatusItemMenuPersistentActionDelegate { // MARK: - Actions reachable from menus func refreshStore( forceTokenUsage: Bool, refreshOpenMenusWhenComplete: Bool = true, interaction: ProviderInteraction = .userInitiated) { Task { await self.performStoreRefresh( forceTokenUsage: forceTokenUsage, refreshOpenMenusWhenComplete: refreshOpenMenusWhenComplete, interaction: interaction) } } func performStoreRefresh( forceTokenUsage: Bool, refreshOpenMenusWhenComplete: Bool, interaction: ProviderInteraction) async { await self.withProviderInteraction(interaction) { await self.store.refresh(forceTokenUsage: forceTokenUsage) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } self.store.scheduleStorageFootprintRefreshForOverview(force: true) if refreshOpenMenusWhenComplete { self.refreshOpenMenusAfterExplicitStoreAction() } else { self.invalidateMenus() } } } func performStoreRefresh( enrichmentMode: UsageStore.RefreshEnrichmentMode, refreshOpenMenusWhenComplete: Bool, interaction: ProviderInteraction) async { await self.withProviderInteraction(interaction) { await self.store.refresh(enrichmentMode: enrichmentMode) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } self.store.scheduleStorageFootprintRefreshForOverview(force: true) if refreshOpenMenusWhenComplete { self.refreshOpenMenusAfterExplicitStoreAction() } else { self.invalidateMenus() } } } func performStoreRefresh( for provider: UsageProvider, refreshOpenMenusWhenComplete: Bool, interaction: ProviderInteraction) async { await self.withProviderInteraction(interaction) { await self.store.awaitForcedRefreshEnrichment() guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } let refreshStartedAt = Date() await self.store.refreshProvider(provider) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshProviderStatus(provider) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshTokenUsageNow(for: provider, force: true) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } if provider == .codex { await self.store.refreshCreditsNow(minimumSnapshotUpdatedAt: refreshStartedAt) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshOpenAIDashboardIfNeeded( force: true, expectedGuard: self.store.freshCodexOpenAIWebRefreshGuard(), bypassCoalescing: true) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } if self.store.openAIDashboardRequiresLogin { await self.store.refreshProvider(.codex) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } await self.store.refreshCreditsNow(minimumSnapshotUpdatedAt: refreshStartedAt) guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } } } self.store.scheduleStorageFootprintRefresh(for: [provider], force: true) self.store.persistWidgetSnapshot(reason: "provider-refresh") if refreshOpenMenusWhenComplete { self.refreshOpenMenusAfterExplicitStoreAction() } else { self.invalidateMenus() } } } private func withProviderInteraction( _ interaction: ProviderInteraction, operation: () async -> Void) async { if interaction == .userInitiated { await BrowserCookieAccessGate.withExplicitRetry { await ProviderInteractionContext.$current.withValue(interaction) { await operation() } } } else { await ProviderInteractionContext.$current.withValue(interaction) { await operation() } } } func refreshOpenMenusAfterExplicitStoreAction() { self.invalidateMenus( refreshOpenMenus: true, deferOpenParentMenuRebuild: true) } @objc func refreshNow() { self.startManualRefresh( for: nil, originatingMenuID: nil, originatingMenuInteractionGeneration: nil) } @objc func refreshMenuItem(_ sender: NSMenuItem) { self.refreshMenuProviderNow(in: sender.menu) } func refreshMenuProviderNow(in menu: NSMenu?) { let originatingMenuID = menu.map(ObjectIdentifier.init) let originatingMenuInteractionGeneration = originatingMenuID.flatMap { self.menuSession.menuInteractionGeneration(for: $0) } self.startManualRefresh( for: self.manualRefreshProvider(for: menu), originatingMenuID: originatingMenuID, originatingMenuInteractionGeneration: originatingMenuInteractionGeneration) } private func refreshMenuProviderNow( menuID: ObjectIdentifier, originatingMenuInteractionGeneration: Int) { let menu = self.openMenus[menuID] ?? self.mergedMenu.flatMap { ObjectIdentifier($0) == menuID ? $0 : nil } let provider = menu.flatMap { self.manualRefreshProvider(for: $0) } ?? self.menuProviders[menuID] self.startManualRefresh( for: provider, originatingMenuID: menuID, originatingMenuInteractionGeneration: originatingMenuInteractionGeneration) } private func startManualRefresh( for provider: UsageProvider?, originatingMenuID: ObjectIdentifier?, originatingMenuInteractionGeneration: Int?) { let scope: ManualRefreshScope = provider.map(ManualRefreshScope.provider) ?? .global let scopedRefreshInFlight = provider.map { self.store.refreshingProviders.contains($0) } ?? !self.store.refreshingProviders.isEmpty // Two different providers may refresh concurrently, but an all-providers (.global) refresh must // not overlap a per-provider one (or vice versa) — that would duplicate the shared fetch work. let conflictsWithOtherScope = scope == .global ? self.manualRefreshTasks.contains { $0.key != .global } : self.manualRefreshTasks[.global] != nil guard !self.hasPreparedForAppShutdown, self.manualRefreshTasks[scope] == nil, !conflictsWithOtherScope, !self.store.hasForcedRefreshEnrichmentInFlight, !self.store.isRefreshing, !scopedRefreshInFlight else { return } let frozenModels = self.frozenManualRefreshMenuCardModels() let viewportRestoreRequests = self.armManualRefreshViewportRestoreRequests( originatingMenuID: originatingMenuID, originatingMenuInteractionGeneration: originatingMenuInteractionGeneration) let task = Task { @MainActor [weak self] in guard let self else { return } var completed = false defer { self.manualRefreshTasks[scope] = nil self.menuCardRefreshMonitor.endManualRefresh(for: provider) self.updatePersistentRefreshItemsEnabled() if completed { self.scheduleCompletedManualRefreshViewportRestore(viewportRestoreRequests) } else { self.cancelManualRefreshViewportRestoreRequests(viewportRestoreRequests) } self.completeParentMenuRebuildAfterHostedSubviewCloseIfNeeded() self.prepareAttachedClosedMenusIfNeeded() } guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } #if DEBUG if let operation = self._test_manualRefreshOperation { await operation() guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } completed = true return } #endif if let provider { await self.performStoreRefresh( for: provider, refreshOpenMenusWhenComplete: true, interaction: .userInitiated) } else { await self.performStoreRefresh( enrichmentMode: .forcedBackground, refreshOpenMenusWhenComplete: true, interaction: .userInitiated) } guard !Task.isCancelled, !self.hasPreparedForAppShutdown else { return } completed = true } self.manualRefreshTasks[scope] = task self.menuCardRefreshMonitor.beginManualRefresh(frozenModels: frozenModels, provider: provider) self.updatePersistentRefreshItemsEnabled() } private func manualRefreshProvider(for menu: NSMenu?) -> UsageProvider? { guard let menu else { return nil } if self.shouldMergeIcons { guard self.mergedMenu == nil || menu === self.mergedMenu else { return nil } guard !self.isMergedOverviewSelected(in: menu) else { return nil } return self.resolvedMenuProvider() } return self.menuProviders[ObjectIdentifier(menu)] } private func frozenManualRefreshMenuCardModels() -> [UsageProvider: UsageMenuCardView.Model] { var providers = self.store.enabledProvidersForDisplay() if let lastMenuProvider, !providers.contains(lastMenuProvider) { providers.append(lastMenuProvider) } if providers.isEmpty, let defaultProvider = self.settings.orderedProviders().first ?? UsageProvider.allCases.first { providers.append(defaultProvider) } var models: [UsageProvider: UsageMenuCardView.Model] = [:] for provider in providers { models[provider] = self.menuCardModel(for: provider) } return models } func performPersistentRefreshAction(in menuID: ObjectIdentifier) { guard let menuInteractionGeneration = self.menuSession.menuInteractionGeneration(for: menuID) else { return } self.performPersistentRefreshAction( in: menuID, menuInteractionGeneration: menuInteractionGeneration) } nonisolated func performPersistentRefreshAction( in menuID: ObjectIdentifier, menuInteractionGeneration: Int) { Task { @MainActor [weak self] in guard let self else { return } self.refreshMenuProviderNow( menuID: menuID, originatingMenuInteractionGeneration: menuInteractionGeneration) } } nonisolated func performPersistentSettingsAction() { Task { @MainActor [weak self] in guard let self else { return } self.closeOpenMenusFromShortcutIfNeeded() self.showSettingsGeneral() } } nonisolated func performPersistentQuitAction() { Task { @MainActor [weak self] in guard let self else { return } self.closeOpenMenusFromShortcutIfNeeded() self.quit() } } nonisolated func performProviderNavigation(_ direction: StatusItemMenuProviderNavigationDirection) { Task { @MainActor [weak self] in self?.navigateProviderSwitcher(direction) } } @objc func refreshAugmentSession() { Task { await self.store.forceRefreshAugmentSession() // Also trigger a full refresh to update the menu and clear any stale errors await ProviderInteractionContext.$current.withValue(.userInitiated) { await self.store.refresh(forceTokenUsage: false) } self.refreshOpenMenusAfterExplicitStoreAction() } } @objc func installUpdate() { self.updater.installUpdate() } @objc func openDashboard() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) let provider = preferred ?? .codex guard let url = self.dashboardURL(for: provider) else { return } NSWorkspace.shared.open(url) } func dashboardURL( for provider: UsageProvider, environment: [String: String] = ProcessInfo.processInfo.environment) -> URL? { if provider == .alibaba { return self.settings.alibabaCodingPlanAPIRegion.dashboardURL } if provider == .alibabatokenplan { return AlibabaTokenPlanUsageFetcher.dashboardURL( region: self.settings.alibabaTokenPlanAPIRegion, environment: environment) } if provider == .minimax { return self.settings.minimaxAPIRegion.dashboardURL } if provider == .opencodego { return self.settings.opencodegoDashboardURL } if provider == .wayfinder { return WayfinderProviderImplementation.dashboardURL( settings: self.settings, environment: environment) } if provider == .zai { return ZaiUsageFetcher.resolveDashboardURL( region: self.settings.zaiAPIRegion, environment: environment, usageScope: self.settings.zaiEffectiveUsageScope()) } if provider == .qoder { return QoderProviderDescriptor.dashboardURL( settings: self.settings.qoderSettingsSnapshot(tokenOverride: nil), sourceLabel: self.store.sourceLabel(for: .qoder)) } let meta = self.store.metadata(for: provider) let urlString: String? = if provider == .claude, self.store.isClaudeSubscription() { meta.subscriptionDashboardURL ?? meta.dashboardURL } else { meta.dashboardURL } guard let urlString else { return nil } return URL(string: urlString) } @objc func openCreditsPurchase() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) let provider = preferred ?? .codex guard provider == .codex else { return } let dashboardURL = self.store.metadata(for: .codex).dashboardURL let purchaseURL = Self.sanitizedCreditsPurchaseURL(self.store.openAIDashboard?.creditsPurchaseURL) let urlString = purchaseURL ?? dashboardURL guard let urlString, let url = URL(string: urlString) else { return } let autoStart = true let accountEmail = self.store.codexAccountEmailForOpenAIDashboard() let cacheScope = self.store.codexCookieCacheScopeForOpenAIWeb() guard OpenAICreditsPurchaseWindowController.canOpenPurchaseWindow( accountEmail: accountEmail, cacheScope: cacheScope) else { self.creditsPurchaseWindow?.close() self.creditsPurchaseWindow = nil return } let controller = self.creditsPurchaseWindow ?? OpenAICreditsPurchaseWindowController() controller.show( purchaseURL: url, accountEmail: accountEmail, cacheScope: cacheScope, autoStartPurchase: autoStart) self.creditsPurchaseWindow = controller } static func sanitizedCreditsPurchaseURL(_ raw: String?) -> String? { guard let raw, let url = URL(string: raw) else { return nil } guard Self.isAllowedChatGPTPurchaseHost(url) else { return nil } let pathComponents = url.pathComponents.map { $0.lowercased() } let allowed = ["settings", "usage", "billing", "credits"] guard pathComponents.contains(where: { allowed.contains($0) }) else { return nil } var components = URLComponents(url: url, resolvingAgainstBaseURL: false) components?.query = nil components?.fragment = nil return components?.url?.absoluteString ?? url.absoluteString } private static func isAllowedChatGPTPurchaseHost(_ url: URL) -> Bool { guard url.scheme?.lowercased() == "https" else { return false } guard let host = url.host?.lowercased() else { return false } return host == "chatgpt.com" || host.hasSuffix(".chatgpt.com") } @objc func openStatusPage() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) self.openStatusPage(for: preferred ?? .codex) } @objc func openStatusPageFromMenuItem(_ sender: NSMenuItem) { let provider = (sender.identifier?.rawValue).flatMap(UsageProvider.init(rawValue:)) ?? self.lastMenuProvider ?? .codex self.openStatusPage(for: provider) } private func openStatusPage(for provider: UsageProvider) { let meta = self.store.metadata(for: provider) let urlString = meta.statusPageURL ?? meta.statusLinkURL guard let urlString, let url = URL(string: urlString) else { return } NSWorkspace.shared.open(url) } @objc func openChangelog() { let preferred = self.lastMenuProvider ?? (self.store.isEnabled(.codex) ? .codex : self.store.enabledProviders().first) let provider = preferred ?? .codex let meta = self.store.metadata(for: provider) guard let urlString = meta.changelogURL, let url = URL(string: urlString) else { return } NSWorkspace.shared.open(url) } @objc func openTerminalCommand(_ sender: NSMenuItem) { let command = sender.representedObject as? String ?? "claude" self.openTerminal(command: command) } @objc func openLoginToProvider(_ sender: NSMenuItem) { guard let urlString = sender.representedObject as? String, let url = URL(string: urlString) else { return } NSWorkspace.shared.open(url) } @objc func addManagedCodexAccountFromMenu(_: NSMenuItem) { guard self.codexAccountPromotionCoordinator.isInteractionBlocked() == false else { self.loginLogger.info("Add Account tap ignored: Codex account change already in-flight") return } guard self.settings.hasUnreadableManagedCodexAccountStore == false else { self.presentLoginAlert( title: L("Managed Codex accounts unavailable"), message: L( "CodexBar could not read managed account storage. " + "Recover the store before adding another account.")) return } Task { @MainActor [weak self] in guard let self else { return } do { let account = try await self.managedCodexAccountCoordinator.authenticateManagedAccount() self.settings.selectAuthenticatedManagedCodexAccount(account) await ProviderInteractionContext.$current.withValue(.userInitiated) { await self.store.refreshCodexAccountScopedState(allowDisabled: true) } } catch { self.presentManagedCodexAccountError(error) } }