Repository navigation
Releases: beihzb/dsh-envsel
Release list
v0.3.1 — state the R a conda env also ships
dsh-envsel v0.3.1
One addition to the per-turn runtime context: when the selected Python
environment also ships R, say so.
Why
conda environments routinely carry R beside Python — a scRNAv2 env installed
with r-base has <env>/Scripts/Rscript.exe right next to <env>/python.exe.
envsel already detected that (rscript is part of every conda catalog entry, and
such an env is eligible for the R slot), but the runtime block only ever
described the R slot. So with python = scRNAv2 and r = R-4.5.1, the model
saw one R installation and had no idea the environment it was told to use for
Python also contained a second, differently-provisioned one.
What changed
The Python block now ends with:
- This environment also provides R: C:\Users\<you>\.conda\envs\scRNAv2\Scripts\Rscript.exe
Rules:
- emitted only when the selected Python entry actually carries an
rscript; - emitted with the same
rscriptCommand/rscriptpreference the R slot uses
(so a WSL entry shows itswsl.exe -d … -- …invocation); - suppressed when the R slot points at the same install prefix — no
duplicated line when one environment fills both slots; - still emitted when the R slot is a different install, which is exactly the
case worth warning about.
Nothing else changes: same selection resolution, same inheritance across
delegated subagents, same shell facts, same header dropdown. This is a rendering
change only — no new DSH API, so the compatibility matrix is untouched (still
needs DSH 0.2.0-rc.1+ for the block itself, still loads on 0.1.7-rc.1+).
Verification
pnpm run typecheckclean.- 40/40 unit tests (4 new): the R line appears for a conda env with an
rscript, is absent when it has none, is suppressed when both slots share one
install, and reappears when they differ.
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.
v0.2.0
v0.2.0
Admits the DSH 0.2.0-rc line, so the plugin is no longer skipped at startup on a 0.2.x runtime.
Why
DSH refuses to boot a plugin bundle whose @deepseek-ai/dsh* peer range excludes the running runtime — it prints
dsh: skipping profile bundle "@beihaizb/dsh-envsel": Error: Plugin @beihaizb/dsh-envsel@0.1.6 is incompatible
with dsh 0.2.0-rc.2: peerDependencies {...}. ... Exact-version exemption: not active.
and then loads the rest of the profile without this bundle. All 18 @deepseek-ai/dsh-* peers were pinned to ^0.1.7-rc.1, whose upper bound is <0.2.0, so a 0.2.x runtime was rejected. The gate is not new — it is the same rule DSH applied on the 0.1.7 line.
Change
peerDependenciesanddevDependencies: every@deepseek-ai/dsh-*entry is now^0.1.7-rc.1 || ^0.2.0-rc.1, which admits0.1.7-rc.2,0.2.0-rc.1,0.2.0-rc.2and0.2.1-alpha.2.- No source change. The seams this plugin uses are unchanged between the two lines; the shipped
lib/is identical to 0.1.6. - README (EN / 中文): Requirements, the version-compatibility table (new 0.2.0 row) and the peer-bound note now describe both lines. The earlier Requirements text claimed only the Typert peer was raised while "the other peers stay at
^0.1.0-rc.7" — that was stale since the 0.1.7 bump and is corrected here.
Install
dsh plugin --profile web add @beihaizb/dsh-envsel@0.2.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.
Verification
- Startup compatibility gate replayed with DSH's own rule (
@deepseek-ai/dsh-app-boot/lib/index.js:286-313) and the realsemver:0.1.7-rc.2/0.2.0-rc.1/0.2.0-rc.2/0.2.1-alpha.2all pass, for both this repo's manifest and an installed copy. pnpm run build(tsc typecheck + tsdown) passes; the rebuilt bundle differs from the committed one only in the emission order of CSS-module class-name keys, so the committed artifact is kept as-is.- On DSH 0.1.7-rc.2 the plugin was verified previously (header dropdown included). The 0.2.0-rc line is admitted by the peer range; the runtime check of the header dropdown on 0.2.0-rc.2 is the follow-up step for this release.
v0.1.6 - header dropdown restored on DSH 0.1.7, fully opaque
v0.1.6
The header dropdown works again on DSH 0.1.7, and it is now fully opaque.
Requirements
- DeepSeek Harness 0.1.7-rc.1 or newer. The Typert protocol peer is
@deepseek-ai/dsh-typert-protocol@^0.1.7-rc.1, so the DSH version gate refuses
this release on 0.1.0-rc.7 through 0.1.5-rc.x — stay on
@beihaizb/dsh-envsel@0.1.3there.
Fixes
- Header dropdown renders on 0.1.7. 0.1.5 loaded, but its header slot entry
crashed while rendering, so the Env button never appeared:
slot entry crashed in 'conversation.session.header.utilities': Error: Minified React error #130 ... args[]=undefined. DSH 0.1.7 renamed the UI icon set, and
IconCheckOutline14/IconCloseFill14/IconChevronDownOutline14no longer
exist; the component now usesIconCheckOutlineRegular/
IconCloseFillRegular/IconChevronDownOutlineRegular. - The dropdown is fully opaque. The panel inherited the theme's translucent
menu fill (--dsw-menu-surface-fill:#43454a73dark,#f8f9fa94light), so
conversation text was readable through the environment list. It now uses
--dsw-alias-button-elevated-fill— the same surface colour at full opacity in
both themes — with--dsw-alias-bg-layer-3as the opaque fallback.
Compatibility work
- The client half is compiled against the DSH version it targets. The client
project (tsconfig.client.json) was never part oftsc -b, which is exactly
why the icon rename was invisible to the typechecker;pnpm buildand
pnpm typechecknow also runtsc -p tsconfig.client.json. - Follows the 0.1.7 client contract.
@deepseek-ai/dsh-client-runtimeis
gone (no 0.1.7 release ships it, and the bundle never required it); the client
root context is cordis'Context; thectx.slots,ctx.remoteand
SessionStandardProps.sessionIdtype merges come from
@deepseek-ai/dsh-client-ui-renderer,@deepseek-ai/dsh-api-remotesand
@deepseek-ai/dsh-client-ui-session. - Every
@deepseek-ai/dsh-*peer and devDependency is^0.1.7-rc.1, so a
single@deepseek-ai/dsh-typert-protocolcopy resolves.
Verified
pnpm build and pnpm typecheck, 23/23 unit tests, validateTypertManifest on
the built manifest, and a headless browser run against a DSH 0.1.7-rc.2
instance: the Env button renders in a session header, its Remote get succeeds,
its panel lists the discovered conda and R environments, and its computed
background is rgb(67, 69, 74) (alpha 1).
Install
dsh plugin --profile web add @beihaizb/dsh-envsel@0.1.6Restart dsh web afterwards, then open a conversation: the Env dropdown
appears in the session header.
v0.1.5 - strict Typert codecs for DSH 0.1.7
v0.1.5
Strict Typert codecs for DSH 0.1.7, so the plugin activates again.
Fixes
- Plugin activation on DSH 0.1.7. DSH 0.1.7-rc.1 replaced the strict codec's
eagerschemafield with a lazycreate()factory:dsh-typert-loaderand
dsh-typert-registry(host and browser side) now require
typeof codec.create === 'function'. 0.1.3 carried onlyschema, so the whole
plugin failed to activate with
typert-loader: ... invocation "@beihaizb/dsh-envsel#envsel/get" parameter codec has no create() factory. Codecs are now emitted throughstrictCodec()
(src/strict-codec.ts). @deepseek-ai/dsh-typert-protocolpeer and devDependency raised to
^0.1.7-rc.1; older DSH stays on@beihaizb/dsh-envsel@0.1.3.
Known issue
The header dropdown does not render on 0.1.7: its slot entry crashes on the
renamed UI icons (React error #130 ... args[]=undefined). Host-side surfaces
work normally — /env, the session_env tool, and DSH_ENV_* shell facts.
Fixed in 0.1.6.
Install
dsh plugin --profile web add @beihaizb/dsh-envsel@0.1.5v0.1.4 — bilingual (default-English) host copy
v0.1.4
Bilingual host copy — the /env command, discovery warnings, and pinned-path messages now follow the DSH interface language: English by default, Chinese when the DSH language preference is set to 中文.
Changes
/envcommand messages (/env,/env help,/env list,/env add,/env unpin,clear,wsl,assign) render product copy in the active locale instead of hardcoded Chinese.- Discovery warnings (conda + WSL) and pinned-path warnings are localized via a new host-copy dictionary (
src/copy.ts). - Default language is English; the locale resolves from DSH
settings.yamllocale.preference— only an explicitzhswitches to Chinese. - Model-facing text unchanged: the
session_envtool description and its error messages stay English. - README badges, language switcher links, and a bilingual feature note.
session_env/selectionContext/DSH_ENV_* remain model-facing English; the client header dropdown already follows the DSH interface language via ctx.locale.
Install
dsh plugin --profile web add @beihaizb/dsh-envselv0.1.2
v0.1.2 — Session environment selector
Fixes
- client: resolve the
envselnamespace viactx.get('remote.envsel')instead ofctx.remote.envsel, which threwcannot get property remote.envsel without inject(Cordis inject chain) and failed every picker call before any network request. - host: persist selections and pinned paths under
~/.dshwith an explicitworkspace-writepolicy rooted at the DSH home — the sandbox previously denied writes outside the session workspace, soset/pin/unpinfailed. Selections now survive restarts (envsel-state.json/envsel-pinned.json).
Install
dsh plugin --profile web add @beihaizb/dsh-envsel