From d455a408d01e0ddedbee04878b410279ba9dcfd7 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sat, 14 Feb 2026 20:15:58 +0800 Subject: [PATCH 1/2] feat(opencode): support multiple browsers for cookie import MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Previously OpenCode only attempted to import cookies from Chrome, hardcoded as preferredBrowsers: [.chrome]. This caused issues for users who use other browsers like Edge, Safari, or Firefox. Now uses the default browser import order (Safari → Chrome → Edge → Brave → Arc → ...) when no preferred browsers are specified, allowing users to authenticate with OpenCode in any supported browser. Fixes: Users with Edge/Safari/Firefox cannot use OpenCode provider --- .../Providers/OpenCode/OpenCodeCookieImporter.swift | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift b/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift index d91261fdb..cc2fb1eec 100644 --- a/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift +++ b/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift @@ -26,13 +26,12 @@ public enum OpenCodeCookieImporter { public static func importSession( browserDetection: BrowserDetection, - preferredBrowsers: [Browser] = [.chrome], + preferredBrowsers: [Browser]? = nil, logger: ((String) -> Void)? = nil) throws -> SessionInfo { let log: (String) -> Void = { msg in logger?("[opencode-cookie] \(msg)") } - let installedBrowsers = preferredBrowsers.isEmpty - ? opencodeCookieImportOrder.cookieImportCandidates(using: browserDetection) - : preferredBrowsers.cookieImportCandidates(using: browserDetection) + let browsersToTry = preferredBrowsers ?? opencodeCookieImportOrder + let installedBrowsers = browsersToTry.cookieImportCandidates(using: browserDetection) for browserSource in installedBrowsers { do { @@ -66,7 +65,7 @@ public enum OpenCodeCookieImporter { public static func hasSession( browserDetection: BrowserDetection, - preferredBrowsers: [Browser] = [.chrome], + preferredBrowsers: [Browser]? = nil, logger: ((String) -> Void)? = nil) -> Bool { do { From 7ad2b700c8ce0e55ae4616c5aa8b45fc4d42a548 Mon Sep 17 00:00:00 2001 From: yuyi Date: Sat, 14 Feb 2026 20:58:42 +0800 Subject: [PATCH 2/2] fix(opencode): exclude failed browser on invalid credentials retry - Add excludeBrowsers parameter to importSession for multi-browser fallback - On invalidCredentials error, exclude the failed browser and retry with next valid browser - This ensures users with stale cookies in one browser can fall back to another browser --- .../OpenCode/OpenCodeCookieImporter.swift | 5 +++- .../OpenCode/OpenCodeProviderDescriptor.swift | 26 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift b/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift index cc2fb1eec..ef2dbae93 100644 --- a/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift +++ b/Sources/CodexBarCore/Providers/OpenCode/OpenCodeCookieImporter.swift @@ -27,10 +27,11 @@ public enum OpenCodeCookieImporter { public static func importSession( browserDetection: BrowserDetection, preferredBrowsers: [Browser]? = nil, + excludeBrowsers: [Browser] = [], logger: ((String) -> Void)? = nil) throws -> SessionInfo { let log: (String) -> Void = { msg in logger?("[opencode-cookie] \(msg)") } - let browsersToTry = preferredBrowsers ?? opencodeCookieImportOrder + let browsersToTry = (preferredBrowsers ?? opencodeCookieImportOrder).filter { !excludeBrowsers.contains($0) } let installedBrowsers = browsersToTry.cookieImportCandidates(using: browserDetection) for browserSource in installedBrowsers { @@ -66,12 +67,14 @@ public enum OpenCodeCookieImporter { public static func hasSession( browserDetection: BrowserDetection, preferredBrowsers: [Browser]? = nil, + excludeBrowsers: [Browser] = [], logger: ((String) -> Void)? = nil) -> Bool { do { _ = try self.importSession( browserDetection: browserDetection, preferredBrowsers: preferredBrowsers, + excludeBrowsers: excludeBrowsers, logger: logger) return true } catch { diff --git a/Sources/CodexBarCore/Providers/OpenCode/OpenCodeProviderDescriptor.swift b/Sources/CodexBarCore/Providers/OpenCode/OpenCodeProviderDescriptor.swift index 18803a46c..43a139ca8 100644 --- a/Sources/CodexBarCore/Providers/OpenCode/OpenCodeProviderDescriptor.swift +++ b/Sources/CodexBarCore/Providers/OpenCode/OpenCodeProviderDescriptor.swift @@ -1,6 +1,10 @@ import CodexBarMacroSupport import Foundation +#if os(macOS) +import SweetCookieKit +#endif + @ProviderDescriptorRegistration @ProviderDescriptorDefinition public enum OpenCodeProviderDescriptor { @@ -54,25 +58,25 @@ struct OpenCodeUsageFetchStrategy: ProviderFetchStrategy { ?? context.env["CODEXBAR_OPENCODE_WORKSPACE_ID"] let cookieSource = context.settings?.opencode?.cookieSource ?? .auto do { - let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: true) + let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: true, excludeBrowsers: []) let snapshot = try await OpenCodeUsageFetcher.fetchUsage( cookieHeader: cookieHeader, timeout: context.webTimeout, workspaceIDOverride: workspaceOverride) - return self.makeResult( - usage: snapshot.toUsageSnapshot(), - sourceLabel: "web") + return self.makeResult(usage: snapshot.toUsageSnapshot(), sourceLabel: "web") } catch OpenCodeUsageError.invalidCredentials where cookieSource != .manual { #if os(macOS) + guard let cached = CookieHeaderCache.load(provider: .opencode) else { + throw OpenCodeUsageError.invalidCredentials + } + let failedBrowser = cached.sourceLabel CookieHeaderCache.clear(provider: .opencode) - let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: false) + let cookieHeader = try Self.resolveCookieHeader(context: context, allowCached: false, excludeBrowsers: [failedBrowser]) let snapshot = try await OpenCodeUsageFetcher.fetchUsage( cookieHeader: cookieHeader, timeout: context.webTimeout, workspaceIDOverride: workspaceOverride) - return self.makeResult( - usage: snapshot.toUsageSnapshot(), - sourceLabel: "web") + return self.makeResult(usage: snapshot.toUsageSnapshot(), sourceLabel: "web") #else throw OpenCodeUsageError.invalidCredentials #endif @@ -83,7 +87,7 @@ struct OpenCodeUsageFetchStrategy: ProviderFetchStrategy { false } - private static func resolveCookieHeader(context: ProviderFetchContext, allowCached: Bool) throws -> String { + private static func resolveCookieHeader(context: ProviderFetchContext, allowCached: Bool, excludeBrowsers: [String]) throws -> String { if let settings = context.settings?.opencode, settings.cookieSource == .manual { if let header = CookieHeaderNormalizer.normalize(settings.manualCookieHeader) { let pairs = CookieHeaderNormalizer.pairs(from: header) @@ -104,7 +108,9 @@ struct OpenCodeUsageFetchStrategy: ProviderFetchStrategy { { return cached.cookieHeader } - let session = try OpenCodeCookieImporter.importSession(browserDetection: context.browserDetection) + let session = try OpenCodeCookieImporter.importSession( + browserDetection: context.browserDetection, + excludeBrowsers: excludeBrowsers.compactMap { Browser(rawValue: $0) }) CookieHeaderCache.store( provider: .opencode, cookieHeader: session.cookieHeader,