@yukari316/dsh-toolcall-compat
v0.1.4
Published
DSH tool-call compatibility: strips sandbox_permissions/justification from tool-call arguments for third-party models (GPT etc.), and lets the user skip possibly-stuck tool calls with an LLM-facing notice.
Maintainers
Readme
dsh-toolcall-compat
DSH 插件,解决第三方模型(GPT 等)用 DSH ToolCall 时的两个问题:
- 模型在工具调用参数里乱带
sandbox_permissions/justification,每次重试都撞上同一个校验错误; - 某些工具调用长时间不返回,整个回合卡住,没有跳过的办法。
- npm:https://www.npmjs.com/package/@yukari316/dsh-toolcall-compat
- 源码:https://github.com/Yukari316/dsh-toolcall-compat
功能一:兼容模式(schema-fix)
DSH 对工具调用的升级参数校验很严格:
sandbox_permissions和justification必须成对出现,且justification必须是非空句子,否则报invalid justification: expected a non-empty sentence;- 请求的
sandbox_permissions必须严格宽于当前生效模式,否则报sandbox escalation to "..." is not strictly wider than this call's current "..." mode。
GPT 这类模型经常把这两个字段塞进每一次调用,结果就是每次重试都在同一个错误上失败。工具参数在派发时会被 deepFreeze,下游 hook 改不了,所以这个插件在更上游的 llm/stream 流里动手:agent loop 是用流里的 block-end chunk 组装 assistant 消息的,在这里改写 tool-call 块的 arguments,派发、日志、回放一次全修好。
怎么判,看本次调用生效的沙箱模式(sandboxPolicy.resolve({ session }).mode,按 DSH 自己的严格更宽阶梯):
- Full access:阶梯顶端没有更宽的模式,
sandbox_permissions传什么都冗余,一律剥离(GPT 反复失败主要就是这种情况); - 受限模式(read-only / workspace-write):
- 参数对畸形(两个键不成对、理由为空或非字符串、目标不是合法模式)→ 剥离,避免执行时报校验错;
- 合法提权(非空理由 + 目标严格更宽于当前模式)→ 原样保留,走 DSH 正常的用户审批流程;
- 模式解析不出来时(没有 sandboxPolicy 服务、找不到会话等)→ 保守处理:只剥离畸形和冗余的,不猜。
开关默认开启。只影响带这两个键的调用,其余参数、调用 ID、工具名原样不动;非 JSON 参数直接放行,不会破坏流。
功能二:跳过卡住的调用(stuck-skip)
Host 侧在 tools/execute 外层记录每个 in-flight 调用,把真实派发和"用户跳过"信号做 race。浏览器端自绘了 tool-call 节点(conversation.chat.node 是单胜者插槽,要在官方卡片上方插提示条只能替换整个渲染器,官方专用视图就看不到了),当某个调用运行超过阈值(默认 15s),卡片上方会出现提示条:
⚠ 工具调用长时间未响应:bash(已运行 42s)[跳过]
点「跳过」之后:
- Host 中止该调用的融合 signal(能配合的工具会终止底层进程);
- race 用错误形状的结果完结这次调用,LLM 下一步会看到类似
skipped because unresponsive ... do not retry的说明; - 派发管线照常提交
tool/result,对话继续。
跳过结果必须用错误形状(isError: true + error.info.code: 'TOOL_SKIPPED'),因为 DSH 会对成功结果按工具自己的 output schema 重新校验(比如 pwsh 只接受 {kind: 'background'|'foreground'} 且禁止额外字段),通用的成功值永远过不了;错误结果不走这条校验。
参数被剥离的那次调用,卡片上会有一个黄色的 compat bypass 徽标,方便你看出这次调用被改过。
安装
装好 DSH 之后,一条命令搞定,不用改任何配置文件。
方式一:官方命令(需要 pnpm)
dsh plugin --profile web add @yukari316/dsh-toolcall-compat方式二:没有 pnpm,用 npm
npx -y @yukari316/dsh-toolcall-compat这个命令会:把包装进 web profile 的 node_modules、自动在 profile 的 dsh.profile.bundles 里注册插件(重复执行不会重复注册)、提示你重启。想装到别的 profile 就加 --profile <名字>。
装完
dsh web插件默认开启,不用额外设置。想改默认值,见下面的「设置项」。
怎么确认生效
让模型(比如 GPT)执行一次会触发沙箱权限的工具调用:
- 不再报
invalid justification/sandbox escalation ... not strictly wider,说明兼容模式在工作; - 装了插件前后的调用日志里,带
sandbox_permissions/justification的调用数量会明显减少。
更新 / 卸载
更新:
dsh plugin --profile web update @yukari316/dsh-toolcall-compat # pnpm
# 或者
npx -y @yukari316/dsh-toolcall-compat # npm,重复执行即更新卸载:从 profile 的 package.json 里删掉 dsh.profile.bundles 中的 @yukari316/dsh-toolcall-compat 和 dependencies 里的对应项,再重启 dsh web。
为什么以前要两步(装包 + 手改
cordis.patch.yml)?DSH 只启动组合配置里列出来的插件,npm install只是把代码放进磁盘。这个包现在声明了dsh.bundle,自带启用 patch(cordis.patch.yml),dsh plugin add/ 上面的 npx 命令会自动完成注册,所以不需要再手动加行。
装完之后:能用的部分
这个插件由两部分组成,0.1.2 起两部分都随包发布:
- 服务端部分:跑在 DSH 进程里,负责修正工具调用参数、跟踪和跳过卡住的调用。兼容模式默认开启,装好重启后就开始起作用。
- 浏览器部分:网页里的界面——设置卡片(设置 → 插件配置 里的 ToolCall Compat)、工具调用卡片上的「跳过」按钮和
compat bypass徽标。这部分打包成 DSH 浏览器模块系统要求的格式随包发布,安装后即可加载。
设置项
| 字段 | 默认 | 说明 |
| --- | --- | --- |
| enabled | true | 兼容模式总开关 |
| renderEscapes | true | 展开卡片时把转义序列显示成字符 |
| stuckAfterMs | 15000 | 调用运行超过多久才提示可跳过(1–600s) |
设置界面随包发布。想改默认值,可以在 $DSH_HOME\settings.yaml 里加一段:
toolcall-compat:
enabled: true
renderEscapes: true
stuckAfterMs: 15000从源码构建(开发者)
npm install
npm run build # tsc → lib/,再把 client 半部打成 DSH 浏览器 bundle
npm test # 契约测试npm publish 前会自动重新构建(prepack)。
License
MIT © Yukari316
