dsh-nested-followups
English | 中文
!dsh-nested-followups —— 为 DeepSeek Harness 提供的嵌套追问会话树
这是一个 DeepSeek Harness 插件,为其网页界面增加会话树。你可以针对此前的任意一条回答提问,新的问题会作为 一条独立分支展开,而不是被追加到主对话的末尾。
   
要解决的问题
DeepSeek Harness 的对话是线性的。当你正在完成一项工程任务,想问清楚早先某条回答 里的一个概念时,只有两个都不理想的选择:在主对话里直接问,这会把无关内容混进任务 上下文,并且此后每次请求都会继续携带它;或者新开一个对话,这又会丢掉那些让这个 问题有意义的上下文。
本插件提供了第三种选择:把追问变成一条分支。分支只继承到你所提问的那条回答为止的 对话内容,不包含其他任何东西,主对话也完全不会看到分支里发生的事。
功能
- 把当前对话显示为树。 每条用户消息和助手回答各自成为一张卡片。主对话向下延伸,
分支向右生长。
- 可以无限层追问。 分支里的回答可以再次被追问,嵌套层数没有限制。
- 真正的上下文隔离。 每条分支都是用官方的会话分叉机制创建的独立会话,而不是靠
提示词要求模型"忽略某些内容"。
- 分支只读。 分支可以读取工作区,但不能修改,因此追问绝不会干扰主对话里正在
进行的工作。
- 大树可渐进折叠。 每个锚点可收成一枚点位,点开后每条分支一枚胶囊,再逐级
展开,深层树也能保持可读。折叠中的分支照常生成,并显示活动标记。
- 不改动原有界面。 原生的对话视图、侧边栏和消息渲染都保持不变,分支也不会出现在
会话列表中。
- 复用模型服务已缓存的上下文。 分支发出的请求前缀与主对话一致,因此无需重新
读取继承来的历史。
环境要求
| 项目 | 版本 |
|---|---|
| DeepSeek Harness | 0.1.0-rc.7(未经修改) |
| Node.js | 22.19 及以上 |
| 包管理器 | pnpm |
安装
dsh plugin --profile web add dsh-nested-followups如果 DeepSeek Harness 的网页服务已在运行,请在安装后重启。
<details> <summary>改用源码安装</summary>
git clone https://github.com/sluminositys/dsh-nested-followups.git
cd dsh-nested-followups
pnpm install
pnpm run check
dsh plugin --profile web add .</details>
卸载插件:
dsh plugin --profile web remove dsh-nested-followups卸载只会移除插件的界面和服务,不会修改你的主对话,也不会删除分支的历史记录。
使用方法
照常打开一个对话,然后点击对话顶栏的 Tree View。在 Chat 和 Tree View 之间切换只改变对话的显示方式,不会复制或转换任何数据。
进入树视图后:
1. 把鼠标移到一条已完成的助手回答上,点击 Ask follow-up; 2. 输入你的问题。它会作为一张卡片出现在所提问回答的右侧,回复在其下方生成; 3. 想在这条分支里继续对话,就在该分支最新的回答上点击 Continue this branch; 想再隔离一层上下文,则再次点击 Ask follow-up; 4. 点击任意卡片可以阅读完整消息。节点较多时,可以使用搜索、聚焦、折叠、缩略图和 缩放控件来浏览。
想继续主任务时,随时切回 Chat。
折叠较大的会话树
首次打开一棵树,看到的就是最小形态:主对话加上每条有分支的回答旁的一枚点位。 点击 ⊕ 后出现每条分支各自的胶囊,再点击某枚胶囊才恢复该分支的消息卡片。打开 点位永远从胶囊列表开始,每一层都由你亲自选择展开哪条;其余胶囊保持折叠。想把卡片 组收回胶囊,把鼠标移到虚线框内侧底边,点击浮现的上箭头阴影区;点击 ⊖ 可把整组 收回点位。
按住 Alt 点击 ⊕ 或胶囊,可以一次深度展开其全部后代;工具栏的 一键全收 会把 所有一级锚点组收成点位。重启后按当前会话恢复布局。折叠状态下,蓝色脉冲表示后代仍在 生成,红色表示其中有失败;搜索命中折叠内容时会自动逐级展开祖先链并定位消息。
两个动作,两种含义
这两个动作的区别不只体现在外观上,也体现在数据结构中:
| 动作 | 生长方向 | 效果 |
|---|---|---|
| Ask follow-up | 向右 | 新建一条分支,继承到所选回答为止的对话内容 |
| Continue this branch | 向下 | 在当前分支中追加下一轮对话 |
Ask follow-up 绝不会向已有分支追加内容,Continue this branch 也绝不会新建 分支。后者只出现在某条分支最新的已完成回答上,主对话中不会出现。
删除分支
删除一条分支时,它下面的所有分支也会一并删除。确认对话框会说明将要删除多少条分支 和多少条消息。主对话和同级的其他分支不受影响。
工作原理
分支隔离
每条分支都是一个真实的 DeepSeek Harness 会话,从其上级对话的一个完整回合处创建。 以从回答 A2 创建的分支为例,它继承从对话开头到 A2 为止的全部内容;主对话在此之后 产生的内容不会进入这条分支,分支里的内容也不会进入主对话。从同一条回答创建的多条 分支之间同样互不可见。
分支会被标记为子代理来源的会话。这样既能让它们不出现在会话列表中,又完整保留了各自 的历史记录——分支从属于它的主对话,而不是变成一个需要你单独管理的条目。
只读执行
分支以只读方式运行:可以查看工作区,但不能改变其中的任何内容。
这一限制是在工具真正执行时生效的,而不是通过对模型隐藏工具来实现。允许使用的工具 如下:
read、read_image、glob、grep、lsp、session_* 系列查询工具、job_list、 job_output、terminal_list、terminal_read、list_agents 和 get_goal。
其余一律拒绝,包括插件不认识的任何工具,因此新增的工具不会因为遗漏而被放行。代码 模式的 run_code 仍然可用,因为程序调用的每个工具都会被逐个检查,其中的写入操作会 被逐个拒绝。
放行读取是有意为之:追问常常就是"这个文件是做什么的"。而写入不能放行,因为分支与 主对话使用同一个工作目录,否则分支可能在任务进行过程中修改文件。
复用模型服务的缓存
插件不会改写分支发出的请求。分支会沿用其上级会话所使用的配置组合,并且完全不改动 工具定义、提示词段落和呈现格式。因此,分支请求的开头部分与主对话在分叉点处的请求 逐字节一致。
这直接关系到响应速度。模型服务会缓存请求的前缀,而工具定义正好位于请求的最前面。 哪怕只移除一条工具定义,开头的字节就变了,整段缓存随之失效,模型服务必须重新读完 继承来的全部对话,才能给出回答的第一个字。限制可见工具列表实现起来更简单,但会白白 放弃这份收益,而且并不会更安全——隐藏一个工具和拒绝执行它,拦下的是同一次调用。
与 DeepSeek Harness 0.1.0-rc.7 的兼容性
当前版本面向未经修改的 @deepseek-ai/dsh 0.1.0-rc.7。以下两项限制源于该版本对 子代理来源会话的处理方式。
分支无法在原生对话界面中续聊。 DeepSeek Harness 用子代理来源标记来判断一个会话 归哪个组件所有,并会拒绝从原生对话界面向这类会话发送消息。原生界面可以显示分支的 历史,但无法向其中追加内容。因此当前版本没有提供"在对话中打开分支"的功能,阅读和 续聊都在树视图中完成。
分支可能出现在子代理菜单中。 由于插件不会安装子代理描述符,对话内置的子代理菜单 可能会把分支显示为不可用的条目。这些条目无法选中,键盘浏览时会被跳过,也不计入活跃 子代理的数量,菜单和对话本身都能正常使用。分支仍然不会出现在侧边栏的会话列表里。
插件中预留了对一项尚未发布的 DeepSeek Harness 能力的检测,该能力将允许在原生对话 界面中续聊分支。检测要求对应版本同时提供该能力并明确声明支持投递用户消息,以免某个 只实现了一半的版本悄悄启用可写界面。在此之前,该功能保持关闭。
开发
pnpm install
pnpm run checkpnpm run check 会依次执行代码检查、宿主端与浏览器端的类型检查、测试、生产构建和 发布包校验。
| 命令 | 用途 |
|---|---|
pnpm run lint | 静态检查 |
pnpm run typecheck | 类型检查 |
pnpm test | 单元测试与集成测试 |
pnpm run build | 生产构建 |
pnpm run check | 以上全部,外加发布包校验 |
参与贡献
欢迎提交问题反馈和合并请求。提交合并请求前,请先运行 pnpm run check。
项目状态
当前实现已在未经修改的 DeepSeek Harness 0.1.0-rc.7 上验证通过。DeepSeek Harness 仍处于开发者预览阶段,即使本软件包声明的兼容范围更宽,后续版本仍可能需要相应更新。
许可证
[MIT](LICENSE)