import Foundation enum UsageMetric: String, Codable, CaseIterable, Identifiable, Sendable { // Cursor case cursorTotalPercentUsed case cursorApiPercentUsed case cursorAutoPercentUsed case cursorPlanUsed case cursorPlanLimit case cursorPlanRemaining case cursorOnDemandUsed case cursorBillingCycleStart case cursorBillingCycleEnd case cursorMembershipType // Claude OAuth case claudeFiveHourUtilization case claudeFiveHourResetsAt case claudeSevenDayUtilization case claudeSevenDayResetsAt case claudeExtraUsage case claudeSevenDayOpusUtilization case claudeSevenDaySonnetUtilization // Claude Admin API case claudeAdminInputTokens case claudeAdminOutputTokens case claudeAdminCostUSD // Cursor Admin API case cursorAdminSpendCents case cursorAdminMemberCount var id: String { rawValue } var providerID: ProviderID { switch self { case .cursorTotalPercentUsed, .cursorApiPercentUsed, .cursorAutoPercentUsed, .cursorPlanUsed, .cursorPlanLimit, .cursorPlanRemaining, .cursorOnDemandUsed, .cursorBillingCycleStart, .cursorBillingCycleEnd, .cursorMembershipType, .cursorAdminSpendCents, .cursorAdminMemberCount: .cursor case .claudeFiveHourUtilization, .claudeFiveHourResetsAt, .claudeSevenDayUtilization, .claudeSevenDayResetsAt, .claudeExtraUsage, .claudeSevenDayOpusUtilization, .claudeSevenDaySonnetUtilization, .claudeAdminInputTokens, .claudeAdminOutputTokens, .claudeAdminCostUSD: .claude } } var displayName: String { switch self { case .cursorTotalPercentUsed: "Total usage %" case .cursorApiPercentUsed: "API usage %" case .cursorAutoPercentUsed: "Auto usage %" case .cursorPlanUsed: "Plan used" case .cursorPlanLimit: "Plan limit" case .cursorPlanRemaining: "Plan remaining" case .cursorOnDemandUsed: "On-demand spend" case .cursorBillingCycleStart: "Billing cycle start" case .cursorBillingCycleEnd: "Billing cycle end" case .cursorMembershipType: "Membership" case .claudeFiveHourUtilization: "5-hour session %" case .claudeFiveHourResetsAt: "5-hour reset" case .claudeSevenDayUtilization: "Weekly usage %" case .claudeSevenDayResetsAt: "Weekly reset" case .claudeExtraUsage: "Extra usage" case .claudeSevenDayOpusUtilization: "Weekly Opus %" case .claudeSevenDaySonnetUtilization: "Weekly Sonnet %" case .claudeAdminInputTokens: "Input tokens (7d)" case .claudeAdminOutputTokens: "Output tokens (7d)" case .claudeAdminCostUSD: "Cost USD (7d)" case .cursorAdminSpendCents: "Team spend (cycle)" case .cursorAdminMemberCount: "Team members" } } static func defaults(for provider: ProviderID, location: MetricLocation) -> [UsageMetric] { switch (provider, location) { case (.cursor, .menuBar): return [.cursorTotalPercentUsed] case (.cursor, .popover): return [ .cursorTotalPercentUsed, .cursorApiPercentUsed, .cursorAutoPercentUsed, .cursorPlanUsed, .cursorPlanLimit, .cursorOnDemandUsed, .cursorBillingCycleEnd, ] case (.claude, .menuBar): return [.claudeFiveHourUtilization] case (.claude, .popover): return [ .claudeFiveHourUtilization, .claudeFiveHourResetsAt, .claudeSevenDayUtilization, .claudeSevenDayResetsAt, ] } } static func metrics(for provider: ProviderID, authMode: AuthMode) -> [UsageMetric] { switch (provider, authMode) { case (.cursor, .adminAPI): return [.cursorAdminSpendCents, .cursorAdminMemberCount] case (.cursor, _): return allCases.filter { $0.providerID == .cursor && !$0.rawValue.hasPrefix("cursorAdmin") } case (.claude, .adminAPI): return [.claudeAdminInputTokens, .claudeAdminOutputTokens, .claudeAdminCostUSD] case (.claude, _): return allCases.filter { $0.providerID == .claude && !$0.rawValue.hasPrefix("claudeAdmin") } } } } enum MetricLocation: String, Codable, Sendable { case menuBar case popover }