296 lines
8.1 KiB
Swift
296 lines
8.1 KiB
Swift
import Foundation
|
|
import SweetCookieKit
|
|
|
|
// swiftformat:disable sortDeclarations
|
|
public enum UsageProvider: String, CaseIterable, Sendable, Codable {
|
|
case codex
|
|
case openai
|
|
case azureopenai
|
|
case claude
|
|
case cursor
|
|
case opencode
|
|
case opencodego
|
|
case alibaba
|
|
case alibabatokenplan
|
|
case factory
|
|
case gemini
|
|
case antigravity
|
|
case copilot
|
|
case devin
|
|
case zai
|
|
case minimax
|
|
case manus
|
|
case kimi
|
|
case kilo
|
|
case kiro
|
|
case vertexai
|
|
case augment
|
|
case jetbrains
|
|
case kimik2
|
|
case moonshot
|
|
case amp
|
|
case t3chat
|
|
case ollama
|
|
case synthetic
|
|
case warp
|
|
case openrouter
|
|
case elevenlabs
|
|
case windsurf
|
|
case zed
|
|
case perplexity
|
|
case mimo
|
|
case doubao
|
|
case sakana
|
|
case abacus
|
|
case mistral
|
|
case deepseek
|
|
case codebuff
|
|
case crof
|
|
case venice
|
|
case commandcode
|
|
case qoder
|
|
case stepfun
|
|
case bedrock
|
|
case grok
|
|
case groq
|
|
case llmproxy
|
|
case litellm
|
|
case deepgram
|
|
case poe
|
|
case chutes
|
|
case crossmodel
|
|
case clawrouter
|
|
case sub2api
|
|
case wayfinder
|
|
}
|
|
|
|
// swiftformat:enable sortDeclarations
|
|
|
|
public enum IconStyle: String, Sendable, CaseIterable {
|
|
case codex
|
|
case openai
|
|
case claude
|
|
case zai
|
|
case minimax
|
|
case manus
|
|
case gemini
|
|
case antigravity
|
|
case cursor
|
|
case opencode
|
|
case opencodego
|
|
case alibaba
|
|
case factory
|
|
case copilot
|
|
case devin
|
|
case kimi
|
|
case kimik2
|
|
case kilo
|
|
case kiro
|
|
case vertexai
|
|
case augment
|
|
case jetbrains
|
|
case moonshot
|
|
case amp
|
|
case t3chat
|
|
case ollama
|
|
case synthetic
|
|
case warp
|
|
case openrouter
|
|
case elevenlabs
|
|
case windsurf
|
|
case zed
|
|
case perplexity
|
|
case mimo
|
|
case doubao
|
|
case sakana
|
|
case abacus
|
|
case mistral
|
|
case deepseek
|
|
case codebuff
|
|
case crof
|
|
case venice
|
|
case commandcode
|
|
case qoder
|
|
case stepfun
|
|
case bedrock
|
|
case grok
|
|
case groq
|
|
case llmproxy
|
|
case litellm
|
|
case deepgram
|
|
case poe
|
|
case chutes
|
|
case crossmodel
|
|
case clawrouter
|
|
case sub2api
|
|
case wayfinder
|
|
case combined
|
|
}
|
|
|
|
public struct ProviderMetadata: Sendable {
|
|
public let id: UsageProvider
|
|
public let displayName: String
|
|
public let sessionLabel: String
|
|
public let weeklyLabel: String
|
|
public let opusLabel: String?
|
|
public let supportsOpus: Bool
|
|
public let supportsCredits: Bool
|
|
public let creditsHint: String
|
|
public let toggleTitle: String
|
|
public let cliName: String
|
|
public let defaultEnabled: Bool
|
|
public let isPrimaryProvider: Bool
|
|
public let usesAccountFallback: Bool
|
|
public let browserCookieOrder: BrowserCookieImportOrder?
|
|
public let dashboardURL: String?
|
|
public let subscriptionDashboardURL: String?
|
|
/// Provider-specific release notes or changelog URL for CLI/provider updates.
|
|
public let changelogURL: String?
|
|
/// Statuspage.io base URL for incident polling (append /api/v2/status.json).
|
|
public let statusPageURL: String?
|
|
/// Browser-only status link (no API polling); used when statusPageURL is nil.
|
|
public let statusLinkURL: String?
|
|
/// Google Workspace product ID for status polling (appsstatus dashboard).
|
|
public let statusWorkspaceProductID: String?
|
|
|
|
public init(
|
|
id: UsageProvider,
|
|
displayName: String,
|
|
sessionLabel: String,
|
|
weeklyLabel: String,
|
|
opusLabel: String?,
|
|
supportsOpus: Bool,
|
|
supportsCredits: Bool,
|
|
creditsHint: String,
|
|
toggleTitle: String,
|
|
cliName: String,
|
|
defaultEnabled: Bool,
|
|
isPrimaryProvider: Bool = false,
|
|
usesAccountFallback: Bool = false,
|
|
browserCookieOrder: BrowserCookieImportOrder? = nil,
|
|
dashboardURL: String?,
|
|
subscriptionDashboardURL: String? = nil,
|
|
changelogURL: String? = nil,
|
|
statusPageURL: String?,
|
|
statusLinkURL: String? = nil,
|
|
statusWorkspaceProductID: String? = nil)
|
|
{
|
|
self.id = id
|
|
self.displayName = displayName
|
|
self.sessionLabel = sessionLabel
|
|
self.weeklyLabel = weeklyLabel
|
|
self.opusLabel = opusLabel
|
|
self.supportsOpus = supportsOpus
|
|
self.supportsCredits = supportsCredits
|
|
self.creditsHint = creditsHint
|
|
self.toggleTitle = toggleTitle
|
|
self.cliName = cliName
|
|
self.defaultEnabled = defaultEnabled
|
|
self.isPrimaryProvider = isPrimaryProvider
|
|
self.usesAccountFallback = usesAccountFallback
|
|
self.browserCookieOrder = browserCookieOrder
|
|
self.dashboardURL = dashboardURL
|
|
self.subscriptionDashboardURL = subscriptionDashboardURL
|
|
self.changelogURL = changelogURL
|
|
self.statusPageURL = statusPageURL
|
|
self.statusLinkURL = statusLinkURL
|
|
self.statusWorkspaceProductID = statusWorkspaceProductID
|
|
}
|
|
}
|
|
|
|
public enum ProviderDefaults {
|
|
public static var metadata: [UsageProvider: ProviderMetadata] {
|
|
ProviderDescriptorRegistry.metadata
|
|
}
|
|
}
|
|
|
|
public enum ProviderBrowserCookieDefaults {
|
|
public static var defaultImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
Browser.defaultImportOrder
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// Safari first for Cursor: active sessions often live only there, and Chromium profiles may carry stale tokens.
|
|
public static var cursorCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.safari] + Browser.defaultImportOrder.filter { $0 != .safari }
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// Preserve the legacy Codex prompt behavior: prefer Safari/Chrome/Firefox before
|
|
/// probing additional Chromium variants that may trigger Safe Storage prompts.
|
|
public static var codexCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
let preferredPrefix: [Browser] = [.safari, .chrome, .firefox]
|
|
return preferredPrefix + Browser.defaultImportOrder.filter { !preferredPrefix.contains($0) }
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// OpenCode web Auto stays Chrome-only by default, with Dia as the one bounded provider exception
|
|
/// because Dia has a confirmed reporter need. Other browsers stay on Manual until users can choose them.
|
|
public static var opencodeCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.chrome, .dia]
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// Grok is normally signed in through Chrome; keep this narrow so CLI/live probes do not touch
|
|
/// unrelated browser keychains.
|
|
public static var grokCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.chrome]
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// MiMo Auto: Safari first (no Keychain prompt), keep the existing Chrome-family
|
|
/// entries from main, and add Firefox/Edge per #1304. Other Chromium forks stay on
|
|
/// Manual import to avoid scanning the full SweetCookieKit default order.
|
|
public static var mimoCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.safari, .chrome, .chromeBeta, .chromeCanary, .firefox, .edge]
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// Devin sessions are normally in Chrome. Keep automatic import narrow so live probes do not
|
|
/// touch unrelated browser keychains; users can select another browser explicitly.
|
|
public static var devinCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.chrome]
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// Copilot budget imports should stay Chrome-only by default to avoid prompting unrelated browsers.
|
|
public static var copilotCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.chrome]
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
|
|
/// Qoder sessions are documented through Chrome cookie import. Keep automatic import narrow
|
|
/// so enabling this provider does not probe unrelated browser keychains.
|
|
public static var qoderCookieImportOrder: BrowserCookieImportOrder? {
|
|
#if os(macOS)
|
|
[.chrome]
|
|
#else
|
|
nil
|
|
#endif
|
|
}
|
|
}
|