dsh-litellm-extra-headers:经 LiteLLM 中继时向请求体注入 extra_headers

前言

在 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 中已核实的结论可以概括为四点:

  1. 客户端 HTTP 头在 LiteLLM 一跳被丢弃;仅 header 方式上游 500,改 body.extra_headers 后 200。
  2. DSH 的 llm-pi-ai 适配器在 profileOptions() 里只白名单转发部分字段,宿主侧没有暴露能塞任意 body 字段的 options.samplingParams。
  3. 现成的 dsh-opencode-session 走的是加 HTTP 头,且默认 providers 为 ['opencode', 'opencode-go'],不含自定义路由键(如 gwds、go)。
  4. pi-ai 的 openai-completions 使用官方 openai SDK(资料记载 v6.40.0),经 globalThis.fetch 发请求,因此运行时替换 globalThis.fetch 是当前可用的宿主注入点。

因此文档建议:不要指望再靠别处单独加 header;需要新字段时往 body 里合并。

核心功能

双层白名单匹配

  1. 在 llm/stream waterfall 中:仅当 options.provider 落在配置的 providers 且存在 options.sessionId 时,把 { value, provider, model, session } 放进 AsyncLocalStorage。
  2. 在 fetch patch 中:仅当目标 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 中给出的验证顺序:

  1. 仓库内 npm test(node --test,19 项单元测试)。
  2. npm run test:e2e:本地 mock 上游 + dsh --profile headless 对照有无插件行,断言 body 出现 extra_headers、同会话值稳定、对照组无该字段、debugFile 有 event: "inject"。
  3. 在能连真实 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
羽毛球分组比赛记分
小程序二维码

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

Xiaoye