From 99da3081961f983f865290aa4657bfaae3530a8a Mon Sep 17 00:00:00 2001 From: Shumin <332587268@qq.com> Date: Thu, 9 Jul 2026 11:05:05 -0400 Subject: [PATCH 1/2] =?UTF-8?q?fix:=20=E5=90=8E=E5=8F=B0=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E5=88=B7=E6=96=B0=E7=BA=B3=E5=85=A5=20setup-token=20=E8=B4=A6?= =?UTF-8?q?=E5=8F=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit setup-token 的 access_token 同为 8h 短期令牌(expires_in=28800), 此前被后台刷新服务排除,到期后请求返回 401 authentication_error。 放开 CanRefresh 与候选查询的 type='oauth' 限制,与手动刷新入口 (account.IsOAuth()) 保持一致;实际刷新仍由 NeedsRefresh 基于 expires_at 门控并在分布式锁下执行,不会过度刷新。 --- backend/internal/repository/account_repo.go | 2 +- backend/internal/service/token_refresher.go | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/internal/repository/account_repo.go b/backend/internal/repository/account_repo.go index a8015ddba0..c3c2f6708a 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 da5edb782c..637efc21cc 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是否需要刷新 From a495d5e3024f93419d981a36fcd983b9732926d7 Mon Sep 17 00:00:00 2001 From: Shumin <332587268@qq.com> Date: Fri, 10 Jul 2026 02:27:33 -0400 Subject: [PATCH 2/2] =?UTF-8?q?test:=20=E6=9B=B4=E6=96=B0=E6=96=AD?= =?UTF-8?q?=E8=A8=80=E4=BB=A5=E8=A6=86=E7=9B=96=20setup-token=20=E7=BA=B3?= =?UTF-8?q?=E5=85=A5=E5=90=8E=E5=8F=B0=E5=88=B7=E6=96=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ListOAuthRefreshCandidates SQL 断言由 type = 'oauth' 改为 type IN ('oauth', 'setup-token')。 - ClaudeTokenRefresher.CanRefresh 增加 anthropic setup-token → true 用例。 --- .../internal/repository/account_repo_temp_unsched_test.go | 3 ++- backend/internal/service/token_refresher_test.go | 6 ++++++ 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/backend/internal/repository/account_repo_temp_unsched_test.go b/backend/internal/repository/account_repo_temp_unsched_test.go index eb123ee6a3..9c3e4cbdf5 100644 --- a/backend/internal/repository/account_repo_temp_unsched_test.go +++ b/backend/internal/repository/account_repo_temp_unsched_test.go @@ -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') <> ''") diff --git a/backend/internal/service/token_refresher_test.go b/backend/internal/service/token_refresher_test.go index d1cf88983b..84cce1de72 100644 --- a/backend/internal/service/token_refresher_test.go +++ b/backend/internal/service/token_refresher_test.go @@ -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,