dsh-llm-headers:为 DeepSeek Harness 的 LLM 请求注入自定义 HTTP 头

前言

把 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-deepseekdsh-llm-pi-ai)都通过全局 fetch 发出模型请求,所以插件只包装一次 fetch,一次配置就能同时作用于所有 LLM provider。

核心功能

工作原理:插件在加载时包装 globalThis.fetch,仅对 URL 匹配 urlPatterns 的请求把配置的 headers 逐项 set() 上去(覆盖同名头,包括适配器强制 attribution 的 user-agent),其余请求原样透传。

三个配置入口,实时生效

  1. Web UI:插件把 Config schema 注册为 llm-headers 用户配置命名空间,Settings 页面自动渲染编辑表单,保存后实时生效(applies: live,无需重启);
  2. cordis.yml:作为 base 层配置;
  3. 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 后:

  1. 打开 Web UI → Settings(设置)页面;
  2. 「插件」→「插件配置」中找到 LLM 请求头 卡片;
  3. 填写 headersurlPatterns 后保存,写入 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、幻方无官方从属关系)

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

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

小夜