From e4ebc2ed2ef3c09c5f89577f5bb8ec159368f2f8 Mon Sep 17 00:00:00 2001 From: icey-zhang Date: Thu, 16 Apr 2026 11:25:58 +0800 Subject: [PATCH] Support bundled Gemini CLI layout for OAuth credential extraction Newer versions of Gemini CLI (installed via npm) use a bundled format where all code is packed into `bundle/chunk-*.js` files instead of the traditional `dist/src/code_assist/oauth2.js` path. This caused token refresh to fail with "Could not find Gemini CLI OAuth configuration". Add `searchBundleDirectory` as a fallback that scans `chunk-*.js` files for embedded OAUTH_CLIENT_ID and OAUTH_CLIENT_SECRET values. Co-Authored-By: Claude Opus 4.6 --- .../Providers/Gemini/GeminiStatusProbe.swift | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift b/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift index d978630aa..445773a64 100644 --- a/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift +++ b/Sources/CodexBarCore/Providers/Gemini/GeminiStatusProbe.swift @@ -514,6 +514,15 @@ public struct GeminiStatusProbe: Sendable { } } + // Bundled format: realPath points into a bundle/ dir containing chunk-*.js files + // with OAuth credentials embedded in one of the chunks. + if let result = self.searchBundleDirectory(binDir, fm: fm) { + return result + } + if let result = self.searchBundleDirectory(baseDir + "/bundle", fm: fm) { + return result + } + return nil } @@ -544,6 +553,18 @@ public struct GeminiStatusProbe: Sendable { return OAuthClientCredentials(clientId: clientId, clientSecret: clientSecret) } + private static func searchBundleDirectory(_ dir: String, fm: FileManager) -> OAuthClientCredentials? { + guard let entries = try? fm.contentsOfDirectory(atPath: dir) else { return nil } + for entry in entries where entry.hasPrefix("chunk-") && entry.hasSuffix(".js") { + let path = (dir as NSString).appendingPathComponent(entry) + guard let content = try? String(contentsOfFile: path, encoding: .utf8) else { continue } + if let result = self.parseOAuthCredentials(from: content) { + return result + } + } + return nil + } + private static func refreshAccessToken( refreshToken: String, timeout: TimeInterval,