dsh-llm-model-tuning
Manifest validPer-model reasoning-effort levels and multimodal input settings for custom providers in the DeepSeek Harness Models settings page.
dsh-llm-model-tuning
Adds a per-model reasoning-effort and multimodal input editor to every custom provider card on the DeepSeek Harness Settings → Models page.
Requires dsh 0.1.7 or newer. This card writes settings through the
configFormsservice; the oldersettingsScopeservice was removed in 0.1.7. See Requirements.
The shipped provider editor deliberately ships no reasoning control: effort is a per-model capability, and the models under one provider disagree about it, so a provider-scoped control could only be set to a value some of them reject. This plugin takes the per-model granularity instead — it lists the route's own model entries and edits two fields on each:
| Field | Meaning |
|---|---|
reasoningEfforts | Which effort levels the model offers, and the wire spelling each one sends. false declares a non-reasoning model; absent inherits the installed catalog. |
input | Which request modalities the model accepts (text, image). Absent inherits the installed catalog. |
It also edits the route-level defaultInput fallback, which is what makes a gateway serving vision models the catalog does not describe usable.
Both fields are written into the llm-pi-ai settings section, so a change reaches the next request with no restart — the adapter resolves profiles per request.
Why this is a client-side plugin
The whole contribution is one card on the settings.models.provider-card seat, keyed by the provider row's own settings namespace. Because every configurable pi-ai route declares settingsNs: 'llm-pi-ai', a single registration under that key receives every custom-provider card — saved rows and the add-provider draft alike — without the Models section knowing anything about this plugin.
The host half is intentionally empty. It exists only so the profile row resolves to a real package, which is what makes @deepseek-ai/dsh-client-modules scan the dsh.client declaration and serve lib/client.js into the browser boot graph.
Install
Install the bundle with the plugin manager, pointing it at this directory:
plugin_manager action: install_bundle target: <absolute path to this package>
That performs the package installation and bundle selection itself — it adds the
dependency, links it into the active profile's node_modules, and appends the
package to dsh.profile.bundles because it declares dsh.bundle.patch. Do not
hand-edit the profile's package.json or cordis.patch.yml, and do not run a
package manager in the profile directory.
The install is a symlink to this directory, so later edits here are picked up without reinstalling. A freshly installed bundle can activate through HMR; a replaced one needs a profile restart to load a fresh JavaScript module generation.
Requirements
- dsh 0.1.7 or newer. This card reads and writes settings through the
configFormsservice. The oldersettingsScopeservice was removed in 0.1.7, and a card still injecting it never activates — the row simply waits forever.test/bundle-contract.mjsguards against that regression. - The
llm-pi-aiadapter must be composed, since it owns the settings namespace this card edits. The card follows it withconfigForms.whileServed, so a deployment without that adapter shows no trace of this card rather than a dead panel.
What the card does with your document
- Edit surface. The card reads and writes the user layer of the
llm-pi-aisection. A route declared only in the composition base is read from the resolved value so it can still be tuned; writing it is what materializes it in the user layer. - Path-addressed writes. Every edit travels as
settings.mutatepath ops against the stored section, so fields the card never rendered cannot be deleted. The namespace revision fences a stale card against a concurrent change. modelsvsmodelOverrides. Amodelslist replaces the installed catalog, whilemodelOverridesreshapes it. The adapter refuses both together, so the card edits whichever the profile already uses and offers to addmodelOverridesentries when neither is present. Amodelslist is an array — and the settings path-op walker refuses to descend through arrays — so that array is written as one value; amodelOverridesdict is addressed field by field.- Text is held on.
inputanddefaultInputreplace a modality list rather than extending it, so declaring images alone would quietly drop text and leave a model the harness can no longer talk to. Text is therefore always kept, and clearing the last optional modality removes the field so the adapter's own default answers instead. - Refusals are named locally.
ConfigFormController.mutatereports whether the Host accepted a write, not which field it rejected. The card therefore reproduces the adapter's ownreasoningEffortsrules (every level needs a wire spelling; onlyoffmay be empty; at least one level beyondoff) so a refusal names the field, and it still reports a Host rejection as a failure rather than success.
Tests
npm test
Four suites, all offline, no dependencies to install:
| Suite | What it proves |
|---|---|
test/harness.mjs | The card's own behaviour, driven through its real inputs against a faithful settings-op simulator. Includes a rejection-never-reported-as-success case, and one proving nothing registers when the Host does not serve the namespace. |
test/integration.mjs | The exact section the card wrote is accepted by the real llm-pi-ai Config schema. |
test/conformance.mjs | Document shapes, and the refusals the card reproduces, checked against that same real schema. |
test/bundle-contract.mjs | The bundle satisfies the loader's registration protocol and requires nothing outside the module baseline. |
The two schema-checked suites need an installed @deepseek-ai/dsh-llm-pi-ai to
compare against. test/dsh-adapter.mjs locates one from DSH_PROFILE_DIR,
DSH_HOME, or the usual ~/.dsh/profiles layout; when none is reachable they
print a labelled SKIP and exit 0 instead of failing, so a contributor without
a DSH installation still gets a green run. Set DSH_PI_AI_DIR to point at an
unusual layout.
The last assertions in conformance.mjs are informative on purpose: the real schema accepts an empty wire value for a thinking level, because only the adapter's resolution step rejects it. That confirms the card's own validation is load-bearing rather than redundant.
Limitations
- The card edits only
reasoningEfforts,input, anddefaultInput. Capacities, compat switches, and credentials stay with the shipped editor andsettings.yaml. - Levels beyond the seven the schema accepts (
off,minimal,low,medium,high,xhigh,max) are preserved on write but not offered for editing. - Settings are stored in the user's
settings.yaml; the card holds no state of its own.
Comments
Loading…
From the same category
by awesome-dsh-plugin
A curated list of plugins for DeepSeek Harness (dsh) · DeepSeek Harness 插件精选列表
★ 17.5k
CC0-1.0
Python
Sep 30, 2026
by zhu1090093659
DeepSeek Harness (DSH) Web Plugin Aggregation Ecosystem · Everything is a plugin, distributed via the Creative Workshop
★ 8.2k
↓ 172/wk
Apache-2.0
TypeScript
Oct 1, 2026
dsh plugin --profile web add dsh-webby yjh051108
dsh-routing-suite — injector + router-standard kit: install the runtime injector first, then the task-aware reasoning-mode router preset (measured P1-P23).
★ 7k
MIT
JavaScript
Sep 18, 2026
dsh plugin --profile web add @dsh-external/dsh-super-injectorby strukto-ai
The World's First Virtual Terminal for AI Agents
★ 3.7k
↓ 264/wk
Apache-2.0
TypeScript
Oct 1, 2026
dsh plugin --profile agent add @struktoai/mirage-dshby xmanrui
通过扫码或机器人凭据把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord和WhatsApp)。 Connect IM bots to DeepSeek Harness via QR code or credentials (9 channels).
★ 1.6k
↓ 17.5k/wk
MIT
JavaScript
Oct 1, 2026
dsh plugin --profile web add @xmanrui/dsh-imby hyhmrright
AI code reviews grounded in 12 classic engineering books — decay risk diagnostics with book citations, severity labels, and 6 analysis modes including full-sweep auto-fix
★ 1.5k
MIT
JavaScript
Sep 28, 2026