baa-conductor

git clone 

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