Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/internal/repository/account_repo.go
Original file line number Diff line number Diff line change
Expand Up @@ -729,7 +729,7 @@ func (r *accountRepository) ListOAuthRefreshCandidates(ctx context.Context) ([]s
FROM accounts
WHERE deleted_at IS NULL
AND status = 'active'
AND type = 'oauth'
AND type IN ('oauth', 'setup-token')
AND platform IN ('anthropic', 'openai', 'gemini', 'antigravity')
AND credentials ? 'refresh_token'
AND btrim(credentials->>'refresh_token') <> ''
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,8 @@ func TestAccountRepository_ListOAuthRefreshCandidates_SQLFilter(t *testing.T) {
normalized := normalizeSQLWhitespace(capturedSQL)
require.Contains(t, normalized, "deleted_at IS NULL")
require.Contains(t, normalized, "status = 'active'")
require.Contains(t, normalized, "type = 'oauth'")
// setup-token 的 access_token 同为 8h 短期令牌,必须与 oauth 一起纳入后台刷新候选
require.Contains(t, normalized, "type IN ('oauth', 'setup-token')")
require.Contains(t, normalized, "platform IN ('anthropic', 'openai', 'gemini', 'antigravity')")
require.Contains(t, normalized, "credentials ? 'refresh_token'")
require.Contains(t, normalized, "btrim(credentials->>'refresh_token') <> ''")
Expand Down
10 changes: 6 additions & 4 deletions backend/internal/service/token_refresher.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,13 @@ func (r *ClaudeTokenRefresher) CacheKey(account *Account) string {
}

// CanRefresh 检查是否能处理此账号
// 只处理 anthropic 平台的 oauth 类型账号
// setup-token 虽然也是OAuth,但有效期1年,不需要频繁刷新
// 处理 anthropic 平台的 oauth 与 setup-token 类型账号。
// 两者的 access_token 均为短期令牌(expires_in=28800,即 8h),到期都需刷新;
// setup-token 之前被排除会导致其 access_token 过期后请求 401。
// 此处与手动刷新入口(account.IsOAuth())保持一致,实际是否刷新由 NeedsRefresh
// 基于 expires_at 门控,并在分布式锁保护下执行,不会造成过度刷新。
func (r *ClaudeTokenRefresher) CanRefresh(account *Account) bool {
return account.Platform == PlatformAnthropic &&
account.Type == AccountTypeOAuth
return account.Platform == PlatformAnthropic && account.IsOAuth()
}

// NeedsRefresh 检查token是否需要刷新
Expand Down
6 changes: 6 additions & 0 deletions backend/internal/service/token_refresher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,12 @@ func TestClaudeTokenRefresher_CanRefresh(t *testing.T) {
accType: AccountTypeOAuth,
want: true,
},
{
name: "anthropic setup-token - can refresh",
platform: PlatformAnthropic,
accType: AccountTypeSetupToken,
want: true,
},
{
name: "anthropic api-key - cannot refresh",
platform: PlatformAnthropic,
Expand Down
Loading