diff --git a/backend/internal/repository/account_repo.go b/backend/internal/repository/account_repo.go index a8015ddba..c3c2f6708 100644 --- a/backend/internal/repository/account_repo.go +++ b/backend/internal/repository/account_repo.go @@ -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') <> '' diff --git a/backend/internal/service/token_refresher.go b/backend/internal/service/token_refresher.go index da5edb782..637efc21c 100644 --- a/backend/internal/service/token_refresher.go +++ b/backend/internal/service/token_refresher.go @@ -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是否需要刷新