DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-auto-reasoning-effort

l

dsh-auto-reasoning-effort

Discovered

Difficulty-aware reasoning_effort scheduling for DeepSeek Harness (dsh): AUTO mode picks low/high/max from the user's message, tool history and error signals. Fork of dsh-thinking-levels (MIT).

dsh-auto-reasoning-effort

Difficulty-driven reasoning effort for DeepSeek Harness (dsh).

Pick Auto in the session model selector and the plugin chooses a reasoning_effort wire level — low, high or max — for this request, based on how hard the current task actually looks: the prompt you just sent, plus the tool activity of the current turn. A one-line lookup stays cheap; a refactor with a stack trace gets the heavy setting. You can still pin any wire level by hand.

A fork, not a rename. This project starts from dsh-thinking-levels 4.4.8 (MIT, © 2026 drscrewdriver) and replaces its scheduling signal: upstream schedules from the session-wide tool-call history, this fork classifies the task's difficulty first and uses tool activity only as a correction. Upstream copyright is preserved — see LICENSE and NOTICE.

Why bother

In a multi-step agent run the model re-thinks before every tool call, and that thinking phase dominates wall-clock time. A fixed high wastes minutes on cat package.json; a fixed low under-thinks a migration. The useful signal is not "how many tools ran" but "how hard is what the user is asking". This plugin makes that the primary input.

What it does

On every agent/request the plugin:

  1. takes the latest user message of the current turn and classifies its difficulty (trivial / simple / moderate / complex, plus an explicit override),
  2. maps the difficulty to a base level (low / high / max),
  3. optionally nudges it by this turn's tool samples (only when the turn has at least two samples),
  4. applies hysteresis so the level does not flap between requests,
  5. clamps to a level the model actually advertises — preferring the nearest lower one,
  6. injects the result as reasoningEffort, and logs the decision with its reasons.

If a manual level was chosen (in the model selector, in the plugin's level config, or by an [effort: …] marker in the message), that wins and the scheduler is skipped.

Relationship to upstream dsh-thinking-levels

This repository is a fork of drscrewdriver/dsh-thinking-levels 4.4.8 (MIT, © 2026 drscrewdriver), not a continuation of its release line. The upstream MIT text is kept verbatim in LICENSE with our copyright line appended, and NOTICE spells out which files are upstream work and which are ours. Upstream history through 4.4.8 stays in the upstream changelog.

What changed is the scheduling semantics: upstream schedules from the session-wide tool history and leaves the rest of the pipeline alone; we classify the task's difficulty first, demote tool history to a correction, and land the eight fixes listed below. The client UI, the settings/volatile-config plumbing and the takeover/pricing helpers are upstream work, carried over unchanged.

Thanks to drscrewdriver for the original plugin.

How it differs from dsh-thinking-levels

dsh-thinking-levels 4.4.8 (upstream)dsh-auto-reasoning-effort (this fork)
Primary signalsession-wide tool-call historydifficulty of the current prompt (length, keywords, structure, errors)
Sample windowone ring buffer for the whole sessionisolated per turn; a new prompt clears the window
Failure behaviorfalls back to a low levelfalls back to high (safeFallback), never silently cheapens the task
Unsupported levelclamps to the highest advertised levelclamps to the nearest lower advertised level
Flappingno dampinghysteresisSteps (default 2): the level moves only after N consecutive identical decisions
Simple tool matcherUnix-flavored namesadds pwsh, shell, powershell, apply_patch
Custom wire ids (ultra, …)can be swallowed by clampingpreserved when the model advertises them
Explainabilitylevel onlyreasons[] per decision (e.g. len:812, kw:重构, stack-trace)

Installation

Requirements: Node.js 22.19+ (or 24+), a DSH build from the peer range declared in package.json (the 14 rc terms up to 0.2.1-rc.3), and the dsh CLI (pnpm 11 ships with it).

1. From GitHub (source; runs the build through prepare)

dsh plugin --profile web add github:lion231226/dsh-auto-reasoning-effort

2. From npm (prebuilt lib/, no build step)

dsh plugin --profile web add dsh-auto-reasoning-effort

3. From dsh-market (GUI)

Open the dsh-market plugin browser, search dsh-auto-reasoning-effort and install it. If the entry is not listed yet, use one of the CLI channels above.

Then restart the host — a running dsh web process does not hot-load a new bundle layer:

dsh web

Notes that save time:

  • The web profile is a pnpm workspace root; if dsh plugin add complains about the workspace, append -w to the command.
  • A GitHub install executes the package's prepare script. pnpm ≥ 10 blocks dependency build scripts by default and asks you to approve dsh-auto-reasoning-effort in the profile's pnpm-workspace.yaml (allowBuilds). Install from npm or a packed tarball if you would rather not grant that.
  • The composition row and the npm package share the name dsh-auto-reasoning-effort; a profile override targets the row id dsh-auto-reasoning-effort.
  • Remove an installed dsh-thinking-levels before installing this one — two schedulers writing reasoningEffort on the same request will fight.

Full prerequisites, verification and troubleshooting: INSTALL.md.

Configuration

Two surfaces share one schema: the plugin row's config: in the profile composition (cordis.yml), and the Settings → Plugins form generated from the plugin's .volatile() schema fields (enabled, level, allowDowngrade, allowUpgrade, hysteresisSteps, safeFallback) — those apply to the next request without a restart. Keyword lists and models are configurer-level: edit the composition.

KeyTypeDefaultMeaning
enabledbooleantrueMaster switch. When off, the plugin injects nothing.
leveloff | on | minimal | low | medium | high | xhigh | max | autoautoDefault level when the session picks nothing. auto means "schedule per request".
allowDowngradebooleantrueLet the scheduler pick low when the task is easy or the turn is dominated by simple tools.
allowUpgradebooleanfalseLet the scheduler pick max for complex tasks and heavy tool payloads. Off caps complex work at high.
hysteresisStepsinteger 1–102Number of consecutive identical decisions required before the wire level actually moves. 1 disables damping.
safeFallbacklow | high | maxhighLevel used when the session projection cannot be read or the difficulty input fails to parse.
difficulty.complexKeywordsstring[]see belowA hit raises the score to at least 0.55, then adds +0.10.
difficulty.heavyKeywordsstring[]see belowA hit adds +0.10.
difficulty.simpleKeywordsstring[]see belowA hit multiplies the score by 0.7.
difficulty.trivialKeywordsstring[]see belowA hit with len < 60 sets the score to min(score × 0.3, 0.2).
modelsmap{}Per-model capability overrides keyed provider/model; each entry may set vision, thinking, efforts (false or a level array) and contextWindow.

Keyword defaults:

complexKeywords: [重构, 架构, 设计, 调试, 排查, 迁移, 性能, 并发, 安全,
                  refactor, design, debug, migrate, optimize, rewrite,
                  从零, from scratch, 实现, implement]
heavyKeywords:   [全部, 整个, 全量, 端到端, complete, entire, whole, all, full, end-to-end]
simpleKeywords:  [读, 查, 看, 列, 搜, 找, 读取, 显示, read, show, list, print, cat]
trivialKeywords: [谢谢, 好的, 收到, 明白, ok, okay, thanks, 继续, 接着, next, continue]

Example composition:

config:
  level: auto
  allowDowngrade: true
  allowUpgrade: true          # allow `max` on complex tasks
  hysteresisSteps: 2
  safeFallback: high
  difficulty:
    complexKeywords: [重构, 架构, refactor, 从零, implement]

The upstream fields takeover, takeoverUi and defaultPricing are retained unchanged; they are orthogonal to scheduling and documented by the upstream project.

Manual override

The model-selector pick always outranks the scheduler: choose off, on, minimal, low, medium, high, xhigh or max and that wire level is used as-is. A single message can also force a level — write [effort: low], [effort: high] or [effort: max] (brackets optional, case-insensitive) and that request bypasses difficulty classification.

Difficulty algorithm

Inputs

InputSourceNotes
messagelatest user message of the current turntruncated to 4000 chars; text parts concatenated
attachmentscurrent turncount only — attachment contents are not read
priorErrorscurrent turn's tool resultstool results carrying error / isError
toolCountcurrent turnall tool calls, not just the sampled window

Step 1 — explicit marker wins

If the message matches a bracketed effort marker — [effort: high], {effort=max}, 【EFFORT = low】 — with one of off, low, high, max, the classification stops immediately with difficulty explicit, score 1.0 and the requested level.

Step 2 — base score from message length

len is the trimmed length of the message.

lenBase score
< 80.05
< 300.15
< 800.30
< 2000.45
< 5000.60
≥ 5000.75

The hit is recorded as len:<n>.

Step 3 — keyword classes

Case-insensitive substring match. The weight is applied once per class (being "about refactoring" is one signal, not three), while every matched word is recorded in reasons[].

ClassEffectReason tag
complexscore = max(score, 0.55), then +0.10kw:<word>
heavy+0.10kw:<word>
simplescore × 0.7kw:<word>
trivialonly when len < 60: score = min(score × 0.3, 0.2)kw:<word>

Step 4 — structural signals

SignalDetectionEffectReason tag
code blockcontains a ``` fence+0.15code-block
stack tracea pasted failure fingerprint (traceback, error:, exception, a source frame, panic)+0.20stack-trace
file patha source-file extension (ts, tsx, js, jsx, py, go, rs, java, json, yaml, toml, md, sql)+0.10file-path
short questionends with ? or ? and len < 60× 0.8short-question

Step 5 — context signals

SignalConditionEffectReason tag
attachmentsattachments > 0+0.05attachments
many toolstoolCount ≥ 6+0.10tool-count
tool errorspriorErrors ≥ 1+0.15tool-error
repeated errorspriorErrors ≥ 3another +0.10tool-error:repeated

Step 6–7 — clamp and bands

The score is clamped to [0, 1], then banded:

ScoreDifficulty
< 0.25trivial
< 0.45simple
< 0.70moderate
≥ 0.70complex

Difficulty → base level

DifficultyBase level
triviallow
simplelow
moderatehigh
complexmax when allowUpgrade, otherwise high
explicitthe requested level, injected directly (scheduler bypassed)

Tool correction (current turn only)

With at least two tool samples in the turn, the base level can be nudged — never below low, never above max, and only in directions the two toggles allow:

ConditionResult
≥ 75% simple tools (small args) and allowDowngrade and base is highlow
largest tool args ≥ 3200 chars and allowUpgrademax (this wins over the downgrade)
fewer than two samplesbase level unchanged

Hysteresis

The scheduler remembers the last level it emitted for the session. A different level must be proposed on hysteresisSteps consecutive requests before it is adopted; a decision that agrees with the level in force cancels the pending candidate, so an alternating high / low pattern never switches. The first decision of a session is adopted immediately. Set hysteresisSteps: 1 for pure per-request behavior.

Worked example

帮我重构 src/auto-schedule-projection.ts 的缓存层,附上报错:TypeError at index.ts:42

  • length ≈ 70 → base 0.30
  • complex keyword (重构) → max(0.30, 0.55) + 0.10 = 0.65
  • file-path → 0.75, stack-trace → 0.95
  • clamped 0.95 → complex → max (when allowUpgrade), otherwise high
  • reasons: ['len:70', 'kw:重构', 'file-path', 'stack-trace']

What changed in this fork

  1. Difficulty comes from the prompt. The classifier reads the latest user message first; tool history is a correction, not the primary signal.
  2. Turn isolation. Tool samples are windowed per turn and cleared when a new prompt arrives, so a long session does not carry stale cheapness (or stale heaviness) into the next question.
  3. Safe fallback direction. A failed projection read or a parse failure falls back to high (configurable via safeFallback) instead of degrading to low.
  4. Clamp downward. When the model does not advertise the chosen level, the auto path picks the nearest lower level rather than jumping to the highest one.
  5. Hysteresis. hysteresisSteps (default 2) prevents the wire level from flapping between adjacent requests.
  6. Windows-aware tool names. pwsh, shell, powershell and apply_patch are recognized as simple tools alongside the Unix names.
  7. Custom wire ids survive. A level the user picked that maps to a custom wire value (for example ultra) is passed through instead of being normalized away.
  8. Explainable decisions. Every decision carries reasons[] (len:, kw:, code-block, stack-trace, tool-error, …) into the log line, so a surprising level can be traced back to the signal that caused it.

Known limitations

  • It is a heuristic. Length and keyword thresholds read a long but trivial prompt as moderate or complex. Tune the keyword lists, pin a level, or use an [effort: …] marker when the guess is wrong.
  • Defaults are Chinese + English. Substring matching works for other languages only if you add your own keywords.
  • Text only. Attachments contribute +0.05; their contents are not classified.
  • Eight samples per turn. The tool correction sees at most the last eight tool calls of the turn; toolCount still counts all of them.
  • Hysteresis has a cost. With hysteresisSteps: 2, a genuine jump (say low → max for an error storm) takes two decisions to land.
  • The scheduler never picks off. Disabling thinking is a manual choice only.
  • Host support. Models that advertise no reasoning effort never receive the field; hosts without the session projection fall back to safeFallback.
  • Upgrading from upstream. This is a separate package and a separate composition row; it does not replace an installed dsh-thinking-levels, and running both would fight over reasoningEffort. Remove the old one first.

Development

pnpm install
pnpm run typecheck
pnpm run test
pnpm run build          # tsc -> lib/, tsdown -> lib/client.js

Static plugin check (guidance package, optional):

node <path-to>/dsh-plugin-guide/bin/dsh-plugin-dev.js check --cwd .

License and acknowledgements

MIT. This repository is a fork of drscrewdriver/dsh-thinking-levels 4.4.8; the upstream MIT text is kept verbatim in LICENSE, with our copyright line added, and NOTICE records the split between upstream code and our additions.

Thanks to drscrewdriver for the original plugin — the host wiring, the client UI and the settings/volatile-config plumbing come from there. The inlined whale-girl mascot is community artwork from HanaAyane/dsh-reasoning-effort, kept with attribution (see NOTICE).

Comments

Loading…

Similar plugins

dsh-task-effort

by zhangzhenwen1

Auto-adjust model reasoning effort per task (off/low/high/max): task classification, [effort=...] markers, in-turn error escalation, DeepSeek peak-pricing-period capping with countdown notices, and ma

Development & InfrastructureManifest valid

★ 0

↓ 61/wk

MIT

JavaScript

Aug 30, 2026

dsh plugin --profile web add dsh-task-effort

by imkingjh999

DSH plugin: auto reasoning_effort (low/high/max) per turn via MiniMax complexity scorer + token ledger + per-reply metadata label

Models & ProvidersManifest valid

★ 0

MIT

TypeScript

Aug 26, 2026

dsh plugin --profile web add dsh-adaptive-effort

by Electricitysheep

Per-round reasoning_effort optimizer for DeepSeek Harness (dsh): auto-downgrades tool-call reasoning for simple tool chains, lifting back for heavy work. Cuts thinking time between tool calls.

Tools & CapabilitiesManifest valid

★ 10

TypeScript

Aug 17, 2026

dsh plugin --profile web add dsh-tool-turbo

by icrefin

Per-model reasoning effort levels inside DeepSeek Harness Settings -> Models, written to that model's reasoningEfforts in cordis.patch.yml.

Manifest valid

★ 0

MIT

TypeScript

Oct 11, 2026

dsh plugin --profile web add dsh-model-reasoning-levels

by Ayowait

Official-style model + reasoning-effort control for the DeepSeek Harness composer: Off/Low/High/Max.

Models & ProvidersManifest valid

★ 0

MIT

JavaScript

Oct 24, 2026

dsh plugin --profile web add dsh-official-reasoning-effort

by peterwangze

DSH (DeepSeek Harness) plugin: unified default reasoning level (thinking effort) for all models — per-model defaults with capability probing, live call statistics, one-command install via dsh plugin

Manifest valid

★ 2

NOASSERTION

JavaScript

Sep 12, 2026

dsh plugin --profile web add dsh-reasoning-level