feat(antigravity): 自动设置隐私并支持后台手动重试
新增 Antigravity OAuth 隐私设置能力,在账号创建、刷新、导入和后台 Token 刷新路径自动调用 setUserSettings + fetchUserInfo 关闭遥测; 持久化后同步内存 Extra,错误处理改为日志记录。 Made-with: Cursor
This commit is contained in:
@@ -9,6 +9,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"log"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
@@ -536,6 +537,8 @@ func (h *AccountHandler) Create(c *gin.Context) {
|
||||
if execErr != nil {
|
||||
return nil, execErr
|
||||
}
|
||||
// Antigravity OAuth: 新账号直接设置隐私
|
||||
h.adminService.ForceAntigravityPrivacy(ctx, account)
|
||||
return h.buildAccountResponseWithRuntime(ctx, account), nil
|
||||
})
|
||||
if err != nil {
|
||||
@@ -883,6 +886,8 @@ func (h *AccountHandler) refreshSingleAccount(ctx context.Context, account *serv
|
||||
|
||||
// OpenAI OAuth: 刷新成功后检查并设置 privacy_mode
|
||||
h.adminService.EnsureOpenAIPrivacy(ctx, updatedAccount)
|
||||
// Antigravity OAuth: 刷新成功后检查并设置 privacy_mode
|
||||
h.adminService.EnsureAntigravityPrivacy(ctx, updatedAccount)
|
||||
|
||||
return updatedAccount, "", nil
|
||||
}
|
||||
@@ -1154,6 +1159,8 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
||||
success := 0
|
||||
failed := 0
|
||||
results := make([]gin.H, 0, len(req.Accounts))
|
||||
// 收集需要异步设置隐私的 Antigravity OAuth 账号
|
||||
var privacyAccounts []*service.Account
|
||||
|
||||
for _, item := range req.Accounts {
|
||||
if item.RateMultiplier != nil && *item.RateMultiplier < 0 {
|
||||
@@ -1196,6 +1203,10 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
||||
})
|
||||
continue
|
||||
}
|
||||
// 收集 Antigravity OAuth 账号,稍后异步设置隐私
|
||||
if account.Platform == service.PlatformAntigravity && account.Type == service.AccountTypeOAuth {
|
||||
privacyAccounts = append(privacyAccounts, account)
|
||||
}
|
||||
success++
|
||||
results = append(results, gin.H{
|
||||
"name": item.Name,
|
||||
@@ -1204,6 +1215,22 @@ func (h *AccountHandler) BatchCreate(c *gin.Context) {
|
||||
})
|
||||
}
|
||||
|
||||
// 异步设置 Antigravity 隐私,避免批量创建时阻塞请求
|
||||
if len(privacyAccounts) > 0 {
|
||||
adminSvc := h.adminService
|
||||
go func() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
slog.Error("batch_create_antigravity_privacy_panic", "recover", r)
|
||||
}
|
||||
}()
|
||||
bgCtx := context.Background()
|
||||
for _, acc := range privacyAccounts {
|
||||
adminSvc.ForceAntigravityPrivacy(bgCtx, acc)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
return gin.H{
|
||||
"success": success,
|
||||
"failed": failed,
|
||||
@@ -1869,6 +1896,42 @@ func (h *AccountHandler) GetAvailableModels(c *gin.Context) {
|
||||
response.Success(c, models)
|
||||
}
|
||||
|
||||
// SetPrivacy handles setting privacy for a single Antigravity OAuth account
|
||||
// POST /api/v1/admin/accounts/:id/set-privacy
|
||||
func (h *AccountHandler) SetPrivacy(c *gin.Context) {
|
||||
accountID, err := strconv.ParseInt(c.Param("id"), 10, 64)
|
||||
if err != nil {
|
||||
response.BadRequest(c, "Invalid account ID")
|
||||
return
|
||||
}
|
||||
account, err := h.adminService.GetAccount(c.Request.Context(), accountID)
|
||||
if err != nil {
|
||||
response.NotFound(c, "Account not found")
|
||||
return
|
||||
}
|
||||
if account.Platform != service.PlatformAntigravity || account.Type != service.AccountTypeOAuth {
|
||||
response.BadRequest(c, "Only Antigravity OAuth accounts support privacy setting")
|
||||
return
|
||||
}
|
||||
mode := h.adminService.ForceAntigravityPrivacy(c.Request.Context(), account)
|
||||
if mode == "" {
|
||||
response.BadRequest(c, "Cannot set privacy: missing access_token")
|
||||
return
|
||||
}
|
||||
// 从 DB 重新读取以确保返回最新状态
|
||||
updated, err := h.adminService.GetAccount(c.Request.Context(), accountID)
|
||||
if err != nil {
|
||||
// 隐私已设置成功但读取失败,回退到内存更新
|
||||
if account.Extra == nil {
|
||||
account.Extra = make(map[string]any)
|
||||
}
|
||||
account.Extra["privacy_mode"] = mode
|
||||
response.Success(c, h.buildAccountResponseWithRuntime(c.Request.Context(), account))
|
||||
return
|
||||
}
|
||||
response.Success(c, h.buildAccountResponseWithRuntime(c.Request.Context(), updated))
|
||||
}
|
||||
|
||||
// RefreshTier handles refreshing Google One tier for a single account
|
||||
// POST /api/v1/admin/accounts/:id/refresh-tier
|
||||
func (h *AccountHandler) RefreshTier(c *gin.Context) {
|
||||
|
||||
Reference in New Issue
Block a user