Repository navigation
v0.3.0
v0.3.0
The selection now reaches the model as text. envsel renders the session's environment into DSH's per-turn runtime context, and a session with no selection of its own — every delegated subagent — inherits the nearest selecting session it descends from.
Why the selection was not always used
Until now the plugin had only two ways to get a selection in front of the model, and neither one states it:
| Channel | What the model gets |
|---|---|
shellEnv contributor |
DSH_ENV_PYTHON / DSH_ENV_RSCRIPT / DSH_ENV_CLI_PREFIX, only inside a shell call's own environment |
session_env tool, /env command |
nothing, until the model thinks to ask |
selectionContext() — the function that writes the sentence "Session Python env (user-selected): scRNAv2 (conda). Use it for all Python work in this session: C:\…\python.exe" — was defined and exported but never called. No code in this repository rendered it anywhere, which the README listed as a known limitation ("the selection is not rendered into the model's system prompt").
The visible effect: a shell call that asks for $env:DSH_ENV_PYTHON sees the right environment, but a shell call that just runs python script.py runs whatever is first on PATH — so compliance depended on the model remembering to look, and it often did not.
DSH 0.2.0-rc.1 removed the obstacle it could not work around before: assembleContextFor(agent, signal) now returns { agent, scope: agent, signal }, and dsh-system-prompt evaluates a context entry as entry.text(context) with that object — so a per-session selection is finally renderable. That is why this release requires 0.2.0-rc.1 for the block, while still loading and working on 0.1.7-rc (just without it).
Change
- Runtime-context block. Registers
systemPrompt.context({ name: 'envsel:session-environment', order: 130, text }), whose provider resolves the assembling agent's session and renders the selection. An empty selection renders'', so a session that chose nothing adds no block and never churns the durable snapshot. - Inheritance along the delegating chain. A lookup now uses the session's own entry, and otherwise walks
SessionHeader.parentSessionfor the nearest session that selected anything. DSH gives every delegated subagent its own session (origin: 'subagent',depth: 1,parentSession: <the session that delegated>), so subagents previously resolved to nothing — every delegated shell call silently ran the host default. The walk is bounded (MAX_INHERIT_HOPS = 8), returns an empty selection when nothing matches, and terminates on a lineage cycle. - New
registerContextconfig key (defaulttrue) to turn the block off. - No new dependency. The host service is reached through a two-field structural type and
ctx.inject(['systemPrompt'], …); the contribution is skipped when the service or its binding is absent.dsh-system-promptships indsh-base, so no peer is added. - The
session_envtool description now says the selection is restated in the runtime context and that a subagent inherits from its parent. - README (EN / 中文): new Features bullet, a
0.3.0compatibility row, theregisterContextconfig row, an inheritance paragraph under How it stores selections, and the stale "no runtime-context text" limitation replaced.
Verification
pnpm run typecheck(tsc against DSH 0.2.0-rc.2 types) andpnpm run build(tsc + tsdown) pass.pnpm test: 36 tests, 36 pass — 13 new, covering the resolution order (own entry wins, immediate parent, skipping unselected intermediates, nearest ancestor wins), the empty cases, the hop bound, and cycle termination; plus the rendered runtime-context text for the python / R / CLI slots.resolveSelectionwas extracted as a pure function precisely so the resolution order is testable without a host.lib/index.jsis rebuilt and republished;lib/client.jsis byte-identical to 0.2.0 (tsdown rewrites the CSS-module key order on every build, so it is restored rather than committed).
Install
dsh plugin --profile web add @beihaizb/dsh-envsel@0.3.0Then restart dsh web.
Version pinning: if you install shortly after this release, pnpm's supply-chain policy (
minimumReleaseAge) may skip the just-published version and install an older one. Pin the version explicitly as above, or use@latestonce the release is older than the policy window.