前言¶
把 DeepSeek Harness(DSH)部署在企业内网时,有一个常见障碍:出口网关会校验请求的 user-agent,不含指定品牌字样的请求直接被拒。而 DSH 的 LLM 适配器会强制写入自己的 attribution user-agent,这不是在配置文件里改一个字段就能绕过的。
dsh-llm-headers 解决的就是这个问题:它是一个 DSH 插件,在 HTTP 层为发往 LLM provider 的请求注入你配置的请求头。下面介绍它的原理、安装方式和典型用法。
这是什么¶
dsh-llm-headers 为 DeepSeek Harness 的自定义 LLM API 请求注入 HTTP Headers,典型用途是改写 user-agent。代码以 MIT 协议发布,当前版本 0.1.0,托管在 GitHub 仓库 QiE2035/dsh-llm-headers。
它的关键性质是提供商无关:DSH 的 LLM 适配器(dsh-llm-deepseek、dsh-llm-pi-ai)都通过全局 fetch 发出模型请求,所以插件只包装一次 fetch,一次配置就能同时作用于所有 LLM provider。
核心功能¶
工作原理:插件在加载时包装 globalThis.fetch,仅对 URL 匹配 urlPatterns 的请求把配置的 headers 逐项 set() 上去(覆盖同名头,包括适配器强制 attribution 的 user-agent),其余请求原样透传。
三个配置入口,实时生效:
- Web UI:插件把 Config schema 注册为
llm-headers用户配置命名空间,Settings 页面自动渲染编辑表单,保存后实时生效(applies: live,无需重启); cordis.yml:作为 base 层配置;settings.yaml:备用通道,保存即热重载。
UI 保存的值优先级高于 cordis.yml 中的 config。
默认安全:
- 默认惰性(
headers为空)时不改写任何请求; urlPatterns中的空字符串会被忽略,不会误匹配全部 URL;- 请求 URL 无法分类(如跨 realm 的
Request实例)时原样透传; - 卸载时仅在自己仍是当前 fetch 包装者的情况下恢复原值,不破坏后续包装者。
并发保护:Web 卡片保存携带最后一次读取的 revision(乐观并发),配置在别处被修改时以冲突提示拒绝并自动刷新;提供「恢复默认」按钮,清空用户层后回到 cordis.yml config 与 schema 默认值。
安装与启用¶
发布形态是 bundle,安装命令如下,会把 llm-headers 追加到指定 profile 的 bundle 层:
dsh plugin --profile <name> add /path/to/llm-headers
安装后默认配置下插件处于惰性状态(headers 为空),不会改写任何请求,需要显式配置才会生效。
开发调试时可以按路径加载本地源码,在任一 cordis.yml(或 patch overlay)里加入:
- insert:
- id: llm-headers
name: /absolute/path/to/llm-headers/src/index.ts
典型用法¶
通过 cordis.yml 配置¶
下面的配置把 user-agent 改写为 opencode/1.0,且只对 URL 含 /chat/completions 的请求生效:
- id: llm-headers
name: dsh-llm-headers
config:
headers:
user-agent: opencode/1.0
urlPatterns:
- /chat/completions
两个字段的含义:
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
headers |
Record<string, string> |
{} |
注入的请求头;同名覆盖,空表示不注入 |
urlPatterns |
string[] |
['/chat/completions'] |
URL 子串匹配规则,命中任一项即注入 |
通过 Web UI 配置¶
安装到含 Web 界面的 profile 后:
- 打开 Web UI → Settings(设置)页面;
- 「插件」→「插件配置」中找到 LLM 请求头 卡片;
- 填写
headers与urlPatterns后保存,写入 user-settings 文档并实时生效。
通过 settings.yaml 配置¶
不用 Web UI 时,也可以在 settings.yaml 里写:
llm-headers:
headers:
user-agent: opencode/1.0
urlPatterns:
- /chat/completions
保存即热重载,无需重启。
端到端验证¶
仓库自带 e2e/echo-server.mjs,它会记录收到的请求头并返回模拟流式响应,用来确认配置的头真的到达了 provider:
node e2e/echo-server.mjs
pnpx @deepseek-ai/dsh --profile headless --patch <overlay.yml> "Reply ok"
先启动 echo 服务器,再跑一个 headless 任务;服务器终端应打印出该请求携带的 user-agent(即 overlay 里配置的值)。仓库还把这个流程脚本化为 pnpm test:e2e,自动备份并还原 settings.yaml,运行需要 DEEPSEEK_API_KEY。
适用场景与注意¶
适合的场景:
- 部署环境有网关校验
user-agent,需要替换为部署者品牌(白标替换); - 需要给所有 LLM 请求统一附加某个自定义头;
- 希望通过 Web UI 在运行时调整请求头,不改配置文件、不重启。
使用前注意:
user-agent覆盖仅在headers中显式配置该头时生效,未配置时 attribution 原样保留;- 多个插件同时包装
fetch会互相覆盖,避免与其他做同类事情的插件叠加; - 运行环境要求 Node
^22.19.0 || >=24.0.0; ./client入口(lib/client.js)是供宿主 Web 模块加载器消费的内部接口,不面向第三方,也不发布类型声明。
另外提醒:插件以当前 dsh 进程的权限运行,安装前应检查源码与许可证。本插件代码 MIT 协议、源码公开,可以自行审阅后再启用。
小结¶
dsh-llm-headers 做的事情很集中:在 HTTP 层为 DSH 的 LLM 请求注入自定义头,默认惰性、实时生效、卸载干净,是 DSH「一切皆插件」思路下解决网关与部署定制问题的一个小而具体的工具。
仓库地址:https://github.com/QiE2035/dsh-llm-headers
社区目录页:https://www.skillhub.cn/plugins/QiE2035/dsh-llm-headers (社区维护的独立站点,与 DeepSeek、幻方无官方从属关系)