From bb089e3f0e690702449a51587c02bfad1c44e6f2 Mon Sep 17 00:00:00 2001 From: yibo Date: Fri, 27 Mar 2026 01:55:26 +0800 Subject: [PATCH] fix: 添加 sendPrompt 120s 空闲超时保护 --- packages/acp-core/protocol/ClaudeCliProtocol.js | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+), 0 deletions(-) diff --git a/packages/acp-core/protocol/ClaudeCliProtocol.js b/packages/acp-core/protocol/ClaudeCliProtocol.js index 256fa5d..ac143f5 100644 --- a/packages/acp-core/protocol/ClaudeCliProtocol.js +++ b/packages/acp-core/protocol/ClaudeCliProtocol.js @@ -85,6 +85,9 @@ class ClaudeCliProtocol extends EventEmitter { const lines = this._buffer.split('\n'); this._buffer = lines.pop() || ''; + // 有 stdout 活动 → 重置超时计时器 + if (this._resetIdleTimer) this._resetIdleTimer(); + for (const line of lines) { if (!line.trim()) continue; try { @@ -182,6 +185,37 @@ class ClaudeCliProtocol extends EventEmitter { this._promptResolve = resolve; this._promptReject = reject; + // 超时保护:如果 120 秒内没有任何 stdout 活动(API hang/rate limit 静默),自动 reject + const IDLE_TIMEOUT_MS = 120_000; + let idleTimer = setTimeout(() => { + if (this._promptReject) { + const err = new Error(`Claude CLI 响应超时 (${IDLE_TIMEOUT_MS / 1000}s 无活动)`); + console.error('[ClaudeCliProtocol]', err.message); + this._promptReject(err); + this._promptResolve = null; + this._promptReject = null; + this._idleTimer = null; + } + }, IDLE_TIMEOUT_MS); + + // 每次收到 stdout 数据时重置超时(说明 CLI 还活着) + this._idleTimer = idleTimer; + this._resetIdleTimer = () => { + if (this._idleTimer) { + clearTimeout(this._idleTimer); + this._idleTimer = setTimeout(() => { + if (this._promptReject) { + const err = new Error(`Claude CLI 响应超时 (${IDLE_TIMEOUT_MS / 1000}s 无活动)`); + console.error('[ClaudeCliProtocol]', err.message); + this._promptReject(err); + this._promptResolve = null; + this._promptReject = null; + this._idleTimer = null; + } + }, IDLE_TIMEOUT_MS); + } + }; + // Claude CLI stream-json 输入格式 const message = { type: 'user', @@ -197,8 +231,10 @@ class ClaudeCliProtocol extends EventEmitter { try { this._child.stdin.write(jsonLine); } catch (e) { + clearTimeout(idleTimer); this._promptResolve = null; this._promptReject = null; + this._idleTimer = null; reject(new Error(`[ClaudeCliProtocol] stdin 写入失败: ${e.message}`)); } }); @@ -260,6 +296,7 @@ class ClaudeCliProtocol extends EventEmitter { }); if (this._promptResolve) { + if (this._idleTimer) { clearTimeout(this._idleTimer); this._idleTimer = null; } this._promptResolve(); this._promptResolve = null; this._promptReject = null; -- libgit2 0.21.4