dsh-thinking-level
A thinking-level (reasoning effort) selector for the DeepSeek Harness Web UI.
The plugin adds an independent full-width strip above the composer card
(the conversation.input.dock slot), so it never replaces the official model
selector. It shows a persistent status hint and offers exactly the thinking
levels the current model declares — nothing is fabricated, and models that
declare no levels are reported honestly.
- Default-max policy — when the current model declares
maxand no explicit effort is in force (the model default is active), the plugin submitsreasoningEffort: "max"once and persists it throughsession.selectModel. When the model does not declaremax, the model's declared default stays untouched. - Shared model directory — the strip rides the same per-session model
directory as the official composer model seat
(
ctx.modelDirectories, from@deepseek-ai/dsh-client-ui-model-selection), so switching models in either surface re-renders the other, and the Host stays the single fact source. - Failure safety — a rejected selection keeps the last valid effort and shows a human-readable inline error.
- Bilingual — Simplified Chinese and English copy, following the active DSH locale.

Status hints
| State | Chinese | English |
|---|---|---|
| Explicit effort in force | 思考强度:Max |
Thinking level: Max |
| On the model's declared default | 模型默认思考强度:High |
Model default thinking level: High |
| No default declared (provider default) | 模型默认思考强度:Default |
Model default thinking level: Default |
| Model declares no levels | 当前模型不支持思考等级 |
This model does not support thinking levels |
| Directory loading | 正在加载模型目录… |
Loading model directory… |
Requirements
- DeepSeek Harness with the default web profile
(
@deepseek-ai/dsh-base+@deepseek-ai/dsh-web-app). @deepseek-ai/dsh-client-ui-model-selectionpresent (it is part of the default web composition; the strip depends on its shared model directory).- A model that declares
reasoningEfforts(pi-ai adapters) or adapter reasoning metadata — the strip only offers what the model declares.
Install
From the npm registry (pre-built; no build authorization needed):
dsh plugin --profile <name> add dsh-thinking-level
From GitHub (source install; pnpm runs the prepare build script — pnpm ≥10
will ask you to allowlist the package first, see
docs/user/develop/basic/publish.zh.md):
dsh plugin --profile <name> add github:<you>/dsh-thinking-level
From a local checkout:
pnpm install && pnpm build
dsh plugin --profile <name> add ./dsh-thinking-level
Restart (or refresh) the Web UI — the strip appears above the composer once a workspace/session is open.
Declaring thinking levels for a model
The plugin never invents levels: they come from the model's declared
reasoning metadata. For pi-ai adapters, declare them per model in
settings.yaml:
llm-pi-ai:
providers:
my-gateway:
api: openai-responses
baseURL: https://gateway.example/v1
models:
- id: my-think-model
name: My Think Model
reasoningEfforts:
off: null # "supported, send nothing"
low: low
high: high
max: max # the level the default-max policy prefers
- id: my-plain-model
reasoningEfforts: false # explicitly non-reasoning
With max declared and no explicit effort set, the strip auto-selects and
persists max for the model.
How it works
- Slot:
conversation.input.dock(list, session scope,replaceRisk: none) — registered with idcommunity-thinking-level, order100. - State: the session's shared
ModelDirectorystore (same instance the official model seat renders), subscribed viauseSyncExternalStore. - Selection:
session.selectModel({ provider, model, reasoningEffort }). - The default-max decision is a pure function in
src/client/policy.ts(unit-tested without a browser).
Development
pnpm install # tooling only; the bundle itself has zero runtime deps
pnpm build # tsdown: lib/index.js (host) + lib/client.js (browser)
pnpm test # vitest: policy + component + plugin-registration suites
pnpm typecheck # needs the DSH checkout (see scripts/link-dsh.mjs)
- The client bundle's only runtime externals are
reactandreact/jsx-runtime; every DSH import is type-only and erased at build time, so the published artifact needs no DSH packages installed. scripts/link-dsh.mjsjunctions the local DSH checkout's builtlib/typesoutput intonode_modules/@dsh-typesfortsc(setDSH_CHECKOUTto point at your checkout).
Limitations
- Requires the default web composition (in particular
@deepseek-ai/dsh-client-ui-model-selection); removing it leaves the strip absent (the plugin stays pending on the service). - Addressed subagent sessions hide the strip (same rule as the official model seat).
- The plugin reports what the model metadata declares; it cannot add levels a model does not advertise (see “Declaring thinking levels”).
- Explicitly chosen efforts are never overridden by the default-max policy.
License
MIT
No comments yet. Be the first to write one.