dsh-tool-cassette:给 DeepSeek Harness 工具调用装一台录像机

前言

给 Agent 工作流写测试,通常要同时应付两类不稳定因素:模型输出和外部工具。官方的 dsh-llm-replay 已经能回放模型流;但 HTTP、MCP、数据库这类工具在测试中仍可能真的访问网络、修改数据,或者依赖一台刚好没开机的服务,第三方接口在 CI 里偶尔还会返回 429

dsh-tool-cassette 是 DeepSeek Harness(下称 DSH)的社区插件,做法很直接:第一次让被选工具真实执行,把规范化结果录进 cassette 文件;之后切到回放模式,真实工具正文调用为 0,录好的结果按精确匹配递回工具链。和手写 mock 相比,它录的是 DSH 规范化后的 value/error,回放时还要重新通过当前的输出契约。下面介绍它的能力、安装方法和使用边界。

这是什么

DSH 的理念是「一切皆插件」,dsh-tool-cassette 就是这个机制下的一个社区插件。它的定位写在 package 描述里:DeepSeek Harness 叶子工具正文边界的确定性录制、完整性校验与离线回放插件。

几项基本信息需要先说清楚:

  • 由社区成员 Lem0nTea2002 独立开发和维护,是非官方社区插件,与 DeepSeek 官方无隶属关系,未获官方审核或背书;
  • 许可证为 MIT;
  • 当前版本 0.1.0,固定兼容 DeepSeek Harness 0.1.0-rc.8(该版本当前位于 npm next 标签),安装与运行需持续使用同一 rc.8 CLI;
  • Node 引擎要求 ^22.19.0 || >=24.0.0;peerDependencies 为 @deepseek-ai/cordis 4.0.1、@deepseek-ai/dsh-tools 0.1.0-rc.8、@deepseek-ai/schemastery 3.18.1。

录制与回放怎样工作

Record:先真实跑一遍

Record 模式下,include 选中的工具(HTTP、MCP、数据库、本地程序)会真实执行,插件把 DSH 规范的 value/error 写入版本化 NDJSON cassette,内容包含 additionalContexts 和取消结果。未选中的工具按原有流程执行,录像机不抢戏。

录制流程是固定的:

1、独占创建 <file>.partial
2、串行追加 headercall/startcall/result 帧;
3、每帧同步到磁盘;
4、全部调用完成后写入 complete 尾帧;
5、关闭文件,以 create-only 方式原子发布正式文件,再删除 partial。

制品自带完整性协议:每帧包含连续 seq、前一帧哈希和本帧 SHA-256,最后一帧为 complete。截断、帧重复、哈希篡改、协议版本错误和缺少尾帧,都会在 Replay 激活前被拦下。正式文件或 partial 已存在时录制器拒绝启动;录制存在未完成调用时保留 .partial 并拒绝发布正式文件。

需要注意,哈希链不含数字签名:它能发现传输损坏、截断和普通篡改,但面对能重写全部帧与哈希的攻击者,应由制品库补充签名、WORM 或不可变存储。

Replay:四项身份精确匹配

Replay 时,插件按四项身份判断是不是同一次调用:

1、工具在调用树中的结构路径;
2、工具名称;
3、递归排序对象键后的无损 JSON 参数;
4、按调用开始顺序分配的 ordinal。

匹配是精确的:参数对象键顺序无关,{ "city": "武汉", "unit": "c" } 换成 { "unit": "c", "city": "武汉" } 仍能命中;但数组顺序、参数值、调用顺序或结构路径一变,回放器立即返回 CASSETTE_MISMATCH。并发调用按开始顺序分配 ordinal,支持倒序完成,先开始后结束的调用不会错配。

Replay 命中后,真实工具正文调用为 0,保存的成功 value 会重新经过当前的输出 schema、renderer、presentation meta 和后置策略。所以回放时仍需注册同名工具,并保持输出契约兼容:录像带只负责保存结果,安检规则仍由当前的 DSH 执行。

对不上就失败关闭

第一次轨迹偏差会让回放器进入 poisoned 状态,后续被选工具持续失败,真实正文不执行,避免一半读录像、一半碰真实服务的混合局面。其余几种情况也有明确处置:

  • 参数、路径、顺序或工具名不一致:返回 CASSETTE_MISMATCH
  • 回放存在额外调用或未消费记录:headless/CI 进程退出码为 1;
  • 更高优先级插件短路 tools/executetools/post-execute:Record 失效、Replay poison;
  • 被选调用在 pre-execute 或 guard 阶段被拒绝:按未进入 cassette 的轨迹失败关闭。

错误诊断只显示工具、路径、ordinal 和参数指纹,不回显原始参数、结果、原始行或绝对路径。

配置与 CLI

配置只有三项

interface Config {
  mode: 'record' | 'replay'
  file: string
  include: string[]
}
  • moderecord 执行真实工具并写制品;replay 精确命中并跳过正文;
  • file:正式 cassette 文件路径,录制期间使用同路径加 .partial 后缀;
  • include:显式选择叶子工具,支持精确名称与 * 通配符;必须非空,空范围、空路径和重复模式在插件启动时直接失败。

先验带,再放带

dsh-tool-cassette verify .dsh-cassettes/weather.tool-cassette.jsonl
dsh-tool-cassette inspect .dsh-cassettes/weather.tool-cassette.jsonl

verify 完整校验协议、帧配对、连续 ordinal、哈希链与完成尾帧,用退出码表达结果;inspect 显示协议版本、工具数、调用数与消费说明。校验失败只输出结构性原因,不回显原始行、工具正文或绝对路径。

安装与启用

前置条件:已安装 pnpm,Node 版本满足 ^22.19.0 || >=24.0.0。插件固定兼容 DSH 0.1.0-rc.8,安装与运行 profile 请使用同一 rc.8 CLI。

安装命令:

pnpm dlx --package @deepseek-ai/dsh@0.1.0-rc.8 dsh plugin --profile headless add dsh-tool-cassette

安装包会通过 cordis.patch.yml 注入一个默认禁用的 tool-cassette 条目。先做录制:在 profile 的 cordis.patch.yml 中覆盖它,填写模式、文件和叶子工具范围。

- id: tool-cassette
  name: dsh-tool-cassette
  disabled: false
  config:
    mode: record
    file: .dsh-cassettes/weather.tool-cassette.jsonl
    include:
      - weather_lookup
      - mcp_*_read

跑完一次真实调用后,把 mode 改成 replay,其余轨迹保持一致:

config:
  mode: replay
  file: .dsh-cassettes/weather.tool-cassette.jsonl
  include:
    - weather_lookup
    - mcp_*_read

经过上面的步骤,再调用 weather_lookup 时,cassette 会递出录制结果,真实工具正文不再执行。

如果想从源码构建并安装本地包:

pnpm install
pnpm run demo
pnpm pack
pnpm dlx --package @deepseek-ai/dsh@0.1.0-rc.8 dsh plugin --profile headless add .\dsh-tool-cassette-0.1.0.tgz

相对路径基于 DSH 进程工作目录解析。

一次离线回放演示

项目自带的演示(pnpm run demo)可以完整跑一遍这个流程:

1、启动一个纯本地 HTTP 天气工具;
2、Record 一次,工具正文与网络请求各发生 1 次;
3、关闭 HTTP 服务;
4、Replay 同一条调用,工具正文与网络请求都变成 0;
5、返回结果保持一致,cassette 中的记录全部消费。

整个演示不调用模型,也不产生付费 API 请求。

另外,模型流回放由官方 dsh-llm-replay 负责,本插件只管被选工具正文边界。两者组合,可以搭出模型流与工具流均可回放的无密钥测试。

适用场景与边界

它适合这些情况:

  • 给 Agent 工作流做离线回归测试;
  • 在 CI 中复现一次昂贵或偶发的工具响应;
  • 验证插件升级后,当前 schema、renderer 和后置策略仍能处理旧结果;
  • 调试 HTTP、MCP、数据库或本地程序工具,不想反复触碰真实服务。

V1 的能力范围是:单 Agent、单场景;显式选择的叶子工具;成功、结构化失败、additionalContexts;并发开始顺序与倒序完成;调用前取消不消费记录。以下明确不支持或留待后续版本:

  • 多 Agent 与并发 subagent;
  • 同时选择复合工具及其子工具;
  • concludesTurn: true
  • 模糊匹配、参数忽略、自动更新 fixture;
  • 延迟与流式取消时序仿真;
  • UI、云端制品库、benchmark DSL、模型 judge。

还有两点行为要知道:回放命中后会消费对应记录,随后的 post 阶段取消不会回滚消费位置;回放消费状态只存在于当前进程,全部消费完毕时卸载成功,poison、额外调用或未消费记录会让 headless/CI 进程退出码变为 1。它不充当缓存、模型回放器或生产幂等层。

安全与使用注意

V1 为了精确回放,会原样保存规范化后的参数、成功 value、失败信息、渲染内容和附加上下文。cassette 应按密钥文件或测试数据库快照对待:

  • 默认 .gitignore 已排除 cassette 与 partial;
  • 只在隔离的本地或 CI 工作目录录制;
  • 分享前人工检查全部内容;
  • 录制结束后关闭不再需要的真实凭据;
  • 参数指纹没有盐,低熵参数仍可能被猜测。

V1 不提供自动脱敏、加密、签名或远端制品库。

最后是通用提醒:作为社区插件,dsh-tool-cassette 以当前 dsh 进程的权限运行,安装前应先检查源码与许可证(MIT),确认兼容的 DSH 版本后再接入。

结尾

dsh-tool-cassette 解决的问题很具体:把一次真实的工具执行变成可校验、可离线复用的测试制品,用精确匹配和失败关闭保住对轨迹漂移的敏感度。它和官方 dsh-llm-replay 各守一边,合起来能覆盖模型流与工具流的离线回归。

  • GitHub:https://github.com/Lem0nTea2002/dsh-tool-cassette
  • 社区插件目录收录页:https://www.skillhub.cn/plugins/Lem0nTea2002/dsh-tool-cassette (目录为独立站点,与 DeepSeek、幻方无官方从属关系)
羽毛球分组比赛记分
小程序二维码

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

小夜