
Security News
PHP Foundation Says Chainguard Broke Security Embargo Ahead of Emergency Patches
The PHP Foundation says Chainguard broke a security embargo ahead of critical RCE patches, as leaks disrupted the coordinated release.
@karoc/dsh-smoothly-opencode-session
Advanced tools
Smoothly OpenCode Session (Smoothly OCS) — 思磨力 OpenCode 会话头: external DeepSeek Harness host plugin that attaches the OpenCode-required x-opencode-session header to model calls routed to OpenCode / OpenCode Go provider routes (stable per-conversation id; f
思磨力 OpenCode 会话头 — an external DeepSeek Harness
(DSH) host plugin that attaches the OpenCode-required x-opencode-session
request header to model calls routed to OpenCode / OpenCode Go provider
routes, using a stable per-conversation id.
Since 2026-09-05 OpenCode's relay rejects any inference request that lacks
this header (400 MissingSessionID); the value is what pins a conversation to
one upstream backend and keeps OpenCode's prompt cache warm across its turns
(tracked upstream in deepseek-harness discussion #5495).
x-opencode-session to requests that
are routed to a configured OpenCode(Go) provider.x-deepseek-harness-session-id).https://opencode.ai),
as are requests that already carry the header, other providers, and calls
without a session id. See hosts.The plugin listens on the llm/stream waterfall — a documented DSH
extension seam ("Waterfall around every streaming model call"). LOOP-built
request options are deep-frozen (mutation throws), so the header cannot be
added by rewriting options; instead the plugin:
provider + sessionId off the waterfall options for each call;AsyncLocalStorage store;globalThis.fetch once, and while such a store is active merges
x-opencode-session: <value> onto the outgoing request (unless the request
already carries the header — an existing value always wins).Both registrations are fiber-scoped (ctx.on listener + ctx.effect
disposer), so stopping / updating / unloading the plugin restores the original
fetch and removes the listener.
There is no official seam for an external plugin to add per-request headers to
adapter requests (options are deep-frozen; provider headers config is static
and deployment-owned). The fetch shim is the only external-plugin mechanism
that can attach a per-conversation value. The correct long-term fix lives
in the provider adapter itself (pi-ai); this plugin is the stopgap until that
ships. See Notes / limitations.
The row's config (in the bundle's cordis.patch.yml, or overridden per
profile) is entirely optional — the code fills defaults for missing keys.
- insert:
- id: dsh-smoothly-opencode-session
name: '@karoc/dsh-smoothly-opencode-session'
config:
providers: [opencode, opencode-go]
mode: session-id
debug: false
Optional narrowing — you normally need no configuration here. The
authoritative discriminator is the request HOST (see hosts): leave
providers unset and every provider whose target host passes the gate is
covered, so a custom route key (for example opencode-go-self) works without
being listed and cannot break silently when it is renamed. Set it only to
restrict injection to specific provider ROUTE KEYS (the pi-ai catalog ids
opencode / opencode-go are then just two ordinary entries). Matching uses
the route key — a provider's display name (for example a UI label such as
"OC Go") is never visible here. When you do set a list, the plugin compares it
against the registered routes at the first model call and warns once about any
key no adapter registered (also written to debugFile when configured, since a
service deployment may not capture the console). The /ocgo command prints
the effective policy — gate, narrowing, mode, registered routes — with no client
UI involved.
The host gate: a request is only modified when its target host is allowed
(default ['https://opencode.ai'], subdomains included). Entries are host
(implicitly https) or scheme://host[:port]; a leading *. is ignored; IDN
entries normalize to punycode; unusable entries are reported in the startup log
instead of being ignored silently. ['*'] disables the gate entirely — use it
only for a mirror you fully trust. If you reach OpenCode through a reverse
proxy or a mirror, list that host here (write the full scheme, and note that a
bare host entry means https) or the header will silently not be attached;
the plugin warns once per blocked provider/host pair.
session-id (default) — header value = the DSH session id of the model
call. Unique per conversation, stable across turns, compaction, retries and
restarts.uuid — a process-stable random UUID derived once per DSH session id
(opaque; resets when the process restarts).debug: true — log every streamed call that enters the injection flow
via ctx.logger (the dsh process console), and reveal raw values in
request-level records.debugFile: <absolute path> — append one JSON line per streamed call
(kind: "stream", with provider/model/session/value) and, when
debugRequests is on, per injected or host-blocked request
(kind: "inject" | "skip"). The stream-level record only means the call
entered the injection flow; the request-level records are what prove what was
actually attached. The stream-level record carries the raw session id and
value (its 0.1.0 format, kept for compatibility); only the request-level
records are hashed by default. The file is append-only (no rotation;
roughly one record per injected request) and written fire-and-forget, so a
short-lived process can lose its tail.debugRequests: true writes one request-level record at the real fetch
moment: {"ts","kind","reason","host","provider","valueHash","valueLen"}
with reason in session / discovery / host-not-allowed /
already-present. These records are hashed by default: the value is reduced to
a 12-hex-character SHA-256 prefix, and the raw value appears only when
debug: true is set as well. (The separate stream-level record described above
keeps the raw session id — see its note.)
discoveryFallback: true (default off) attaches a process-stable UUID to
bare discovery requests that carry no session id: only GET requests whose
path ends in /models and whose host passes the gate. The Models page listing
works without this today; enable it only if your OpenCode endpoint starts
rejecting that listing.
To override configuration in a profile without editing this package, add a
patch entry with the same id to the profile's own cordis.patch.yml (it
replaces the whole config, so restate every key you need). The patch entry
form is id-targeted, not insert — see Install.
dsh plugin --profile web add @karoc/dsh-smoothly-opencode-session
Then fully restart your dsh profile (bundle layers are read at startup). The startup log shows:
[dsh-smoothly-opencode-session] active for providers [opencode, opencode-go] with mode session-id
If you run DSH from a source checkout instead, load it as an overlay:
pnpm dsh web --patch ./cordis.patch.yml.
dsh plugin --profile web add git+https://github.com/karoc/dsh-smoothly-opencode-session.git
dsh plugin --profile web update @karoc/dsh-smoothly-opencode-session
Restart dsh web afterwards.
dsh plugin --profile web remove @karoc/dsh-smoothly-opencode-session
Restart dsh web afterwards. Removal is safe: the original fetch is
restored on unload, so no other provider is affected.
src/index.ts host plugin: llm/stream listener + fetch shim
cordis.patch.yml bundle layer (inserts the plugin row with defaults)
scripts/ release gate + post-publish verification
tests/ node --test unit + fake-cordis integration tests
lib/ built output (npm package entry)
npm install # installs dev deps (tsdown, @deepseek-ai/cordis types, @types/node)
npm run bundle # emits lib/index.js
npm test # node --test tests/*.test.ts (runs TypeScript directly)
pnpm works too (pnpm bundle, pnpm test); this checkout documents the npm
path because pnpm is not always on PATH.
llm/stream call receive
the header. The one-shot model listing used by the Models page
(GET <baseURL>/models) is a separate flow and does not receive it; if your
OpenCode endpoint rejects that listing too, that is a separate issue.fetch. If
a future DSH version swaps its network stack, the header silently stops
being sent (the 400 comes back) — uninstall then. This is an external-plugin
stopgap until the provider adapter itself (pi-ai) sends the header.discoveryFallback is enabled.Do not retire this plugin on faith; verify, in this order:
<dsh-root>/packages/llm/llm-pi-ai/node_modules/@earendil-works/pi-ai/package.json
(a flat <dsh-root>/node_modules/@earendil-works/pi-ai/package.json is the
fallback; the package does not export package.json, so require.resolve
will not find it). If the path cannot be located, keep the plugin and
re-check after the next DSH upgrade.dist/ contains x-opencode-session
(grep -rl x-opencode-session <that package>/dist), determine what its
injection is keyed on: the provider id (opencode / opencode-go) or the
base URL (opencode.ai).opencode-go-self is
still not covered, so either keep the plugin or migrate that route to the
built-in opencode-go provider first.@earendil-works/pi-ai dependency
(npm view "@earendil-works/pi-ai@<declared-range>" version reports the
newest version that range allows).MIT
See CONTRIBUTING.md.
FAQs
Smoothly OpenCode Session (Smoothly OCS) — 思磨力 OpenCode 会话头: external DeepSeek Harness host plugin that attaches the OpenCode-required x-opencode-session header to model calls routed to OpenCode / OpenCode Go provider routes (stable per-conversation id; f
The npm package @karoc/dsh-smoothly-opencode-session receives a total of 0 weekly downloads. As such, @karoc/dsh-smoothly-opencode-session popularity was classified as not popular.
We found that @karoc/dsh-smoothly-opencode-session demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
The PHP Foundation says Chainguard broke a security embargo ahead of critical RCE patches, as leaks disrupted the coordinated release.

Security News
PHP releases emergency patches for two critical RCE vulnerabilities as agencies urge organizations to take unpatched sites offline.

Threat Research
/Security News
A supply chain attack compromised LiteLLM 1.107.0 on PyPI and Docker, spreading malware that steals cloud credentials, developer secrets, and AI provider keys.