baa-conductor

git clone 

baa-conductor / plans
im_wower  ·  2026-03-30

WATCHDOG_V2_CONDUCTOR_INTEGRATED.md

  1# Watchdog V2 — Conductor 集成方案
  2
  3> 日期: 2026-03-30
  4> 状态: 方案设计
  5
  6## 问题
  7
  8当前看门狗依赖 Claude 手动设心跳文件状态(working → waiting),Claude 经常忘记,导致续命失效。
  9
 10## 核心洞察
 11
 12Conductor 已拦截每个 AI 的 SSE final-message。收到 final-message = AI 回复结束 = 需要续命。
 13
 14**不需要 Claude 手动设状态,conductor 天然知道。**
 15
 16## 链路
 17
 18```
 19Claude 回复结束
 20  → 浏览器 SSE 流结束
 21  → Firefox 插件拦截 final-message
 22  → WS 发给 conductor
 23  → conductor ingest 处理
 24  → ingest 末尾触发续命 hook
 25  → 延迟 N 秒
 26  → 通过 a11y 给 Safari 对话页发续命消息
 27```
 28
 29## 实现位置
 30
 31`firefox-ws.ts``handleBrowserFinalMessage` 末尾,或 `ingest.ts``ingestAssistantFinalMessage` 末尾。
 32
 33## 配置
 34
 35```typescript
 36interface WatchdogConfig {
 37  enabled: boolean;           // 开关
 38  targetTab: string;          // Safari 标签页全名
 39  platform: string;           // 监控哪个平台,如 "claude"
 40  delayMs: number;            // final-message 后延迟多久(默认 5000ms)
 41  renewalMessage: string;     // 续命消息
 42  cooldownMs: number;         // 冷却期,避免连续续命(默认 30000ms)
 43  conversationId?: string;    // 可选:只监控特定对话
 44}
 45```
 46
 47## 逻辑
 48
 49```typescript
 50let lastRenewalTime = 0;
 51
 52function onFinalMessage(platform: string, conversationId: string) {
 53  if (!config.enabled) return;
 54  if (platform !== config.platform) return;
 55  if (config.conversationId && conversationId !== config.conversationId) return;
 56  const now = Date.now();
 57  if (now - lastRenewalTime < config.cooldownMs) return;
 58  
 59  setTimeout(() => {
 60    exec(`bash tools/watchdog/a11y_msg.sh "${config.targetTab}" "${config.renewalMessage}"`);
 61    lastRenewalTime = Date.now();
 62  }, config.delayMs);
 63}
 64```
 65
 66## 触发条件
 67
 681. watchdog enabled
 692. final-message 来自指定平台
 703. 距上次续命超过冷却期
 714. 可选:匹配 conversationId
 72
 73## 对比
 74
 75| | V1(当前) | V2(本方案) |
 76|---|---|---|
 77| 触发 | 心跳文件 + 定时轮询 | 事件驱动 |
 78| 依赖手动操作 | 是 | 否 |
 79| 延迟 | 最多 60 秒 | 5 秒 |
 80| 进程管理 | launchd 独立进程 | conductor 内置 |
 81| 失败模式 | 忘设状态→永不续命 | SSE 链路通就续命 |
 82| 复杂度 | 心跳+状态机+进度文件 | 一个 hook + setTimeout |
 83
 84## V1 保留为兜底
 85
 86V2 依赖 SSE 链路(插件→WS→conductor),链路断了 V2 不工作。V1 独立于 conductor,作为最后保险。
 87
 88## 实现步骤
 89
 901. conductor-daemon 加 watchdog 配置读取
 912. ingest/firefox-ws 加 final-message hook
 923. hook 调 a11y_msg.sh 或直接 osascript
 934. 加开关端点:POST /v1/watchdog/enable, /disable
 945. 测试验证
 95
 96## 风险
 97
 98- conductor 和 Safari 不在同一台机器时不工作(a11y 是本机操作)
 99- osascript 在 node 子进程可能有 TCC 权限问题
100- final-message 漏掉(SSE 异常中断)→ V1 兜底