前言¶
在 DeepSeek Harness(DSH)里走 OpenAI 兼容接口、中间又挂 LiteLLM 一类反向代理时,常见需求是给上游带会话类 HTTP 头(例如 x-opencode-session)。实测在客户端只加请求头,经 LiteLLM 这一跳往往仍会上游 500;把同样信息放进 JSON body 的 extra_headers 字段后,代理才会转发,上游才能 200。
DSH 自带的 llm-pi-ai 适配器对白名单字段转发有限,不能像随意改 body 那样纯靠配置塞 extra_headers;社区里「只加 HTTP 头」的会话插件在这条链路上也无效。dsh-litellm-extra-headers 是维护者 chenyifawan-cell 发布的宿主插件(分类:联网工具),在命中的 provider 与上游 host 上,通过 patch globalThis.fetch,把 extra_headers 写进 POST .../chat/completions 的 JSON body——这是 README 里写明、经 LiteLLM 中继仍能生效的注入点。
下面介绍插件定位、配置方式与使用注意。
这是什么¶
- 名称:
dsh-litellm-extra-headers(npm 包名同名,当前资料版本0.1.0) - 维护者:chenyifawan-cell(GitHub:
chenyifawan-cell/dsh-litellm-extra-headers) - 许可证:MIT
- 一句话:给 DSH 用的宿主插件,对配置里列出的 provider 路由和上游 host,在 OpenAI 兼容的 chat/completions 请求 body 里合并
extra_headers: { "<header>": "<value>" },用于绕过 LiteLLM 等代理丢弃客户端 HTTP 头的问题。
社区目录页:https://www.skillhub.cn/plugins/chenyifawan-cell/dsh-litellm-extra-headers
源码与说明:https://github.com/chenyifawan-cell/dsh-litellm-extra-headers
为什么需要 body 级 extra_headers¶
README 中已核实的结论可以概括为四点:
- 客户端 HTTP 头在 LiteLLM 一跳被丢弃;仅 header 方式上游 500,改
body.extra_headers后 200。 - DSH 的
llm-pi-ai适配器在profileOptions()里只白名单转发部分字段,宿主侧没有暴露能塞任意 body 字段的options.samplingParams。 - 现成的
dsh-opencode-session走的是加 HTTP 头,且默认providers为['opencode', 'opencode-go'],不含自定义路由键(如gwds、go)。 - pi-ai 的
openai-completions使用官方openaiSDK(资料记载 v6.40.0),经globalThis.fetch发请求,因此运行时替换globalThis.fetch是当前可用的宿主注入点。
因此文档建议:不要指望再靠别处单独加 header;需要新字段时往 body 里合并。
核心功能¶
双层白名单匹配¶
- 在
llm/streamwaterfall 中:仅当options.provider落在配置的providers且存在options.sessionId时,把{ value, provider, model, session }放进AsyncLocalStorage。 - 在
fetchpatch 中:仅当目标 URL 的host落在配置的hosts时修改 body。
路由键与上游地址都未配置时,插件保持惰性并打 warning,避免对未告知的网关偷偷加字段。
只改 chat/completions 的 JSON body¶
条件包括:method === 'POST'、content-type 含 application/json、init.body 为字符串、路径以 /chat/completions 结尾。解析失败则原样放行;若 body 里已有 extra_headers,则合并且不覆盖调用方已有同名键。
取值模式¶
通过 mode 决定写入 extra_headers 的值来源:
| 模式 | 含义 |
|---|---|
session-id(默认) |
DSH 会话 id,跨轮次、跨重启稳定 |
uuid |
每会话一个进程内随机 uuid |
fixed |
配置项 value 的字面量;未提供 value 会在加载时报错 |
默认头字段名为 x-opencode-session,可用 header 改成其它名称。
实现约束(资料中的边界)¶
- 零依赖(
node:async_hooks/node:crypto/node:fs/promises);安装与卸载用ctx.effect(),dispose 时按引用还原globalThis.fetch。 input为Request对象、body 无法同步读出时不改;当前 pi-ai + openai SDK 走 URL + 字符串 body,不触发该路径。- 只注入
extra_headers,不做重试、不改 HTTP 头、不改其它 body 字段。
安装与启用¶
包已发布在 npm:dsh-litellm-extra-headers@0.1.0。Node 要求 >=20。
# npm(推荐)
dsh plugin --profile web add dsh-litellm-extra-headers
其它安装方式(README 原文):
# 从本地目录(开发时推荐,link 安装,改动即时生效)
dsh plugin --profile web add ./dsh-litellm-extra-headers
# 从打包产物
dsh plugin --profile web add ./dsh-litellm-extra-headers-0.1.0.tgz
# 从 git 主机(本包是纯 JS,无需 pnpm 放行构建脚本)
dsh plugin --profile web add github:chenyifawan-cell/dsh-litellm-extra-headers
dsh plugin add 识别到包内 dsh.bundle 后会自动把插件写入 profile 的 bundles;包内 cordis.patch.yml 会插入对应插件行。装完后可确认配置里是否出现本插件:
dsh --profile web --dump-config | Select-String litellm-extra-headers
也可手工把插件行写进 profile 的 cordis.patch.yml(指向包名或 index.js 路径)。
典型配置¶
包内默认 providers / hosts 为空列表(空 = 惰性,不注入)。需要把你的路由键和上游地址填进去才生效。示例来自 README:
- insert:
- id: litellm-extra-headers
name: dsh-litellm-extra-headers
config:
providers: [gwds, go] # 你的路由键
hosts: ["litellm.internal:4000"] # 只有这些上游才注入
header: x-opencode-session
mode: session-id
value: null
debug: false
debugFile: null
配置字段说明¶
| 字段 | 类型 | 默认 | 说明 |
|---|---|---|---|
providers |
string[] |
[] |
llm/stream 的 options.provider 路由键白名单,必须显式列出,大小写不敏感 |
hosts |
string[] |
[] |
允许注入的上游 host[:port];带 scheme/path 会归一化,必须显式列出 |
header |
string |
x-opencode-session |
写入 extra_headers 的键名 |
mode |
session-id | uuid | fixed |
session-id |
取值来源 |
value |
string |
— | mode: fixed 时的字面量 |
debug |
boolean |
false |
每次注入决策打 ctx.logger.info |
debugFile |
string |
— | 每次注入决策追加一行 JSON,便于无控制台时排错 |
验证与排错思路¶
维护者在 README 中给出的验证顺序:
- 仓库内
npm test(node --test,19 项单元测试)。 npm run test:e2e:本地 mock 上游 +dsh --profile headless对照有无插件行,断言 body 出现extra_headers、同会话值稳定、对照组无该字段、debugFile有event: "inject"。- 在能连真实 LiteLLM 的机器上再跑一轮,用
debugFile确认注入记录;对照curl仅 HTTP 头 vs body 带extra_headers的行为差异。
日常使用时,可把 debug 或 debugFile 打开,对照 provider、model、session、host、path 与 reason 字段判断是否命中白名单。
适用场景与注意¶
适合谁
- DSH 通过自定义 provider 路由到 LiteLLM(或同类只认
body.extra_headers的网关),上游要求会话亲和或自定义头,且无法依赖客户端 HTTP 头透传的场景。 - 需要按 provider + 上游 host 精细控制「只给自己的网关加字段」的团队。
使用前请知悉
- 插件以当前 dsh 进程权限 运行,会 patch 全局
fetch;安装前应阅读源码与 MIT 许可证,确认与现有插件无冲突。 providers或hosts留空时插件 deliberately 不工作,这是设计行为,不是装坏。- SkillHub 等社区目录为独立站点,与 DeepSeek / 幻方无官方从属关系;DSH 生态强调「一切皆插件」,本包是其中一例联网工具类扩展。
结尾¶
dsh-litellm-extra-headers 解决的是「LiteLLM 中继丢 HTTP 头、DSH 又难以从配置直写 body」的组合问题:在明确列出的 provider 与上游 host 上,把会话等信息写进 extra_headers,让代理能转发、上游能认。
- 目录页:https://www.skillhub.cn/plugins/chenyifawan-cell/dsh-litellm-extra-headers
- GitHub:https://github.com/chenyifawan-cell/dsh-litellm-extra-headers