From 979114db45fe817a2741d63f971c2287533b0bc0 Mon Sep 17 00:00:00 2001 From: IanShaw027 <131567472+IanShaw027@users.noreply.github.com> Date: Thu, 5 Feb 2026 13:57:02 +0800 Subject: [PATCH] =?UTF-8?q?fix(gemini):=20=E4=BF=AE=E5=A4=8D=E5=B7=B2?= =?UTF-8?q?=E6=B3=A8=E5=86=8C=E7=94=A8=E6=88=B7=20OAuth=20=E6=8E=88?= =?UTF-8?q?=E6=9D=83=E6=97=B6=E9=94=99=E8=AF=AF=E8=B0=83=E7=94=A8=20onboar?= =?UTF-8?q?dUser=20=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 问题:Google One Ultra 等已注册用户在 OAuth 授权时,如果 LoadCodeAssist 返回了 currentTier/paidTier 但没有返回 cloudaicompanionProject,之前的 逻辑会继续调用 onboardUser,导致 INVALID_ARGUMENT 错误。 修复:对齐 Gemini CLI 的处理逻辑: - 当检测到用户已注册(有 currentTier/paidTier)时,不再调用 onboardUser - 先尝试从 Cloud Resource Manager 获取可用项目 - 如果仍无法获取,返回友好的错误提示,引导用户手动填写 Project ID 这个修复解决了 Google One 订阅用户无法正常授权的问题。 --- .../internal/service/gemini_oauth_service.go | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/backend/internal/service/gemini_oauth_service.go b/backend/internal/service/gemini_oauth_service.go index bc84baeb..fd2932e6 100644 --- a/backend/internal/service/gemini_oauth_service.go +++ b/backend/internal/service/gemini_oauth_service.go @@ -944,6 +944,32 @@ func (s *GeminiOAuthService) fetchProjectID(ctx context.Context, accessToken, pr return strings.TrimSpace(loadResp.CloudAICompanionProject), tierID, nil } + // 关键逻辑:对齐 Gemini CLI 对“已注册用户”的处理方式。 + // 当 LoadCodeAssist 返回了 currentTier / paidTier(表示账号已注册)但没有返回 cloudaicompanionProject 时: + // - 不要再调用 onboardUser(通常不会再分配 project_id,且可能触发 INVALID_ARGUMENT) + // - 先尝试从 Cloud Resource Manager 获取可用项目;仍失败则提示用户手动填写 project_id + if loadResp != nil { + registeredTierID := strings.TrimSpace(loadResp.GetTier()) + if registeredTierID != "" { + // 已注册但未返回 cloudaicompanionProject,这在 Google One 用户中较常见:需要用户自行提供 project_id。 + log.Printf("[GeminiOAuth] User has tier (%s) but no cloudaicompanionProject, trying Cloud Resource Manager...", registeredTierID) + + // Try to get project from Cloud Resource Manager + fallback, fbErr := fetchProjectIDFromResourceManager(ctx, accessToken, proxyURL) + if fbErr == nil && strings.TrimSpace(fallback) != "" { + log.Printf("[GeminiOAuth] Found project from Cloud Resource Manager: %s", fallback) + return strings.TrimSpace(fallback), tierID, nil + } + + // No project found - user must provide project_id manually + log.Printf("[GeminiOAuth] No project found from Cloud Resource Manager, user must provide project_id manually") + return "", tierID, fmt.Errorf("user is registered (tier: %s) but no project_id available. Please provide Project ID manually in the authorization form, or create a project at https://console.cloud.google.com", registeredTierID) + } + } + + // 未检测到 currentTier/paidTier,视为新用户,继续调用 onboardUser + log.Printf("[GeminiOAuth] No currentTier/paidTier found, proceeding with onboardUser (tierID: %s)", tierID) + req := &geminicli.OnboardUserRequest{ TierID: tierID, Metadata: geminicli.LoadCodeAssistMetadata{