dsh-opencode-session-fallback:为 OpenCode 路由上的无 session 请求补上兜底 sessionId

前言

在 DeepSeek Harness(DSH)里走 OpenCode / OpenCode Go 路由时,网关要求每个推理请求携带 x-opencode-session 头;缺省会直接返回 400 MissingSessionID。主对话、子代理等请求通常带有 sessionId,dsh-llm-pi-ai 会据此让 pi-ai 补上该头。但启用 auto 权限预设时,工具调用会先经过 @deepseek-ai/dsh-experimental-auto-review 的 reviewer;这条 reviewer 请求是手工组装的,没有 sessionId,于是 reviewer 在 OpenCode 侧 400,审查失败,DSH 按 fail-closed 策略不会执行工具体。下面介绍社区插件 dsh-opencode-session-fallback(维护者 zlxlsy666,分类:工作流),它只在 LLM 流式调用层为「缺 session 且命中 OpenCode 路由」的请求注入兜底 id,不碰全局 fetch、不改 provider 配置。

这是什么

dsh-opencode-session-fallback 是一个体量很小的 DSH 插件(npm 包名同插件 id,当前版本 0.1.0,MIT 许可)。它在 DSH 启动时对 ctx.llm.stream 做一次包装:已有 sessionId 的请求、或非 OpenCode 系列 provider 的请求原样透传;只有 无 sessionId 且 provider 在配置列表内 的请求(实践中主要是 auto-review 的 reviewer 调用)会带上配置的 fallbackSessionId,再由 pi-ai 自动加上 x-opencode-session。

问题与修复思路

OpenCode / OpenCode Go 拒绝不带 x-opencode-session 的推理请求,典型错误体如下:

400 {"type":"error","error":{"type":"MissingSessionID","message":"Request is missing x-opencode-session ..."}}

在 opencode-go 路由 + auto 预设下,链路是:

  1. 每次工具调用先发给 reviewer 模型;
  2. reviewer 请求无 session 头 → 网关 400;
  3. 审查失败 → 工具体不执行,日志中可见类似 Auto review of tool "pwsh" failed; its body was not executed 与 INVALID_REQUEST: 400: {"type":"MissingSessionID", ...}。

插件的决策逻辑可以概括为:

ctx.llm.stream(options)
  ├─ options.sessionId 已存在 .......... 透传(主对话、子代理、压缩、标题等)
  ├─ provider 不在 opencode/opencode-go .. 透传(官方 deepseek 等不受影响)
  └─ 无 sessionId + OpenCode 路由 ...... 合并 fallback sessionId 后再走 pi-ai

README 明确说明:不采用替换 globalThis.fetch 的做法,以免包住宿主应用自身的出网调用并引发 UI 连接错误;本插件只改 LLM 服务上的 stream 方法。

行为保证

资料中列出的保证包括:

  • 已有 sessionId 不会被替换,会话级路由与 prompt-cache 亲和性保持不变。
  • 其他 provider 不受影响。
  • 传入的 options 不会被原地修改(使用拷贝,冻结对象也可)。
  • 卸载后 自动恢复 原始 ctx.llm.stream。
  • 若未来 DSH 中服务形态变化、无法注入,插件 打 warning 并保持空操作,避免拖垮启动。

安装与启用

插件在 DSH 启动时装配,安装或卸载后都需要 重启 DSH。

从 npm 安装(web profile):

dsh plugin --profile web add dsh-opencode-session-fallback

也可在 GUI:Settings → Plugins → install,包名填 dsh-opencode-session-fallback。

从 Git 仓库安装:

dsh plugin --profile web add git+https://github.com/zlxlsy666/dsh-opencode-session-fallback.git

本地目录(示例路径来自 README,请按本机路径替换):

dsh plugin --profile web add "file:C:\path\to\dsh-opencode-session-fallback"

桌面应用使用 desktop profile,应由应用内 Plugin Manager 管理,而不是上述 CLI 的 --profile web。

启动成功后,日志中应出现类似一行:

[opencode-session-fallback] active for providers [opencode, opencode-go], fallback session id "dsh-opencode-session-fallback"

可选配置

在对应 profile 的 cordis.patch.yml 中,用插件条目 id opencode-session-fallback 覆盖默认值:

- id: opencode-session-fallback
  name: dsh-opencode-session-fallback
  config:
    providers: [opencode, opencode-go]    # 需要 session id 的路由
    fallbackSessionId: my-stable-id       # 请求无 session 时使用的值
    debug: false                          # 为 true 时记录每次注入

卸载

dsh plugin --profile web remove dsh-opencode-session-fallback

卸载后同样需重启 DSH;ctx.llm.stream 会恢复为安装前行为。

兼容性与验证环境

  • 插件依赖 DSH 中存在 ctx.llm.stream(inject: ['llm']);否则只打 warning、不生效。
  • README 记载在 DSH 0.2.1-rc.2(desktop)上,配合 opencode-go 与 deepseek-v4.1-flash 端到端验证:auto 预设下工具可执行,reviewer 正常返回 allow/deny。
  • 与自带 pi-ai OpenCode providers 的 DSH 版本搭配使用即可。
  • 运行环境要求 Node >=20(见 package.json engines)。

适用场景与注意

适合谁: 在 DSH 中使用 OpenCode / OpenCode Go 路由,并启用 auto 权限预设(或任何会触发无 sessionId 的 LLM 请求且走 OpenCode 网关的场景),且遇到 MissingSessionID 导致 auto-review 或同类调用失败时。

注意: DSH 社区插件目录(如 SkillHub 上的条目)为独立生态站点,与 DeepSeek / 幻方无官方从属关系;插件以当前 DSH 进程权限运行,安装前请自行查看 GitHub 源码 与 MIT 许可证。兜底 sessionId 仅用于满足网关头要求,不应替代你为主对话刻意配置的 per-conversation session 策略——插件设计上不会覆盖已有 sessionId。

结尾

dsh-opencode-session-fallback 用最小侵入的方式解开 OpenCode 路由上 auto-review reviewer 因缺 x-opencode-session 而全线 400 的卡点,让 auto 预设下的工具审查链路能继续工作。目录页:https://www.skillhub.cn/plugins/zlxlsy666/dsh-opencode-session-fallback;源码与完整说明:https://github.com/zlxlsy666/dsh-opencode-session-fallback。

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

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

Xiaoye