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。

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

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

小夜