fix: 工具执行期间不再误判 idle 超时,长工具不被误杀#264
Conversation
|
Claude finished @lishuceo's task in 4m 17s —— View job Code Review — idle timeout 误杀长工具修复Verdict: ✅ Approved — clean, well-scoped fix with solid test coverage.
AssessmentThe root-cause analysis is correct: the sliding idle window only resets on SDK messages, and a single in-flight tool (foreground Bash up to 600s, big-repo clone, compile) emits nothing while running — so the idle timer fired mid-execution and aborted a healthy agent. Reusing the existing The implementation holds up under the cases I traced:
Minor, non-blocking observations (confidence < 75 — no action required)
Both are negligible; nothing here blocks merge. The fix matches CLAUDE.md conventions (ESM, pure-function-for-testability, feat+test pairing) and the test additions are appropriate.
|
idle 计时器本意是捕捉"模型/API 停止产出且无工具在跑"的真·卡死,但单条 工具调用(如最长可达 600s 的前台 Bash、克隆大仓、长编译)执行期间不会有 任何 SDK 消息到达,会被误判为空闲而 abort——线上表现为 "Query idle timeout ... (total elapsed 701s)",导致跑批等长任务中断。 改动:利用已有的 pendingToolCalls(tool_use 入、tool_result 出)作为 "工具是否在执行中"的信号。idle 计时器触发时若仍有工具在执行且未超过工具 硬顶(CLAUDE_TOOL_TIMEOUT,默认 900s,高于 SDK 单条 Bash 上限 600s), 则延展计时而非 abort;超过硬顶才判定工具挂死并以独立错误信息 abort。 模型空闲(无工具在跑)路径行为不变。 - 新增 config.claude.toolTimeoutSeconds(env CLAUDE_TOOL_TIMEOUT,默认 900) - 新增 ExecuteInput.toolTimeoutSeconds 覆盖项 - 抽出纯函数 shouldExtendIdleTimer 承载延展/abort 判定,便于单测 - 区分 toolStuck 与 idle 两类超时错误信息 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- shouldExtendIdleTimer 纯函数单测(in-flight/空闲/超硬顶/并发工具) - executor 集成测试(假计时器):工具执行中延展不被误杀、超硬顶才 abort; 无工具在执行时仍按 idle 窗口 abort,两类错误信息可区分 - config 解析 CLAUDE_TOOL_TIMEOUT - 补充两处 executor 测试 config mock 的 toolTimeoutSeconds 字段 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
bab8f97 to
5d961aa
Compare
|
Claude finished @lishuceo's task in 2m 36s —— View job Code Review — idle timeout 误杀长工具修复Verdict: ✅ Approved — correct root-cause fix, well-scoped, properly tested. No new issues found on this synchronize.
AssessmentThe diagnosis holds: the sliding idle window only resets on SDK messages, and a single in-flight tool (foreground Bash up to 600s, big-repo clone, compile) emits nothing while running — so the idle timer fired mid-execution and killed a healthy agent. Reusing the existing Traced the lifecycle end-to-end and it's sound:
Tests are appropriate: pure-function unit cases (in-flight / idle / over-cap / concurrent), fake-timer integration covering both the extend-then-cap-abort path and the model-idle abort path, plus the Minor, non-blocking (no action required)
Nothing here blocks merge.
|
背景
线上反复出现
Query idle timeout after 600s with no activity (total elapsed: 701s),在跑批 / 长编译 / 克隆大仓等场景中断 agent。根因
executor.ts的滑动窗口 idle 计时器每收到一条 SDK 消息(或canUseTool)就重置,本意是捕捉「模型/API 停止产出」的真·卡死。但单条工具调用执行期间不会有任何 SDK 消息到达:canUseTool批准 → 重置计时器即:idle 计时器在「工具正常执行中」误判为「卡死」。
改动
利用已有的
pendingToolCallsMap(tool_use入、tool_result出)作为「工具是否在执行中」的信号:CLAUDE_TOOL_TIMEOUT,默认 900s,高于 SDK 单条 Bash 上限 600s),延展计时而非 abort;判定逻辑抽成纯函数
shouldExtendIdleTimer,便于单测。新增配置
config.claude.toolTimeoutSeconds(envCLAUDE_TOOL_TIMEOUT,默认 900)ExecuteInput.toolTimeoutSeconds覆盖项测试
shouldExtendIdleTimer纯函数单测:in-flight / 空闲 / 超硬顶 / 并发工具tool execution timeoutidle timeout(两类错误信息可区分)CLAUDE_TOOL_TIMEOUTnpm run typecheck通过;相关测试全绿。全量回归仅memory/quality.test.ts一条 embedding 检索质量断言失败,经git stash验证在改动前的干净树上同样失败,与本 PR 无关。关于自重启
本改动落在服务源码,合并后部署目录需
git pull+npm install+ build + 重启才生效。本 PR 不自动重启。🤖 Generated with Claude Code