TreeCom — 对话树
Tree-shaped conversation branching for DeepSeek Harness. Keep one visible conversation; manage its branches as a tree.
版本 0.1.0 · MIT · DeepSeek Harness Web 插件
用一个对话窗口和一棵可平移的画布树管理它的分支;分支仍然是普通会话,会出现在左侧工作区:
- 画布上每个圆点是一个节点;根节点在顶部,分支向下展开,按叶序从左到右排开;
- 拖动空白画布即可上下左右平移;滚轮 / 触控板缩放,树可以无限延伸;画布左上角「回到当前」定位当前叶子,「居中」把树移回视野中心;
- 点击节点 = 选中并在右侧打开该轮详情,不会跳转、也不会分叉;详情里的「回到这一轮」才会切换分支并定位;
- 右侧详情固定显示:上下文窗口占用(百分比 + 进度条 + 精确 token)、从该节点开始还能继续多少轮、可上下滚动的完整提问 / 回答,以及归档、重命名、分叉;
- 鼠标悬停节点会浮出小预览:轮次、本轮用户提问、上下文占用、后续轮数;点击后看详情;
- 没有分叉的连续轮次会折叠成一个带数字的节点;点击该节点展开整段连续对话,再次变成普通节点;
- 树数据按会话缓存,只在会话内容发生变化(新轮次、切换/新增对话、标题变化等)时更新;空闲时不轮询,生成中的会话会低频刷新;右上角刷新按钮可强制重新加载;
- 当前所在节点用主题绿色圆点;选中节点用主题强调色;「你在这里」保持绿色;
- 分支叶子节点仍与对话区会话标题同步:在对话区改名会同步到树的叶子;在树上重命名也会同步回会话标题;中间轮次节点的标签只影响树内展示;
- 从标题栏打开浮层时会隐藏对话区和输入框,浮层默认铺满内容区;拖动左边缘可缩到最小 560px,最大为整个窗口宽度;
- 两个入口:
- 标题栏右上角的「对话树」按钮:打开从右侧滑入、铺满内容区的浮层;再点该按钮或按 Esc 以滑出动画收回;
- 会话视图里的「对话树」标签页:和「对话 / 轨迹 / 上下文」并排,全宽显示画布 + 右侧详情;
- 浮层打开时铺满内容区并遮住左侧会话列表,需要切换会话时先关闭浮层;右侧栏 tab、输入框上方的路径条都没有;
- 重命名 / 归档 / 分叉按钮固定显示在右侧详情的标题下方,不再藏在长对话底部;
- 每次对话结束后的分叉统一使用宿主自带的「在新对话中分支」,插件不再额外加「分叉」按钮;树节点详情里的「分叉」用于从任意旧节点开分支;
- 新分支不再自动归档,会直接出现在左侧工作区;每个非根节点在详情里有「归档」;
- 归档同步:已归档的分支不在树里显示;在左侧取消归档后,它会自动回到树里。
为什么底层是 fork
DSH 的会话日志是 append-only 的线性 surface,聊天区只渲染「追加」消息。
在一个物理会话里用 surfaceOp: replace 切分支,只会改变模型看到的内容,
不会改变聊天记录;要做到「界面也跟着切」,只能重写整套 Chat 渲染层。
DSH 官方支持的分支原语是 fork:把某一轮之前的完整事件前缀复制成子会话。 子会话的聊天区显示的就是「到该轮为止的同一段对话」,因此切分支看起来是 「回到那一轮」,不是打开一个新对话。TreeCom 把这个过程藏在一个树面板后面。
环境要求
- DeepSeek Harness(Web UI),已启用本地插件/bundle。
- 插件是纯 JavaScript,无构建步骤;Host 半与 Client 半都在仓库里。
安装
dsh plugin 会把参数转发给 profile 目录里的 pnpm,因此 npm 包名、github:、link:、file: 等 pnpm 支持的 spec 都可以。
从 GitHub 直接安装(当前可用):
dsh plugin --profile web add github:Serenity-2026/dsh-treecom
发布到 npm 后,也可以只写包名:
dsh plugin --profile web add dsh-treecom
本地开发时,克隆后把目录 link 进 profile:
git clone https://github.com/Serenity-2026/dsh-treecom.git
dsh plugin --profile web add link:"$PWD/dsh-treecom"
安装或更新后刷新 DSH Web 页面(Host 半的 /treecom 路由需要重新加载)。
仓库名是
dsh-treecom,当前 npm 包名是treecom;npm 上计划使用dsh-treecom。在 npm 发布前,请使用上面的github:spec。
使用
- 点标题栏右上角的「对话树」,或会话视图里的「对话树」标签页;
- 拖动空白处平移画布;滚轮 / 触控板缩放,节点始终按树形展开;没有分叉的连续轮次会折叠成一个节点,点击展开;
- 点任意节点,在右侧查看该轮详情;点「回到这一轮」才切换分支并定位到那一轮;
- 悬停节点可快速看本轮提问、上下文占用和后续轮数;
- 在详情里「分叉」开新分支,新分支会作为普通会话出现在左侧;
- 在详情里「重命名」改名,对话区会话标题会同步;叶子节点也会同步显示会话标题;
- 在详情里「归档」把分支移出树;在左侧取消归档即可恢复。
结构与数据
index.js:Host 半。只读索引/treecom,读sessionQuery的会话日志, 把轮次按inheritedEventCount归一化,共享主干只画一次;标签写到~/.dsh/storages/treecom/state.json。不写任何会话日志。plugin.client.js:Client 半。可平移/缩放画布树、右侧详情面板、标题栏入口、 会话视图「对话树」标签页;数据按会话缓存,会话变化时刷新;fork/切换走正常 Client 服务。locale/:中英文案;icon.svg:插件图标;cordis.patch.yml:bundle 挂载行。
所有数据都在本地:树索引读本地会话日志,标签写本地 sidecar 文件,只与本机 DSH 的 /treecom 路由通信,不发起外部网络请求。
已知边界
- 底层每个分支是一条 fork 会话,会正常出现在左侧工作区(标题带 (1)、(2) 后缀)。
- 点节点的「分叉」才会创建分支;如果随后不提问,会留下一个空分支, 在树里显示为「新分支 · 等待提问」;它也会出现在侧栏,可在节点上归档,或在左侧取消归档恢复。
- 当前分支正在生成时,分叉按钮、树上的分叉动作和归档按钮会禁用;
- 刷新按钮会转圈,完成后弹出「刷新成功」提示;空闲时不会自动轮询,避免打开浮层时反复重绘;生成中的会话会低频刷新;
- 卸载插件后所有会话仍在;归档的分支可在 DSH 的归档列表里取消归档。
License
MIT © 2026 Minchuan Deng
No comments yet. Be the first to write one.