前言¶
在 DeepSeek Harness(DSH)里跑 Agent Loop,工具调用通常走 provider 原生的 tool-call 事件。若上游经 Sub2API 等渠道把 DeepSeek 的工具意图写进 reasoning 或 text 的 DSML 文本,而不是标准 tool-call,DSH 侧往往无法继续执行,Agent 会卡在「有调用语义、没有可执行事件」的状态。社区插件 dsh-llm-sub2api-dsml(维护者 Nicolas-One,GitHub 仓库 dsh-llm-sub2api-dsml)在现有 LLM provider 流上做缓冲与解析,把完整、合法的 DSML 转成 DSH 原生工具事件,让 Loop 按 finish(kind=tool-calls) 继续走权限检查与工具执行。下面介绍它的定位、能力与安装方式。
这是什么¶
dsh-llm-sub2api-dsml 是 DSH 的 DSML 兼容插件(MIT 许可证,作者 wwj)。它不新建上游连接、不保存密钥;原适配器仍负责协议、SSE、认证、附件与历史序列化。插件根据模型 ID 是否包含 deepseek(不区分大小写)自动匹配任意 provider 的流,沿用原模型分组,无需切换模型或维护提供商名单。
处理链路可概括为:
现有 LLM provider → reasoning / text 中的 DSML
→ 流式缓冲 → 当前工具 schema 校验 → DSH tool-call
→ finish(kind=tool-calls) → DSH 权限检查与工具执行
目录页:skillhub.cn 插件页(社区目录,与 DeepSeek / 幻方无官方从属关系)。
兼容要求¶
使用前请核对环境与前提:
- DSH:当前插件在资料中声明并验证支持
0.2.1-rc.3(package 版本0.2.1-rc.3.1)。 - Node.js:
>=22.19.0;CI 覆盖 22.19.0 与 24。 - 已配置且可用的 LLM provider,且所用模型 ID 包含
deepseek;deepseek-v4.1-flash、prefix/DeepSeek-R1等均可自动匹配。 - 不限定提供商或上游协议;模型 ID 不含
deepseek的别名不会被识别,正常响应保持原样,仅在检测到完整合法 DSML 时才转换。
核心功能¶
自动匹配与透传¶
- 安装并加载后,任意已有 provider 下满足模型 ID 规则的请求都会参与检测;辅助请求(
purpose非空)直接透传。 - 若原生 tool-call 先到,不再转换 DSML,避免重复提交。
解析与校验¶
- 支持跨 SSE 分片的标签、reasoning / text,以及最终
block-end权威文本。 - 只识别独立成行、代码围栏外的
<|DSML| calls>或<|DSML| tool_calls>根节点;行内示例、围栏内示例和无根 XML 不会被执行。 - 支持多个
invoke、带或不带 DSML 前缀的内部标签、单双引号属性、字符串与 JSON 参数。 - 按当前请求声明的工具 schema 校验;未知工具、重复参数、缺参、非法 JSON 或类型不符会失败,不猜测参数或补全闭合标签。
- 每段最多 64 个调用,每个调用生成独立 ID;完整合法 DSML 到达后立即关闭上游流并提交,调用段后的生成不再读取。
配置¶
| 字段 | 说明 |
|---|---|
dsmlCompatibility |
默认 true;设为 false 关闭转换。 |
maxBufferChars |
DSML 缓冲上限,默认 1048576 字符,允许 1024 到 8388608。 |
升级旧配置时,compatibleProviders 仍可被读取但不再限制模型匹配,可删除。sourceProvider 默认留空;仅当需要继续使用旧内部路由的会话才显式填写源 provider ID,此时可通过 provider 指定内部路由 ID(默认 sub2api-deepseek-dsml)。
明确不覆盖的范围¶
资料中说明:本插件不设置推理强度,也不解决所有 thinking 历史回传问题。 Sub2API 的推理强度显示、output_config.effort 映射,以及 content[].thinking must be passed back 等需另行核对上游协议与原适配器配置。插件只产生原生事件,无法恢复已结束的历史回合;主动结束流时可能收不到最终 usage,只保留已收到的用量。
安装与启用¶
插件以 tarball 形式安装到指定 profile。官方 README 给出的流程如下:在源码目录安装依赖、测试并打包,再用 dsh plugin add 指向生成的 .tgz(将 web 换成你的 profile)。
git clone https://github.com/Nicolas-One/dsh-llm-sub2api-dsml.git
cd dsh-llm-sub2api-dsml
npm install --ignore-scripts
npm test
npm pack
dsh plugin --profile web add ./dsh-llm-sub2api-dsml-1.0.0.tgz
包内已含 JavaScript 入口与 dsh.bundle 配置层,无需额外构建。安装与配置层机制见 DSH 官方插件打包文档。
若之前手动挂载过同名插件,请先统一安装方式,避免重复插件行与内部路由冲突。
如需关闭转换或调整缓冲上限,可将配置合并到 $DSH_HOME/profiles/web/cordis.patch.yml 顶层数组:
- id: sub2api-dsml
config:
dsmlCompatibility: true
maxBufferChars: 1048576
已有其他配置项时保留其数组项;此行会覆盖 bundle 插入的插件配置,覆盖会替换整个 config,请完整保留上述字段。可复制仓库内 配置示例。
用下面命令检查最终配置:
dsh --profile web --dump-config
让目标实例加载新配置后,继续选择原 provider 下的 DeepSeek 模型即可。是否可热加载取决于宿主;安排重启时应先结束正在运行的任务——已开始的请求不会被转换。
典型用法¶
安装并校验配置后,用法与平时一致:在已有 provider 下选用模型 ID 含 deepseek 的模型,在 DSH Agent 中声明工具 schema 并发起对话。当模型在 reasoning 或 text 中输出完整、合法的 DSML 根节点时,插件将其转为 DSH tool-call,后续由 DSH 做权限检查与执行。
本地仅做解析与组装、不执行工具时,可使用仓库中的 replay 入口(从标准输入读消息与 schema):
npm install --ignore-scripts
npm test
测试说明见 README:test/replay.mjs 仅解析和组装,不要将真实会话、命令或凭据提交到仓库。
适用场景与注意¶
适合谁: 已在 DSH 0.2.1-rc.3 上配置 DeepSeek 相关模型,且上游把工具调用以 DSML 形式出现在 reasoning/text 中、导致 Agent Loop 无法继续的开发者。
权限与安全: 插件在当前 DSH 进程权限下运行;安装前请阅读源码与 MIT 许可证,确认行为符合你的环境策略。插件不保存密钥,但工具执行仍受 DSH 权限模型约束。
失败与边界: DSML 未闭合前若取消、错误或截断,不会产生工具调用;未闭合调用在正常结束时返回 DSML_INVALID_CALL。修改响应后会丢弃旧 replayState,下一次请求由原适配器按标准历史序列化。
卸载时,确认旧会话不再使用隐藏路由后,删除 profile 中 sub2api-dsml 覆盖配置,再执行:
dsh plugin --profile web remove dsh-llm-sub2api-dsml
结尾¶
dsh-llm-sub2api-dsml 在不动原 provider 的前提下,把泄漏到 reasoning/text 中的完整 DSML 转成 DSH 原生工具调用,是「模型推理」类场景里补全 Sub2API 链路的实用插件。问题反馈见 GitHub Issues。
- 目录页:https://www.skillhub.cn/plugins/Nicolas-One/dsh-llm-sub2api-dsml
- 源码与文档:https://github.com/Nicolas-One/dsh-llm-sub2api-dsml