dsh-turn-sieve · 回合筛
不用新开会话,也能把一段对话里不再有价值的问答或单条消息从后续上下文中筛掉,并且可以撤销上一次删除。
DSH 的会话日志是只追加的:一旦聊长了,早期的寒暄、走错方向的尝试、重复的排错过程就会一直占着上下文。dsh-turn-sieve 在会话右上角的工具区加了一个「回合筛」入口,把当前会话按整段问答或单条消息列出来,你可以勾掉不需要的部分,让它们不再进入后续请求。
从 0.5.1 开始,任意助手回复旁的「筛除」完全在原位完成,不再弹出任何窗口:点击「筛除」后,这一段对话会立刻加深背景并带上圆角阴影,右侧操作条出现 ✓(确认删除) 与 ✕(取消),中间还能切换「整段 / 仅本条」;确认后这段内容会直接从对话里消失,需要时再在「回合筛」里撤销即可恢复。
安装
在 DSH Web 的插件页点击「添加插件」,输入:
dsh-turn-sieve
或者使用命令行:
dsh plugin add dsh-turn-sieve
安装后无需重启,打开任意会话即可在右上角看到漏斗图标和「回合筛」。
使用
- 打开一个已经聊了多轮的会话。
- 点击右上角的 回合筛。面板默认使用液态玻璃外观,标题栏的「液态玻璃」「动效」两个开关可以随时关闭,偏好会保存在本机。
- 选择模式:
- 按整段:一次提问及其后续全部回复、工具调用作为一个整体;
- 按单条消息:逐条勾选,适合只丢掉某一段冗长回复或某次工具输出。
- 在列表上方的搜索框里输入关键词,可以快速缩小范围;勾选后,列表上方会固定显示「将要删除的内容」,它对应会话里的原始提问和回复,方便在确认前再核对一次。
- 勾选不再需要的内容(可以多选,也可以全选可移除项)。
- 点击「移除所选对话 / 消息」,再点一次确认。
- 如果点错了,点击「撤销上一次删除」,再确认一次即可恢复最近一次删除的内容。
直接从原回复删除
不想打开长列表时,可以把鼠标移到任意一条助手回复下方,点击「筛除」:
- 不弹出任何窗口:点击后这段对话在原位直接被选中——背景明显加深、首尾边角变成 18px 圆角并带阴影,左侧还有一条品牌色竖条;
- 选中的默认范围是「整段问答」;如果这段受保护或不可整段删除,会自动退回「仅本条」;
- 右侧操作条会出现 ✓(红色,确认删除) 和 ✕(取消选中),两者之间是「整段 / 仅本条」切换;切换时被高亮的范围会立即跟着变,所以确认前就能看清到底会删掉哪几段;
- 点 ✓ 删除:这段内容会立刻从对话里消失(前端隐藏对应的聊天节点),同时从后续上下文中移除;
- 点 ✕ 取消选中,一切恢复原样;
- 删除后仍可在「回合筛」主面板点「撤销上一次删除」,内容会立刻重新出现在原来的位置。
✓ 的含义是「确认、选中、正确」,✕ 才是取消——这是 0.5.1 特意修正的交互。
列表里每一行会显示(并可随时核对):
- 这段对话或这条消息的开头;
- 第几轮、包含多少条消息(整段模式);
- 大约占用多少 tokens;
- 工具调用数量;
- 是否属于运行时注入;
- 受保护的原因(如果有)。
移除后,这些内容不会再进入后续模型上下文;当前上下文会立即变短,下一轮请求即可生效。
两种模式
按整段
- 从每一条真实用户输入开始新的一段,把这次提问引发的所有助手回复和工具调用都收在同一段里;
- 系统提示与会话初始上下文受保护;
- 最近一轮受保护,避免误删正在进行的任务;
- 适合清理“整段走错方向”的尝试或大段排错过程。
按单条消息
- 一条消息一个可选单元;
- 含 tool-call 的 assistant 消息会和它后续的 tool-result 一起删除,不会留下悬空的工具调用历史;
- 只保护 surface 节点 0 的 system/developer 上下文,不保护最近一轮——因为这一模式的目的就是删掉某一条不想要的回复;
- 适合只丢掉一条特别长的工具输出、一次重复回答或一段无关寒暄。
撤销
- 只保留最近一次删除的撤销记录;
- 撤销会把原始消息重新追加到会话日志,并解除对应区间的前端隐藏。助手回复、工具调用会在原位恢复;用户提问因为消息 id 会重新生成,会显示在对话末尾,但它能重新进入后续上下文;
- 撤销记录保存在 Host 进程内存中,DSH 重启后不可用;
- 助手正在回复时不能撤销,等本轮结束后再试。
安全边界
- 不会删除原始日志。 插件只向 Session 追加一个空的
system/message事件,并用replacesurface 操作覆盖选中的区间。原始事件仍完整保留在会话日志里,可用于导出或审计。 - “从对话中消失”是前端视觉清除。 被筛除的区间由 Host 计算出对应的聊天节点集合(
GET /api/dsh-turn-sieve/hidden),客户端把这些节点隐藏;刷新页面、重新加载会话或 DSH 重启后,隐藏状态都会从日志里的删除标记自动重建,不需要额外开关。 - 系统提示与会话初始上下文受保护。 包含 surface 节点 0 的 system/developer 上下文不会被移除。
- 整段模式保护最近一轮。 单条模式允许删最近的内容,但工具调用与其结果始终成组处理。
- 助手回复期间不可操作。 当前回合没有结束时,插件会拒绝修改,等本轮结束后再试。
- 不拆散工具调用。 assistant 的 tool-call 与对应 tool-result 会被当作一个整体,避免产生不完整的工具调用历史。
- 撤销只有一层。 且撤销记录保存在内存中,Host 重启后会丢失。
和上下文压缩插件的关系
dsh-turn-sieve 不是自动压缩:
- 压缩插件(如
dsh-compaction-basic、billion-context)在上下文接近上限时自动把旧内容总结成 checkpoint; - 回合筛是手动、可挑选的:由你决定哪几段问答或哪几条消息不再重要,然后直接把它们从未来上下文中移除,不生成摘要,也不额外消耗一次总结请求。
两者可以同时安装。
工作原理
DSH 的 Session 有一个「surface」概念:日志保存全部事件,surface 决定哪些事件会投影成模型消息。dsh-turn-sieve 做的事是:
- 读取
session.surface.nodes,按 surface 顺序扫描事件:- 整段模式:每遇到一条真实用户输入就开启一段新的问答;DSH 在每一步注入的运行时上下文(
source.kind === 'runtime-context',以及旧会话里的Time sampled...、Current runtime context.、<system-reminder>、<hindsight_pages>等)虽然也以user/message记录,但会并入当前问答,不会把一段问答拆散。开头的 system/developer 上下文单独成组并受保护。 - 单条模式:一条事件一个单元;assistant 消息中的 tool-call 会等待后续匹配的 tool-result 并合并成一个原子单元;此前删除留下的空 system 标记会被隐藏。
- 整段模式:每遇到一条真实用户输入就开启一段新的问答;DSH 在每一步注入的运行时上下文(
- 对每个单元生成预览、消息数量、工具调用数和 token 估算。
- 用户勾选后,为每个选中区间追加:
session.append('system/message', {
turn,
step: 0,
message: { id, role: 'system', source: { kind: 'system-prompt' }, content: [] },
}, {
surfaceOp: { op: 'replace', startSeq, endSeq },
sourceEventSeqs: shadowedSeqs,
});
空内容的 system message 不会投影成模型消息,因此整段区间从 deriveMessages() 中消失;日志本身没有被修改。
- 删除前把被覆盖的原始事件复制到内存的撤销槽;撤销时以
surfaceOp: 'append'把它们重新追加到末尾,并写入一个turn-sieve-restored-…-r<startSeq>-<endSeq>标记。 - 每个删除标记的消息 id 里编码了被覆盖的区间(
turn-sieve-<stamp>-<index>-r<startSeq>-<endSeq>[-t<turns>])。hiddenState(session)扫描会话事件即可还原“哪些区间被筛掉了”:把区间内每条事件映射成聊天节点 key(13:input-message<消息 id>、14:assistant-step<turn>:<step>、9:tool-call<callId>、16:developer-message<消息 id>),再加上整段模式里完整包含在该区间内的轮次号。客户端拿到{ keys, turns, ranges }后隐藏对应 DOM 节点,并在轮次容器内所有子节点都被隐藏时一并收起容器;一个MutationObserver负责在翻页、重新挂载后重新应用。
注意:替换会让该区间之后的 KV 缓存前缀失效。下一轮请求的输入会明显变小,但首 token 延迟可能略有变化,这是 surface 替换的正常代价。
Agent 工具
插件同时注册了 turn_sieve 工具,助手可以在你明确要求时列出、移除或撤销:
action: "list":返回当前会话的单元列表、受保护标记和 token 估算;mode可选group/message;action: "prune":传入mode和ranges: [{ startSeq, endSeq }]执行移除;action: "undo":恢复最近一次删除。
工具和界面共用同一套 Host 逻辑,行为一致。删除操作仍然只作用于当前会话。
外观与动效
- 液态玻璃:主面板默认采用液态玻璃质感——半透明渐变、
blur(52px) saturate(240%)的背景模糊、边缘高光、顶部斜向流光,以及背后两团缓慢漂移的柔光;标题栏的「液态玻璃」开关可以一键切回普通主题底色。 - 动效:「动效」开关控制两团柔光的漂移和流光扫过;关闭后玻璃质感保留但完全静止。液态玻璃关闭时该开关会自动禁用。
- 两个开关都是带圆点的胶囊按钮,状态保存在浏览器
localStorage(键名dts-glass、dts-motion),刷新后仍然生效。 - 系统设置了
prefers-reduced-motion: reduce时,动画会自动关闭,只保留静态玻璃质感。 - 原位选中的加深背景、圆角与阴影使用 DSH 的主题变量(
--dsw-alias-label-primary、--dsw-alias-brand-primary),浅色和深色主题下都清晰可见。
限制
- 只支持当前在 Host 中处于活动状态的会话;已归档或未加载的会话请先打开。
- 「筛除」动作只出现在已完成的助手回复下方;正在进行的回合结束后才会出现。
- “从对话中消失”是前端视觉清除:原始日志仍然保留,导出会话或在别的设备上打开仍会看到完整内容。
- 隐藏状态按会话推导,多个浏览器标签页各自应用;另一个标签页需要刷新后才会同步隐藏效果。
- 撤销只有最近一次,且只保存在内存里;重启后无法撤销更早的操作(已隐藏的内容仍会保持隐藏)。
- token 数来自
tokenMeter的估算,界面上显示为“约”,用于比较相对大小。 - 需要 DSH
>= 0.2.2-rc.2(Node.js>= 24.9.0)。
开发
git clone https://github.com/GuYou9799/dsh-turn-sieve.git
cd dsh-turn-sieve
npm test
项目结构:
lib/index.js Host 插件:HTTP 路由(groups/prune/undo/lookup/hidden)、分组、surface 替换、隐藏区间推导、撤销、Agent 工具
lib/client.js Web 客户端:会话头部入口、原位「筛除」选中与 ✓ 确认、聊天节点隐藏、液态玻璃面板、搜索与预览
locale/*.json 插件市场元数据
cordis.patch.yml Bundle 插入补丁
test/*.test.mjs 分组、移除、撤销、lookup、隐藏状态与客户端加载测试
本地安装:
# 在 DSH 中执行,或使用 GUI 的“安装本地 Bundle”
dsh plugin add /absolute/path/to/dsh-turn-sieve
License
MIT © 2026 Gu You
No comments yet. Be the first to write one.