Initial commit: 让多个 AI 智能体通过文件总线在共享聊天室里互相 @、协作与交接任务

This commit is contained in:
WpyQwq
2026-09-19 11:52:42 +08:00
commit 103f0b32f5
28 changed files with 5834 additions and 0 deletions
+90
View File
@@ -0,0 +1,90 @@
# 排错(troubleshooting)
下面每一条都是 2026-09-18 在**本机真实撞到过**的,不是设想。
## 一、唤醒失败类
### 无头 DSH 说"我写不了房间",只能口头转述
DSH 无头会话的沙箱由 **`DSH_PERMISSION_MODE`** 决定,默认 `workspace-write` 且工作区 = cwd;
总线在 `~/.ai-groups`(工作区之外),于是它发不了言、推不动游标。
`aig` 已给 dsh 通道默认注入 `DSH_PERMISSION_MODE=danger-full-access`;想收紧就
`AIGROUP_DSH_PERMISSION_MODE=workspace-write`(但要接受它写不了房间),或把总线放进工作区。
### 回复被截断成半句 / 混进模型内心独白
不要抓 CLI 的渲染流:opencode 的横幅走 stderr、答复走 stdout 渲染流,模型的"思考"也可能混进 stdout。
`aig` 现在让 opencode 用 `--format json`、让 cbc 用 `--output-format json`,只取最终答复。
真要查原始两路输出:`AIGROUP_DEBUG_RAW=<目录> node aig.mjs wake <成员>`,会把 stdout / stderr / 完整 argv 落盘。
### `EPERM: operation not permitted, mkdir '...\.codebuddy\local_storage'`
WorkBuddy 的 CodeBuddy CLI 要写 `~/.codebuddy/`,被宿主沙箱挡住了(DSH 的 workspace-write 只放行工作区)。
→ 让跑 `aig` 的那个进程有 `~/.codebuddy/` 写权限;或在 WorkBuddy 里跑(它自己的沙箱允许自己的目录)。
### `Error: EPERM ... unlink '...\dsh-home\profiles\node_modules\@deepseek-ai\dsh'`
`dsh --profile headless` 启动时会「修复」自己 profile 目录里的符号链接,需要写 `$DSH_HOME`。
→ 同样是要写权限;headless 一旦跑起来就不需要再动它。
### `Unknown: FileSystem.open (...\.local\share\opencode\log\opencode.log)`
opencode 起手就写日志,日志目录不可写时会直接报这个(连 `opencode models` 都会挂)。
→ 放行 `~/.local/share/opencode/`。
### `curl: (35) schannel: AcquireCredentialsHandle failed: SEC_E_NO_CREDENTIALS`
沙箱里 curl 走 schannel 拿不到凭据。**不是网络问题**:同一时刻 Node 的 `fetch` 是通的。
→ 体检网络用 `node -e "await (await fetch(url)).text()"`,别用 curl。
### 醒来后回了句「没有未读消息,不需要唤醒」(exit 0)
不是 bug:`wake` 只把**该成员的未读**交给它。自己发的消息对自己不算未读,
所以「dsh 发了广播再 `wake dsh`」本来就无事可做。要让某成员有未读,得由**别人**发。
### `AIGROUP_NO_WAKE=1` 卡住
被唤醒的 agent 环境里带着这个变量(防止互相唤醒死循环)。手动在同一个 shell 里接着跑 `wake` 会被拒(exit 5)。
→ 新开 shell,或显式 `--force-wake`。
### `This model is not available in your country.`
opencode Zen 的部分免费档(实测 `muse-spark-1.2/1.3-contributor-free`)有地域限制。
→ 换 `opencode models` 里能实测跑通的免费档。
## 二、命令组装类
### 为什么不直接 `spawn('dsh', ...)` 或 `spawn('opencode', ...)`
Windows 上这两条在 PATH 里是 `.cmd`/`.ps1` 垫片,Node 出于安全限制**不能无 shell 直接 spawn `.cmd`**;
一旦加 shell,提示词里的中文、引号、换行就会进入 cmd 的转义地狱。
→ 所以 `aig` 一律解析成**真 EXE 或用 `node <entry.js>`**,并且把提示词作为**单个 argv** 传,从不拼命令行字符串。
### 提示词长度
Windows 命令行上限约 32k 字符,`aig` 另外把提示词截到 6000 字符(保留最新消息)。
历史很长时,让成员自己用 `read --all --limit 30` 去读,而不是把历史全塞进提示词。
### 提示词里的换行会不会坏掉
不会:提示词是 argv 的一个元素,Node 会正确加引号;opencode / cbc / node 收到的就是原样的多行字符串。
## 三、总线语义类
### `read --all` 会推进游标
这是**故意的**(表示「我已经看过房间」),但用它做「只是看看」会吃掉未读。
→ 只读用 `read --peek`,或 `tail` / `history`(这两个不动游标)。
### 消息丢了 / 房间卡住
- 先看 `rooms/<room>/messages.jsonl` 是否真有那行(`tail` 也能看)。
- 锁残留:`rooms/<room>/.lock` 目录存在且超过 20s 会被自动清掉;8s 拿不到锁会报
`等待房间锁超时`。确认没有卡死的 `node aig.mjs` 进程后再重试。
- 坏行不会阻塞:解析失败的行会被跳过(宁可少一条也不整屋读不出来)。
### 找不到房间
`aig` 的默认房间解析顺序:`--room` → `AIGROUP_ROOM` → `~/.ai-groups/current-room` → `main`。
`AIGROUP_HOME` 不同会看到完全不同的世界,先 `aig rooms` 确认。
## 四、WorkBuddy 侧沙箱
WorkBuddy 的 agent 跑在自己的沙箱里,`~/.ai-groups/` 可能不在白名单里。
`install.mjs` 会(带备份地)往 `~/.workbuddy/settings.json` 的 `sandbox.extraAllowWrite` 里加一条 `~/.ai-groups/`,
跳过这一步用 `--no-wb-settings`。改回去只需要把那一行删掉,或恢复 `settings.json.bak-*`。
## 五、快速体检
```bash
node aig.mjs detect --json # 我是谁(环境变量 / 宿主标记 / 进程链)
node aig.mjs doctor # 房间可写?三个成员的通道在哪?装到哪了?
node aig.mjs members # 谁在线、游标到哪、能不能唤醒
node aig.mjs wake opencode --dry-run # 看将发送的确切命令与提示词,不真调用
node scripts/selfcheck.mjs # 44 项离线端到端自检(不花钱、不调模型)
```