dsh-opencode-session-fix: Injecting x-opencode-session into Sessionless Opencode Requests

前言

在 DeepSeek Harness(DSH)里启用 Auto review(实验权限预设 EXP),并把当前模型切到 opencode 系列(例如 opencode-go)时,被审查的工具调用往往在真正执行前就失败。日志里常见的是 reviewer 以 INVALID_REQUEST: 400 结束,响应体指向 MissingSessionID,说明请求缺少 x-opencode-session。主对话里的 agent 会带上 sessionId,而 Auto review 在 classifyRisk 路径里构造的 LLM 请求没有这一字段,经 pi-ai 适配器转发到 opencode 时就不会注入对应头,网关直接拒收。这不是 provider 配错,而是旧版 DSH 里 reviewer 与主 agent 请求构造不一致。社区插件 dsh-opencode-session-fix(维护者 imx123,npm 包名同目录)在 Host 侧为「没有 sessionId 的 opencode 路由请求」补一个稳定 id,让 Auto review 能走完审查流程。README 写明:DSH 0.2.2 已在 upstream 修复;本插件仅针对 0.2.1-rc.5 及更早 版本,在 0.2.2+ 上相当于空操作,可卸载。

这是什么

dsh-opencode-session-fix 是 Host-only 的 DSH 插件(分类:客户端),通过 Cordis patch 在运行中的 Host 里包装 LLM 适配器的 prepareCall()(而非仅 stream()),在 sessionId 缺失或为空时注入可配置的 session id,使 pi-ai 能为 opencode 路由发出 x-opencode-session。已有 sessionId 的主对话请求原样转发,不受影响。插件不发起网络请求、不写盘、不碰凭证,卸载时恢复被包装的方法。

问题从哪来(简要)

环节 说明
Auto review dsh-experimental-auto-review 的 classifyRisk 调用 ctx.llm.stream(options),options 冻结且 无 sessionId
主 agent dsh-agent-loop 同路径调用 带 sessionId: this.session.id
pi-ai / opencode-headers 无 sessionId 时不注入头 → opencode 返回 400

插件选择在 prepareCall() 返回的对象上打补丁,是因为 0.2.1-rc.5 里 reviewer 走 prepared call 的闭包 stream,只包实例 stream() 修不到该路径。

核心行为

  • 默认作用于 provider 路由 opencode-go 与 opencode(可在配置里收窄或扩展列表)。
  • sessionId 缺失或空白 → 注入稳定 id(默认每次插件激活一个 dsh-opencode-session-<uuid>,或用 config.sessionId)。
  • 已有 sessionId → 不改,主对话仍用真实 session,路由桶不与 reviewer 混用。
  • 其他 provider、非目标路由 → 不改动。
  • Auto review 深冻结的请求会被 复制 后再改,不原地 mutate。
  • llm/adapters-updated 时补丁迁到新 adapter;卸载时恢复;若 llm.adapters 不是 Map,仅 warn 一次,不阻断 profile 激活。

安装与启用

CLI(将 web 换成你的 profile 名;desktop profile 由 Electron 占用,CLI 不能写,需走应用内安装):

dsh plugin --profile web add dsh-opencode-session-fix
dsh --profile web --dump-config

dump-config 输出中应出现 - id: opencode-session-fix。包已发布 npm,也可在应用内插件中心用包名 dsh-opencode-session-fix 或仓库 URL 安装。源码安装(README 原文):

dsh plugin --profile web add github:imx123/dsh-opencode-session-fix

亦可用本地 checkout 路径。测试环境 README 记录为 DSH Desktop 0.2.1-rc.5,profile bundle 含 @deepseek-ai/dsh-experimental-auto-review 与 @deepseek-ai/dsh-llm-pi-ai,provider 为 opencode-go。

配置

在 profile 的 cordis.patch.yml 里覆盖对应插件行的 config(覆盖会替换整个 config 块):

- id: opencode-session-fix
  name: dsh-opencode-session-fix
  config:
    providers: ['opencode-go']   # 默认 ['opencode-go', 'opencode']
    sessionId: ''                # 空 = 每次激活新 UUID

典型验证方式

仓库内自检:

node --check lib/index.js
node test/wrapper.test.mjs

真机:开启 Auto review(EXP),选 opencode-go 模型,触发对 write 等工具的审查。会话日志里可见 permission/preset 为 auto;审查应正常返回,而不再是 auto-review of tool "write" failed ... 400 MissingSessionID。回归时主对话的 x-opencode-session 仍应等于真实 session id(不是插件注入的 id);卸载插件后 400 应复现,说明补丁可逆。

适用场景与注意

适合谁: 仍在 DSH 0.2.1-rc.5 及更早 上使用 Auto review + opencode 系列 provider,且被 MissingSessionID 挡在审查门外的人。不必装: 已升级到 DSH 0.2.2+(upstream commit 6fcb9b6c 为 auto-review 传入独立 sessionId)的用户,插件无维护承诺,可移除。

权限与信任: 插件以当前 DSH Host 进程权限运行,只影响所配置 opencode 路由上的 x-opencode-session。安装前建议阅读 GitHub 源码 与 MIT 许可证;README 声明为社区插件,与 DeepSeek 无隶属或背书关系。

局限(资料原文): ctx.llm.adapters 非文档化扩展点,字段改名会降级为警告;所有被修复的 reviewer 请求共用一个注入 id(路由/缓存粒度粗于真实 session,行为仍正确);不修改 app.asar,不为无关 provider 补 session,也不尝试在 llm/stream 里改写 options。

结尾

dsh-opencode-session-fix 针对旧版 DSH 里 Auto review 与 opencode 网关之间的 session 头缺口,用 Host 侧最小包装补上 x-opencode-session,让审查链路能跑通,同时不动主对话 session。新版本用户应依赖 upstream 修复而非长期依赖本插件。

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

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

Xiaoye