Commit ab16b18fdabcf4c5b0ce32a7d2c96eb84ea2ff56

Authored by yibo
1 parent a8ba36d3

fix: 拦截 Claude CLI 最终的错误 报文

核心发现:当底层 API (如 MiniMax) 发生 429 时,Claude CLI 内部会自动开启一段漫长的 exponential backoff 重试逻辑(期间完全静默,耗时可达 3 分钟之久)。
如果最终依然失败,它会抛出一个合法的 JSON 格式的 `type: "result"` 报文,此时 `is_error: true`。

旧版本会将这个 result 报文当做正常的 Agent 文本流式处理,导致把错误输出混进正常消息里。
新版本增加逻辑,在解析到 result 且 is_error 为 true 时,不进行正常 resolve,而是立即 reject Promise 抛给上层,中断一切任务并给前台报红。
packages/acp-core/protocol/ClaudeCliProtocol.js
@@ -298,6 +298,22 @@ class ClaudeCliProtocol extends EventEmitter { @@ -298,6 +298,22 @@ class ClaudeCliProtocol extends EventEmitter {
298 298
299 case 'result': 299 case 'result':
300 this.sessionId = event.session_id || this.sessionId; 300 this.sessionId = event.session_id || this.sessionId;
  301 +
  302 + // 【核心发现】Claude CLI 会在自己内部重试(长达3分钟),最后如果依然失败,
  303 + // 会输出 result 事件,但带有 "is_error": true,并且 result 字段放着错误信息。
  304 + if (event.is_error) {
  305 + if (this._idleTimer) { clearTimeout(this._idleTimer); this._idleTimer = null; }
  306 + const err = new Error(`API 请求失败 (内部重试后放弃): ${event.result || 'Unknown HTTP/RateLimit Error'}`);
  307 + console.error(`[ClaudeCliProtocol] 收到错误 result:`, err.message);
  308 + if (this._promptReject) {
  309 + this._promptReject(err);
  310 + this._promptResolve = null;
  311 + this._promptReject = null;
  312 + }
  313 + // 不要再发送正常 result notification
  314 + break;
  315 + }
  316 +
301 this.emit('acp_event', { 317 this.emit('acp_event', {
302 type: 'notification', 318 type: 'notification',
303 method: 'session/result', 319 method: 'session/result',