import CodexBarCoreimport Commander#if canImport(AppKit)import AppKit#endif#if canImport(Darwin)import Darwin#elseimport Glibc#endifimport Foundation#if canImport(FoundationNetworking)import FoundationNetworking#endif @mainenum CodexBarCLI { static func main() async { let rawArgv = Array(CommandLine.arguments.dropFirst()) let argv = Self.effectiveArgv(rawArgv) // Fast path: global help/version before building descriptors. if let helpIndex = argv.firstIndex(where: { $0 == "-h" || $0 == "--help" }) { let command = helpIndex == 0 ? argv.dropFirst().first : argv.first Self.printHelp(for: command) } if argv.contains("-V") || argv.contains("--version") { Self.printVersion() } let usageSignature = CommandSignature .describe(UsageOptions()) let costSignature = CommandSignature .describe(CostOptions()) let descriptors: [CommandDescriptor] = [ CommandDescriptor( name: "usage", abstract: "Print usage as text or JSON", discussion: nil, signature: usageSignature), CommandDescriptor( name: "cost", abstract: "Print local cost usage as text or JSON", discussion: nil, signature: costSignature), ] let program = Program(descriptors: descriptors) do { let invocation = try program.resolve(argv: argv) Self.bootstrapLogging(values: invocation.parsedValues) switch invocation.descriptor.name { case "usage": await self.runUsage(invocation.parsedValues) case "cost": await self.runCost(invocation.parsedValues) default: Self.exit(code: .failure, message: "Unknown command") } } catch let error as CommanderProgramError { Self.exit(code: .failure, message: error.description) } catch { Self.exit(code: .failure, message: error.localizedDescription) } } // MARK: - Commands private static func runUsage(_ values: ParsedValues) async { let provider = Self.decodeProvider(from: values) let format = Self.decodeFormat(from: values) let includeCredits = format == .json ? true : !values.flags.contains("noCredits") let includeStatus = values.flags.contains("status") let pretty = values.flags.contains("pretty") let sourceModeRaw = values.options["source"]?.last let parsedSourceMode = Self.decodeSourceMode(from: values) if sourceModeRaw != nil, parsedSourceMode == nil { Self.exit(code: .failure, message: "Error: --source must be auto|web|cli|oauth.") } let sourceMode = parsedSourceMode ?? .auto let antigravityPlanDebug = values.flags.contains("antigravityPlanDebug") let augmentDebug = values.flags.contains("augmentDebug") let webDebugDumpHTML = values.flags.contains("webDebugDumpHtml") let webTimeout = Self.decodeWebTimeout(from: values) ?? 60 let verbose = values.flags.contains("verbose") let noColor = values.flags.contains("noColor") let useColor = Self.shouldUseColor(noColor: noColor, format: format) let resetStyle = Self.resetTimeDisplayStyleFromDefaults() let fetcher = UsageFetcher() let browserDetection = BrowserDetection(cacheTTL: 0) let claudeFetcher = ClaudeUsageFetcher(browserDetection: browserDetection) #if !os(macOS) if sourceMode.usesWeb { Self.exit(code: .failure, message: "Error: --source web/auto is only supported on macOS.") } #endif var sections: [String] = [] var payload: [ProviderPayload] = [] var exitCode: ExitCode = .success let fetchContext = ProviderFetchContext( runtime: .cli, sourceMode: sourceMode, includeCredits: includeCredits, webTimeout: webTimeout, webDebugDumpHTML: webDebugDumpHTML, verbose: verbose, env: ProcessInfo.processInfo.environment, settings: nil, fetcher: fetcher, claudeFetcher: claudeFetcher, browserDetection: browserDetection) for p in provider.asList { let status = includeStatus ? await Self.fetchStatus(for: p) : nil var antigravityPlanInfo: AntigravityPlanInfoSummary? let outcome = await Self.fetchProviderUsage( provider: p, context: fetchContext) if verbose { Self.printFetchAttempts(provider: p, attempts: outcome.attempts) } switch outcome.result { case let .success(result): var dashboard = result.dashboard if antigravityPlanDebug, p == .antigravity { antigravityPlanInfo = try? await AntigravityStatusProbe().fetchPlanInfoSummary() if format == .text, let info = antigravityPlanInfo { Self.printAntigravityPlanInfo(info) } } if augmentDebug, p == .augment { #if os(macOS) let dump = await AugmentStatusProbe.latestDumps() if format == .text, !dump.isEmpty { Self.writeStderr("Augment API responses:\n\(dump)\n") } #endif } if dashboard == nil, format == .json, p == .codex { dashboard = Self.loadOpenAIDashboardIfAvailable(usage: result.usage, fetcher: fetcher) } let descriptor = ProviderDescriptorRegistry.descriptor(for: p) let shouldDetectVersion = descriptor.cli.versionDetector != nil && result.strategyKind != .webDashboard let version = Self.normalizeVersion( raw: shouldDetectVersion ? Self.detectVersion(for: p, browserDetection: browserDetection) : nil) let source = result.sourceLabel let header = Self.makeHeader(provider: p, version: version, source: source) switch format { case .text: var text = CLIRenderer.renderText( provider: p, snapshot: result.usage, credits: result.credits, context: RenderContext( header: header, status: status, useColor: useColor, resetStyle: resetStyle)) if let dashboard, p == .codex, sourceMode.usesWeb { text += "\n" + Self.renderOpenAIWebDashboardText(dashboard) } sections.append(text) case .json: payload.append(ProviderPayload( provider: p, version: version, source: source, status: status, usage: result.usage, credits: result.credits, antigravityPlanInfo: antigravityPlanInfo, openaiDashboard: dashboard)) } case let .failure(error): exitCode = Self.mapError(error) Self.printError(error) } } switch format { case .text: if !sections.isEmpty { print(sections.joined(separator: "\n\n")) } case .json: if !payload.isEmpty { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 encoder.outputFormatting = pretty ? [.prettyPrinted, .sortedKeys] : [] if let data = try? encoder.encode(payload), let output = String(data: data, encoding: .utf8) { print(output) } } } Self.exit(code: exitCode) } // MARK: - Helpers private static func bootstrapLogging(values: ParsedValues) { let isJSON = values.flags.contains("jsonOutput") let verbose = values.flags.contains("verbose") let rawLevel = values.options["logLevel"]?.last let level = Self.resolvedLogLevel(verbose: verbose, rawLevel: rawLevel) CodexBarLog.bootstrapIfNeeded(.init(destination: .stderr, level: level, json: isJSON)) } static func resolvedLogLevel(verbose: Bool, rawLevel: String?) -> CodexBarLog.Level { CodexBarLog.parseLevel(rawLevel) ?? (verbose ? .debug : .error) } static func effectiveArgv(_ argv: [String]) -> [String] { guard let first = argv.first else { return ["usage"] } if first.hasPrefix("-") { return ["usage"] + argv } return argv } static func decodeProvider(from values: ParsedValues) -> ProviderSelection { let rawOverride = values.options["provider"]?.last return Self.providerSelection(rawOverride: rawOverride, enabled: Self.enabledProvidersFromDefaults()) } static func providerSelection(rawOverride: String?, enabled: [UsageProvider]) -> ProviderSelection { if let rawOverride, let parsed = ProviderSelection(argument: rawOverride) { return parsed } if enabled.count >= 3 { return .all } if enabled.count == 2 { let enabledSet = Set(enabled) let primary = Set(ProviderDescriptorRegistry.all.filter(\.metadata.isPrimaryProvider).map(\.id)) if !primary.isEmpty, enabledSet == primary { return .both } return .custom(enabled) } if let first = enabled.first { return ProviderSelection(provider: first) } return .single(.codex) } static func decodeFormat(from values: ParsedValues) -> OutputFormat { if let raw = values.options["format"]?.last, let parsed = OutputFormat(argument: raw) { return parsed } if values.flags.contains("jsonShortcut") || values.flags.contains("json") { return .json } return .text } static func shouldUseColor(noColor: Bool, format: OutputFormat) -> Bool { guard format == .text else { return false } if noColor { return false } let env = ProcessInfo.processInfo.environment if env["TERM"]?.lowercased() == "dumb" { return false } return isatty(STDOUT_FILENO) == 1 } private static func detectVersion(for provider: UsageProvider, browserDetection: BrowserDetection) -> String? { ProviderDescriptorRegistry.descriptor(for: provider).cli.versionDetector?(browserDetection) } private static func normalizeVersion(raw: String?) -> String? { guard let raw, !raw.isEmpty else { return nil } if let match = raw.range(of: #"(\d+(?:\.\d+)+)"#, options: .regularExpression) { return String(raw[match]).trimmingCharacters(in: .whitespacesAndNewlines) } return raw.trimmingCharacters(in: .whitespacesAndNewlines) } private static func makeHeader(provider: UsageProvider, version: String?, source: String) -> String { let name = ProviderDescriptorRegistry.descriptor(for: provider).metadata.displayName if let version, !version.isEmpty { return "\(name) \(version) (\(source))" } return "\(name) (\(source))" } private static func printFetchAttempts(provider: UsageProvider, attempts: [ProviderFetchAttempt]) { guard !attempts.isEmpty else { return } self.writeStderr("[\(provider.rawValue)] fetch strategies:\n") for attempt in attempts { let kindLabel = Self.fetchKindLabel(attempt.kind) var line = " - \(attempt.strategyID) (\(kindLabel))" line += attempt.wasAvailable ? " available" : " unavailable" if let error = attempt.errorDescription, !error.isEmpty { line += " error=\(error)" } self.writeStderr("\(line)\n") } } private static func fetchKindLabel(_ kind: ProviderFetchKind) -> String { switch kind { case .cli: "cli" case .web: "web" case .oauth: "oauth" case .apiToken: "api" case .localProbe: "local" case .webDashboard: "web" } } private static func fetchStatus(for provider: UsageProvider) async -> ProviderStatusPayload? { let urlString = ProviderDescriptorRegistry.descriptor(for: provider).metadata.statusPageURL guard let urlString, let baseURL = URL(string: urlString) else { return nil } do { return try await StatusFetcher.fetch(from: baseURL) } catch { return ProviderStatusPayload( indicator: .unknown, description: error.localizedDescription, updatedAt: nil, url: urlString) } } private static func enabledProvidersFromDefaults() -> [UsageProvider] { // Prefer the app's defaults domain so CLI mirrors in-app toggles. let domains = [ "com.steipete.codexbar", "com.steipete.codexbar.debug", ] var toggles: [String: Bool] = [:] for domain in domains { if let dict = UserDefaults(suiteName: domain)?.dictionary(forKey: "providerToggles") as? [String: Bool], !dict.isEmpty { toggles = dict break } } if toggles.isEmpty { toggles = UserDefaults.standard.dictionary(forKey: "providerToggles") as? [String: Bool] ?? [:] } return ProviderDescriptorRegistry.all.compactMap { descriptor in let meta = descriptor.metadata let isOn = toggles[meta.cliName] ?? meta.defaultEnabled return isOn ? descriptor.id : nil } } private static func resetTimeDisplayStyleFromDefaults() -> ResetTimeDisplayStyle { let domains = [ "com.steipete.codexbar", "com.steipete.codexbar.debug", ] for domain in domains { if let value = UserDefaults(suiteName: domain)?.object(forKey: "resetTimesShowAbsolute") as? Bool { return value ? .absolute : .countdown } } let fallback = UserDefaults.standard.object(forKey: "resetTimesShowAbsolute") as? Bool ?? false return fallback ? .absolute : .countdown } private static func fetchProviderUsage( provider: UsageProvider, context: ProviderFetchContext) async -> ProviderFetchOutcome { let descriptor = ProviderDescriptorRegistry.descriptor(for: provider) if !descriptor.fetchPlan.sourceModes.contains(context.sourceMode) { let error = SourceSelectionError.unsupported( provider: descriptor.cli.name, source: context.sourceMode) return ProviderFetchOutcome(result: .failure(error), attempts: []) } return await descriptor.fetchOutcome(context: context) } private enum SourceSelectionError: LocalizedError { case unsupported(provider: String, source: ProviderSourceMode) var errorDescription: String? { switch self { case let .unsupported(provider, source): "Source '\(source.rawValue)' is not supported for \(provider)." } } } private static func loadOpenAIDashboardIfAvailable( usage: UsageSnapshot, fetcher: UsageFetcher) -> OpenAIDashboardSnapshot? { guard let cache = OpenAIDashboardCacheStore.load() else { return nil } let codexEmail = (usage.accountEmail(for: .codex) ?? fetcher.loadAccountInfo().email)? .trimmingCharacters(in: .whitespacesAndNewlines) guard let codexEmail, !codexEmail.isEmpty else { return nil } if cache.accountEmail.lowercased() != codexEmail.lowercased() { return nil } if cache.snapshot.dailyBreakdown.isEmpty, !cache.snapshot.creditEvents.isEmpty { return OpenAIDashboardSnapshot( signedInEmail: cache.snapshot.signedInEmail, codeReviewRemainingPercent: cache.snapshot.codeReviewRemainingPercent, creditEvents: cache.snapshot.creditEvents, dailyBreakdown: OpenAIDashboardSnapshot.makeDailyBreakdown( from: cache.snapshot.creditEvents, maxDays: 30), usageBreakdown: cache.snapshot.usageBreakdown, creditsPurchaseURL: cache.snapshot.creditsPurchaseURL, updatedAt: cache.snapshot.updatedAt) } return cache.snapshot } private static func decodeWebTimeout(from values: ParsedValues) -> TimeInterval? { if let raw = values.options["webTimeout"]?.last, let seconds = Double(raw) { return seconds } return nil } private static func decodeSourceMode(from values: ParsedValues) -> ProviderSourceMode? { if values.flags.contains("web") { return .web } guard let raw = values.options["source"]?.last?.lowercased() else { return nil } return ProviderSourceMode(rawValue: raw) } private static func renderOpenAIWebDashboardText(_ dash: OpenAIDashboardSnapshot) -> String { var lines: [String] = [] if let email = dash.signedInEmail, !email.isEmpty { lines.append("Web session: \(email)") } if let remaining = dash.codeReviewRemainingPercent { let percent = Int(remaining.rounded()) lines.append("Code review: \(percent)% remaining") } if let first = dash.creditEvents.first { let day = first.date.formatted(date: .abbreviated, time: .omitted) lines.append("Web history: \(dash.creditEvents.count) events (latest \(day))") } else { lines.append("Web history: none") } return lines.joined(separator: "\n") } static func mapError(_ error: Error) -> ExitCode { switch error { case TTYCommandRunner.Error.binaryNotFound, CodexStatusProbeError.codexNotInstalled, ClaudeUsageError.claudeNotInstalled, GeminiStatusProbeError.geminiNotInstalled: ExitCode(2) case CodexStatusProbeError.timedOut, TTYCommandRunner.Error.timedOut, GeminiStatusProbeError.timedOut, CostUsageError.timedOut: ExitCode(4) case ClaudeUsageError.parseFailed, ClaudeUsageError.oauthFailed, CostUsageError.unsupportedProvider, UsageError.decodeFailed, UsageError.noRateLimitsFound, GeminiStatusProbeError.parseFailed: ExitCode(3) default: .failure } } static func printError(_ error: Error) { self.writeStderr("Error: \(error.localizedDescription)\n") } private static func printAntigravityPlanInfo(_ info: AntigravityPlanInfoSummary) { let fields: [(String, String?)] = [ ("planName", info.planName), ("planDisplayName", info.planDisplayName), ("displayName", info.displayName), ("productName", info.productName), ("planShortName", info.planShortName), ] self.writeStderr("Antigravity plan info:\n") for (label, value) in fields { guard let value, !value.isEmpty else { continue } self.writeStderr(" \(label): \(value)\n") } } static func exit(code: ExitCode, message: String? = nil) -> Never { if let message { self.writeStderr("\(message)\n")Lines 1–500 of 865. Load more
import CodexBarCore import Commander #if canImport(AppKit) import AppKit #endif #if canImport(Darwin) import Darwin #else import Glibc #endif import Foundation #if canImport(FoundationNetworking) import FoundationNetworking #endif @main enum CodexBarCLI { static func main() async { let rawArgv = Array(CommandLine.arguments.dropFirst()) let argv = Self.effectiveArgv(rawArgv) // Fast path: global help/version before building descriptors. if let helpIndex = argv.firstIndex(where: { $0 == "-h" || $0 == "--help" }) { let command = helpIndex == 0 ? argv.dropFirst().first : argv.first Self.printHelp(for: command) } if argv.contains("-V") || argv.contains("--version") { Self.printVersion() } let usageSignature = CommandSignature .describe(UsageOptions()) let costSignature = CommandSignature .describe(CostOptions()) let descriptors: [CommandDescriptor] = [ CommandDescriptor( name: "usage", abstract: "Print usage as text or JSON", discussion: nil, signature: usageSignature), CommandDescriptor( name: "cost", abstract: "Print local cost usage as text or JSON", discussion: nil, signature: costSignature), ] let program = Program(descriptors: descriptors) do { let invocation = try program.resolve(argv: argv) Self.bootstrapLogging(values: invocation.parsedValues) switch invocation.descriptor.name { case "usage": await self.runUsage(invocation.parsedValues) case "cost": await self.runCost(invocation.parsedValues) default: Self.exit(code: .failure, message: "Unknown command") } } catch let error as CommanderProgramError { Self.exit(code: .failure, message: error.description) } catch { Self.exit(code: .failure, message: error.localizedDescription) } } // MARK: - Commands private static func runUsage(_ values: ParsedValues) async { let provider = Self.decodeProvider(from: values) let format = Self.decodeFormat(from: values) let includeCredits = format == .json ? true : !values.flags.contains("noCredits") let includeStatus = values.flags.contains("status") let pretty = values.flags.contains("pretty") let sourceModeRaw = values.options["source"]?.last let parsedSourceMode = Self.decodeSourceMode(from: values) if sourceModeRaw != nil, parsedSourceMode == nil { Self.exit(code: .failure, message: "Error: --source must be auto|web|cli|oauth.") } let sourceMode = parsedSourceMode ?? .auto let antigravityPlanDebug = values.flags.contains("antigravityPlanDebug") let augmentDebug = values.flags.contains("augmentDebug") let webDebugDumpHTML = values.flags.contains("webDebugDumpHtml") let webTimeout = Self.decodeWebTimeout(from: values) ?? 60 let verbose = values.flags.contains("verbose") let noColor = values.flags.contains("noColor") let useColor = Self.shouldUseColor(noColor: noColor, format: format) let resetStyle = Self.resetTimeDisplayStyleFromDefaults() let fetcher = UsageFetcher() let browserDetection = BrowserDetection(cacheTTL: 0) let claudeFetcher = ClaudeUsageFetcher(browserDetection: browserDetection) #if !os(macOS) if sourceMode.usesWeb { Self.exit(code: .failure, message: "Error: --source web/auto is only supported on macOS.") } #endif var sections: [String] = [] var payload: [ProviderPayload] = [] var exitCode: ExitCode = .success let fetchContext = ProviderFetchContext( runtime: .cli, sourceMode: sourceMode, includeCredits: includeCredits, webTimeout: webTimeout, webDebugDumpHTML: webDebugDumpHTML, verbose: verbose, env: ProcessInfo.processInfo.environment, settings: nil, fetcher: fetcher, claudeFetcher: claudeFetcher, browserDetection: browserDetection) for p in provider.asList { let status = includeStatus ? await Self.fetchStatus(for: p) : nil var antigravityPlanInfo: AntigravityPlanInfoSummary? let outcome = await Self.fetchProviderUsage( provider: p, context: fetchContext) if verbose { Self.printFetchAttempts(provider: p, attempts: outcome.attempts) } switch outcome.result { case let .success(result): var dashboard = result.dashboard if antigravityPlanDebug, p == .antigravity { antigravityPlanInfo = try? await AntigravityStatusProbe().fetchPlanInfoSummary() if format == .text, let info = antigravityPlanInfo { Self.printAntigravityPlanInfo(info) } } if augmentDebug, p == .augment { #if os(macOS) let dump = await AugmentStatusProbe.latestDumps() if format == .text, !dump.isEmpty { Self.writeStderr("Augment API responses:\n\(dump)\n") } #endif } if dashboard == nil, format == .json, p == .codex { dashboard = Self.loadOpenAIDashboardIfAvailable(usage: result.usage, fetcher: fetcher) } let descriptor = ProviderDescriptorRegistry.descriptor(for: p) let shouldDetectVersion = descriptor.cli.versionDetector != nil && result.strategyKind != .webDashboard let version = Self.normalizeVersion( raw: shouldDetectVersion ? Self.detectVersion(for: p, browserDetection: browserDetection) : nil) let source = result.sourceLabel let header = Self.makeHeader(provider: p, version: version, source: source) switch format { case .text: var text = CLIRenderer.renderText( provider: p, snapshot: result.usage, credits: result.credits, context: RenderContext( header: header, status: status, useColor: useColor, resetStyle: resetStyle)) if let dashboard, p == .codex, sourceMode.usesWeb { text += "\n" + Self.renderOpenAIWebDashboardText(dashboard) } sections.append(text) case .json: payload.append(ProviderPayload( provider: p, version: version, source: source, status: status, usage: result.usage, credits: result.credits, antigravityPlanInfo: antigravityPlanInfo, openaiDashboard: dashboard)) } case let .failure(error): exitCode = Self.mapError(error) Self.printError(error) } } switch format { case .text: if !sections.isEmpty { print(sections.joined(separator: "\n\n")) } case .json: if !payload.isEmpty { let encoder = JSONEncoder() encoder.dateEncodingStrategy = .iso8601 encoder.outputFormatting = pretty ? [.prettyPrinted, .sortedKeys] : [] if let data = try? encoder.encode(payload), let output = String(data: data, encoding: .utf8) { print(output) } } } Self.exit(code: exitCode) } // MARK: - Helpers private static func bootstrapLogging(values: ParsedValues) { let isJSON = values.flags.contains("jsonOutput") let verbose = values.flags.contains("verbose") let rawLevel = values.options["logLevel"]?.last let level = Self.resolvedLogLevel(verbose: verbose, rawLevel: rawLevel) CodexBarLog.bootstrapIfNeeded(.init(destination: .stderr, level: level, json: isJSON)) } static func resolvedLogLevel(verbose: Bool, rawLevel: String?) -> CodexBarLog.Level { CodexBarLog.parseLevel(rawLevel) ?? (verbose ? .debug : .error) } static func effectiveArgv(_ argv: [String]) -> [String] { guard let first = argv.first else { return ["usage"] } if first.hasPrefix("-") { return ["usage"] + argv } return argv } static func decodeProvider(from values: ParsedValues) -> ProviderSelection { let rawOverride = values.options["provider"]?.last return Self.providerSelection(rawOverride: rawOverride, enabled: Self.enabledProvidersFromDefaults()) } static func providerSelection(rawOverride: String?, enabled: [UsageProvider]) -> ProviderSelection { if let rawOverride, let parsed = ProviderSelection(argument: rawOverride) { return parsed } if enabled.count >= 3 { return .all } if enabled.count == 2 { let enabledSet = Set(enabled) let primary = Set(ProviderDescriptorRegistry.all.filter(\.metadata.isPrimaryProvider).map(\.id)) if !primary.isEmpty, enabledSet == primary { return .both } return .custom(enabled) } if let first = enabled.first { return ProviderSelection(provider: first) } return .single(.codex) } static func decodeFormat(from values: ParsedValues) -> OutputFormat { if let raw = values.options["format"]?.last, let parsed = OutputFormat(argument: raw) { return parsed } if values.flags.contains("jsonShortcut") || values.flags.contains("json") { return .json } return .text } static func shouldUseColor(noColor: Bool, format: OutputFormat) -> Bool { guard format == .text else { return false } if noColor { return false } let env = ProcessInfo.processInfo.environment if env["TERM"]?.lowercased() == "dumb" { return false } return isatty(STDOUT_FILENO) == 1 } private static func detectVersion(for provider: UsageProvider, browserDetection: BrowserDetection) -> String? { ProviderDescriptorRegistry.descriptor(for: provider).cli.versionDetector?(browserDetection) } private static func normalizeVersion(raw: String?) -> String? { guard let raw, !raw.isEmpty else { return nil } if let match = raw.range(of: #"(\d+(?:\.\d+)+)"#, options: .regularExpression) { return String(raw[match]).trimmingCharacters(in: .whitespacesAndNewlines) } return raw.trimmingCharacters(in: .whitespacesAndNewlines) } private static func makeHeader(provider: UsageProvider, version: String?, source: String) -> String { let name = ProviderDescriptorRegistry.descriptor(for: provider).metadata.displayName if let version, !version.isEmpty { return "\(name) \(version) (\(source))" } return "\(name) (\(source))" } private static func printFetchAttempts(provider: UsageProvider, attempts: [ProviderFetchAttempt]) { guard !attempts.isEmpty else { return } self.writeStderr("[\(provider.rawValue)] fetch strategies:\n") for attempt in attempts { let kindLabel = Self.fetchKindLabel(attempt.kind) var line = " - \(attempt.strategyID) (\(kindLabel))" line += attempt.wasAvailable ? " available" : " unavailable" if let error = attempt.errorDescription, !error.isEmpty { line += " error=\(error)" } self.writeStderr("\(line)\n") } } private static func fetchKindLabel(_ kind: ProviderFetchKind) -> String { switch kind { case .cli: "cli" case .web: "web" case .oauth: "oauth" case .apiToken: "api" case .localProbe: "local" case .webDashboard: "web" } } private static func fetchStatus(for provider: UsageProvider) async -> ProviderStatusPayload? { let urlString = ProviderDescriptorRegistry.descriptor(for: provider).metadata.statusPageURL guard let urlString, let baseURL = URL(string: urlString) else { return nil } do { return try await StatusFetcher.fetch(from: baseURL) } catch { return ProviderStatusPayload( indicator: .unknown, description: error.localizedDescription, updatedAt: nil, url: urlString) } } private static func enabledProvidersFromDefaults() -> [UsageProvider] { // Prefer the app's defaults domain so CLI mirrors in-app toggles. let domains = [ "com.steipete.codexbar", "com.steipete.codexbar.debug", ] var toggles: [String: Bool] = [:] for domain in domains { if let dict = UserDefaults(suiteName: domain)?.dictionary(forKey: "providerToggles") as? [String: Bool], !dict.isEmpty { toggles = dict break } } if toggles.isEmpty { toggles = UserDefaults.standard.dictionary(forKey: "providerToggles") as? [String: Bool] ?? [:] } return ProviderDescriptorRegistry.all.compactMap { descriptor in let meta = descriptor.metadata let isOn = toggles[meta.cliName] ?? meta.defaultEnabled return isOn ? descriptor.id : nil } } private static func resetTimeDisplayStyleFromDefaults() -> ResetTimeDisplayStyle { let domains = [ "com.steipete.codexbar", "com.steipete.codexbar.debug", ] for domain in domains { if let value = UserDefaults(suiteName: domain)?.object(forKey: "resetTimesShowAbsolute") as? Bool { return value ? .absolute : .countdown } } let fallback = UserDefaults.standard.object(forKey: "resetTimesShowAbsolute") as? Bool ?? false return fallback ? .absolute : .countdown } private static func fetchProviderUsage( provider: UsageProvider, context: ProviderFetchContext) async -> ProviderFetchOutcome { let descriptor = ProviderDescriptorRegistry.descriptor(for: provider) if !descriptor.fetchPlan.sourceModes.contains(context.sourceMode) { let error = SourceSelectionError.unsupported( provider: descriptor.cli.name, source: context.sourceMode) return ProviderFetchOutcome(result: .failure(error), attempts: []) } return await descriptor.fetchOutcome(context: context) } private enum SourceSelectionError: LocalizedError { case unsupported(provider: String, source: ProviderSourceMode) var errorDescription: String? { switch self { case let .unsupported(provider, source): "Source '\(source.rawValue)' is not supported for \(provider)." } } } private static func loadOpenAIDashboardIfAvailable( usage: UsageSnapshot, fetcher: UsageFetcher) -> OpenAIDashboardSnapshot? { guard let cache = OpenAIDashboardCacheStore.load() else { return nil } let codexEmail = (usage.accountEmail(for: .codex) ?? fetcher.loadAccountInfo().email)? .trimmingCharacters(in: .whitespacesAndNewlines) guard let codexEmail, !codexEmail.isEmpty else { return nil } if cache.accountEmail.lowercased() != codexEmail.lowercased() { return nil } if cache.snapshot.dailyBreakdown.isEmpty, !cache.snapshot.creditEvents.isEmpty { return OpenAIDashboardSnapshot( signedInEmail: cache.snapshot.signedInEmail, codeReviewRemainingPercent: cache.snapshot.codeReviewRemainingPercent, creditEvents: cache.snapshot.creditEvents, dailyBreakdown: OpenAIDashboardSnapshot.makeDailyBreakdown( from: cache.snapshot.creditEvents, maxDays: 30), usageBreakdown: cache.snapshot.usageBreakdown, creditsPurchaseURL: cache.snapshot.creditsPurchaseURL, updatedAt: cache.snapshot.updatedAt) } return cache.snapshot } private static func decodeWebTimeout(from values: ParsedValues) -> TimeInterval? { if let raw = values.options["webTimeout"]?.last, let seconds = Double(raw) { return seconds } return nil } private static func decodeSourceMode(from values: ParsedValues) -> ProviderSourceMode? { if values.flags.contains("web") { return .web } guard let raw = values.options["source"]?.last?.lowercased() else { return nil } return ProviderSourceMode(rawValue: raw) } private static func renderOpenAIWebDashboardText(_ dash: OpenAIDashboardSnapshot) -> String { var lines: [String] = [] if let email = dash.signedInEmail, !email.isEmpty { lines.append("Web session: \(email)") } if let remaining = dash.codeReviewRemainingPercent { let percent = Int(remaining.rounded()) lines.append("Code review: \(percent)% remaining") } if let first = dash.creditEvents.first { let day = first.date.formatted(date: .abbreviated, time: .omitted) lines.append("Web history: \(dash.creditEvents.count) events (latest \(day))") } else { lines.append("Web history: none") } return lines.joined(separator: "\n") } static func mapError(_ error: Error) -> ExitCode { switch error { case TTYCommandRunner.Error.binaryNotFound, CodexStatusProbeError.codexNotInstalled, ClaudeUsageError.claudeNotInstalled, GeminiStatusProbeError.geminiNotInstalled: ExitCode(2) case CodexStatusProbeError.timedOut, TTYCommandRunner.Error.timedOut, GeminiStatusProbeError.timedOut, CostUsageError.timedOut: ExitCode(4) case ClaudeUsageError.parseFailed, ClaudeUsageError.oauthFailed, CostUsageError.unsupportedProvider, UsageError.decodeFailed, UsageError.noRateLimitsFound, GeminiStatusProbeError.parseFailed: ExitCode(3) default: .failure } } static func printError(_ error: Error) { self.writeStderr("Error: \(error.localizedDescription)\n") } private static func printAntigravityPlanInfo(_ info: AntigravityPlanInfoSummary) { let fields: [(String, String?)] = [ ("planName", info.planName), ("planDisplayName", info.planDisplayName), ("displayName", info.displayName), ("productName", info.productName), ("planShortName", info.planShortName), ] self.writeStderr("Antigravity plan info:\n") for (label, value) in fields { guard let value, !value.isEmpty else { continue } self.writeStderr(" \(label): \(value)\n") } } static func exit(code: ExitCode, message: String? = nil) -> Never { if let message { self.writeStderr("\(message)\n")