dsh-header-masq:把 DSH 会话 id 映射到 OpenCode 等 Harness 请求头

前言

在 DeepSeek Harness(DSH)里走自定义模型厂商或 pi-ai 路由时,出站 HTTP 往往不会带上 x-deepseek-harness-session-id——这是 0.2.1-rc.2 上不同 LLM 适配器的差异,不是网关偶发丢头。下游若按 OpenCode Go 等生态约定读 x-opencode-session 做会话亲和或审计,就会拿不到与 DSH Session 一致的标识。维护者 Deliay 的联网工具插件 dsh-header-masq 在模型调用路径上把持久化 session id 写入可配置的目标请求头,并在缺省情况下与 DeepSeek 官方适配器发出的 harness 头对齐。

这是什么

dsh-header-masq 面向 DSH 0.2.1-rc.2(兼容范围 >=0.2.1-rc.2 <0.3.0),通过 Cordis 补丁拦截 globalThis.fetch 并监听 llm/stream,把当前会话 id 暴露成其他 harness 认识的请求头。npm 包版本 0.2.1,许可证 MIT。社区目录页:skillhub.cn/plugins/Deliay/dsh-header-masq;源码:github.com/Deliay/dsh-header-masq(目录为独立站点,与 DeepSeek / 幻方无官方从属关系)。

默认映射效果如下:

x-deepseek-harness-session-id: session-05681fd4-...
x-opencode-session:            session-05681fd4-...

为什么需要关心「源头」差异

DSH 0.2.1-rc.2 里,是否发送 x-deepseek-harness-session-id 取决于适配器:

适配器 用途 是否发送 x-deepseek-harness-session-id
@deepseek-ai/dsh-llm-deepseek deepseek-official、自定义 baseURL 的 Messages 兼容网关 发送,值为 GenerateOptions.sessionId
@deepseek-ai/dsh-llm-pi-ai 自定义模型厂商、OpenAI / Anthropic 兼容路由、pi-ai 目录里的 provider 完全不发送

dsh-llm-pi-ai 只把 sessionId 交给 pi-ai 的 streamSimple,wire extension 头由 dsh-llm-deepseek 实现。因此自定义厂商侧看到的是没有这个头,而不是空值;没有 Session 的一次性调用同样不会带该头。

插件以 llm/stream 的 GenerateOptions.sessionId 作为规范值:

  • 同一 session 的主对话、标题生成、压缩、重试共用同一 id;
  • pi-ai / 自定义厂商没有 x-deepseek-harness-session-id 时,直接使用该值;
  • 新建 session 时 DSH 给出新 id,映射随之变化;
  • 仅在拿不到活动 session id(例如模型流之外的调用)时,才回退读取 source 配置的请求头(默认 x-deepseek-harness-session-id)。

同一 session 内 x-opencode-session(或你配置的 targets)在多轮对话、标题生成、压缩、重试、以及「自定义厂商 vs DeepSeek 适配器」之间保持一致;进程重启后继续同一 session 仍相同(持久化 Session id,非每次请求随机)。插件不会给所有 session 共用一个固定值。

核心行为

经过上面的语义约定,插件在运行时做这些事:

  1. 在模型调用流中,把该次调用的持久化 sessionId 写入 targets 中的每个请求头。
  2. 拿不到活动 sessionId 时,从 source 读取并写入同一值。
  3. 目标头已存在时覆盖,避免残留旧 session。
  4. 支持 fetch 的 Headers、普通对象、Request 三种入参形式。
  5. 卸载时恢复原始 fetch 与 llm/stream 监听,不破坏之后安装的其他补丁。

实现只依赖 globalThis.fetch、llm/stream 事件和 Cordis 的 ctx.effect,不导入 DSH 内部模块。Node.js 要求 >=20。

安装与启用

先做本地或 GitHub 安装,再重启 DSH 引擎;包内 cordis.patch.yml 会被自动激活。

本地目录:

dsh plugin --profile web add file:/absolute/path/to/dsh-header-masq

从 GitHub:

dsh plugin --profile web add github:Deliay/dsh-header-masq

插件以当前 dsh 进程权限运行,安装前建议阅读仓库源码与 MIT 许可证,确认出站请求头改写符合你的合规与网关策略。

配置

配置位于 Cordis 插入项 header-masq(见 cordis.patch.yml),字段均可选:

键 默认值 说明
source x-deepseek-harness-session-id 没有活动 sessionId 时读取的请求头
targets [x-opencode-session] 要写入的请求头列表
fallbackToSessionId true 使用 llm/stream 的 sessionId 作为固定规范值
hosts [] 目标主机白名单;空表示所有主机
debug false 每次应用映射时写一条 info 日志

典型用法:只对 OpenCode Go 主机生效,并同时写多个头:

- insert:
    - id: header-masq
      name: dsh-header-masq
      config:
        source: x-deepseek-harness-session-id
        targets:
          - x-opencode-session
          - x-session-affinity
        fallbackToSessionId: true
        hosts:
          - opencode.ai
        debug: true

适用场景与注意

适合在 DSH web profile 下需要让自定义 LLM 出站请求携带 OpenCode 会话亲和(x-opencode-session)或自建 targets 头的场景;也可通过 hosts 限制只对特定 API 域名改写,避免误改无关 fetch。

务必记住:fallbackToSessionId: true 时以 DSH 持久化 Session 为准,与适配器是否发送 x-deepseek-harness-session-id 无关;关闭回退且既无活动 sessionId 又无源头的场景下,插件无法凭空造 id。

DSH 理念是「一切皆插件」;本插件归类为联网工具,当前 GitHub 星标为 0,不代表功能完整性,以 README 与版本约束为准。

结尾

dsh-header-masq 解决的是 harness 请求头命名与适配器实现不一致的问题:在 fetch 层统一写入可配置的 session 标识,使 pi-ai 与自定义路由也能满足下游对 x-opencode-session 等头的期望。

  • 目录页:https://www.skillhub.cn/plugins/Deliay/dsh-header-masq
  • GitHub:https://github.com/Deliay/dsh-header-masq
羽毛球分组比赛记分
小程序二维码

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

Xiaoye