dsh-rheostat (滑动变阻器)

August 27, 2026 · View on GitHub

English | 中文

A session style dial for DeepSeek Harness: one position in [0, 1] that slides the model's response style between 0 mode (terse, quiet, minimal) and 1 mode (expressive, lively, detailed), with a blend in between.

  • The user slides the dial with the /rheostat [<0..1>] command (bare /rheostat reads it).
  • The model slides it with the rheostat_set tool and reads it with rheostat_get.
  • Every request renders a rheostat:style prompt section describing the current position and its style instruction.
  • The position is durable per-session state (rheostat/position session event, last write wins, default 0.5), so resume and fork restore it. Dial-state events carry the ignorable envelope marker, so a harness outside this repo (whose generated event vocabulary lacks these plugin types) skips them on read instead of refusing the session log.

Install

The plugin is published to the npm registry:

npm install @johndoe0827/dsh-rheostat

Requires an official harness from the next version family (@deepseek-ai/dsh-* ≥ 0.1.1-rc.2): the plugin declares peer dependencies on that family, which the official packages mutually lock. Older harness families (e.g. 0.1.0-rc.6) conflict by design — upgrade the harness to the next tag, or install with npm install --legacy-peer-deps while staying on an older family.

Run this outside a pnpm workspace (npm does not support the workspace: protocol). Then mount the plugin in your harness profile — add it to your cordis.yml overlay or pass it as a --patch file:

- name: '@johndoe0827/dsh-rheostat'

It injects tools and systemPrompt; the /rheostat command activates when a commands service is composed.

Version note: the current release is 0.1.6 (zero-effect close and the ignorable event markers).

Using a DeepSeek Harness monorepo checkout? This plugin also lives inside the JohnDoe0827/deepseek-harness fork at packages/context/rheostat (package name @deepseek-ai/dsh-rheostat, pending upstream merge), mounted in the base bundle — nothing to install there. On a pnpm workspace use pnpm add github:JohnDoe0827/rheostat instead of npm.

Usage

ControlEffect
/rheostatread the current state
/rheostat offturn the dial off (no style instructions)
/rheostat onturn it back on at the last position
/rheostat 0switch to 0 mode (terse, quiet)
/rheostat 1switch to 1 mode (expressive, lively)
/rheostat 0.7blend, leaning expressive
rheostat_set(position)model slides the dial (0..1) — a no-op while the dial is off
rheostat_get()model reads the state programmatically

Sliding the dial always turns it on — via the /rheostat command. While the dial is off, the rheostat_set tool is a no-op (the model cannot re-open it), so a harness that cannot hide the tools still sees zero effect from the plugin.

Mode bands: position ≤ 0.25 renders 0 mode · Terse & Quiet; position ≥ 0.75 renders 1 mode · Expressive & Lively; in between renders Balanced (between 0 and 1).

Known limitations

  • Official npm harness 0.1.1-rc.2 cannot write the ignorable marker. The published @deepseek-ai/dsh-session@0.1.1-rc.2 Session.append accepts only surface metadata (sourceEventSeqs, surfaceOp); the ignorable write option exists in the repository's newer builds (repo-next and the fork above). On that official release the dial-state events are written without the marker, so a session that used the dial cannot be resumed — the persistence read path refuses the unknown event types. Harness builds that honor the marker restore such sessions cleanly. Track deepseek-ai/deepseek-harness for the upstream fix.

Same prompt, different positions

One prompt (你喜欢花生吗 — "Do you like peanuts?"), three dial positions (recorded from a live session). Full responses:

PositionModeResponse (translated)
0.000 mode · Terse & QuietYes.
0.50Balanced (between 0 and 1)Yes. Peanuts are plain and solid: crisp, fragrant, chewy — raw ones are crunchy, boiled ones soft, fried ones flaky, each way has its own charm. Salted fried peanuts go with beer, peanut-and-trotter soup for slow-cooking, and peanut butter for spreading on bread. Xu Dishan's essay The Peanut puts it well too — dug out of the earth dusty and plain, yet genuinely good and dependable.

As for the downsides: fried ones are easy to overeat, and allergy sufferers can't touch them; other than that, no complaints. How do you usually eat peanuts?
1.001 mode · Expressive & LivelyHaha, I love them! And not just a little — for me, the peanut is basically the "hexagonal all-rounder of the food world," and it deserves a proper shout-out! 🥜

Texture first: raw peanuts are crunchy, boiled ones soft, fried ones flaky, roasted ones fragrant. One tiny bean (strictly speaking, the seed of a legume) can pull off four completely different textures — isn't that amazing?

Then flavor: that nutty oil aroma with a hint of sweetness — the kind of fragrance that keeps you reaching for more. Whether it's the late-night street-stall plate of salted fried peanuts, perfect with beer; the vinegar-soaked peanuts Sichuan diners snack on before hotpot, tangy and appetite-whetting; the rich old-Beijing millet porridge (面茶) topped with crushed peanuts; or the peanut-and-trotter soup southerners slow-cook until it melts in the mouth.

And the sentimental bonus: even Lu Xun wrote about the "falling peanut" — Xu Dishan's school essay The Peanut is etched into generations of DNA: "A person should be useful, not merely respectable." A peanut, dug out of the earth dusty and plain, is the real deal — so much character!

Even its bad reputation is endearing: people say peanuts make you fat — please, that's on the frying oil and sugar coating; plain peanuts are a source of good fats and protein, and gym-goers eat peanut butter on purpose. The only real pity is that allergy sufferers have to keep away — and we should respect that, gently.

So the verdict: yes, I love them. On a rainy evening, a plate of freshly roasted peanuts and a pot of hot tea on the table — the night is already half won. 🌰✨

What about you? Which way do you like your peanuts — fried, boiled, or ground into butter for bread?

Development

npm install
npm run build   # tsc → lib/
npm test        # vitest: unit + invariant + real-Loader composition + full-loop mock-model