P3 — 三端同步(补全)+ P1/P2 上三端#
调研后修正:三端同步的地基比预想完整得多,真空很窄。
已有(不用做)#
| 能力 | 现状 | file:line |
|---|---|---|
| 单 worker + 共享 git SessionDB | 三端连同一 worker、读同一真值 | worker/lock.py, agent/session_db.py |
| running 状态位 | _running_tasks 注册表 + running_task/running_task_clear 广播(驱动 sidebar 呼吸灯 + composer 状态) |
webui/server.py:187-224 |
| 重连补历史 | handle_sync(session_id, known_seqs) 把缺的消息帧补发 |
ws_actions/runtime.py:436-450 |
| 事件广播 | EventBus + _broadcast,一处 emit 所有 WS 客户端收到 | events/bus.py, server.py _broadcast |
→ 一端发起的 turn,其它端本来就收到同样的 stream 事件;重连本来就补历史 + running 灯。所以"一端做了另一端看不到"在 webui/TUI(都走 worker WS)路径上基本不成立。
真空(P3 要做)#
G1 — 重连不补 running_task 状态#
handle_sync 只补消息帧,不补当前 running_task 指示。新连/重连的客户端要等下一次 _emit_running_task_event 才看到"正在跑"。
修:handle_sync 末尾对该 session 调一次 _emit_running_task_event(或直接给这个 ws 发当前 running_task 快照)。一行级改动。
G2 — P1 值守开关上三端(WS action + 会话状态)#
attended 现在是进程级标志(CLI 用)。要让 TUI/web 也能切,需:
- WS action
{action:"set_attended", session_id, attended: bool}→ 调attended.set_attended+ 广播一个attended_changed状态帧,三端同步显示当前模式。 - 注意:attended 现在是进程全局,不是 per-session。webui 单 worker 多 session 时,全局开关会互相影响。决策:P3 把 attended 改成会话级(dict[session_id]→bool),CLI 那条传自己的 session。
- 前端:TUI 一个 toggle 键 + 状态显示;web 一个 toggle 按钮。
G3 — P2 steer 上三端(WS action)#
steer 现在只有 CLI 子命令(写文件收件箱)。加:
- WS action
{action:"steer", session_id, message}→steering.push(session_id, message)(已是文件收件箱,worker 写、跑着的进程读)+ 广播一个回执帧。 - 子进程场景:research_agent 在子进程跑,文件收件箱用的是同一个 session_dir,子进程读得到 —— 无需额外 IPC(文件天然跨进程)。这点比预想简单。
- 前端:TUI/web 一个"发送干预指令"输入框(任务跑着时可用)。
顺序#
G1(一行)→ G2(attended 改会话级 + WS action + 前端 toggle)→ G3(steer WS action + 前端输入框)。
待拍板#
- attended 改 per-session:确认要(单 worker 多 session 时全局开关会串)。默认仍 unattended。
- 前端改动:TUI(Ink, cli/src)+ web(web/)两套前端都要加 toggle/输入框。工作量主要在这。先做后端 WS action(三端共享、可测),前端 UI 随后。
Last updated · 2026-08-13