- 变更规模:新增 514 / 修改 62 / 重命名 155 / 删除 4(归档重组与文档轮次) - .gitignore 修:`归档/**/db-cwd归一-备份-*/` —— 原规则写绝对层级(归档/db-cwd归一-…), 目录搬进 归档/配置与备份/ 后**静默失效**,43 MB 的 DB 备份又变成未跟踪 - .gitignore 补:嵌套 git 内部数据(归档/内嵌git-20261008/、归档/skills-git-旧线-20261007/dotgit-原样移出/) - .gitignore 补:运行态与部署副本(.workbuddy/collab/、.workbuddy/tools/、.workbuddy/.load-pending、.workbuddy/tmp-*) - .gitignore 补:备份件(*.bak-*) - 未跟踪文件从 2190 降到 890(其余为 归档/ 归档件与 .workbuddy/memory/ 知识文件,按口径入库)
4.2 KiB
4.2 KiB
「活会话」是什么 · 怎么往任意会话发消息
2026-09-29 · 工作区
E:/ProgramData/AIProject/ai1net-dsh-server· 结论全部来自源码实读 + 真机实测
一、「活会话」到底是什么
它不是"正在运行的会话",而是「桌面当前打开的那一个会话」。
源码依据(WorkBuddy 网关 resolveLiveSessionFollow() / replySession()):
// 活会话 = 网关进程内存里的这个
let L = this.sessionManager.sessionSubject.value;
if (!L) return { sessionId: null, writerOccupied: false };
GET /api/v1/sessions/live返回的sessionId就是它;为null= 桌面当前没打开任何会话。writerOccupied= 这个会话是否正被某个客户端持有写权(ACP 连接 / 桌面正在跑)。
为什么 reply 只认它? 上游给 reply 的定位就是"向当前活会话投递回复(不占用 ACP writer)" ——
即"手机跟随桌面正在聊的那一个",而不是"手机遥控任意会话"。所以:
| 目标 | POST /sessions/{id}/reply |
|---|---|
| 就是当前活会话 | ✅ 200 {"delivered":true} |
| 别的会话 | ❌ 409 SESSION_FOLLOW_NOT_LIVE |
二、怎么"往任意会话发消息"(已实现并实测通过)
用 ACP 借用:把一个会话切成活会话,发完再还回去。
connect → initialize
→ session/load {sessionId, cwd, mcpServers: []} ← 把目标切成活会话
→ session/prompt {sessionId, prompt:[{type:"text",text}]}
→ (可选)session/load 回原活会话 ← 归还
实测结果(对非活会话 b419f820-… 发一条):
| 步骤 | 结果 |
|---|---|
session/load |
200,回放 404 事件,且 GET /sessions/live 切到了目标 ✅ |
session/prompt |
agent 真回复(agent_message_chunk 348 个)✅ |
目标会话 replay |
出现 user_message_chunk,文本逐字一致 ✅ |
🔴 三条硬约束(⛔ 别踩)
session/load/session/new必须带cwd与mcpServers—— 缺则-32602 Invalid params。cwd取自GET /api/v1/info(⚠️ 作用域列表/api/v1/sessions不返回cwd)。- 目标会话若已被外部 writer 占用 ⇒ 无法借用:
-32000 "Persistent Session already has an external writer" {reason:"writer_occupied"}⇒ 正被桌面打开/正在跑的会话,外部接管不了;空闲会话可以。 这正是「当前对话的主权在桌面」的体现。 - 只有与网关口同工作目录的会话可达。跨项目会话连
history/replay都 404SESSION_NOT_FOUND。 (本机实测:同目录 5 条可达;跨项目 19 条不可达。)
副作用(必须知道)
session/load 会把桌面的"当前对话"切到目标会话。所以实现里默认借用完归还;
但归还也可能失败(原活会话若被 writer 占用)—— 这时在桌面上点一下你要用的会话即可归位。
三、现在手机上的行为
| 你点的那条会话 | 手机发消息时 |
|---|---|
| 带绿色「活会话」标 | 走官方 reply —— 不切换桌面,立即投递 |
| 其他(同项目) | 借用方式:短暂切桌面当前会话 → 发送 → 归还 |
| 标灰「不在当前项目」 | ⛔ 不可发(网关读不到它) |
页面「发送」已统一改走桥的 POST /__bridge/send {sessionId, text},
它在内部自动选路(活会话→reply;否则→ACP 借用),默认异步(立刻返回,agent 回复稍后同步)。
四、⛔ 已知的运维限制(本轮踩到的)
沙箱会杀掉跑太久的前台命令,并连带杀掉桥。
实测 >45100 秒的前台命令会被终止,桥(后台任务)随之死掉 ⇒ 手机突然打不开。
⇒ 对策:命令切短步、长任务走异步;桥需要"现场重开"(我这边一条命令即可重启,口令自动取自进程环境)。
⚠️ 你自己开的 cmd 窗口拿不到口令(口令在 WorkBuddy 进程环境里),所以现在只能由我从 WorkBuddy 里拉起桥。
长期方案 = 把桥做成 WorkBuddy 侧常驻组件(即 棒 1)。