gausszhou/dsh-opencode-session-id

Plugin插件 Native原生 ⭐ 13 MIT Sessions & Context会话与上下文

dsh session IDs for opencode, zero config.

Project Overview项目介绍

This is a DeepSeek Harness (DSH) plugin for opencode session ID. It automatically adds compliant session ID headers to outgoing HTTP requests for the opencode gateway. Use it when working with opencode or opencode-go model providers. It only covers fetch-based protocols, and does not support websocket transport.

这是DeepSeek Harness(DSH)的opencode会话ID插件,默认无需额外配置。可自动为发往opencode网关的出站HTTP请求添加符合要求的会话ID请求头,使用opencode或opencode-go模型时可用,仅支持走fetch的请求协议,不覆盖websocket传输。

Or use CLI install (for developers)或使用命令行安装(适合开发者)

CLI Install命令行安装

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

gausszhou/dsh-opencode-session-id 加入你的 DSH 配置(web profile)即可启用。

READMEREADME

dsh-opencode-session-id

dsh session IDs for opencode, zero config.

npm version License: MIT

English | 简体中文

A DeepSeek Harness (dsh) plugin: when you use an opencode model (providers such as opencode / opencode-go that point at the opencode.ai gateway), it makes the actual outgoing HTTP requests carry a session id — the same way the opencode client itself does.

Usage

Add the plugin to a dsh profile (install by package name once published to npm):

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

After installing, restart dsh web (systemctl --user restart dsh-web) so the bundle takes effect. The default configuration works out of the box: requests to opencode.ai automatically get x-opencode-session (the session header used by the opencode gateway) plus x-session-affinity / x-client-request-id / x-session-id. The header value defaults to a pure-alphanumeric nanoid(8) derived from the uuid portion of the session id (e.g. 0RpJJnxJ — the session- prefix does not participate in the hash; the token is deterministically derived from the uuid via SHA-256). With verbose: true, the journal logs the mapping between the original id and the wire token:

journalctl --user -u dsh-web -f | grep opencode-session-id

How it works

The opencode gateway branch uses x-opencode-session to carry the session id; this plugin listens on the llm/stream scope, wraps fetch, and adds that header at the wire layer. By default it hashes the uuid portion of session-<uuid> (the session- prefix is excluded) into an alphanumeric nanoid(8) before it goes on the wire. Only request headers are touched — the request body, URL, method, and everything else pass through unchanged. See docs/design.md for the full design rationale.

Configuration

Zero configuration needed by default (the install command above is all you need). To enable injection logging through the patch layer:

- id: opencode-session-id
  config:
    verbose: true

All options (each optional, defaults shown):

Key Default Description
providers [opencode, opencode-go] llm-pi-ai route names whose sessionId should be tagged
hosts [opencode.ai] URL host suffixes (including subdomains) that get session headers
baseURLs [] Additional exact URL prefixes to match (custom gateways)
headers [x-opencode-session, x-session-affinity, x-client-request-id, x-session-id] Request header names to inject
extraHeaders {} Optional static extra headers (e.g. opencode fingerprint family x-opencode-client: native / x-opencode-request: dsh)
userAgent empty Override User-Agent (opencode itself sends opencode/<version>; untouched by default)
sessionIdEnv empty Environment variable name to fall back on for the session id
verbose false Log every injection (including the original id → wire token mapping)
seedSessionId false Seed options.sessionId for opencode routes
nanoidSessionId true Hash session-<uuid> to a nanoid(8) before sending; false sends the raw id
nanoidLength 8 Token length (4–32)
nanoidAlphabet alphanumeric alphanumeric (pure A-Za-z0-9, no _/-) or urlsafe (classic 64-character set)
disableFetchInjection false When true, keep only the waterfall session scoping

Verification

node test/verify.mjs   # 10 checks: unit tests + real pi-ai wire request + concurrent isolation + headers-only guarantee
node test/smoke-apply.mjs  # apply() wiring: listener registration, scoped fetch, mount/dispose lifecycle

verify.mjs fires a real opencode-go request through the pi-ai bundled with the dsh CLI, asserting that the wire request headers really carry the session id; it also verifies concurrent-session isolation and that non-opencode endpoints are unaffected.

Notes & limitations

  • The session id comes from options.sessionId (agent-loop fills it in per session); without a session context, the fallback chain is sessionIdEnv > DSH_SESSION_ID (the process's startup session in web deployments) > an in-process random id.
  • Covers protocols that go through fetch, such as openai-completions / openai-responses / anthropic-messages; transport: websocket does not use fetch and is out of scope.
  • The global fetch wrapper only appends request headers when an opencode endpoint is matched — nothing else is changed. The wire token is a one-way SHA-256 hash of the uuid portion of session-<uuid> (the session- prefix excluded, e.g. 0RpJJnxJ), so the backend cannot reverse it to the original id; changing nanoidAlphabet / nanoidLength changes every token, breaking association with old records.
上一个 Prev dsh-sessions-manager 下一个 Next dsh-turn-fold