91 lines
5.4 KiB
Markdown
91 lines
5.4 KiB
Markdown
# 排错(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 项离线端到端自检(不花钱、不调模型)
|
||
```
|