前言¶
在 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 预设下,链路是:
- 每次工具调用先发给 reviewer 模型;
- reviewer 请求无 session 头 → 网关 400;
- 审查失败 → 工具体不执行,日志中可见类似
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.jsonengines)。
适用场景与注意¶
适合谁: 在 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。