diff --git a/backend/internal/handler/admin/account_handler.go b/backend/internal/handler/admin/account_handler.go index 188aa0ec..bbf5d026 100644 --- a/backend/internal/handler/admin/account_handler.go +++ b/backend/internal/handler/admin/account_handler.go @@ -547,9 +547,18 @@ func (h *AccountHandler) Refresh(c *gin.Context) { } } - // 如果 project_id 获取失败,先更新凭证,再标记账户为 error + // 特殊处理 project_id:如果新值为空但旧值非空,保留旧值 + // 这确保了即使 LoadCodeAssist 失败,project_id 也不会丢失 + if newProjectID, _ := newCredentials["project_id"].(string); newProjectID == "" { + if oldProjectID := strings.TrimSpace(account.GetCredential("project_id")); oldProjectID != "" { + newCredentials["project_id"] = oldProjectID + } + } + + // 如果 project_id 获取失败,更新凭证但不标记为 error + // LoadCodeAssist 失败可能是临时网络问题,给它机会在下次自动刷新时重试 if tokenInfo.ProjectIDMissing { - // 先更新凭证 + // 先更新凭证(token 本身刷新成功了) _, updateErr := h.adminService.UpdateAccount(c.Request.Context(), accountID, &service.UpdateAccountInput{ Credentials: newCredentials, }) @@ -557,14 +566,10 @@ func (h *AccountHandler) Refresh(c *gin.Context) { response.InternalError(c, "Failed to update credentials: "+updateErr.Error()) return } - // 标记账户为 error - if setErr := h.adminService.SetAccountError(c.Request.Context(), accountID, "missing_project_id: 账户缺少project id,可能无法使用Antigravity"); setErr != nil { - response.InternalError(c, "Failed to set account error: "+setErr.Error()) - return - } + // 不标记为 error,只返回警告信息 response.Success(c, gin.H{ - "message": "Token refreshed but project_id is missing, account marked as error", - "warning": "missing_project_id", + "message": "Token refreshed successfully, but project_id could not be retrieved (will retry automatically)", + "warning": "missing_project_id_temporary", }) return } diff --git a/backend/internal/service/antigravity_oauth_service.go b/backend/internal/service/antigravity_oauth_service.go index 3850fa57..fa8379ed 100644 --- a/backend/internal/service/antigravity_oauth_service.go +++ b/backend/internal/service/antigravity_oauth_service.go @@ -142,12 +142,13 @@ func (s *AntigravityOAuthService) ExchangeCode(ctx context.Context, input *Antig result.Email = userInfo.Email } - // 获取 project_id(部分账户类型可能没有) - loadResp, _, err := client.LoadCodeAssist(ctx, tokenResp.AccessToken) - if err != nil { - fmt.Printf("[AntigravityOAuth] 警告: 获取 project_id 失败: %v\n", err) - } else if loadResp != nil && loadResp.CloudAICompanionProject != "" { - result.ProjectID = loadResp.CloudAICompanionProject + // 获取 project_id(部分账户类型可能没有),失败时重试 + projectID, loadErr := s.loadProjectIDWithRetry(ctx, tokenResp.AccessToken, proxyURL, 3) + if loadErr != nil { + fmt.Printf("[AntigravityOAuth] 警告: 获取 project_id 失败(重试后): %v\n", loadErr) + result.ProjectIDMissing = true + } else { + result.ProjectID = projectID } return result, nil diff --git a/backend/internal/service/antigravity_token_refresher.go b/backend/internal/service/antigravity_token_refresher.go index 2beb9e84..e33f88d0 100644 --- a/backend/internal/service/antigravity_token_refresher.go +++ b/backend/internal/service/antigravity_token_refresher.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "log" + "strings" "time" ) @@ -56,22 +57,31 @@ func (r *AntigravityTokenRefresher) Refresh(ctx context.Context, account *Accoun } newCredentials := r.antigravityOAuthService.BuildAccountCredentials(tokenInfo) + // 合并旧的 credentials,保留新 credentials 中不存在的字段 for k, v := range account.Credentials { if _, exists := newCredentials[k]; !exists { newCredentials[k] = v } } - // 如果 project_id 获取失败但之前有 project_id,不返回错误(只是临时网络故障) - // 只有真正缺失 project_id(从未获取过)时才返回错误 + // 特殊处理 project_id:如果新值为空但旧值非空,保留旧值 + // 这确保了即使 LoadCodeAssist 失败,project_id 也不会丢失 + if newProjectID, _ := newCredentials["project_id"].(string); newProjectID == "" { + if oldProjectID := strings.TrimSpace(account.GetCredential("project_id")); oldProjectID != "" { + newCredentials["project_id"] = oldProjectID + } + } + + // 如果 project_id 获取失败,只记录警告,不返回错误 + // LoadCodeAssist 失败可能是临时网络问题,应该允许重试而不是立即标记为不可重试错误 + // Token 刷新本身是成功的(access_token 和 refresh_token 已更新) if tokenInfo.ProjectIDMissing { - // 检查是否保留了旧的 project_id if tokenInfo.ProjectID != "" { - // 有旧的 project_id,只是本次获取失败,记录警告但不返回错误 + // 有旧的 project_id,本次获取失败,保留旧值 log.Printf("[AntigravityTokenRefresher] Account %d: LoadCodeAssist 临时失败,保留旧 project_id", account.ID) } else { - // 真正缺失 project_id,返回错误 - return newCredentials, fmt.Errorf("missing_project_id: 账户缺少project id,可能无法使用Antigravity") + // 从未获取过 project_id,本次也失败,但不返回错误以允许下次重试 + log.Printf("[AntigravityTokenRefresher] Account %d: LoadCodeAssist 失败,project_id 缺失,但 token 已更新,将在下次刷新时重试", account.ID) } }