bug: Anthropic 会话 Auto-review 持续 429 且不可自诊断——one-shot 裸打 /v1/messages、错误正文被丢弃、重试不理会限流
- Dominant language
- TypeScript
- Stars
- 2.7k
- Forks
- 395
- Avg merge
- 21h 48m
- Merged PRs (30d)
- 776
Description
### 问题描述 / What happened
会话模型为 Anthropic(claude-opus-5 / claude-fable-5)且权限为 **Auto-review** 时,权限评审持续失败并弹 `AUTO_REVIEW_UNAVAILABLE`,动作全部退回手动确认。同一时刻同一会话的主对话(Claude Code SDK 通道)完全正常。
**观测(2026-08-13,0.1.46):**
```
[utility-model:one-shot] explicit utility text provider failed {
providerId: 'anthropic', model: 'claude-opus-5',
transport: 'litellm-chat-completions', reason: 'http_error', httpStatus: 429 }
```
- 22:55:47–22:56:03 两轮评审 6 次调用全部 429(重试间隔 100/200ms)。
- 一整天多个时段(00:02 / 00:43 / 22:55)同样模式;#2429 的 [1m] 404 修掉之后,anthropic 会话的 Auto-review 仍因 429 不可用。
- 主对话同时间正常出流 → 不是账号配额单纯耗尽,更像该请求形态命中了不同的限流/拒绝桶。
**机制疑点(oneShotCandidates.ts anthropic 分支):**
1. one-shot 拿 claude.ai 订阅 OAuth token 直打 `/v1/messages`(`anthropic-beta: oauth-2025-04-20`),与正常聊天的 Claude Code SDK 通道请求形态完全不同;上游对这类裸调用的接受度/限流桶未知。
2. `requestProviderHttpText` 对非 2xx **丢弃响应正文**只留状态码——429 究竟是 `rate_limit_error` 还是别的拒绝,日志无从判断,用户看到的永远是 "network or service hiccup"。
3. 评审重试是 100/200ms 固定退避,共 3 次;对 429 来说 300ms 内 3 连打只会连吃 3 个 429,重试预算完全无效,也不读 `Retry-After`。
### 复现步骤 / Steps to reproduce
1. Anthropic 订阅 OAuth 登录(claude.ai Pro/Max)。
2. 会话模型 claude-opus-5,权限 Auto-review。
3. 触发需要评审的动作,观察 banner 与 `main-*.log` 中连续 429。
### 期望行为 / Expected
至少满足其一:
1. 429/4xx 时把上游错误正文的**脱敏指纹**(error.type + message 截断)写进日志,让用户/开发者能定位真实原因(与 #2684 同一条盲区);
2. 429 视为不可快速重试:读 `Retry-After` 或直接放弃本轮评审,不做 300ms 内 3 连打;
3. 评审 429 持续发生时,考虑评审请求走与主对话一致的通道形态,而不是另拼一条裸 /v1/messages。
### 环境 / Environment
- Cindy 0.1.45 / 0.1.46(arm64,macOS 15 / Darwin 25.6.0)
- Anthropic 登录方式:claude.ai 订阅 OAuth
- 复现频率:当晚 100%(6/6);跨天多时段复现
### 关联
- #2684(xai 会话同一条 one-shot 路径的 400,已定位到字段,PR 已附)
- #2429([1m] 后缀 404,已修)——本 issue 是 anthropic 会话 Auto-review 在该修复之后仍不可用的部分
Contributor guide
Research direction
Start with oneShotCandidates.ts and trace the Anthropic branch into requestProviderHttpText, then inspect the Auto-review retry entry point. Reproduce the 429 path and examine existing handling for non-2xx bodies and Retry-After. Done means the failure exposes a useful redacted cause and the retry behavior no longer rapidly repeats rate-limited requests, with tests covering the chosen behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- ai, backend-api-design
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100