From 2d6e1d26c0a6fd361768e8421eda23a34075b9c4 Mon Sep 17 00:00:00 2001 From: ianshaw Date: Thu, 25 Dec 2025 21:24:35 -0800 Subject: [PATCH] =?UTF-8?q?feat(backend):=20=E6=89=A9=E5=B1=95=20Gemini=20?= =?UTF-8?q?OAuth=20Repository=20=E5=B1=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 更新 gemini_oauth_client.go: 支持 AI Studio OAuth 客户端 - 更新 geminicli_codeassist_client.go: 适配新的认证流程 --- .../repository/gemini_oauth_client.go | 28 ++++++++++++++++--- .../repository/geminicli_codeassist_client.go | 14 ++++++++-- 2 files changed, 36 insertions(+), 6 deletions(-) diff --git a/backend/internal/repository/gemini_oauth_client.go b/backend/internal/repository/gemini_oauth_client.go index 07364368..7814c976 100644 --- a/backend/internal/repository/gemini_oauth_client.go +++ b/backend/internal/repository/gemini_oauth_client.go @@ -28,10 +28,20 @@ func NewGeminiOAuthClient(cfg *config.Config) ports.GeminiOAuthClient { func (c *geminiOAuthClient) ExchangeCode(ctx context.Context, code, codeVerifier, redirectURI, proxyURL string) (*geminicli.TokenResponse, error) { client := createGeminiReqClient(proxyURL) + // Both Code Assist and AI Studio OAuth use the same token endpoint and OAuth client. + oauthCfg, err := geminicli.EffectiveOAuthConfig(geminicli.OAuthConfig{ + ClientID: c.cfg.Gemini.OAuth.ClientID, + ClientSecret: c.cfg.Gemini.OAuth.ClientSecret, + Scopes: c.cfg.Gemini.OAuth.Scopes, + }, "code_assist") + if err != nil { + return nil, err + } + formData := url.Values{} formData.Set("grant_type", "authorization_code") - formData.Set("client_id", c.cfg.Gemini.OAuth.ClientID) - formData.Set("client_secret", c.cfg.Gemini.OAuth.ClientSecret) + formData.Set("client_id", oauthCfg.ClientID) + formData.Set("client_secret", oauthCfg.ClientSecret) formData.Set("code", code) formData.Set("code_verifier", codeVerifier) formData.Set("redirect_uri", redirectURI) @@ -54,11 +64,21 @@ func (c *geminiOAuthClient) ExchangeCode(ctx context.Context, code, codeVerifier func (c *geminiOAuthClient) RefreshToken(ctx context.Context, refreshToken, proxyURL string) (*geminicli.TokenResponse, error) { client := createGeminiReqClient(proxyURL) + // Both Code Assist and AI Studio OAuth use the same token endpoint and OAuth client. + oauthCfg, err := geminicli.EffectiveOAuthConfig(geminicli.OAuthConfig{ + ClientID: c.cfg.Gemini.OAuth.ClientID, + ClientSecret: c.cfg.Gemini.OAuth.ClientSecret, + Scopes: c.cfg.Gemini.OAuth.Scopes, + }, "code_assist") + if err != nil { + return nil, err + } + formData := url.Values{} formData.Set("grant_type", "refresh_token") formData.Set("refresh_token", refreshToken) - formData.Set("client_id", c.cfg.Gemini.OAuth.ClientID) - formData.Set("client_secret", c.cfg.Gemini.OAuth.ClientSecret) + formData.Set("client_id", oauthCfg.ClientID) + formData.Set("client_secret", oauthCfg.ClientSecret) var tokenResp geminicli.TokenResponse resp, err := client.R(). diff --git a/backend/internal/repository/geminicli_codeassist_client.go b/backend/internal/repository/geminicli_codeassist_client.go index 63f1719c..6bae36e2 100644 --- a/backend/internal/repository/geminicli_codeassist_client.go +++ b/backend/internal/repository/geminicli_codeassist_client.go @@ -34,11 +34,15 @@ func (c *geminiCliCodeAssistClient) LoadCodeAssist(ctx context.Context, accessTo SetSuccessResult(&out). Post(c.baseURL + "/v1internal:loadCodeAssist") if err != nil { + fmt.Printf("[CodeAssist] LoadCodeAssist request error: %v\n", err) return nil, fmt.Errorf("request failed: %w", err) } if !resp.IsSuccessState() { - return nil, fmt.Errorf("loadCodeAssist failed: status %d, body: %s", resp.StatusCode, geminicli.SanitizeBodyForLogs(resp.String())) + body := geminicli.SanitizeBodyForLogs(resp.String()) + fmt.Printf("[CodeAssist] LoadCodeAssist failed: status %d, body: %s\n", resp.StatusCode, body) + return nil, fmt.Errorf("loadCodeAssist failed: status %d, body: %s", resp.StatusCode, body) } + fmt.Printf("[CodeAssist] LoadCodeAssist success: status %d, response: %+v\n", resp.StatusCode, out) return &out, nil } @@ -47,6 +51,8 @@ func (c *geminiCliCodeAssistClient) OnboardUser(ctx context.Context, accessToken reqBody = defaultOnboardUserRequest() } + fmt.Printf("[CodeAssist] OnboardUser request body: %+v\n", reqBody) + var out geminicli.OnboardUserResponse resp, err := createGeminiCliReqClient(proxyURL).R(). SetContext(ctx). @@ -57,11 +63,15 @@ func (c *geminiCliCodeAssistClient) OnboardUser(ctx context.Context, accessToken SetSuccessResult(&out). Post(c.baseURL + "/v1internal:onboardUser") if err != nil { + fmt.Printf("[CodeAssist] OnboardUser request error: %v\n", err) return nil, fmt.Errorf("request failed: %w", err) } if !resp.IsSuccessState() { - return nil, fmt.Errorf("onboardUser failed: status %d, body: %s", resp.StatusCode, geminicli.SanitizeBodyForLogs(resp.String())) + body := geminicli.SanitizeBodyForLogs(resp.String()) + fmt.Printf("[CodeAssist] OnboardUser failed: status %d, body: %s\n", resp.StatusCode, body) + return nil, fmt.Errorf("onboardUser failed: status %d, body: %s", resp.StatusCode, body) } + fmt.Printf("[CodeAssist] OnboardUser success: status %d, response: %+v\n", resp.StatusCode, out) return &out, nil }