☰
opencode 我们为什么删除了看门狗机制
2026/10/10 11:00:53 网站建设 项目流程

opencode 我们为什么删除了看门狗机制

本文基于 opencode-goal 插件(开源,SDK 1.18)真实实现编写。主题:旧版独立 watchdog 定时器的删除理由,以及卡死救护如何内聚进 TICK 门链。

1. 旧架构

旧版存在两套后台定时器:

  • TICK(1 秒):驱动自动续推;
  • 独立 watchdog(按配置时限):自动中止卡死的子代理。

watchdog 的删除(2026-08-29 TICK 重构)不是能力削减,而是职责重分配:卡死救护仍存在,但决策移入 TICK 内部。

2. 删除理由

2.1 多驱动路径 = 多故障源

watchdog 的 abort 是独立于 TICK 的派发路径。会话存在两条驱动路径(TICK 续推 + watchdog 中止)时,日志、竞态、错误处理全部翻倍。单一驱动器原则下,任何"自动"动作都应当由同一个循环决策。

2.2 计时与事实脱节

watchdog 按自身计时器计数,而会话活动由事件刷新。两者不同步时,"看似卡死、实则刚活动过"的会话会被误中止。误杀子代理的代价(上下文丢失)远高于等待。

2.3 定时器生命周期

watchdog 需要按会话启动/重置/取消,并与压缩、重启门、中止判定交错。多定时器时序难以穷举验证,边界 bug 集中于此。

2.4 与既有原则冲突

系统原则为"事件只记录状态,TICK 才做决策"。watchdog 是事件/时间驱动的兜底,违背该原则,保留即持续引入复杂度。

3. 替代设计:卡死救护内聚 TICK

删除 watchdog 后,救护逻辑成为drive_session门链的一环:

快照显示 busy/retry? → session_busy_since 记录首次出现时刻(单调 TICK 时钟) → 超过 STUCK_RESCUE_STALL_MS(默认 90 秒,env GOAL_STUCK_STALL_MS) 且期间无任何事件(逐事件刷新窗口) 且无进行中工具(tool_inflight 非空则豁免) → session.abort 一次解除卡死;每会话每停滞窗口至多一次 → 否则跳过

关键性质:

  • 判定基于权威快照 + 事件印记,而非独立计数器(无脱节);
  • 单一时钟、单一循环、单一状态源;
  • 工具豁免:长工具调用(如 5 分钟 bash)期间不误杀;
  • 合法长生成持续产生part.updated事件,自动续刷窗口,不会触发。

3.1 救护指纹归属

救护 abort 产生的错误与用户 ESC 同为MessageAbortedError/"Aborted"。救护发起时记录时间戳;指纹 5 秒窗口内到达归因救护、不暂停目标。完整判定链见《opencode 用户操作中断取消判定》。

3.2 子代理边界

  • 主会话卡死:TICK 自动 abort;
  • 子代理:不设自动中止(自动杀子代理的进度损失风险大于收益),由 TUI 伴侣插件提供手动入口(命令面板 → Poke session → Abort)。

4. 收益与边界

维度删除前删除后
驱动路径TICK + watchdog单一 TICK
卡死判定依据独立计时器(可与事实脱节)权威快照 + 事件窗口
定时器多套交错一套,dispose 一次清理
子代理救护定时自动中止仅手动(TUI)

边界:若会话在 90 秒内不产生事件且无进行中工具,会被视为停滞(合法静默场景罕见,且每停滞窗口仅 abort 一次,不无限重试)。指纹归因窗口 5 秒,救护 abort 事件本地即时到达,窗口内可收。

约束要点:任何自动动作(续推、压缩、救护中止)都必须由单一循环决策,禁止为单个动作引入独立定时器或事件触发路径;卡死判定必须以权威快照与事件窗口为据,禁止以独立计数器代替。

5. 验证

  • goal-noprogress-test.mjs/goal-user-abort-test.mjs:停滞救护与指纹归属;
  • goal-fault-injection-test.mjs:SDK 挂起/重放注入后救护触发且目标不暂停;
  • goal-regression-gates-test.mjs(13 断言):门链回归。

6. 结论

删除 watchdoog 的实质:救护不是"TICK 之外的另一个看守",而是"TICK 自己决策该救什么"。单一驱动循环 + 权威状态 + 确定性门序,使卡死处理成为可验证的一环,而非散布的补丁。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询