dsh-diy-subagentui
v0.6.2
Published
DSH subagent split view: leader conversation left, worker panel right, live rendering, draggable divider.
Readme
dsh-diy-subagentui
English | 中文
一句话: 零侵入的 DSH 插件,把对话界面变成分屏工作区 —— 左 leader 对话、右 worker 面板,实时渲染、可拖拽分隔线、实时流式,全在插件目录内完成,不碰 DSH 一行源码。

功能
- 分屏 — 左侧主对话,右侧 worker 面板。可拖拽分隔线(默认各半,限制 20%–80%)。
- 子代理标签栏 — 每个 worker 一个标签,点击切换。选中标签绿点、未选中灰点。
- 实时渲染 — 通过
sessions.binding(workerId)+useSyncExternalStore订阅实时快照。助手消息流式打字效果。 - 事件驱动目录 — 子代理列表读取
sessions.list.subagentsByParent(与 DSH 官方子代理目录同源)。轮询api.subagents.list仅作兜底。 - 富消息渲染 — 用户气泡、助手正文、Think 折叠行(推理过程)、工具调用 IN/OUT 卡片、流式输出。
- 不修改 DSH 源码 — 只操作 DOM 内联样式,不碰任何 DSH 文件。
快速开始
从 GitHub 安装(推荐)
dsh plugin --profile web add github:Elpsycoogroo/dsh-diy-subagentui完事 —— 不用克隆、不用手动构建、不用配置。如果 profile 不叫 web,把名字换成你自己的即可。
pnpm 默认拦截构建脚本:从 GitHub 安装会执行项目自带的构建脚本,pnpm 默认不允许跑。直接跑一次上面命令,pnpm 会打印要加到
~/.dsh/profiles/web/pnpm-workspace.yaml的allowBuilds下的那个 key,加进去再装一次即可。
从 npm 安装
dsh plugin --profile web add dsh-diy-subagentui本仓库手动安装
把插件放到/克隆到 dsh/plugins/dsh-diy-subagentui,构建一次:
cd dsh/plugins/dsh-diy-subagentui
npm run build⚠️ 不要把
lib/单独复制到 profile 的node_modules/——缺少package.json(和cordis.patch.yml)的残缺副本无法被 DSH loader 解析(报Cannot find package ... index.js)。要同步就同步整个包:package.json+lib/+cordis.patch.yml。
持续开发请用 node dev.mjs(监听 src/ → 自动构建 → 自动整包同步到 profile,无需手动复制)。
子代理由 host / Orca 流程创建,本插件不负责创建,只把它们变成标签展示。
⚠️ 二开前必读(踩坑实录)
package.json的exports必须包含"./package.json":DSH 的 client-modules 用require.resolve('<包名>/package.json')读取插件清单。exports若未导出该子路径,会抛ERR_PACKAGE_PATH_NOT_EXPORTED,插件表现为在插件列表可见、但页面里永远不会加载 client.js(分屏不出现)。- 三处 name 必须一致:
package.json的name、插件自带cordis.patch.yml里的name、你在 profile patch 里引用的名字。曾以 scoped 名@elpsycoogroo/dsh-diy-subagentui发布的,改成无 scope 后极易残留旧名。 - 改完 manifest/重装后必须重启 dsh:client-modules 的"非客户端插件"判定是进程内永久缓存(never expires),只刷新页面不会生效。
给开源作者
本地开发、调试、接入指南见 DEVELOPING.md / DEVELOPING.zh.md —— 涵盖克隆、构建、接入本地 DSH profile、解读诊断日志。
工作原理
分屏机制
centerCol 原生就是 display: grid,插件通过内联样式控制其 grid-template-columns:
- 有子代理 →
grid-template-columns: var(--dsh-split-left, 50%) minmax(0, 1fr)— 左对话右面板。 - 无子代理 →
grid-template-columns: minmax(0, 1fr)— 对话全屏。
面板容器作为 centerCol 的子元素(grid 第二列)挂载。无子代理时容器 display: none,centerCol 恢复单列,不会残留分屏布局。
数据源
- 主数据源:
sessions.list.subagentsByParent[currentSessionId]— 事件驱动。选中会话时 manager 自动刷新目录,host 帧推送 activity 更新。 - 兜底:每 3s 轮询
api.subagents.list。新子代理产生时 host 只标 expandable、不把新条目 push 进目录,需要轮询补上。
实时快照
每个 worker 会话通过 sessions.binding(workerId) 建立绑定,其 session 暴露 getSnapshot() 和 subscribe()(与 leader 对话同款通道)。插件用 useSyncExternalStore 消费:
ConversationSnapshot.nodes— 扁平节点列表(user、assistant、steering、context、tool-result、command、turn-error等)。ConversationSnapshot.partial— 流式中的助手输出(生成中 blocks 持续累积)。ConversationSnapshot.runningCalls— 正在运行的工具调用。
实时快照可用时事件驱动渲染;绑定未建立时,面板降级到轮询 api.subagents.history。
文件结构
dsh-diy-subagentui/
├── package.json
├── tsconfig.json
├── tsdown.config.ts
├── cordis.patch.yml
├── README.md # English docs
├── README.zh.md # 中文文档
├── DEVELOPING.md # English contributor guide
├── DEVELOPING.zh.md # 中文开发者指南
└── src/client/
├── index.ts # 插件入口;挂载分屏。
├── split-mount.tsx # DOM 挂载 + grid 控制(setActive)。
├── SplitView.tsx # 数据编排:目录、轮询、标签选择、拖拽中缝。
├── WorkerTabs.tsx # 子代理标签栏(绿/灰圆点,点击切换)。
└── WorkerPanel.tsx # Worker 会话视图:实时快照 + 历史兜底 + 输入框。
# 同时包含 ThinkRow、ToolRowView、MarkdownText、SendIcon。构建
cd dsh/plugins/dsh-diy-subagentui
npm run build然后同步整个包到 DSH profile(不能只同步 lib/——loader 还需要 package.json 和 cordis.patch.yml):
node dev.mjs # watch 模式:自动构建 + 自动整包同步构建一次用 npm run build;开发循环用 node dev.mjs(监听源码、自动构建并整包同步 profile)。
控制台日志
只保留必要日志,所有调试/轮询噪音已清除。
| 来源 | 级别 | 说明 |
|------|------|------|
| index.ts | log | 版本加载(v0.6.0 loaded) |
| WorkerPanel.tsx | log | 实时快照状态(去重,仅变化时打印) |
| WorkerPanel.tsx | error | 历史拉取失败 |
| WorkerPanel.tsx | error | 发送失败 |
| SplitView.tsx | error | 子代理列表拉取失败 |
许可证
MIT
