DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-opencode-session-header

b

dsh-opencode-session-header

Manifest valid6

Per-conversation x-opencode-session injection for OpenCode Go in DeepSeek Harness - fixes 400 MissingSessionID without breaking other providers

hasBundlePatch

dsh-opencode-session-header

npm version license node

Per-conversation x-opencode-session header injection for DeepSeek Harness (DSH)OpenCode Go.

It fixes the 400 MissingSessionID rejection and keeps OpenCode's per-conversation routing / prompt-cache optimization working — scoped strictly to opencode.ai, runtime-switchable without restart, zero dependencies.

中文文档

The problem

Since 2026-09-05, OpenCode Go requires a stable x-opencode-session header on every inference request (used for routing and prompt caching). DeepSeek Harness ≤ 0.1.2-rc.1 sends no such header on any adapter path, so every opencode-go model call fails:

400: {"type":"MissingSessionID","message":"Error from provider (Console Go): Request is missing x-opencode-session ..."}

Upstream fix is tracked in deepseek-harness discussion #5495 but has not shipped yet. This plugin fills the gap locally.

Why not the common workarounds?

| | Static headers in settings.yaml | Global opencode_zen profile (dsh-custom-header) | This plugin | |---|---|---|---| | Fixes the 400 | ✅ | ✅ | ✅ | | Per-conversation id (cache / routing optimal) | ❌ one shared id → cache misses, slower & pricier | ✅ | ✅ real DSH session id | | Other providers untouched | ✅ | ❌ rewrites UA + x-opencode-* on every host | ✅ opencode.ai only | | Toggle without restart | — | — | ✅ JSON file flip | | Extra dependencies | — | third-party plugin, client bundle | none |

Install

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

or from a local clone / checkout:

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

Then restart dsh web once — plugins load at boot. The startup log should show:

[dsh-opencode-session-header] loaded: header=x-opencode-session hosts=opencode.ai fallback=dsh-default
[dsh-opencode-session-header] runtime switch: <DSH_HOME>\plugins\dsh-opencode-session-header.json ({"enabled":false} disables; missing file = enabled)

Runtime switch (no restart needed)

State file: <DSH_HOME>/plugins/dsh-opencode-session-header.json (defaults to ~/.dsh):

{ "enabled": false }
  • false → injection off (all requests pass through untouched);
  • true or file missing → injection on;
  • the file is re-read on every LLM request, so toggling takes effect immediately.

How it works

Two seams, both proven inside DSH 0.1.2-rc.1:

  1. llm/stream waterfall observer — wraps every adapter stream iteration in an AsyncLocalStorage carrying GenerateOptions.sessionId (stable per DSH conversation across turns, compaction and retries; fresh per conversation / fork / subagent).
  2. Fetch transport middleware — stamps x-opencode-session only when the request host matches the allowlist (default: opencode.ai + subdomains). Value = the current session id, or the fallback id (dsh-default) outside any LLM context (e.g. model discovery). Every other host passes through byte-for-byte untouched.

The fetch pipeline runs under this plugin's own Symbol.for key (mechanics vendored from @aizigao/pi-fetch-pipeline, MIT), so it coexists with other fetch-patching plugins instead of clobbering them. Header merging follows the fetch spec: whichever of init.headers / Request.headers would reach the wire is used as the merge base.

Testing

npm test        # 13 assertions: injection, fallback, allowlist, runtime switch,
                # concurrent-session isolation, llm/stream propagation, subdomains

Compatibility & retirement

  • Built and verified against DSH 0.1.2-rc.1 (npm latest at release time).
  • Depends on DSH outbound LLM traffic using the process-global fetch. If a future DSH build switches its network stack, the plugin silently stops injecting — the symptom is simply the 400 returning; uninstall then.
  • Once upstream ships native per-conversation session headers (discussion #5495), retire this plugin:
dsh plugin --profile web remove dsh-opencode-session-header

then restart dsh web (optionally delete the switch file).

Credits

License

MIT

Compatibility

DSH 0.1.5-rc.2: errorDSH 0.1.6-alpha.1: errorDSH 0.1.5-rc.1: errorDSH 0.1.5-alpha.2: errorDSH 0.1.5-alpha.1: errorDSH 0.1.3-alpha.2: errorDSH 0.1.2-rc.1: errorDSH 0.1.2-alpha.5: errorDSH 0.1.2-alpha.4: errorDSH 0.1.2-alpha.3: errorDSH 0.1.2-alpha.2: error

Versions

Latest versionPublishedSize
0.1.0

Similar plugins

dsh-web-search-opencode-go

by leeyoung1

Fix DSH web_search through OpenCode Go / Zen: auto-inject x-opencode-session. Drop-in patched fork of @deepseek-ai/dsh-web-search-deepseek.

Manifest valid

0

MIT

JavaScript

Sep 10, 2026

dsh plugin --profile web add dsh-web-search-opencode-go

by duanyunlun

Per-provider request headers in the DeepSeek Harness Models settings page, with per-conversation ${sessionId} expansion.

Manifest valid

0

MIT

JavaScript

Sep 11, 2026

dsh plugin --profile web add dsh-provider-headers

by PwnKY

DeepSeek Harness 的 Codex 式会话深度链接插件:dsh:// 深链,跨对话读取上下文

Sessions & MessagesManifest valid

6

MIT

JavaScript

Sep 10, 2026

dsh plugin --profile web add dsh-session-link

by robbywang25

Codex-style pinned sessions for DeepSeek Harness — always visible above the sidebar list

Manifest valid

3

MIT

JavaScript

Sep 6, 2026

dsh plugin --profile web add dsh-codex-pins

by gausszhou

dsh session IDs for opencode, zero config.

Manifest valid

13

MIT

JavaScript

Sep 14, 2026

dsh plugin --profile web add @gausszhou/dsh-opencode-session-id

by MichaelGong

Codex-style user-message navigation for DeepSeek Harness conversations

Manifest valid

0

JavaScript

Aug 27, 2026

dsh plugin --profile web add dsh-session-hover-preview