Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
Menu
Open sidebar
陈曦
sub2api
Commits
a5547b2f
Unverified
Commit
a5547b2f
authored
Jan 24, 2026
by
Wesley Liddick
Committed by
GitHub
Jan 24, 2026
Browse files
Merge pull request #380 from DDZS987/fix/oauth-token-refresh-missing-project-id-retry
fix(oauth): 修复 OAuth 令牌刷新时 missing_project_id 误报问题
parents
b0aa2354
ffaa6c4a
Changes
3
Hide whitespace changes
Inline
Side-by-side
backend/internal/service/antigravity_oauth_service.go
View file @
a5547b2f
...
@@ -237,21 +237,60 @@ func (s *AntigravityOAuthService) RefreshAccountToken(ctx context.Context, accou
...
@@ -237,21 +237,60 @@ func (s *AntigravityOAuthService) RefreshAccountToken(ctx context.Context, accou
tokenInfo
.
Email
=
existingEmail
tokenInfo
.
Email
=
existingEmail
}
}
// 每次刷新都调用 LoadCodeAssist 获取 project_id
// 每次刷新都调用 LoadCodeAssist 获取 project_id
,失败时重试
client
:=
antigravity
.
NewClient
(
proxyURL
)
existingProjectID
:=
strings
.
TrimSpace
(
account
.
GetCredential
(
"project_id"
)
)
loadResp
,
_
,
err
:=
client
.
LoadCodeAssist
(
ctx
,
tokenInfo
.
AccessToken
)
projectID
,
loadErr
:=
s
.
loadProjectIDWithRetry
(
ctx
,
tokenInfo
.
AccessToken
,
proxyURL
,
3
)
if
err
!=
nil
||
loadResp
==
nil
||
loadResp
.
CloudAICompanionProject
==
""
{
// LoadCodeAssist 失败或返回空,保留原有 project_id,标记缺失
if
loadErr
!=
nil
{
existingProjectID
:=
strings
.
TrimSpace
(
account
.
GetCredential
(
"
project_id
"
))
// LoadCodeAssist 失败,保留原有
project_id
tokenInfo
.
ProjectID
=
existingProjectID
tokenInfo
.
ProjectID
=
existingProjectID
tokenInfo
.
ProjectIDMissing
=
true
// 只有从未获取过 project_id 且本次也获取失败时,才标记为真正缺失
// 如果之前有 project_id,本次只是临时故障,不应标记为错误
if
existingProjectID
==
""
{
tokenInfo
.
ProjectIDMissing
=
true
}
}
else
{
}
else
{
tokenInfo
.
ProjectID
=
loadResp
.
CloudAICompanionP
roject
tokenInfo
.
ProjectID
=
p
roject
ID
}
}
return
tokenInfo
,
nil
return
tokenInfo
,
nil
}
}
// loadProjectIDWithRetry 带重试机制获取 project_id
// 返回 project_id 和错误,失败时会重试指定次数
func
(
s
*
AntigravityOAuthService
)
loadProjectIDWithRetry
(
ctx
context
.
Context
,
accessToken
,
proxyURL
string
,
maxRetries
int
)
(
string
,
error
)
{
var
lastErr
error
for
attempt
:=
0
;
attempt
<=
maxRetries
;
attempt
++
{
if
attempt
>
0
{
// 指数退避:1s, 2s, 4s
backoff
:=
time
.
Duration
(
1
<<
uint
(
attempt
-
1
))
*
time
.
Second
if
backoff
>
8
*
time
.
Second
{
backoff
=
8
*
time
.
Second
}
time
.
Sleep
(
backoff
)
}
client
:=
antigravity
.
NewClient
(
proxyURL
)
loadResp
,
_
,
err
:=
client
.
LoadCodeAssist
(
ctx
,
accessToken
)
if
err
==
nil
&&
loadResp
!=
nil
&&
loadResp
.
CloudAICompanionProject
!=
""
{
return
loadResp
.
CloudAICompanionProject
,
nil
}
// 记录错误
if
err
!=
nil
{
lastErr
=
err
}
else
if
loadResp
==
nil
{
lastErr
=
fmt
.
Errorf
(
"LoadCodeAssist 返回空响应"
)
}
else
{
lastErr
=
fmt
.
Errorf
(
"LoadCodeAssist 返回空 project_id"
)
}
}
return
""
,
fmt
.
Errorf
(
"获取 project_id 失败 (重试 %d 次后): %w"
,
maxRetries
,
lastErr
)
}
// BuildAccountCredentials 构建账户凭证
// BuildAccountCredentials 构建账户凭证
func
(
s
*
AntigravityOAuthService
)
BuildAccountCredentials
(
tokenInfo
*
AntigravityTokenInfo
)
map
[
string
]
any
{
func
(
s
*
AntigravityOAuthService
)
BuildAccountCredentials
(
tokenInfo
*
AntigravityTokenInfo
)
map
[
string
]
any
{
creds
:=
map
[
string
]
any
{
creds
:=
map
[
string
]
any
{
...
...
backend/internal/service/antigravity_token_refresher.go
View file @
a5547b2f
...
@@ -3,6 +3,7 @@ package service
...
@@ -3,6 +3,7 @@ package service
import
(
import
(
"context"
"context"
"fmt"
"fmt"
"log"
"time"
"time"
)
)
...
@@ -61,9 +62,17 @@ func (r *AntigravityTokenRefresher) Refresh(ctx context.Context, account *Accoun
...
@@ -61,9 +62,17 @@ func (r *AntigravityTokenRefresher) Refresh(ctx context.Context, account *Accoun
}
}
}
}
// 如果 project_id 获取失败,返回 credentials 但同时返回错误让账户被标记
// 如果 project_id 获取失败但之前有 project_id,不返回错误(只是临时网络故障)
// 只有真正缺失 project_id(从未获取过)时才返回错误
if
tokenInfo
.
ProjectIDMissing
{
if
tokenInfo
.
ProjectIDMissing
{
return
newCredentials
,
fmt
.
Errorf
(
"missing_project_id: 账户缺少project id,可能无法使用Antigravity"
)
// 检查是否保留了旧的 project_id
if
tokenInfo
.
ProjectID
!=
""
{
// 有旧的 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"
)
}
}
}
return
newCredentials
,
nil
return
newCredentials
,
nil
...
...
backend/internal/service/token_refresh_service.go
View file @
a5547b2f
...
@@ -237,7 +237,8 @@ func (s *TokenRefreshService) refreshWithRetry(ctx context.Context, account *Acc
...
@@ -237,7 +237,8 @@ func (s *TokenRefreshService) refreshWithRetry(ctx context.Context, account *Acc
}
}
// isNonRetryableRefreshError 判断是否为不可重试的刷新错误
// isNonRetryableRefreshError 判断是否为不可重试的刷新错误
// 这些错误通常表示凭证已失效,需要用户重新授权
// 这些错误通常表示凭证已失效或配置确实缺失,需要用户重新授权
// 注意:missing_project_id 错误只在真正缺失(从未获取过)时返回,临时获取失败不会返回此错误
func
isNonRetryableRefreshError
(
err
error
)
bool
{
func
isNonRetryableRefreshError
(
err
error
)
bool
{
if
err
==
nil
{
if
err
==
nil
{
return
false
return
false
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment