dsh-ptc-noargs:修复 run_code 中无参工具调用的 binding 报错

前言

在 DeepSeek Harness(DSH)里用 PTC 的 run_code 写一小段 TypeScript,再调用宿主暴露的工具,是常见工作流。不少工具的首参是可选对象:模型往往会写成 await tools.job_list() 或 await tools.job_list(undefined),而不是显式传 {}。PTC worker 在把调用交给宿主前,会对绑定参数做 lossless JSON 快照;undefined 没有可序列化表示,调用会在 worker 侧被拒绝,宿主收不到请求,报错通常是 binding arguments must be lossless JSON。手动改成 await tools.job_list({}) 可以绕过,但很难保证模型每次都写对。下面介绍 Cordis 插件 dsh-ptc-noargs(维护者 TLEWA,分类:工作流):在不大改 runtime 的前提下,对 run_code 里 TypeScript function-body 的执行副本注入一行 prelude,把「省略首参」和「显式 undefined」归一成 {}。

这是什么

dsh-ptc-noargs 是一个最小的 Cordis 插件,面向 DSH PTC 的 run_code 绑定场景。它监听共享工具流水线的 tools/execute waterfall;仅当工具是 run_code、程序为 TypeScript function-body、且参数里含 code 时,在实际执行的 code 前追加 prelude,用包装后的 tools 命名空间拦截无参或首参为 undefined 的调用。

插件不修改 PTC runtime、不修改工具定义,也不改模型与日志里的原始 code;只有执行副本带 prelude。

问题与原理

报错从哪来

在 run_code 中若写成:

await tools.job_list()
await tools.job_list(undefined)

PTC worker 会因 binding 参数无法做 lossless JSON 序列化而失败,典型错误为:

binding arguments must be lossless JSON

显式传对象可以绕过,例如 await tools.job_list({}),但这依赖模型习惯,不稳定。

插件怎么做

prelude 会克隆 tools,对每个函数做薄包装:首参省略或为 undefined 时改为 {},其余参数原样传递;用户代码仍使用名字 tools。null 不会被改写。插件只处理 run_code 的 PTC 绑定,不适用于原生工具执行器下的普通工具调用。

支持范围与限制

安装前建议通读 README 中的限制,避免误判「没生效」:

  1. 仅支持 TypeScript function-body(PTC 默认模式);Python、REPL、script 模式会跳过。
  2. prelude 占一行,用户代码行号整体后移 1 行;报错栈中的行号也会偏移。
  3. 依赖 tools/execute 上可替换 arguments 的执行对象;上游若收紧行为,插件会安全跳过(warn,不阻断调用)。
  4. 已在 DSH 0.2.2-rc.1 验证;更低版本需自行核对 engines。

安装与启用

插件应放在稳定目录,不要只留在临时工作区。DSH 社区插件目录(SkillHub)与 GitHub 仓库相互独立,并非 DeepSeek / 幻方官方应用商店;安装方式以仓库 README 为准。

方式一:桌面端插件页(推荐,通常无需重启)

  1. 打开 插件 → 添加插件,输入插件的本地目录路径(需先自行将仓库放到稳定位置,README 示例使用 git clone 到固定路径,此处不重复克隆命令)。
  2. 安装后点 立即启用;管理器显示「运行中」即已生效。

若 dsh 不在 PATH,可改用 DSH 安装目录下的 resources\runtime\cli\bin\dsh.cmd(Windows 路径以 README 为准)。

dsh plugin --profile desktop add "link:C:\Users\<you>\.dsh\local-plugins\dsh-ptc-noargs"

也可在插件目录执行 npm pack,用生成的包安装(不依赖源码目录继续存在):

dsh plugin --profile desktop add "C:\path\to\dsh-ptc-noargs-0.1.0.tgz"

CLI 安装后需重启 DSH;插件页热加载通常不用重启。

卸载

dsh plugin --profile desktop remove dsh-ptc-noargs

从插件管理器卸载后立即恢复行为;CLI 卸载后需重启。插件不写入 DSH 安装目录;link: 安装主要在 profile 的 package.json / Cordis 组合中增加一项,卸载后应恢复原状。

安全提示:插件随当前 DSH 进程权限运行。安装前应阅读 lib/ 与 cordis.patch.yml、确认 MIT 许可证与来源归属,再启用。

典型用法与验证

启用后,在 run_code 的 TypeScript function-body 中可继续使用模型常用的无参写法:

await tools.job_list()
await tools.list_agents()

预期返回正常结果,而不是 binding arguments must be lossless JSON。README 中的对照还包括 await tools.job_list(undefined)、await tools.get_goal() 等;未启用时同一 await tools.job_list() 会恢复该报错。

开发者在插件仓库内可跑单元测试:

node test/prelude.test.mjs

README 说明 12 项测试覆盖省略首参、undefined、null、非 TS runtime 跳过等情形。

适用场景

  • 经常在 run_code 里编排 DSH 工具、且模型爱写 tools.foo() / tools.foo(undefined) 的开发者。
  • 希望少改提示词、少教模型「空对象也要写 {}」的工作流场景。
  • 不需要 Python / REPL / script 模式下的同类修补(本插件会跳过)。

若你关心 PTC 以外的体验,同一维护者还在 README 中列出其他 DSH 项目(如 dsh-better-choice、dsh-fastload 等),可按需从 GitHub 查阅,与本插件无安装依赖。

结尾

dsh-ptc-noargs 用一行 prelude 在 run_code 执行路径上归一化首参,专门对付 binding arguments must be lossless JSON,改动面刻意保持很小。查阅说明与源码:GitHub;在 DSH 里从社区目录进入:SkillHub 插件页。

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

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

Xiaoye