1 line
13 KiB
JSON
1 line
13 KiB
JSON
{"repo": "afk-surf/openbridge", "files": {"macos/OpenBridge/Agent/BridgeAIProviderSettings.swift": {"a9ca905547309a7db9d6e9f246c554c4cc416a3c": {"t": 1785674617.108795, "n": 12682, "h": "70aba4a4cc43ba5c", "c": "import Foundation\nimport KWWKAI\n\nnonisolated enum BridgeAIProvider: String, CaseIterable, Codable, Identifiable, Sendable {\n case openAI = \"openai\"\n case openAIChatCompletions = \"openai-chat-completions\"\n case anthropic\n case googleGemini = \"google-gemini\"\n case amazonBedrock = \"amazon-bedrock\"\n case azureOpenAIResponses = \"azure-openai-responses\"\n case cerebras\n case cloudflareAIGateway = \"cloudflare-ai-gateway\"\n case cloudflareWorkersAI = \"cloudflare-workers-ai\"\n case deepSeek = \"deepseek\"\n case fireworks\n case githubCopilot = \"github-copilot\"\n case groq\n case huggingFace = \"huggingface\"\n case kimiCoding = \"kimi-coding\"\n case minimax\n case minimaxCN = \"minimax-cn\"\n case mistral\n case moonshotAI = \"moonshotai\"\n case moonshotAICN = \"moonshotai-cn\"\n case opencode\n case opencodeGo = \"opencode-go\"\n case openRouter = \"openrouter\"\n case vercelAIGateway = \"vercel-ai-gateway\"\n case xAI = \"xai\"\n case xiaomi\n case zAI = \"zai\"\n case openAICompatible = \"openai-compatible\"\n\n var id: String {\n rawValue\n }\n\n static var displayOrder: [BridgeAIProvider] {\n [\n .openAI,\n .anthropic,\n .googleGemini,\n .amazonBedrock,\n .azureOpenAIResponses,\n .cerebras,\n .cloudflareAIGateway,\n .cloudflareWorkersAI,\n .deepSeek,\n .fireworks,\n .githubCopilot,\n .groq,\n .huggingFace,\n .kimiCoding,\n .minimax,\n .minimaxCN,\n .mistral,\n .moonshotAI,\n .moonshotAICN,\n .opencode,\n .opencodeGo,\n .openRouter,\n .vercelAIGateway,\n .xAI,\n .xiaomi,\n .zAI,\n .openAIChatCompletions,\n ]\n }\n\n var displayName: String {\n switch self {\n case .openAI: \"OpenAI\"\n case .openAIChatCompletions: \"OpenAI Chat Completions\"\n case .anthropic: \"Anthropic\"\n case .googleGemini: \"Google Gemini\"\n case .amazonBedrock: \"Amazon Bedrock\"\n case .azureOpenAIResponses: \"Azure OpenAI Responses\"\n case .cerebras: \"Cerebras\"\n case .cloudflareAIGateway: \"Cloudflare AI Gateway\"\n case .cloudflareWorkersAI: \"Cloudflare Workers AI\"\n case .deepSeek: \"DeepSeek\"\n case .fireworks: \"Fireworks\"\n case .githubCopilot: \"GitHub Copilot\"\n case .groq: \"Groq\"\n case .huggingFace: \"Hugging Face\"\n case .kimiCoding: \"Kimi Coding\"\n case .minimax: \"MiniMax\"\n case .minimaxCN: \"MiniMax CN\"\n case .mistral: \"Mistral AI\"\n case .moonshotAI: \"Moonshot AI\"\n case .moonshotAICN: \"Moonshot AI CN\"\n case .opencode: \"OpenCode\"\n case .opencodeGo: \"OpenCode Go\"\n case .openRouter: \"OpenRouter\"\n case .vercelAIGateway: \"Vercel AI Gateway\"\n case .xAI: \"xAI\"\n case .xiaomi: \"Xiaomi\"\n case .zAI: \"Z.ai\"\n case .openAICompatible: \"OpenAI-compatible\"\n }\n }\n\n var iconName: String {\n switch self {\n case .openAI, .openAIChatCompletions: \"sparkles\"\n case .anthropic: \"brain.head.profile\"\n case .googleGemini: \"diamond\"\n case .amazonBedrock: \"cube.transparent\"\n case .azureOpenAIResponses: \"cloud\"\n case .cerebras: \"cpu\"\n case .cloudflareAIGateway, .cloudflareWorkersAI: \"cloud\"\n case .deepSeek: \"waveform.path.ecg\"\n case .fireworks: \"sparkles\"\n case .githubCopilot: \"person.crop.circle.badge.checkmark\"\n case .groq: \"bolt\"\n case .huggingFace: \"face.smiling\"\n case .kimiCoding, .moonshotAI, .moonshotAICN: \"moon\"\n case .minimax, .minimaxCN: \"slider.horizontal.3\"\n case .mistral: \"wind\"\n case .opencode, .opencodeGo: \"curlybraces\"\n case .openRouter: \"arrow.triangle.branch\"\n case .vercelAIGateway: \"triangle\"\n case .xAI: \"xmark\"\n case .xiaomi: \"square\"\n case .zAI: \"sparkle.magnifyingglass\"\n case .openAICompatible: \"server.rack\"\n }\n }\n\n var logoImageName: String {\n switch self {\n case .openAI, .openAIChatCompletions: \"openai\"\n case .anthropic: \"claude\"\n case .googleGemini: \"google\"\n case .amazonBedrock: \"amazonaws\"\n case .azureOpenAIResponses: \"microsoftazure\"\n case .cerebras: \"cerebras\"\n case .cloudflareAIGateway, .cloudflareWorkersAI: \"cloudflare\"\n case .deepSeek: \"deepseek\"\n case .fireworks: \"fireworks\"\n case .githubCopilot: \"copilot\"\n case .groq: \"groq\"\n case .huggingFace: \"huggingface\"\n case .kimiCoding: \"kimi\"\n case .minimax, .minimaxCN: \"minimax\"\n case .mistral: \"mistral\"\n case .moonshotAI, .moonshotAICN: \"moonshot\"\n case .opencode, .opencodeGo: \"opencode\"\n case .openRouter: \"openrouter\"\n case .vercelAIGateway: \"vercel\"\n case .xAI: \"xai\"\n case .xiaomi: \"xiaomi\"\n case .zAI: \"zai\"\n case .openAICompatible: \"openai\"\n }\n }\n\n var usesTemplateLogoRendering: Bool {\n switch self {\n case .openAI, .openAIChatCompletions, .openAICompatible:\n true\n case .anthropic, .googleGemini, .amazonBedrock, .azureOpenAIResponses, .cerebras, .cloudflareAIGateway,\n .cloudflareWorkersAI, .deepSeek, .fireworks, .githubCopilot, .groq, .huggingFace, .kimiCoding, .minimax,\n .minimaxCN, .mistral, .moonshotAI, .moonshotAICN, .opencode, .opencodeGo, .openRouter, .vercelAIGateway,\n .xAI, .xiaomi, .zAI:\n false\n }\n }\n\n var defaultBaseURL: String {\n switch self {\n case .openAI, .openAIChatCompletions: \"https://api.openai.com\"\n case .anthropic: \"https://api.anthropic.com\"\n case .googleGemini: \"https://generativelanguage.googleapis.com\"\n case .amazonBedrock: \"us-east-1\"\n case .azureOpenAIResponses: \"https://YOUR-RESOURCE.openai.azure.com\"\n case .cerebras: \"https://api.cerebras.ai/v1\"\n case .cloudflareAIGateway: \"https://gateway.ai.cloudflare.com/v1/{CLOUDFLARE_ACCOUNT_ID}/{CLOUDFLARE_GATEWAY_ID}\"\n case .cloudflareWorkersAI: \"https://api.cloudflare.com/client/v4/accounts/{CLOUDFLARE_ACCOUNT_ID}/ai/v1\"\n case .deepSeek: \"https://api.deepseek.com\"\n case .fireworks: \"https://api.fireworks.ai/inference\"\n case .githubCopilot: \"https://api.individual.githubcopilot.com\"\n case .groq: \"https://api.groq.com/openai/v1\"\n case .huggingFace: \"https://router.huggingface.co/v1\"\n case .kimiCoding: \"https://api.kimi.com/coding\"\n case .minimax: \"https://api.minimax.io/anthropic\"\n case .minimaxCN: \"https://api.minimaxi.com/anthropic\"\n case .mistral: \"https://api.mistral.ai\"\n case .moonshotAI: \"https://api.moonshot.ai/v1\"\n case .moonshotAICN: \"https://api.moonshot.cn/v1\"\n case .opencode: \"https://opencode.ai/zen\"\n case .opencodeGo: \"https://opencode.ai/zen/go/v1\"\n case .openRouter: \"https://openrouter.ai/api/v1\"\n case .vercelAIGateway: \"https://ai-gateway.vercel.sh\"\n case .xAI: \"https://api.x.ai/v1\"\n case .xiaomi: \"https://token-plan-ams.xiaomimimo.com/anthropic\"\n case .zAI: \"https://api.z.ai/api/coding/paas/v4\"\n case .openAICompatible: \"\"\n }\n }\n\n var apiKeyPlaceholder: String {\n switch self {\n case .openAI, .openAIChatCompletions: \"sk-...\"\n case .anthropic: \"sk-ant-...\"\n case .googleGemini: \"AIza...\"\n case .amazonBedrock: \"AWS_ACCESS_KEY_ID:AWS_SECRET_ACCESS_KEY[:AWS_SESSION_TOKEN]\"\n case .azureOpenAIResponses: \"Azure OpenAI API key\"\n case .githubCopilot: \"Use OAuth\"\n case .openRouter: \"sk-or-...\"\n default: \"API key\"\n }\n }\n\n var supportedAuthMethods: [BridgeAIProviderAuthMethod] {\n switch self {\n case .openAI, .anthropic, .githubCopilot:\n [.oauth, .apiKey]\n case .openAIChatCompletions, .googleGemini, .amazonBedrock, .azureOpenAIResponses, .cerebras,\n .cloudflareAIGateway, .cloudflareWorkersAI, .deepSeek, .fireworks, .groq, .huggingFace, .kimiCoding,\n .minimax, .minimaxCN, .mistral, .moonshotAI, .moonshotAICN, .opencode, .opencodeGo, .openRouter,\n .vercelAIGateway, .xAI, .xiaomi, .zAI, .openAICompatible:\n [.apiKey]\n }\n }\n\n var defaultAuthMethod: BridgeAIProviderAuthMethod {\n supportedAuthMethods.first ?? .apiKey\n }\n\n var modelProviderIDs: Set<String> {\n switch self {\n case .openAI:\n [\"chatgpt-codex\", \"openai\", \"openai-codex\"]\n case .openAIChatCompletions:\n [rawValue]\n case .anthropic:\n [\"anthropic\"]\n case .googleGemini:\n [\"google\", \"google-gemini\", \"google-gemini-cli\", \"google-antigravity\", \"google-vertex\"]\n case .openAICompatible:\n []\n default:\n [rawValue]\n }\n }\n\n static func provider(for model: Model) -> BridgeAIProvider? {\n if model.api == \"openai-completions\",\n model.provider == \"openai\" || model.provider == openAIChatCompletions.rawValue\n {\n return .openAIChatCompletions\n }\n return allCases.first { $0.modelProviderIDs.contains(model.provider) }\n }\n}\n\nnonisolated enum BridgeAIProviderAuthMethod: String, CaseIterable, Codable, Identifiable, Sendable {\n case apiKey\n case oauth\n\n var id: String {\n rawValue\n }\n\n var displayName: String {\n switch self {\n case .apiKey: \"API Key\"\n case .oauth: \"OAuth\"\n }\n }\n}\n\nnonisolated struct BridgeAIProviderConfig: Codable, Equatable, Sendable {\n var isEnabled: Bool\n var authMethod: BridgeAIProviderAuthMethod\n var baseURL: String\n var oauthExpiresAt: Date?\n var oauthAccountID: String?\n var modelIDs: [String]?\n\n init(\n isEnabled: Bool = false,\n authMethod: BridgeAIProviderAuthMethod = .oauth,\n baseURL: String = \"\",\n oauthExpiresAt: Date? = nil,\n oauthAccountID: String? = nil,\n modelIDs: [String]? = nil\n ) {\n self.isEnabled = isEnabled\n self.authMethod = authMethod\n self.baseURL = baseURL\n self.oauthExpiresAt = oauthExpiresAt\n self.oauthAccountID = oauthAccountID\n self.modelIDs = modelIDs\n }\n\n func resolvedBaseURL(for provider: BridgeAIProvider) -> String? {\n let trimmed = baseURL.trimmingCharacters(in: .whitespacesAndNewlines)\n guard !trimmed.isEmpty, trimmed != provider.defaultBaseURL else { return nil }\n return trimmed\n }\n}\n\nnonisolated struct BridgeAIProviderSettings: Codable, Equatable, Sendable {\n private enum CodingKeys: String, CodingKey {\n case providers\n case selectedModelProvider\n case selectedModelID\n }\n\n var providers: [BridgeAIProvider: BridgeAIProviderConfig]\n var selectedModelProvider: String\n var selectedModelID: String\n\n init(\n providers: [BridgeAIProvider: BridgeAIProviderConfig] = [:],\n selectedModelProvider: String = \"openai\",\n selectedModelID: String = \"gpt-5\"\n ) {\n var configs = providers\n for provider in BridgeAIProvider.allCases {\n if configs[provider] == nil {\n configs[provider] = BridgeAIProviderConfig(\n authMethod: provider.defaultAuthMethod,\n baseURL: provider.defaultBaseURL\n )\n }\n }\n self.providers = configs\n self.selectedModelProvider = selectedModelProvider\n self.selectedModelID = selectedModelID\n }\n\n init(from decoder: Decoder) throws {\n let container = try decoder.container(keyedBy: CodingKeys.self)\n try self.init(\n providers: container.decodeIfPresent(\n [BridgeAIProvider: BridgeAIProviderConfig].self,\n forKey: .providers\n ) ?? [:],\n selectedModelProvider: container.decodeIfPresent(String.self, forKey: .selectedModelProvider)\n ?? \"openai\",\n selectedModelID: container.decodeIfPresent(String.self, forKey: .selectedModelID)\n ?? \"gpt-5\"\n )\n }\n\n subscript(provider: BridgeAIProvider) -> BridgeAIProviderConfig {\n get {\n providers[provider] ?? BridgeAIProviderConfig(\n authMethod: provider.defaultAuthMethod,\n baseURL: provider.defaultBaseURL\n )\n }\n set { providers[provider] = newValue }\n }\n}\n"}}}} |