Install
Inside DeepSeek Harness, with dsh-market
dsh plugin --profile web add dshmarket
Or from the command line
dsh plugin --profile web add dsh-reasoning-options
Installing runs third-party code with your own permissions — it can read your files, use your credentials and reach the network. Review the source first, and pin a commit (github:owner/repo#sha) when you can.
README
Configuration page (DSH 0.2.0-rc.2 and later)
Open Plugins → Installed → dsh-reasoning-options from the homepage sidebar to configure and save this plugin. The page uses the official plugins.bundle.config interface, without a duplicate entry in global Settings. Web and Desktop share the page. This version requires DSH 0.2.0-rc.2 or a later 0.2.x host; existing configuration is retained.
GitHub: Scorp1o117/dsh-reasoning-options · npm: dsh-reasoning-options · 中文
A small DeepSeek Harness plugin that automatically adds a reasoning-effort picker to every pi-ai (third-party gateway) model, and auto-injects required routing headers (such as x-opencode-session for OpenCode Go).
Why
- Reasoning Effort Selection: dsh's built-in DeepSeek models show a reasoning-effort selector in the Web UI because the DeepSeek adapter declares reasoning capability for them. Models configured through
llm-pi-ai(OpenCode Go, GOAT, Volcengine Ark, ...) don't — pi-ai only offers effort levels for models that explicitly declarereasoningEfforts, and hand-declared gateway models never do. - OpenCode Go Compatibility: OpenCode Go (
opencode.ai/zen/go/v1) strictly requires anx-opencode-sessionHTTP header to route requests and manage prompt cache. Without it, requests fail with400: {"type":"MissingSessionID", ...}.
This plugin closes both gaps: it scans the llm-pi-ai namespace, adds the full level set (off / minimal / low / medium / high / xhigh / max) and default reasoning: high to models without declarations, and injects x-opencode-session into OpenCode Go provider headers if not already set. Writes go through DSH's native settings pipeline into the Profile patch.
The plugin only gives users a convenient way to pick and ensures gateway requirements are satisfied. Which level a model actually supports is the user's call; the plugin does not judge model fitness.
Desktop install
Use the Desktop-installed dsh command (Application → Manage dsh Command), or the app’s Plugins page. Then install into the Desktop profile:
dsh plugin --profile desktop add dsh-reasoning-options@0.3.1
Restart the Desktop app to load the client bundle. Desktop keeps its profile under $DSH_HOME/profiles/desktop.
Compatibility (v0.3.1)
Verified with DSH 0.1.7-rc.2 (Web) and 0.2.0-rc.2 (Desktop runtime) in isolated profiles. The Desktop app uses its own desktop profile. Other DSH prereleases remain unverified.
Install
dsh plugin --profile web add dsh-reasoning-options
Or mount manually in a profile patch:
- insert:
- id: reasoning-efforts
name: 'dsh-reasoning-options'
config:
enabled: true
How it works
- Read the current user layer of the
llm-pi-ainamespace (settings.describe()re-reads the profile patch from disk every time). - For each model without
reasoningEfforts, generate a mutation writing the full seven-level declaration at the exact path. - For provider routes without a
reasoningdefault, addreasoning: high. - For OpenCode Go providers (
baseURLcontainingopencode.ai), auto-injectx-opencode-session: dsh-sessionintoheadersif missing. - Writes are schema-validated by pi-ai, persisted, and hot-committed; dsh's native UI/request path takes over.
- Idempotent and serialized: models and headers that are already declared are untouched, and a scan that finds nothing writes nothing. Only one pass runs at a time, so repeated triggers never contend for the settings file lock.
- When it runs: on
settings/document-updated(a model changed through the Web UI), onapp-boot/config-reload, and as a fallback everypollIntervalMs. A trigger only flags the namespace; the write itself runs from this plugin's own timer context. dsh emits the settings event from inside the hot-reload transaction that is applying the change, and a write issued inside that transaction is refused outright (HMR transactions cannot be nested).
Config
| Field | Default | Meaning |
|---|---|---|
enabled |
true |
Set false to stop auto-patching |
autoSessionHeader |
true |
Auto-inject x-opencode-session for opencode.ai gateways |
sessionHeaderValue |
'dsh-session' |
Value for injected x-opencode-session header |
pollIntervalMs |
30000 |
Fallback rescan period in ms; 0 disables polling |
Want different defaults or wire values? After the patch they live in the
llm-pi-aientry of the active Profile patch — edit them freely; the plugin never overwrites existing declarations.
Notes
- The plugin reads and mutates the
llm-pi-ainamespace but does not own it (pi-ai registers it exclusively). All writes use the publicsettings.updateAPI — equivalent to editing via the Web UI. - Arrays are replaced wholesale, so every write restates the full
modelslist of each provider it touches. Each write carries the revision it was planned from, so a namespace that moved in the meantime is re-read and re-planned instead of clobbering the concurrent editor. - The plugin writes the
configof thellm-pi-airow in the profile patch, which is rewritten as a whole (YAML comments inside that row are lost). - Hand-editing
cordis.patch.ymlno longer needs a dsh restart: the next poll (within 30s by default) adds the missing declarations and hot-applies the new models along the way. LowerpollIntervalMsto shorten the delay. - Wire spellings are OpenAI-compatible (
low/medium/high/...). Most OpenAI-compatible gateways accept them; if one expects its own spelling, adjust the values in the Profile patch.
The page configures reasoning augmentation, automatic session headers, session identity and polling interval through the existing Host configuration lifecycle.
Comments
Comments live in GitHub Discussions. Sign in with GitHub to post or react.