feat(pool,trace): 账号封禁原因细分与请求追踪 attempted_only 过滤

- 将账号封禁原因从笼统的"账号异常"细分为封禁/停用/需要验证三类,
  前后端关键词组同步拆分,号池管理页面展示对应分类标签
- trace API 新增 attempted_only 参数,支持仅返回实际尝试过的候选,
  前端时间线组件默认启用过滤,排除 available/unused/skipped 记录
This commit is contained in:
fawney19
2026-03-05 17:32:21 +08:00
parent a7697032a4
commit 694167f78f
8 changed files with 226 additions and 52 deletions

View File

@@ -1,7 +1,19 @@
// 账号级别封禁/异常的关键词匹配(用于判断 oauth_invalid_reason 是否属于账号封禁)
const ACCOUNT_BLOCK_REASON_KEYWORDS = [
// -- 按原因细分的关键词组 --
// 封禁类 (suspended / banned)
const KEYWORDS_SUSPENDED = [
'suspended',
'account_block',
'account blocked',
'封禁',
'封号',
'被封',
'账户已封禁',
'账号异常',
]
// 停用类 (disabled / deactivated)
const KEYWORDS_DISABLED = [
'account has been disabled',
'account disabled',
'account has been deactivated',
@@ -9,19 +21,22 @@ const ACCOUNT_BLOCK_REASON_KEYWORDS = [
'account deactivated',
'organization has been disabled',
'organization_disabled',
'deactivated',
'访问被禁止',
'账户访问被禁止',
]
// 需要验证类
const KEYWORDS_VERIFICATION = [
'validation_required',
'verify your account',
'suspended',
'deactivated',
// Kiro quota refresher 写入的确切文本
'账户已封禁',
// Antigravity quota refresher 写入的确切文本
'账户访问被禁止',
'封禁',
'封号',
'被封',
'访问被禁止',
'账号异常',
]
// 合并的完整列表
const ACCOUNT_BLOCK_REASON_KEYWORDS = [
...KEYWORDS_SUSPENDED,
...KEYWORDS_DISABLED,
...KEYWORDS_VERIFICATION,
]
export function isAccountLevelBlockReason(reason: string | null | undefined): boolean {
@@ -33,6 +48,14 @@ export function isAccountLevelBlockReason(reason: string | null | undefined): bo
return ACCOUNT_BLOCK_REASON_KEYWORDS.some(keyword => lowered.includes(keyword))
}
export function classifyAccountBlockLabel(reason: string): string {
const lowered = reason.toLowerCase()
if (KEYWORDS_VERIFICATION.some(kw => lowered.includes(kw))) return '需要验证'
if (KEYWORDS_DISABLED.some(kw => lowered.includes(kw))) return '账号停用'
if (KEYWORDS_SUSPENDED.some(kw => lowered.includes(kw))) return '账号封禁'
return '账号异常'
}
export function cleanAccountBlockReason(reason: string): string {
return reason.replace(/^\[ACCOUNT_BLOCK\]\s*/i, '').trim()
}