muche-dsh-plugin
Chat panel for the MuChe companion with per-user backend settings, plus an outbound bridge that runs tasks on the user's local dsh.
Install
dsh plugin --profile web add muche-dsh-plugin
Sandbox test results
| Stage | Result |
|---|---|
| 1 install | ✗ |
| 2 list | — |
| 3 mount | — |
| 4 boot | — |
dsh: initialized profile web at /home/node/.dsh/profiles/webFour stages run in an isolated sandbox: install (network on) → list → mount → boot (last three with no network).
README
muche-dsh-plugin — 和有持续状态的小沐聊天



连接小沐(MuChe 数字生命)的 dsh 插件:可以和有持续状态的小沐聊天,小沐可调用本机 dsh 执行任务。
- 聊天与桌面窗:左下角「小沐」入口打开菜单,显示桌面小沐后点击立绘打开聊天面板;支持未读提示与图片粘贴。
- 服务端直读:聊天记录只在服务端,面板首屏单页、增量归一、游标翻页;本机不存任何聊天文件,重装换机天然可用。
- 反向桥接:小沐可调用你本机 dsh 执行任务(出站常驻连接,不开入站端口)。
- 设置页:后端地址 + API key,每用户各自配置。
安装
在 DSH Desktop 的 DSH Terminal 里执行(裸命令默认装到当前激活 profile,
装完在托盘重启 DSH Desktop 即用):
dsh plugin add muche-dsh-plugin
升级使用同一条命令。当前市场版本为 0.8.14。
支持 DSH 0.2.1-rc.5(latest)和 0.2.2-alpha.3(alpha);engines.dsh 只接受这两个版本。
桥接协议 v2 协商取消、输入送达及已读等能力,旧宿主按实际能力降级。
注意 dsh --profile desktop plugin add 的父 flag 写法上游不接受(plugin
子命令自带 --profile,见上游 rejectParentOptions),必报
required option '--profile <name>' not specified——别写。
使用
1. 打开 dsh 设置 → 小沐,填后端地址和 API key(小沐后台生成),保存。
2. 点击左下角「小沐」打开菜单,选择「显示小沐」;点击桌面立绘打开聊天,拖动立绘可调整位置。菜单中的「设置」打开 DSH 设置。非 Desktop 环境可通过菜单中的「打开聊天面板」进入聊天。
3. 第一次显示时会下载 Electron 桌面组件。显示偏好与窗口位置保存在 DSH_HOME/muche-desktop/state.json(默认 ~/.dsh/muche-desktop/),手动删除该目录可清除桌面组件缓存和位置偏好。聊天记录仍保存在后端。
4. 输入框支持 Ctrl+V 粘贴剪贴板图片;反向桥接配好 key 后按连接状态启动。
5. 本工作区的聊天面板顶部「任务」图标打开任务抽屉:显示任务状态与 stage(等你回答/被阻塞会高亮)、追加输入、最近执行和完整已存结果;进行中任务可停止,后续需求在聊天中提出并由任务路由决定是否续接。
桌面立绘取自 PC2005-cloud/dsh-pet,素材限非商业使用;形象按 CC BY-NC-SA 4.0 授权,出处与署名见 [素材说明](desktop-helper/assets/README.md)。
后端地址口径:填实际后端基址(如 <公网基址>/api)。插件不再补写、不再要求 /api 结尾、也不替用户判定地址形态——部署路径归项目决定,成不成立由「测试连接」的真实请求说了算。统一健康口 GET /api/muche/health 一次返回鉴权+历史+WS 三段结论,设置页「测试连接」可带候选值试连(不写回配置)。
面板状态与提示
标题栏指示的是聊天通道是否可收发(与反向桥接无关):
显示 · 含义
连接中 · 启动后正在建立聊天连接
在线 · 收发两侧都已就绪
离线 · 连接不可用
配置类问题统一显示「请检查配置」,不出现地址、接口路径等技术细节;网络中断显示「连接暂时中断,正在重连」,恢复后自动消失;额度耗尽是独立提示,不影响在线状态。结构性故障固定在面板顶部、不随消息滚动消失。
判断口径按凭据与连接分层:只有握手认证被拒(401/403,说明本机保存的 key 不被接受)才显示「请检查配置」;服务端主动关闭已建立的连接(4003/4401/1011 等,常见于凭证轮换或账号重置)按「连接暂时中断,正在重连」处理并自动重连,重连握手会重新认证。设置页显式保存(即使值没变)会强制重建面板与桥接连接,可用于手动重试。
卸载
dsh plugin remove 'muche-dsh-plugin'
remove 只摘层与代码;本机配置(profile patch 里 muche 条目的配置)保留,重装免配。0.5.0 起插件不在本机存任何聊天文件;旧版遗留的本地存档(~/muche-dsh-workspace/messages/)原样保留,可手动删除。装完在托盘重启 DSH Desktop 生效。彻底清掉:删掉 profile patch 里 muche 条目的 config 段。
反向桥接只调用户本机:后端把任务帧从该用户的桥接连递下来,插件在本地 dsh 进程内执行、结果原路回传。桥不在时后端明确失败,不回退服务器。
技术细节
<details>
<summary>架构(勿改回)与模块说明</summary>
小沐聊天 = 插件自绘面板 + 直连后端(HTTP 收发 + 后端 WS 下行),不进 dsh agent 循环、不建 dsh 会话(dsh 会话的隐藏机制与可聊天互斥,会话内 LLM 调用会注入 AGENTS.md 等噪音——面板形态从根上消除注入面)。
状态只有一条链路:官方配置 → 宿主运行状态(runtime-state.js)→ 完整快照/SSE → 浏览器镜像(client/src/runtime-store.js)→ 面板呈现。每个维度只有一个真源:连接是否可用、某次操作是否失败、输入是否合规、额度是否用尽是四个独立维度,互不覆盖。所有异步结果按 {runtimeId, configNs, generation} 校验代际,配置一改,HTTP、面板下行与桥接同时切换,旧的迟到结果一律拒收。
文件 · 职责
cordis.patch.yml · 组合包层:dsh plugin add 自动进 profile 层列表,免手写 YAML
lib/index.js · Host 入口(inject/apply)
lib/config.js · 插件 Config(全 volatile,官方 settings 读写)
lib/backend.js · 后端地址唯一真源:归一+拼装+形态判定
lib/errors.js · 失败分类唯一真源(classifyFailure 返回 kind/code/text/advice/retryable;调用方只给事实,不猜正文、不猜地址形态)
lib/http.js · 后端 JSON/二进制请求唯一出口(归一前置+UPSTREAM_HTML 分流)
lib/runtime-state.js · 宿主运行状态 Owner:配置代际、聊天收发就绪、桥接生命周期的唯一投影(快照无凭据,订阅即回放当前全量)
lib/runtime-contract.js · 宿主/浏览器共用的快照契约与故障去重(同因只去重一次,无关错误不吞)
lib/routes.js · /api/muche/{runtime,chat,history,image,health,events} 同源路由(配置读写走官方服务,不在此;历史直读服务端唯一真源,本机零落盘;游标 422 转 CURSOR_INVALID;聊天/候选健康 JSON 在缓冲前分别限 40 MiB/64 KiB,跨层预算见 ARCHITECTURE.md §7)
lib/connections.js · 连接生命周期唯一 Owner(面板上游+桥接各持一个 ChannelConnection,指纹换连)
lib/backend_ws.js · 后端 WS 传输类(桥接通道+面板 SSE 上游,ping/重连/缓冲;ready 只由后端真实 hello 置真)
lib/panel-events.js · 面板 SSE 扇出 Owner:首位订阅先发完整快照,业务帧按配置 context 盖章
lib/register-guard.js · 注册事务守卫:双挂载降级时原子撤销本轮注册,不留混合 Owner 的孤儿路由
lib/dsh-bridge.js + lib/dsh-call.js · 反向桥接:宿主归属、稳定指令、应用回执、只读查询;执行订阅先于 prompt,按所属 turn 收口
lib/protocol.json · 桥接 v2 版本、能力和执行失败枚举的唯一真源;后端读取同一文件
client/src/ · 面板源码(pure.js 纯格式函数+api.js 同源封装+runtime-store.js 浏览器镜像+entry.js 工厂与 UI),esbuild 打包到 client/client.js(构建产物随包发布,不手改)
反向桥接先用 dsh_hello 登记持久的宿主身份与 v2 能力,后端以 dsh_hello_ack 确认登记成功与否(成功带 host_id 回显,失败带已有枚举 code 且不登记);插件只认该 ACK 为登记事实,不以 socket hello 或本地 ready 代替,未收到 ACK 前保持 starting。任务只发送给所属宿主,旧插件需升级;同 session_id 串行、稳定 task_id 去重,执行阶段和结果分别上报。会话不存在保留具体上游事实,由小沐说明并按剩余任务续接新会话;失效的 sN 不再复用。断连与未知结果保留受理确定性,不据此重做副作用任务;重启恢复先只读查询原 task。
在途追加只在相同 live run 的自有 turn 使用公开 Agent.steer,用同 cohort 的 createUserMessage 构造消息并同步受理;原任务尚未进入自有 turn 时返回 turn_pending,后端保留同一 append_id 重试。终态后拒收,不转成无人收结果的新轮。明确拒收的追加保留完整任务,等原任务结果落账后由小沐续办;曾丢失回执的追加仍保留结果未知事实。授权/提问先登记 resolver 再经 dsh_interactive 上行,每次交互有独立 opaque id,原始问题与选项完整保留。其他 turn 透传。小沐能拿捏就提交决定,需要用户时提交真实问题并保留等待;dsh_decide_result 只确认本地校验提交;后续原生 tool/result 或迟到答案接收事件以 dsh_interactive_result 确认原生接收,执行最终结果另报。宿主进程缓存相同 command_id 的回执:活跃 run 的收据保留,终态收据按最近 200 项收敛;相同身份不同内容拒收。
停止通过所属会话的 sessionController.cancel 请求原生取消,并等待自有 turn 的中止终态;请求停止后拒绝新增追加,只按消息身份移除该执行尚未消费的追加,保留其他来源的收件箱内容。取消或待处理输入状态无法确认时不返回已停止。
用户等待暂停活跃执行计时。卸载、断连、取消、上限与错误均清理订阅/等待,保留终态和部分输出;技术失效不表示用户拒绝。宿主 bridgeId 经官方 settings 保存且同宿主双挂载共享,排障勿删除或复制该身份。
回答与追加的交付有独立尝试预算;原任务结束、交互超期或交付耗尽后,本地技术收口保留原决定和未知回执,resolver 关闭最多尝试一次,不等待离线宿主无限返回 ACK。未完成追加与恢复事实原子保存,正常等待用户不消耗交付次数。已结束问题的重复上报不会重新暂停后端执行计时。
执行核通过宿主 cohort 接口进程内直调 sessionController.create/prompt,回复走 session/event 事件订阅(assistant/message 累积文本,turn/end 按 reason.kind 判定完成)。turn/end 共六种终态(completed/aborted/blocked/error/max-tokens/interrupted),调用方按种收敛,不静默。
执行前同时订阅 agent/inbox/claimed,按消息 rpcId 与所属 turn 绑定来源;上游 pre-step 在写入正文前拒绝或结束时仍保留实际终态,其他 turn 不结算当前任务,所有退出清理两类订阅。
依赖:@deepseek-ai/cordis、@deepseek-ai/schemastery 、@deepseek-ai/dsh-llm 与 @deepseek-ai/dsh-tools 为 peer(用宿主同 cohort 的服务和消息类型);ws、undici 自带。改
…(truncated)
Rendered from the README published on npm. Formatted only, not edited.
Versions
Published on npm::41,最后更新 2026-11-04