303 lines · 12.4 KB · Swift
RawDownload
import CodexBarCoreimport Foundationimport SwiftUI struct CodexProviderImplementation: ProviderImplementation {    let id: UsageProvider = .codex    let supportsLoginFlow: Bool = true     @MainActor    func presentation(context _: ProviderPresentationContext) -> ProviderPresentation {        ProviderPresentation { context in            context.store.version(for: context.provider) ?? "not detected"        }    }     @MainActor    func observeSettings(_ settings: SettingsStore) {        _ = settings.codexUsageDataSource        _ = settings.codexCookieSource        _ = settings.codexCookieHeader    }     @MainActor    func settingsSnapshot(context: ProviderSettingsSnapshotContext) -> ProviderSettingsSnapshotContribution? {        .codex(context.settings.codexSettingsSnapshot(            tokenOverride: context.tokenOverride,            activeSourceOverride: context.codexActiveSourceOverride))    }     @MainActor    func defaultSourceLabel(context: ProviderSourceLabelContext) -> String? {        context.settings.codexUsageDataSource.rawValue    }     @MainActor    func decorateSourceLabel(context: ProviderSourceLabelContext, baseLabel: String) -> String {        if context.settings.codexCookieSource.isEnabled,           context.store.openAIDashboard != nil,           !context.store.openAIDashboardRequiresLogin,           !baseLabel.contains("openai-web")        {            return "\(baseLabel) + openai-web"        }        return baseLabel    }     @MainActor    func sourceMode(context: ProviderSourceModeContext) -> ProviderSourceMode {        switch context.settings.codexUsageDataSource {        case .auto: .auto        case .oauth: .oauth        case .cli: .cli        }    }     func makeRuntime() -> (any ProviderRuntime)? {        CodexProviderRuntime()    }     @MainActor    func settingsToggles(context: ProviderSettingsContext) -> [ProviderSettingsToggleDescriptor] {        let extrasBinding = Binding(            get: { context.settings.openAIWebAccessEnabled },            set: { enabled in                context.settings.openAIWebAccessEnabled = enabled                Task { @MainActor in                    await context.store.performRuntimeAction(                        .openAIWebAccessToggled(enabled),                        for: .codex)                }            })        let batterySaverBinding = context.boolBinding(\.openAIWebBatterySaverEnabled)        let historicalTrackingSubtitle = [            L("Stores local Codex usage history (8 weeks) to personalize Pace predictions."),            "[\(L("weekly_progress_work_days_title")) = \(L("Automatic"))]",        ].joined(separator: " ")         return [            ProviderSettingsToggleDescriptor(                id: "codex-local-session-cost-ledger",                title: "Local session cost estimates",                subtitle: [                    "Uses this Mac's Codex sessions instead of the selected managed account's session history.",                    "Works with organization API keys and does not require OpenAI billing or administrator access.",                    "Uses locally cached or bundled model prices without making a network request.",                    "This provider-specific toggle does not enable cost summaries for other providers.",                ].joined(separator: " "),                binding: context.boolBinding(\.codexLocalSessionCostLedgerEnabled),                statusText: nil,                actions: [],                isVisible: nil,                onChange: nil,                onAppDidBecomeActive: nil,                onAppearWhenEnabled: nil),            ProviderSettingsToggleDescriptor(                id: "codex-historical-tracking",                title: "Historical tracking",                subtitle: historicalTrackingSubtitle,                binding: context.boolBinding(\.historicalTrackingEnabled),                statusText: nil,                actions: [],                isVisible: nil,                onChange: nil,                onAppDidBecomeActive: nil,                onAppearWhenEnabled: nil),            ProviderSettingsToggleDescriptor(                id: "codex-spark-usage-visible",                title: "Show Codex Spark usage",                subtitle: [                    "Shows Codex Spark quota rows in the menu and provider preview.",                    "Requires optional credits and extra usage in Display settings.",                ].joined(separator: " "),                binding: context.boolBinding(\.codexSparkUsageVisible),                statusText: nil,                actions: [],                isVisible: nil,                isEnabled: { context.settings.showOptionalCreditsAndExtraUsage },                onChange: nil,                onAppDidBecomeActive: nil,                onAppearWhenEnabled: nil),            ProviderSettingsToggleDescriptor(                id: "codex-openai-web-extras",                title: "OpenAI web extras",                subtitle: [                    "Optional.",                    "Turn this on to show code review, usage breakdown, and credits history via chatgpt.com.",                ].joined(separator: " "),                binding: extrasBinding,                statusText: nil,                actions: [],                isVisible: nil,                onChange: nil,                onAppDidBecomeActive: nil,                onAppearWhenEnabled: nil),            ProviderSettingsToggleDescriptor(                id: "codex-openai-web-battery-saver",                title: "Battery Saver",                subtitle: [                    "Limits background chatgpt.com refreshes to reduce battery and network usage.",                    "Dashboard extras may stay stale until you refresh them manually.",                ].joined(separator: " "),                binding: batterySaverBinding,                statusText: nil,                actions: [],                isVisible: { context.settings.openAIWebAccessEnabled },                onChange: nil,                onAppDidBecomeActive: nil,                onAppearWhenEnabled: nil),        ]    }     @MainActor    func settingsPickers(context: ProviderSettingsContext) -> [ProviderSettingsPickerDescriptor] {        let usageBinding = Binding(            get: { context.settings.codexUsageDataSource.rawValue },            set: { raw in                context.settings.codexUsageDataSource = CodexUsageDataSource(rawValue: raw) ?? .auto            })        let cookieBinding = Binding(            get: { context.settings.codexCookieSource.rawValue },            set: { raw in                context.settings.codexCookieSource = ProviderCookieSource(rawValue: raw) ?? .auto            })         let usageOptions = CodexUsageDataSource.allCases.map {            ProviderSettingsPickerOption(id: $0.rawValue, title: $0.displayName)        }        let cookieOptions = ProviderCookieSourceUI.options(            allowsOff: true,            keychainDisabled: context.settings.debugDisableKeychainAccess)         let cookieSubtitle: () -> String? = {            ProviderCookieSourceUI.subtitle(                source: context.settings.codexCookieSource,                keychainDisabled: context.settings.debugDisableKeychainAccess,                auto: "Automatic imports browser cookies for dashboard extras.",                manual: "Paste a Cookie header from a chatgpt.com request.",                off: "Disable OpenAI dashboard cookie usage.")        }         return [            ProviderSettingsPickerDescriptor(                id: "codex-usage-source",                title: "Quota usage source",                subtitle: [                    "Controls live session and weekly quota fetching only.",                    "Local session cost estimates work independently.",                ].joined(separator: " "),                binding: usageBinding,                options: usageOptions,                isVisible: nil,                onChange: nil,                trailingText: {                    guard context.settings.codexUsageDataSource == .auto else { return nil }                    let label = context.store.sourceLabel(for: .codex)                    return label == "auto" ? nil : label                }),            ProviderSettingsPickerDescriptor(                id: "codex-cookie-source",                title: "OpenAI cookies",                subtitle: "Automatic imports browser cookies for dashboard extras.",                dynamicSubtitle: cookieSubtitle,                binding: cookieBinding,                options: cookieOptions,                isVisible: { context.settings.openAIWebAccessEnabled },                onChange: nil,                trailingText: {                    ProviderCookieSourceUI.cachedTrailingText(provider: .codex)                }),        ]    }     @MainActor    func settingsFields(context: ProviderSettingsContext) -> [ProviderSettingsFieldDescriptor] {        [            ProviderSettingsFieldDescriptor(                id: "codex-cookie-header",                title: "",                subtitle: "",                kind: .secure,                placeholder: "Cookie: …",                binding: context.stringBinding(\.codexCookieHeader),                actions: [],                isVisible: {                    context.settings.codexCookieSource == .manual                },                onActivate: { context.settings.ensureCodexCookieLoaded() }),        ]    }     @MainActor    func appendUsageMenuEntries(context: ProviderMenuUsageContext, entries: inout [ProviderMenuEntry]) {        guard context.settings.showOptionalCreditsAndExtraUsage,              context.metadata.supportsCredits        else { return }         if let credits = context.store.credits {            let remaining = credits.codexCreditLimit?.remaining ?? credits.remaining            entries.append(.text(                String(format: L("credits_remaining"), UsageFormatter.creditsString(from: remaining)),                .primary))            if let limit = credits.codexCreditLimit {                var parts = [                    L("%@ used", UsageFormatter.creditsNumberString(from: limit.used)),                ]                if let resetsAt = limit.resetsAt {                    parts.append(L("resets %@", UsageFormatter.resetDescription(from: resetsAt)))                }                entries.append(.text(parts.joined(separator: " · "), .secondary))            }            if let latest = credits.events.first {                entries.append(.text(                    String(format: L("last_spend"), UsageFormatter.creditEventSummary(latest)),                    .secondary))            }        } else {            let hint = context.store.userFacingLastCreditsError ?? context.metadata.creditsHint            entries.append(.text(hint, .secondary))        }    }     @MainActor    func loginMenuAction(context _: ProviderMenuLoginContext)        -> (label: String, action: MenuDescriptor.MenuAction)?    {        ("Add Account...", .addCodexAccount)    }     @MainActor    func appendActionMenuEntries(context: ProviderMenuActionContext, entries: inout [ProviderMenuEntry]) {        let projection = context.settings.codexVisibleAccountProjection        guard !projection.visibleAccounts.isEmpty else { return }         let isInteractionBlocked = context.codexAccountPromotionCoordinator?.isInteractionBlocked() ?? false         let submenuItems = projection.visibleAccounts.map { account in            let isChecked = account.id == projection.liveVisibleAccountID            let isEnabled = !isInteractionBlocked &&                !isChecked &&                account.storedAccountID != nil            let action = account.storedAccountID.map(MenuDescriptor.MenuAction.requestCodexSystemPromotion)            return MenuDescriptor.SubmenuItem(                title: account.displayName,                action: action,                isEnabled: isEnabled,                isChecked: isChecked)        }        guard submenuItems.count > 1 || submenuItems.contains(where: { $0.isEnabled && $0.action != nil }) else {            return        }         entries.append(.submenu(            "System Account",            MenuDescriptor.MenuActionSystemImage.systemAccount.rawValue,            submenuItems))    }     @MainActor    func runLoginFlow(context: ProviderLoginContext) async -> Bool {        await context.controller.runCodexLoginFlow()        return true    }}