# bk02 · DSH × OpenClaw ACP 集成说明 > **用途**:本机 DeepSeek Harness(dsh)的部署与「OpenClaw → DSH」ACP 协同链路的完整说明。新会话/新人接手读本文件即可,无需历史对话。 > **配套**:`bk02-openclaw-系统说明.md`(OpenClaw 本体)、`openclaw-升级与维护.md` > **主机**:bk02 / `xuan-asus-nj` · Debian 12 bookworm · 首次落地 2026-09-16 > > ⚠️ 本目录**不含明文口令**,凭据位置见 §8。 --- ## 0. 30 秒速览 | 项 | 值 | |---|---| | DSH 版本 | `@deepseek-ai/dsh` **0.1.5-rc.1**(nvm Node **v26.8.2**,全局安装) | | DSH ACP 入口 | `dsh --profile acp` —— 官方 `@deepseek-ai/dsh-acp` 的 **ACP v1 stdio server** | | DSH Web 服务 | `dsh-web.service`(**用户级** systemd),监听 `127.0.0.1:18787` | | Web 访问入口 | **`https://bk02.baiji-algieba.ts.net:18787/?token=<启动时打印>`**(tailscale serve,仅 tailnet 内可达) | | OpenClaw 侧 | `@openclaw/acpx` 插件 2026.9.4,harness 别名 **`dsh`**,已注册为 OpenClaw agent `dsh` | | 链路 | **微信/飞书 → OpenClaw agent → `sessions_spawn(runtime:"acp", agentId:"dsh")` → `dsh --profile acp` → 干活 → 结果回传** | | DSH 状态目录 | `~/.dsh`(profiles/ sessions/ .env / AGENTS.md) | | 已装插件 | web profile:`skillhub-plugin` 0.2.16 + `superpowers-dsh` 0.1.1;**acp profile:仅 `superpowers-dsh`**(skillhub 的启动自检会往 stdout 打印,污染 ACP 协议流,见 §3.1) | | 全局指令 | `~/.dsh/AGENTS.md` —— 交互与思考一律中文,所有 profile / 所有会话生效 | **最常用的四条命令**: ```bash export PATH=$HOME/.nvm/versions/node/v26.8.2/bin:$PATH # 每次登录先做 systemctl --user status dsh-web # DSH Web 状态 journalctl --user -u dsh-web -f # DSH Web 日志(含带 token 的访问 URL) journalctl --user -u openclaw-gateway -f # OpenClaw 网关日志(ACP spawn 记录在这里) node ~/.openclaw/docs/dsh-acp-smoke.mjs # DSH ACP 独立冒烟(不经过 OpenClaw) ``` --- ## 1. 架构与职责边界 ``` 微信 / 飞书 / 其他渠道 │ ▼ ┌──────────────────────────────┐ │ OpenClaw Gateway (18789) │ ← 渠道接入、路由、会话、结果投递 │ @openclaw/acpx 插件 │ ← ACP 客户端侧(acpx 0.13.2 内嵌) └──────────────────────────────┘ │ ACP v1 over stdio(JSON-RPC) ▼ ┌──────────────────────────────┐ │ dsh --profile acp │ ← 每会话一个子进程;ACP server 侧 │ @deepseek-ai/dsh-acp │ 模型 deepseek-official / deepseek-v4-flash │ dsh-base(工具/沙箱/持久化) │ 权限 preset workspace-write └──────────────────────────────┘ │ ▼ 真实干活:读写文件、跑命令、再回传 ``` 职责分工(官方定位): - **OpenClaw 拥有**:渠道、路由、后台任务状态、投递、绑定、策略。 - **DSH 拥有**:provider 登录、模型目录、文件系统行为、原生工具、会话持久化。 > 关键认知:**ACP 是 stdio 直连,不需要任何网络暴露**。DSH Web(18787)是给人用的浏览器界面,与 ACP 链路彼此独立。 --- ## 2. 为什么不是「把 DSH 装成一个别的 ACP 工具」 DSH 自带官方 ACP 服务端,无需自研桥接: - npm 包 `@deepseek-ai/dsh-acp`:`Automation-only Agent Client Protocol server for driving DeepSeek Harness agents over JSON-RPC stdio`。 - dsh ≥0.1.5 内置 `acp` profile 模板(bundles = `@deepseek-ai/dsh-base` + `@deepseek-ai/dsh-acp-app`),`dsh --profile acp` 开箱即用。 - 默认组合已配好 `provider: deepseek-official` / `model: deepseek-v4-flash`。 - ACP 能力:`initialize / session/new / session/list / session/resume / session/close / session/prompt / session/cancel / session/set_config_option`、`session/update` 语义流、`session/request_permission` 权限询问、stdio 与 HTTP MCP。 - 明确不支持(写代码时别指望):`session/load`、删除、fork、附加目录、SSE MCP、计划/终端/客户端文件系统操作、elicitation。 --- ## 3. DSH 侧安装(可复现步骤) ```bash # 1) 用 nvm 的 Node(系统 /usr/bin/node 是 22.x,不用) export PATH=$HOME/.nvm/versions/node/v26.8.2/bin:$PATH # 2) 全局安装 dsh(必须显式放行 install scripts,否则 node-pty / spawn helper 不生成) npm i -g --allow-scripts=@deepseek-ai/dsh-subprocess-local,koffi,node-pty,@google/genai,protobufjs \ @deepseek-ai/dsh@0.1.5-rc.1 # 3) 初始化 ACP profile(首次执行自动创建 ~/.dsh/profiles/acp) dsh --profile acp --help # 4) 写入模型凭据(600 权限;凭据来源优先级见 §8) printf 'DEEPSEEK_API_KEY=<见 §8>\n' > ~/.dsh/.env && chmod 600 ~/.dsh/.env # 5) 独立冒烟:不经过 OpenClaw,直接与 dsh 的 ACP server 对话 node ~/.openclaw/docs/dsh-acp-smoke.mjs ``` `~/.dsh/profiles/acp/` 由 CLI 自动生成,**不要手改**(除非要换模型): ```json { "dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-acp-app"], "patchReload": "startup" } } } ``` 要改模型/provider,在 `~/.dsh/profiles/acp/cordis.patch.yml` 里按 id 覆盖 `acp` 行: ```yaml - id: acp config: provider: deepseek-official model: deepseek-v4-pro # 默认是 deepseek-v4-flash ``` ### 3.1 插件与全局中文指令(2026-09-16 追加) **前置:`dsh plugin` 是 pnpm 的转发器,先装 pnpm**(本机原先没有): ```bash export PATH=$HOME/.nvm/versions/node/v26.8.2/bin:$PATH npm i -g pnpm # → pnpm 12.4.2,落在 ~/.nvm/versions/node/v26.8.2/bin/pnpm ``` **装插件**(插件是否属于某个 profile,取决于 `dsh --profile `,所以要分别装): ```bash # Web 界面用的 profile:两个都装(HTTP 传输,不受 stdout 约束) dsh plugin --profile web add skillhub-plugin superpowers-dsh # ACP 自动化 profile:只装 superpowers-dsh —— 详见下方「stdout 纪律」 dsh plugin --profile acp add superpowers-dsh ``` 装完 profile 的 `package.json` 会自动登记(`dsh plugin` 会按已装状态 reconcile 层列表): ```json { "dependencies": { "skillhub-plugin": "^0.2.16", "superpowers-dsh": "^0.1.1" }, "dsh": { "profile": { "bundles": ["@deepseek-ai/dsh-base", "@deepseek-ai/dsh-web-app", "skillhub-plugin", "superpowers-dsh"] } } } ``` 校验(不需要起服务): ```bash dsh --profile web --dump-config | grep -iE "skillhub|superpowers" ``` #### ⚠️ stdout 纪律:`skillhub-plugin` 不能装进 acp profile `skillhub-plugin` 0.2.16 在插件加载时跑一个 fire-and-forget 启动自检,**用 `console.log` 往 stdout 打印**: ``` [skillhub] self-check ok: 插件分页两页零重复(5+5 条, total=2714) ``` 而 ACP 的 stdout **只允许承载协议流量**(`dsh-acp` 文档原话:*Stdout carries only protocol traffic, so keep logging off it*)。该行会被 ACP 客户端当成非法 JSON 帧。实测:装进 acp profile 后,ACP 冒烟脚本每轮都会捕获到这条非 JSON 输出(脚本用宽容解析才没崩,acpx 的行为不作保证);从 acp profile 移除后立即干净: ```bash dsh plugin --profile acp remove skillhub-plugin node ~/.openclaw/docs/dsh-acp-smoke.mjs # 输出里不应再出现「非 JSON 的 stdout 输出」 ``` 该输出硬编码在 `lib/host.js` 的 `selfCheckPluginPaging()` 里(同函数另外两处用 `console.error` → stderr,无害),**没有配置开关**。若将来非要在 ACP 侧用技能市场,需要给该行打补丁改走 stderr,而不是直接安装。 #### 全局中文指令(交互 + 思考) `~/.dsh/AGENTS.md`(DSH_HOME 级,**所有 profile、所有会话生效**;权限 600): ```markdown # 用户全局指令(User-Global Instructions) 以下约定适用于所有 DSH 会话、所有项目目录,作为全局行为准则,优先于工具描述中的一般性提示: ## 语言 - 交互:与用户的所有交流(回复、提问、澄清、说明)一律使用中文。 - 思考:内部推理与思考过程也一律使用中文。 ``` 与 wit01 上 `~/.dsh/AGENTS.md` 内容一致。验证方式(脚本 `dsh-lang-check.mjs`,走 ACP 提问,故意用英文): | 提问 | DSH 回复 | 判定 | |---|---|---| | `Answer in ONE short sentence, English only: what is 2+2?` | `2 + 2 = 4.` | 用户显式指定 English → 遵从用户(预期行为) | | `Reply with a single short sentence: name one benefit of unit tests.` | `单元测试能在改动代码时快速发现回归缺陷。` | ✅ 未指定语言时输出中文,**指令生效** | > 判定中文指令是否生效,要用**未指定语言**的英文提问;像第一行那样显式要求 English only 时,模型服从当次用户指令是正确行为,不算指令失效。 --- ## 4. OpenClaw 侧配置(4 处,缺一不可) 配置全部落在 `~/.openclaw/openclaw.json`(用 `openclaw config patch` 写入,勿手改 JSON 后不校验)。 ### 4.1 插件清单必须放行 `acpx` `plugins.allow` 是**限制性白名单**,不在里面 = 插件被阻止加载(`/acp doctor` 会报缺失 allowlist 项): ```json5 "plugins": { "allow": ["deepseek","memory-core","ollama","searxng","openclaw-weixin", "dingtalk-connector","openclaw-lark","feishu", "acpx"] } ``` ### 4.2 acpx 插件里注册 DSH harness ```json5 "plugins": { "entries": { "acpx": { "enabled": true, "config": { "permissionMode": "approve-all", // 非交互会话必需,否则写/执行被拒(见 §9 安全) "timeoutSeconds": 900, "cwd": "/home/yangxuan/.openclaw/workspace", "agents": { "dsh": { "command": "/home/yangxuan/.nvm/versions/node/v26.8.2/bin/dsh", "args": ["--profile", "acp"] } } } } } } ``` > `agents.` 是 acpx 插件自带的扩展点(schema:`{ command, args? }`),**用绝对路径**,因为网关服务的 PATH 未必包含 nvm 目录。 ### 4.3 开启 ACP 策略 ```json5 "acp": { "enabled": true, "dispatch": { "enabled": true }, "backend": "acpx", "defaultAgent": "dsh", "allowedAgents": ["dsh"], "stream": { "deliveryMode": "live" } } ``` ### 4.4 把 `dsh` 注册成一个 OpenClaw agent(关键,易漏) 只做 4.2 + 4.3 会得到 `dispatch_failed: Unknown agent id "dsh"`:ACP spawn 会拼出子会话键 `agent:dsh:acp:`,Gateway 用 `listAgentIds()` 校验该 agent 必须**真实存在**。 ```bash openclaw agents add dsh --workspace /home/yangxuan/.openclaw/workspace-dsh --non-interactive # 再用 config patch 给它接上 ACP 运行时: # agents.entries.dsh.runtime = { type: "acp", acp: { agent: "dsh", backend: "acpx" } } ``` 最终 `agents.entries.dsh`: ```json5 { "name": "DSH", "workspace": "/home/yangxuan/.openclaw/workspace-dsh", "agentDir": "/home/yangxuan/.openclaw/agents/dsh/agent", "runtime": { "type": "acp", "acp": { "agent": "dsh", "backend": "acpx" } } } ``` 改完配置:`openclaw gateway restart`(插件类改动必须重启;纯 `agents.entries` 改动可热加载)。 --- ## 5. 验证(2026-09-16 实测,均已通过) | 检查 | 命令 | 结果 | |---|---|---| | ACP 独立冒烟 | `node ~/.openclaw/docs/dsh-acp-smoke.mjs` | `initialize` → `deepseek-harness-acp 0.0.1`;`session/new` → sessionId + 模型下拉(deepseek-v4-flash/pro…);`session/prompt` → 助手回「1+1 等于 2。」;`stopReason: end_turn` | | 后端就绪 | 网关日志 | `embedded acpx runtime backend registered (cwd: /home/yangxuan/.openclaw/workspace)` → `backend ready` | | 端到端派发 | `openclaw agent --agent main --session-key acp-e2e -m "请调用 sessions_spawn(runtime=acp, agentId=dsh, task=在 /tmp/dsh-e2e/ 创建 proof2.txt …)"` | 子会话 `agent:dsh:acp:ce3e4ea5…`,runId `b175b303-…`,约 5 秒完成 | | DSH 侧留痕 | `~/.dsh/sessions/--home-yangxuan-.openclaw-workspace-dsh--//session.v3.jsonl.zstd` | 含 `permission/preset: workspace-write`、`sandbox/mode: workspace-write`、`approval/policy: ask` 及用户消息原文 | | 产物落地 | `ls /tmp/dsh-e2e/` | `proof2.txt` / `proof3.txt` = `dsh-acp-e2e-ok` | | Web 跨机访问 | `curl -L "https://bk02.baiji-algieba.ts.net:18787/?token="` | 303 → Set-Cookie → **200**(27724 字节 HTML) | | 自然语言派发(**部署 skill 前**) | `openclaw agent --agent main -m "这个活我不想自己干,请转给 dsh 执行:…"` | ❌ **假成功**:回复称「已交给 dsh」,但 DSH 侧无新会话 —— 实际是默认 `subagent` + `exec` 干完再复述(工具轨迹 10 次调用 / 4 次失败) | | 自然语言派发(**部署 skill 后**) | 同上措辞(用户不必知道参数) | ✅ DSH 侧新增会话 `332ef715-28e4-4dfb-812e-4152f3c33afd`(`cwd=workspace-dsh`、`permission/preset: workspace-write`),任务描述被自动补全验收标准,产物 `nl2.txt` = `skill-ok` | > 证据判据:**别只看 OpenClaw 的回复文本**。回复正确可能来自 OpenClaw 内嵌运行时(`executionTrace.runner="embedded"`)。要确认真的走了 DSH,看两处:网关日志里的 `agent:dsh:acp:` 子会话,以及 `~/.dsh/sessions/--home-yangxuan-.openclaw-workspace-dsh--/` 下是否新增会话目录。 --- ## 6. DSH Web 界面(给人用,与 ACP 无关) `~/.config/systemd/user/dsh-web.service`: ```ini [Unit] Description=DeepSeek Harness Web (dsh web on 18787, tailscale) After=network-online.target Wants=network-online.target [Service] Type=simple Environment=PATH=/home/yangxuan/.nvm/versions/node/v26.8.2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin Environment=DSH_HOME=/home/yangxuan/.dsh ExecStart=/home/yangxuan/.nvm/versions/node/v26.8.2/bin/node \ /home/yangxuan/.nvm/versions/node/v26.8.2/bin/dsh web \ --host 127.0.0.1 --port 18787 --no-open \ --trusted-host bk02.baiji-algieba.ts.net --trusted-host bk02.baiji-algieba.ts.net:18787 \ --trusted-host localhost:18787 --trusted-host 127.0.0.1:18787 Restart=on-failure RestartSec=5 [Install] WantedBy=default.target ``` 对外暴露(仅 tailnet 可达,https,复用 tailscale 证书): ```bash sudo -n tailscale serve --bg --https=18787 http://127.0.0.1:18787 sudo -n tailscale serve status # https://bk02.baiji-algieba.ts.net:18787 (tailnet only) ``` **访问必须带 token**(每次启动随机生成、只打印一次): ```bash journalctl --user -u dsh-web --no-pager | grep -o 'token=[A-Za-z0-9]*' | tail -1 # → 浏览器打开 https://bk02.baiji-algieba.ts.net:18787/?token=<上面那串> ``` 不带 token 访问返回 `401 dsh web authentication required; reopen the URL printed by dsh web.`;带 token 会用 303 + `Set-Cookie: dsh-auth-*` 落地,之后正常浏览。 两个已知坑: 1. `--host` **只接受 `127.0.0.1` 或 `0.0.0.0`**;写 `--host 100.115.195.192` 会在启动时报 `ValidationError: $.host expected "127.0.0.1" | "0.0.0.0" but got "100.115.195.192"`。 所以要「tailscale 上的 18787」就用 `127.0.0.1` + `tailscale serve`(本方案),不要指望直绑 tailscale IP。 2. 首次启动会初始化 `~/.dsh/profiles/web`,约 10–40 秒才监听端口;systemd 里已在等待逻辑外,需自行 `ss -ltn | grep 18787` 确认。 --- ## 7. 微信 → DSH 的接法(2026-09-16 实测结论) **结论:微信 / 飞书 / 钉钉只能走「助手按需派活」,渠道级 ACP 绑定在这三家都不存在。** ### 7.1 渠道能力实测(为什么不能直接绑定会话) OpenClaw 判定一个渠道能否「把当前会话绑到 ACP 会话」的代码是: `getChannelPlugin(id)?.conversationBindings?.supportsCurrentConversationBinding === true`;持久 `bindings[] type="acp"` 还需要适配器提供 `bindings.compileConfiguredBinding` / `matchInboundConversation`(Telegram 适配器就是这么实现的)。 体检本机三个渠道插件的结果: | 渠道 | 插件 | `conversationBindings` | `supportsCurrentConversationBinding` | `threadBindings` | |---|---|---|---|---| | 微信 | `@tencent-weixin/openclaw-weixin` 2.4.8 | 0 处 | 0 处 | 0 处 | | 飞书 | `~/.openclaw/extensions/openclaw-lark` | 0 处 | 0 处 | 0 处 | | 钉钉 | `@dingtalk-real-ai/dingtalk-connector` | 0 处 | 0 处 | 0 处 | | Telegram(对照组,官方内置) | `dist/channel-*.mjs` | 有 | `true`(`bindingStore: "adapter"`) | 有 | 因此: - ❌ **`/acp spawn dsh --bind here`** 在微信/飞书/钉钉不可用(会得到 "Conversation bindings are unavailable …")。 - ❌ **持久 `bindings[] type="acp"`** 同样不可用(适配器没有绑定钩子)。 - ✅ **助手派活**是最短可用路径(也是本机唯一路径)。 ### 7.2 唯一可用路径:助手把活派给 DSH(已部署) 链路:**微信消息 → OpenClaw `main` 助手 → `sessions_spawn(runtime:"acp", agentId:"dsh")` → `dsh --profile acp` → 干活 → 结果回传微信**。 为了让它**稳定**,已部署技能 `~/.openclaw/skills/delegate-to-dsh/SKILL.md`:触发词为「交给 dsh / 让 dsh 干 / 用 DSH 跑 / 转给 dsh」,并写明纪律(必须带 `runtime:"acp"`、禁止自己用 `exec` 或默认 subagent 兜底、派发失败要如实报错、结果原样回传)。 > ⚠️ **不加这个技能不可靠**:实测 17:19 那次用户说「转给 dsh 执行」,`main` 声情并茂地回了"已交给 dsh 并执行完成",但工具轨迹里是 `sessions_spawn`(默认 `subagent`)+ `exec`,DSH 侧**没有任何新会话** —— 即它由 OpenClaw 内嵌运行时干完,然后复述成 dsh 的口气。技能上线后同一句话(17:21)DSH 侧新增会话 `332ef715…`,`cwd=/home/yangxuan/.openclaw/workspace-dsh`,产物落地。 ### 7.3 怎么确认真的交给了 DSH ```bash # ① DSH 侧会话数是否 +1(最硬的证据) ls -lt ~/.dsh/sessions/--home-yangxuan-.openclaw-workspace-dsh--/ | head # ② 网关日志里的 ACP 子会话 / 后端就绪 journalctl --user -u openclaw-gateway --since "10 minutes ago" | grep -iE "agent:dsh:acp:|acpx runtime backend" # ③ 会话内容(含 cwd 与 permission preset) L=$(ls -t ~/.dsh/sessions/--home-yangxuan-.openclaw-workspace-dsh--/ | head -1) zstd -dc ~/.dsh/sessions/--home-yangxuan-.openclaw-workspace-dsh--/$L/session.v3.jsonl.zstd | head -5 ``` 判据:回复文本**不算证据**(见 7.2 的反例),要看 ①/③。 ### 7.4 其他说明 - `agents.entries.dsh.runtime.type="acp"` **不会**让发给 `dsh` 的普通消息自动走 ACP(实测 `openclaw agent --agent dsh` 仍是 `executionTrace.runner="embedded"`)。它的作用只有一个:让 `dsh` 能作为 `sessions_spawn(runtime:"acp", agentId:"dsh")` 的合法目标。 - 想换成「某个微信账号的消息全量交给 DSH」,在当前渠道能力下做不到「消息直通」;可行的近似做法是把该账号绑定的 agent 换成 `dsh`,但那只会让 OpenClaw 内嵌运行时换个身份干活,不是 ACP。 - 若将来 OpenClaw 侧或渠道插件补上 `conversationBindings`,再考虑 `/acp spawn --bind here`。 --- ## 8. 凭据位置(本项目文档不含明文) | 凭据 | 位置 | 说明 | |---|---|---| | DSH 模型 API Key | `~/.dsh/.env`(600)里的 `DEEPSEEK_API_KEY` | DSH 凭据解析优先级:**继承的进程环境** > `~/.dsh/.credentials.yaml` > 调用目录 `.env` > `~/.dsh/.env`。写 `.env` 最省事;Web 的 Models 页写入则会落到 `.credentials.yaml` 并覆盖 `.env` | | DSH Web 访问 token | 运行时随机生成 | 见 §6,从 `journalctl` 取;不落盘 | | OpenClaw 各类密钥 | `~/.openclaw/.env` / `~/.openclaw/openclaw.json` | 见 `bk02-openclaw-系统说明.md` §6 | --- ## 9. 排错清单(按遇到概率排序) | 症状 | 原因 | 处置 | |---|---|---| | `dispatch_failed: Unknown agent id "dsh"` | 只注册了 acpx harness 别名,没建同名 OpenClaw agent | 做 §4.4:`openclaw agents add dsh` + `runtime.type="acp"` | | `ACP runtime backend is not configured` | `@openclaw/acpx` 没装 / 被 `plugins.allow` 拦 / 网关没重启 | `openclaw plugins install @openclaw/acpx`;把 `acpx` 加进 `plugins.allow`;重启网关 | | 回复看着对但 DSH 侧没有新会话 | 其实是 OpenClaw 内嵌运行时干的 | 看 `executionTrace.runner`;确认 `agent:dsh:acp:` 子会话与 `~/.dsh/sessions/...-workspace-dsh--` | | `PermissionPromptUnavailableError: Permission prompt unavailable in non-interactive mode` | 非交互 ACP 会话撞上写/执行门禁 | `plugins.entries.acpx.config.permissionMode = "approve-all"`(或 `nonInteractivePermissions="deny"` 降级) | | `dsh: profile "acp" does not exist` | dsh 版本 < 0.1.5(无内置 acp 模板) | 升级 dsh,或 `dsh plugin --profile acp add @deepseek-ai/dsh-acp` 后手写 profile | | 网关日志 `security warning: dangerous config flags … permissionMode=approve-all` | 预期告警 | `approve-all` 等于把 bk02 上的写/执行权限交给 DSH 会话,见下方安全说明 | | Web 打开 401 | 没带 token | 从 `journalctl --user -u dsh-web` 取带 token 的 URL | | Web 启动即崩、日志报 `$.host expected …` | `--host` 传了具体 IP | 改 `127.0.0.1`(+ tailscale serve) | | `dsh` 命令找不到 | 该 shell 没加载 nvm 的 Node | `export PATH=$HOME/.nvm/versions/node/v26.8.2/bin:$PATH` | | `dsh plugin …` 报 `pnpm not found on PATH` | 本机没装 pnpm(`dsh plugin` 只是 pnpm 转发器) | `npm i -g pnpm` | | ACP 会话报 JSON 解析错 / 客户端把某行当非法帧 | acp profile 里装了会往 **stdout** 打印的插件(已知:`skillhub-plugin` 自检行) | `dsh plugin --profile acp remove skillhub-plugin`;装任何插件后都跑一遍冒烟脚本确认无「非 JSON 的 stdout 输出」 | **安全说明**:`permissionMode=approve-all` 让 DSH 会话在 bk02 上自动获得写文件/执行命令的许可(这是「让 DSH 干活」的代价)。可收紧为 `approve-reads`,但写/执行类任务会需要交互确认,非交互会话可能直接失败。DSH 自身仍带 `workspace-write` 沙箱 preset 与 `approval/policy: ask` 记录,可在 `~/.dsh/sessions/*/session.v3.jsonl.zstd` 审计。 --- ## 10. 回滚 ```bash # OpenClaw:配置回滚到接入前(备份在 ~/.openclaw/openclaw.json.bak--pre-dsh-acp) cp ~/.openclaw/openclaw.json.bak-20260916-170416-pre-dsh-acp ~/.openclaw/openclaw.json openclaw gateway restart # DSH Web:停用 + 撤掉 tailscale 暴露 systemctl --user disable --now dsh-web sudo -n tailscale serve --https=18787 off # DSH 本体 npm rm -g @deepseek-ai/dsh # 配置与历史留在 ~/.dsh(可整体删除) ``` --- ## 11. 变更记录 | 时间 | 变更 | |---|---| | 2026-09-16 17:01 | bk02 安装 `@deepseek-ai/dsh@0.1.5-rc.1`(nvm v26.8.2),自动初始化 `acp` profile | | 2026-09-16 17:02 | 写入 `~/.dsh/.env` 的 `DEEPSEEK_API_KEY`;ACP stdio 冒烟通过 | | 2026-09-16 17:04 | 安装 `@openclaw/acpx`;`plugins.allow` 放行;写入 `acp` 段与 acpx `agents.dsh`;网关重启 | | 2026-09-16 17:11 | 创建 OpenClaw agent `dsh`(workspace-dsh)并接 ACP runtime | | 2026-09-16 17:12 | 端到端 ACP 派发成功(proof2/proof3 由 DSH 创建) | | 2026-09-16 17:15 | `dsh-web.service` 落地(127.0.0.1:18787)+ `tailscale serve --https=18787`;跨机访问 200 | | 2026-09-16 17:20 | 查明微信/飞书/钉钉渠道**均无** `conversationBindings` 能力(仅 Telegram 等内置渠道有)→ 排除 `/acp spawn --bind here` 与持久 `bindings[]` 两条路;部署技能 `~/.openclaw/skills/delegate-to-dsh/SKILL.md` 并重启网关 | | 2026-09-16 17:21 | 自然语言派发验证通过(DSH 侧新会话 `332ef715…`),「微信 → OpenClaw → DSH → 结果回传」链路可用 | | 2026-09-16 17:23 | 装 pnpm 12.4.2;web profile 增装 `skillhub-plugin` + `superpowers-dsh`;写 `~/.dsh/AGENTS.md` 全局中文指令(交互 + 思考) | | 2026-09-16 17:24 | 发现 `skillhub-plugin` 自检用 `console.log` 污染 ACP stdout → 从 acp profile 移除(保留 `superpowers-dsh`),复测协议流干净;语言复测中文生效 | | 2026-09-16 17:25 | 端到端回归:OpenClaw 派发仍正常(DSH 会话 6→7,产物 `nl3.txt`) |