- TypeScript 83.3%
- JavaScript 16.7%
| Filename | Latest commit message | Latest commit date |
|---|---|---|
| examples | ||
| scripts | ||
| src | ||
| tests | ||
| .gitignore | ||
| cordis.patch.yml | ||
| LICENSE | ||
| package.json | ||
| README.md | ||
dsh-llm-opencode-go-session
A DeepSeek Harness (DSH) plugin: an OpenCode Go provider route whose every
inference request carries x-opencode-session with the harness's stable
per-conversation id.
OpenCode's managed-inference gateways (Go, Zen, Console Go — opencode.ai)
started answering 400 MissingSessionID on 2026-09-05 for requests without
that header. Upstream DSH's dsh-llm-pi-ai can only send static header
values, which would collapse every conversation into one gateway affinity
bucket — requests pass, but cache locality degrades and cost/latency go up.
This plugin sends the real per-conversation id instead, which is what the
gateway needs to route and keep each conversation's cache warm.
Fork-free: it registers the opencode-go route through DSH's public
ctx.llm.registerAdapter() seam and implements the thin LlmAdapter on top
of pi-ai's shipped opencode-go provider (endpoint, model catalog, and
openai-completions / openai-responses / anthropic-messages protocols all come
from @earendil-works/pi-ai/providers/opencode-go). Nothing in DSH is
patched; delete the plugin the day upstream ships a sessionHeader profile
field.
Status
- DSH: tested against master
c389f96(2026-09-08),dsh-llm0.1.3-alpha.2,@earendil-works/pi-ai0.85.1. - Wire behavior verified by the test suite against a local mock gateway:
every
chat/completionsrequest carriesx-opencode-session: <conversation id>plus the gateway auth fromOPENCODE_API_KEY, and SSE responses translate into harness chunks. - The Go gateway accepts the raw
session-<uuid>conversation id (HTTP 200 at the wire, per the test suite and the discussion thread); no UUID re-formatting needed.
Install
Install the package into the same node_modules tree as DSH, then mount it in
your profile's cordis.yml:
plugins:
# config is entirely optional: see the full example below
- id: llm-opencode-go-session
name: dsh-llm-opencode-go-session
With no config, the adapter reads OPENCODE_API_KEY from the process
environment (pi-ai's own provider auth). Everything else is optional:
- id: llm-opencode-go-session
name: dsh-llm-opencode-go-session
config:
apiKeyEnv: OPENCODE_API_KEY # resolve through the harness credentials seam instead of process.env
sessionHeader: x-opencode-session
Pick the models on the opencode-go route (all 28 Go models, e.g.
deepseek-v4-flash, glm-5.3-flash, plus the openai-responses Muse Spark
and anthropic-messages routes) exactly like any pi-ai provider.
Important: keep opencode-go out of llm-pi-ai settings
Adapter routes are exclusive — one owner per route, all-or-nothing
registration. If llm-pi-ai's settings also declare opencode-go, one of the
two plugins fails at mount. Configure OpenCode Go only through this
plugin; use llm-pi-ai for its other providers. If the route is already
owned, this plugin skips with a loud warning instead of breaking the whole
composition.
What is intentionally not covered
- Images: the generic adapter refuses image blocks
(
UNSUPPORTED_CONTENT) — DSH's durable attachment service is not integrated. Text, tool calls, and tool results are fully supported. - Replay envelopes:
finishchunks carry no adapter replay state, so assistant history is reconstructed from durable content (the same content-only posture DSH uses for foreign history). Fine for live use. - Settings UI / model discovery: no settings section is registered; the
route appears in model pickers via
listProviders()/listModels().apiKeyEnvis the only config knob, set incordis.yml.
Development
The package typechecks against a real DSH checkout (its built lib/types,
so it compiles exactly as installed) and runs pure-Node tests against a local
mock gateway:
DSH_REPO=/path/to/deepseek-harness node scripts/dev-setup.mjs # once; creates node_modules links + tsconfig.check.json
node scripts/build.mjs # strict typecheck (tsc) + transpile src/ -> lib/
node --test "lib/tests/*.spec.js" # 11 tests, incl. the wire-header assertion
node_modules/, lib/, and tsconfig.check.json are gitignored; the
shipped surface is src/ + scripts/ + examples/.
License
MIT. Message/stream conversion adapted from @deepseek-ai/dsh-llm-pi-ai
(DeepSeek Harness, MIT, © 2026 DeepSeek); see LICENSE.