前言¶
在 DSH(DeepSeek Harness)里做 agent 调试时,最常见的需求不是一直聊下去,而是「换一条路再试一次」。原生会话列表是一条平铺的线:你想开条新分支的时候,通常只能新开一个会话,把上下文重新粘一遍,或者手动翻历史。dsh-branch-tree 解决的就是这件事——把左侧工作区的会话列表变成一棵树,母会话是可展开的文件夹行,分支是挂在它下面的缩进子行。
它由 YB313(Yige Bao)维护,分类是工作流,GitHub 仓库目前 1 个 star,许可证 MIT,当前版本 v1.3.1。只提供一个 client.js,在 web 客户端侧加载,没有构建步骤。
这是什么¶
一句话:dsh-branch-tree 是 DSH 的一个 web 端插件,把会话列表改造成树,并提供「派生分支」能力,分支可选择从母会话继承多少记忆。
它不做合一:拖拽只改树结构,不拼接对话;母会话之后的修改也不会同步进分支。
核心功能¶
三种继承模式¶
创建分支时可以在三种模式里选,决定分叉点和继承到什么:
| 模式 | 分叉点 | 分支继承到什么 |
|---|---|---|
全景继承(full,默认) |
母会话最后一次真实对话处 | 到该点为止的全部对话,逐字复制进分支会话 |
压缩继承(inherit) |
空会话 | 母会话到目前为止的压缩摘要,作为分支自己的第一条消息写入,原始历史一条都不带 |
开头继承(opening) |
母会话第一轮结束处 | 只继承最初的需求消息,不含之后的对话 |
默认给全景,理由是分支的意义是接着试:摘要有损,丢掉的恰好是让分支有用的细节——已否决的方案、只说过一次的需求、约束的原话。
实现上的几个坑,README 也写明了:
- 分叉点过滤注入块:宿主注入的内容(运行上下文、技能目录、时间上下文、记忆前置说明)不算对话,判轮次时过滤掉,切口落在助手真正说过的最后一句回复上。
- 空壳检测:宿主有可能「成功」建出一个 0 事件的分支。插件读子会话的继承事件数,为 0 就先不带边界重 fork 一次;仍然为 0 就在行上标记
emptyFork,不装作成功。 - 压缩继承不污染母会话:摘要在一次性的临时 scratch 会话里生成,母会话自己不会插入提示语。摘要作为种子消息写进分支,带
<!-- dsh-branch-tree:seed ... -->标记。 - 压缩兜底:模型超时或答得不含摘要小节时,自动退回机械摘要(逐轮截断的对话记录,≤12k 字)。
明确的边界¶
- 不合并对话。拖动会话只重挂载树结构(宿主支持
workspaces.create时可能建子工作区目录),两个会话不会被拼接、共同摘要或合并。 - 不与母会话联动。母会话之后的编辑不同步进已存在的分支。
- 不复制 md 文件。每个分支实时读取同一批 md,母会话改了需求,分支下次读取即生效。
本地状态¶
树结构、折叠状态、当前会话提示、分支任务状态、分支计数显隐、归档/隐藏标记,全部存 localStorage 前缀 dsh.branch-tree. 下。清掉只会重置视图,不动任何会话数据。
安装与启用¶
DSH 以 profile package 形式加载插件,官方给了两条路。挑一条:
# 本地 checkout(README 里开发用的就是这条)
dsh plugin --profile web add /absolute/path/to/dsh-branch-tree
# GitHub tag 的 tarball(不需要本机 git)
dsh plugin --profile web add https://github.com/YB313/dsh-branch-tree/archive/refs/tags/v1.3.1.tar.gz
装完重启 web GUI(或刷新页面),再看左侧工作区。卸载:
dsh plugin --profile web remove dsh-branch-tree
注意:未发布到 npm,目前只有 GitHub tarball 和本地路径。插件是 web 客户端插件,需要带 web 能力的 profile,宿主侧依赖 dsh.client.inject 声明的五个包:@deepseek-ai/dsh-client-ui-sidebar、@deepseek-ai/dsh-client-ui-conversation、@deepseek-ai/dsh-client-ui-primitives、@deepseek-ai/dsh-api-session-controller、@deepseek-ai/dsh-api-workspace-files。
典型用法¶
1、在会话行的右键菜单点 + 派生分支…(分支行上是 + 子分支…),起名、选继承模式、创建。
2、点文件夹行展开或折叠它的分支。
3、拖拽调整归属:把会话拖到文件夹行上即重挂载,拖到工作区标题即移过去。拖拽不合并内容。
4、分支树面板支持搜索、查看每个分支的任务状态、重命名、归档/取消归档、「移出树」和诊断。
5、分支产物默认落在 制图/<母会话>/<分支>/。
树接管了原生的侧边栏会话入口。如果宿主挂载点抛异常,插件会把 dsh.branch-tree.takeover 置为 off,让原生列表继续工作;可以在 localStorage 里把它改回 on 再试。
适用场景与注意¶
适合在 web 端调试 agent 的人:想在不改母会话的前提下开条新路,或者想把「正着聊一遍、歪着再试一遍」的多轮实验的从属关系留在侧边栏里。README 写的是在 dsh 开发者预览版下验证的,宿主仍在变动,建议跟上版本的 install 命令一起核对。
需要提醒的是,插件以当前 dsh 进程的权限运行,能读写它能力范围内的会话与工作区文件;安装前通读一遍 client.js 源码和 MIT 许可证是必要的。GitHub 仓库 1 个 star,基本是个人维护项目,升级和兼容性风险由你自行评估。
小结¶
dsh-branch-tree 做的事很窄也很具体:把侧边栏从列表变成树,加一个可控记忆跨度的派生分支入口,同时明确划清「不合并、不联动、不复制文件」的边界。如果你觉得分支这件事值得显式看见,可以试试;如果只是想平铺聊天,原生列表就够了。
目录页:https://www.skillhub.cn/plugins/YB313/dsh-branch-tree
GitHub:https://github.com/YB313/dsh-branch-tree