Files
2026Technology-Competition/docs/superpowers/specs/2026-08-29-ai-retry-design.md
T
范智鹏 d6b8a3c897 feat: AI 调用稳定性增强(可重试错误分类 + 指数退避 + 修复链路错误透传)
- providers/base.ts 引入 ApiRequestError 与 isRetryableError,按 429/5xx/超时/网络错误/401 分类
- chatWithRetry 升级为最多 3 次指数退避(1s/2s/4s),非重试错误立即上抛;新增 setRetryBaseDelayForTest 钩子
- aiFixEngine/customFixEngine 不再吞错,修复失败原因透传为 ai-error: <原因>
- 扩展 ai-empty-response/customFixEngine 测试覆盖重试与分类
2026-08-31 21:57:54 +08:00

2.8 KiB
Raw Blame History

AI 调用稳定性增强(重试 + 统一兜底)设计

日期:2026-08-29 状态:已批准(Stage ④ 通过)

背景与目标

评审报告「稳定性与易用性 12/15」指出:缺少显式重试机制;未见对 AI 调用异常的统一兜底。现状核实:

  • chatWithRetrysrc/ai/engine.ts)仅对 EmptyContentError 重试 1 次,网络错误/超时/429/5xx 均直接上抛
  • requestFixsrc/fix/aiFixEngine.tscatch 后静默返回 null,用户看不到 AI 失败原因
  • engine 主入口已有 degraded + error 兜底结构(Promise.allSettled + i18n 错误聚合),无需改动
  • 多 AI 供应商切换已被评审认可为降级策略,无需改动

方案

1. 错误分类(src/ai/providers/base.ts

新增 ApiRequestError(携带 HTTP status+ isRetryableError()

错误 可重试
EmptyContentError
HTTP 429 / 5xx
超时(AbortError / DOMException name==='AbortError'
网络错误(TypeError
401、其他 4xx、JSON 解析错 否,立即失败

2. provider 统一结构化抛错

openai-compatible.ts / gemini.ts / claude.ts:非 2xx 响应抛 ApiRequestError(携带 status 与响应文本)。401 保留现有 i18n 消息语义,同样结构化、不可重试。

3. chatWithRetry 增强(src/ai/engine.ts

固定策略:最多 3 次重试、指数退避 1s/2s/4s、按分类决定重试或立即上抛。所有调用入口(engine 三入口 + fix 链路)自动受益。

4. fix 链路兜底透传(src/fix/aiFixEngine.ts

requestFix 不再吞错,将最终错误消息透传到 FixResult.message,复用 commands.ts 现有 t('fix.aiFailed') 通知管道。

5. 单元测试

扩展既有 tests/ai-empty-response.test.tschatWithRetry 测试的既有归属,避免新建文件):mock provider 抛可重试/不可重试错误,验证重试次数、退避行为、立即失败路径、isRetryableError 分类。tests/customFixEngine.test.ts 一处测试名随行为语义更新。

实现修订(编码期同步)

  • src/fix/customFixEngine.ts 存在与 aiFixEngine 相同的吞错模式(同一评审批评点),按同一模式修复:requestFix 不再吞错,aiFixReviewIssue 调用处 catch 后透传 ai-error: <原因>FixResult.message
  • 引擎内部导出 setRetryBaseDelayForTest 测试钩子,避免测试真实等待 1s/2s/4s 退避

验证链

npm run lintnpm run compilenpm test

涉及文件

  • src/ai/providers/base.ts
  • src/ai/providers/openai-compatible.ts
  • src/ai/providers/gemini.ts
  • src/ai/providers/claude.ts
  • src/ai/engine.ts
  • src/fix/aiFixEngine.ts
  • src/fix/customFixEngine.ts
  • tests/ai-empty-response.test.ts
  • tests/customFixEngine.test.ts