elegant01/dsh-scalpel:在 DSH 会话里做上下文对比与裁剪

前言

DSH(DeepSeek Harness)的会话是 append-only 的事件日志,而模型每次请求都拿到一份由历史拼出来的 messages。这带来一个具体难题:同一会话里问了两次同一个问题,想并排看两次回答的差异;或者长会话里前面几轮已经没用了,但它们仍然留在每一次发给模型的请求里,既不划算也影响后续判断。已有的做法一般是开新会话,代价是丢掉上下文;手工改会话文件则会破坏 replay。

下面介绍的插件是 elegant01/dsh-scalpel,维护者 elegant01,分类为「记忆」,许可证 MIT。它只做两件事:同会话对比两次(最多三次)回答,以及把指定的若干轮从之后每次请求里摘掉。它的定位是「上下文手术刀」,而不是会话管理器——会话文件、界面、别人的视角都不动。

核心功能

同会话对比。 同一个会话里选两条(或三条)回答,段落级对齐 + 词级高亮。面板提供左中右三列、⇄ 交换、仅看差异 折叠相同段,以及按关键词只留命中段落的搜索。

真实用量对照。 每条回答的 token 总量、未缓存输入、缓存读取 / 写入、输出和缓存命中率左右并排展示;VS 头也带一行 X tok · 缓存命中 Y%。

同会话剔除。 把指定轮从之后每一次发给模型的请求里摘掉。规则按 sessionId + 轮号区间 存盘,每轮重读,改规则不用重启。

按预算选删。 选目标 200K / 500K / 1M 和保留最近几轮,插件自动算该删 #1–#K,预览删完还剩多少 tok。

规则可视化。 面板可直接查看当前生效的剔除区间,一键应用或撤销,走宿主半提供的本地接口,不用回终端。

需要先澄清的是:这里的「剔除」不是「删除」。历史落盘后不可改,插件只改写发给模型那份副本。因此它永远不剔除当前正在回答的那一轮,也只能按整轮切,不能拆单条消息,以保证 tool_use / tool_result 成对,避免 400。前缀一变会让 prompt cache 冷一次,这是设计选择。

安装与启用

dsh plugin --profile desktop add dsh-scalpel
# 把 dsh.profile.bundles 里加上 "dsh-scalpel",然后完全退出 DSH 再启动

该插件要求 dsh >=0.2.1-rc.1 <0.2.2。bundle 是开机捕获的,只刷新页面不生效。

本地开发时把仓库链进 profile 的 node_modules,在 package.json 中加依赖 "dsh-scalpel": "link:../../local-plugins/dsh-scalpel",并把 dsh-scalpel 写入 dsh.profile.bundles,然后完全退出 DSH 再启动。注意 ~/.dsh/local-plugins/<name>/ 不会被自动扫描,文件夹存在不等于加载。

典型用法

对比有三个入口:会话视图切换栏顶部的「对比」tab、assistant 消息动作行的「⚖ 对比」、以及终端的 scalpel compare。面板里左选一条、右选一条,还能加第三条做三路对比;没有重复提问时默认选最近两条。端到端可复现的命令行:

scalpel sessions --limit 5                 # 最近的会话
scalpel turns latest                        # 这个会话有几轮
scalpel compare latest --a 1 --b 2          # 第 1 轮 vs 第 2 轮
scalpel compare latest --a 1 --b 2 --json   # 结构化输出,给别的工具吃

剔除主要走面板:顶部切到「删除范围」,在回合表里点两行选一个区间,每一行自己报 N 字 · 约 X tok。也可以命令行直接操作:

scalpel drop latest --from 5 --to 7 --dry   # 只打印将写入的规则,不落盘
scalpel drop latest --from 5 --to 7         # 真摘
scalpel undrop latest                       # 全撤
scalpel rules                               # 当前规则
scalpel audit --limit 20                    # 每轮摘了几条

规则文件是 ~/.dsh/scalpel-drop.json,格式如下:

{
  "version": 1,
  "sessions": {
    "<sessionId>": {
      "dropTurns": [[5, 7]],   // 剔除第 5~7 轮;轮 = 一条用户消息开始的一段
      "dryRun": false          // true 时只写审计,不动 messages
    }
  }
}

会话数据来自 ~/.dsh/sessions/<workspace>/session-<uuid>/session.v4.jsonl.zstd,多帧 zstd 按 magic 28 B5 2F FD 切帧解压,Node 22 内置 zstdDecompressSync 直接读,无第三方依赖。每轮摘了几条、省了多少字符,写进 ~/.dsh/scalpel-audit.jsonl。

关于轮号,有两个容易踩的定义:工具返回(role: "user" + tool_result 块)不另起一轮;宿主给的是 session-<uuid>,CLI 和面板用的是裸 <uuid>,两种写法都能命中。

装了但没生效时先跑诊断:

scalpel doctor

它会一次列出 Node 有没有 zstd、exports["./client"] 在不在、dsh.client 的 platform/immediately 对不对、依赖和 dsh.profile.bundles 两处是否都写了、探针多久没更新等。最常见的坑是只加了依赖没加 dsh.profile.bundles(宿主不加载、不报错),以及改完只刷新页面(探针时间戳会暴露这一点)。

适用场景与注意

适合这样的开发者:需要在长会话里控制发给模型的上下文体积,或者想确认两次回答到底差在哪,并且希望变更规则后不必重启。它是纯 ESM、无构建步骤,client.js 是手写 bundle。测试用 npm test 即可在不装 DSH 的情况下验证宿主半行为。

几点需要留意:插件以当前 DSH 进程的权限运行,安装前应检查源码与许可证(MIT)。它不适用于想让模型「以后再也不提 B」的场景——剔除只是让模型看不见,你自己的会话里 B 仍在,要彻底干净请开新会话加交接稿。也不要用它物理删除某段历史,直接改 session.v4.jsonl.zstd 会破坏 replay,真要删就整会话归档。

结尾

dsh-scalpel 的价值在于把「对比」和「裁剪」这两类上下文操作收进一个插件,且只作用于发给模型的副本,不动真相源。目录页见 https://www.skillhub.cn/plugins/elegant01/dsh-scalpel ,源码见 https://github.com/elegant01/dsh-scalpel 。社区目录是独立站点,与 DeepSeek / 幻方无官方从属关系。

羽毛球分组比赛记分
小程序二维码

欢迎使用《羽毛球分组比赛记分》微信小程序

小夜