dsh-max-compact
Compact model input for DeepSeek Harness (DSH >= 0.2): shrink what the model sees — tool definitions, prompt sections, preset compositions — without shrinking what the deployment can do.
Three mechanisms, one plugin, all opt-in:
- Lazy tool surface. Most tools hide behind
mc_discover: the model sees a small resident surface (fs + shell + messaging) and activates anything else on demand — the dsh-ops discovery pattern, generalized to every plugin's tools, not just one catalog. - Editable prompt layer + persona shadow. A trailing system-prompt
section the deployment owns — inline text, an external
prompt.md-style file (re-read every step, mtime-cached), or named profiles — plus a per-agentdeployment:persona-prefixoverride that shadows whatever the preset's persona row declared, without touching the preset. - Preset composer.
agentPresets.list()shows the whole roster — official, foreign, managed.readDocument+registerclone any preset under a new id with per-rowdisabledtoggles (the dsh-custom-mode capability, but for all presets, since foreign declarations are read-only but clonable).
Everything is capability-probed: a missing seam disables the feature with an
honest /mc status line, never a crash.
Install
npm install dsh-max-compact
# or straight from GitHub:
npm install github:20genesis14-sys/dsh-max-compact
# or add the plugin directory to the profile's plugin list
The bundle mounts one global row (id: max-compact) — intentionally not
inside a preset, so all three mechanisms cover every agent and every preset,
including foreign ones. With the default config nothing changes.
Commands
/mc # status: seams, lazy stats, layer, persona, presets
/mc lazy on|off # enable/disable the compact surface
/mc lazy keep|hide|default <tool> # adjust the resident/lazy policy
/mc lazy release <tool> | reset # re-mask activated tool(s) on this session
/mc lazy list # hidden vs activated for this session
/mc sections # last assembled system-prompt sections (chars each)
/mc prompt # show the active layer
/mc prompt set <text...> # inline layer text
/mc prompt file <path|off> # external prompt file (re-read each step)
/mc prompt clear # drop the layer from the prompt
/mc prompt profile save|use|rm|list # named layer profiles
/mc persona set <text...> | off # per-agent persona shadow
/mc persona scope all|subagents|<id> # limit the shadow to delegated/selected agents
/mc prompt scope all|subagents|<id> # limit the prompt layer the same way
/mc presets # roster: foreign + managed, incl. broken
/mc preset show <id> # row tree with [disabled]/[group] flags
/mc preset clone <src> <newId> [name] # clone any preset -> managed
/mc preset toggle <id> <row> [on|off] # flip a row's disabled flag, re-register
/mc preset rm <id> # unmount + forget a managed preset
In-session the model gets mc_discover:
mc_discover({query: "web"}) -> "Selected web_search, web_fetch. They become
callable on the next model step; nothing was executed."
How it works
Lazy surface (lib/dsh/lazy-tools.js, lib/core/lazy-catalog.js)
agent.ctx.tools.registerputsmc_discoverin the agent's own layer — restrictions never cover own-layer registrations, so the activation path can never mask itself. Its disposer lives inownLifts, separate from the restrict masks thatreconcilelifts on every recompute.agent.ctx.tools.restrict({deny})masks the lazy set per agent. Reconcile follows the official-tool-hiding discipline: a public-surface snapshot diff guards against publication feedback loops, all masks lift before recompute, a failed plan hides nothing, anddenynarrows on scope-local or unknown names (restrictthrows naming the offender — that tool is honestly reported as unmaskable rather than silently kept).- Activations queue into
pendingand commit at the next step boundary (agent/pre-step,session/eventstep/endas fallback) — republishing mid-step would invalidate the in-flight request's tool list. Activated tools stay visible for the agent's lifetime (/mc lazy release <tool>orresetre-masks them). - A global
ctx.tools.guard(exec => …)keyed onexec.agentdenies hidden-tool executions even from conversation history; activation lifts the denial automatically. - Keep beats hide, hide beats default-lazy;
run_code+ own tools are never hidden (reserved transport + own-layer registrations throw inrestrict).
Section hygiene (lib/dsh/lazy-prompt.js)
One global system-prompt/assemble listener (context.scope = the
assembling agent) drops sections that document currently-masked tools —
tools:workflow and friends stop burning tokens while their tool is lazy.
The waterfall cannot rewrite a complete section (the host restores it);
that limit is documented, not worked around. /mc sections inspects the
last assembly.
Prompt layer (lib/core/prompt-layer.js, lib/dsh/files.js)
Section maxcompact:layer (order 10500, after deployment:persona-prefix
and suffix) resolves each assembly: file > active profile > inline. Files
are re-read every step through an mtime/size cache — external edits land on
the next model call with no reload.
Persona shadow (lib/dsh/persona.js)
deployment:persona-prefix (order 0) registered in the agent's own
scope shadows the preset's persona row — same-name sections shadow across
layers (duplicate names only collide within one layer). Off by default;
/mc persona set/off refreshes every live agent.
Preset composer (lib/core/presets.js, lib/dsh/preset-registry.js)
agentPresets.list()— every declared preset incl.brokendiagnostics.readDocument(id)— the full composition YAML, parsed with a!!js→{__jsExpr}schema so host-evaluated predicates survive cloning verbatim.- Clone registers under a new id (foreign declarations are never
touched);
group/isolatestructure is preserved so service rows keep their realms; relative./x.mjsspecifiers become absolutefile://URLs. - Toggle =
disabled: trueon the row + dispose/re-register (duplicate ids throw — disposal first). New sessions pick up the new revision; running sessions keep their retained generation. That's the platform's revision-retention design, not a limitation of this plugin. - Managed specs persist through the volatile
managedPresetsfield and the settings document (nsmax-compact) — clones survive restarts.
Config
All fields are volatile (WebUI-editable, persisted via the settings document):
| Field | Default | Meaning |
|---|---|---|
lazyEnabled |
false |
Master switch for the compact surface |
lazyKeep |
[] |
Extra tool names to keep resident |
lazyHide |
[] |
Tool names forced lazy (beats keep) |
lazyHideSections |
[] |
Section names always filtered from assemblies |
customPrompt |
'' |
Inline layer text |
customPromptFile |
'' |
External prompt file path |
promptProfiles |
{} |
{name: text} named layers |
activePromptProfile |
'' |
Selected profile |
customPersona |
'' |
Persona shadow text |
layerPresets |
[] |
Layer scope: [] all, [':subagent'] delegates only, preset ids |
personaPresets |
[] |
Persona scope, same vocabulary |
managedPresets |
[] |
Cloned preset specs |
Honest limitations
- Preview APIs.
agentPresets,tools.restrict/guard,system-prompt/assembleare preview surfaces — all probed; missing seams degrade features, never crash. - Global rows can still add tools. Profile-global plugins mount on top
of any preset — no preset or mask fences their own-layer additions, so
/mc lazy listreports what the host actually shows, not an ideal count. - Foreign presets are read-only.
readDocumentis "for viewing only" — clone under a new id to customize; the original is never edited in place. completesections can't be rewritten by the assemble waterfall — including acompletepersona. The persona shadow uses a named prefix section instead, which layering does shadow.- Revision retention. Preset toggles affect new sessions; running sessions keep the generation they mounted.
Development
npm test # 45 tests — pure core + mocked-ctx smoke
npm run check # node --check every lib file
npm run pack:check # npm pack --dry-run
lib/core/ is pure logic (no DSH imports, no I/O); lib/dsh/ is the only
place that knows DSH exists; lib/index.js wires the two. Per-agent state
lives in WeakMaps keyed on agent objects — never session-id strings.
No comments yet. Be the first to write one.