Skip to content

Releases: beihzb/dsh-envsel

v0.3.1 — state the R a conda env also ships

Choose a tag to compare

@beihzb beihzb released this 31 Oct 09:10

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/rscript preference the R slot uses
    (so a WSL entry shows its wsl.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 typecheck clean.
  • 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

Choose a tag to compare

@beihzb beihzb released this 10 Oct 07:54

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.parentSession for 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 registerContext config key (default true) 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-prompt ships in dsh-base, so no peer is added.
  • The session_env tool 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.0 compatibility row, the registerContext config 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) and pnpm 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. resolveSelection was extracted as a pure function precisely so the resolution order is testable without a host.
  • lib/index.js is rebuilt and republished; lib/client.js is 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.0

Then 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 @latest once the release is older than the policy window.

v0.2.0

Choose a tag to compare

@beihzb beihzb released this 09 Oct 10:46

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

  • peerDependencies and devDependencies: every @deepseek-ai/dsh-* entry is now ^0.1.7-rc.1 || ^0.2.0-rc.1, which admits 0.1.7-rc.2, 0.2.0-rc.1, 0.2.0-rc.2 and 0.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.0

Then 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 @latest once 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 real semver: 0.1.7-rc.2 / 0.2.0-rc.1 / 0.2.0-rc.2 / 0.2.1-alpha.2 all 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

Choose a tag to compare

@beihzb beihzb released this 29 Sep 01:54

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.3 there.

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 / IconChevronDownOutline14 no longer
    exist; the component now uses IconCheckOutlineRegular /
    IconCloseFillRegular / IconChevronDownOutlineRegular.
  • The dropdown is fully opaque. The panel inherited the theme's translucent
    menu fill (--dsw-menu-surface-fill: #43454a73 dark, #f8f9fa94 light), 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-3 as 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 of tsc -b, which is exactly
    why the icon rename was invisible to the typechecker; pnpm build and
    pnpm typecheck now also run tsc -p tsconfig.client.json.
  • Follows the 0.1.7 client contract. @deepseek-ai/dsh-client-runtime is
    gone (no 0.1.7 release ships it, and the bundle never required it); the client
    root context is cordis' Context; the ctx.slots, ctx.remote and
    SessionStandardProps.sessionId type merges come from
    @deepseek-ai/dsh-client-ui-renderer, @deepseek-ai/dsh-api-remotes and
    @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-protocol copy 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.6

Restart 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

Choose a tag to compare

@beihzb beihzb released this 29 Sep 01:54

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
    eager schema field with a lazy create() factory: dsh-typert-loader and
    dsh-typert-registry (host and browser side) now require
    typeof codec.create === 'function'. 0.1.3 carried only schema, 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 through strictCodec()
    (src/strict-codec.ts).
  • @deepseek-ai/dsh-typert-protocol peer 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.5

v0.1.4 — bilingual (default-English) host copy

Choose a tag to compare

@beihzb beihzb released this 21 Aug 02:56

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

  • /env command 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.yaml locale.preference — only an explicit zh switches to Chinese.
  • Model-facing text unchanged: the session_env tool 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-envsel

v0.1.2

Choose a tag to compare

@beihzb beihzb released this 19 Aug 02:23

v0.1.2 — Session environment selector

Fixes

  • client: resolve the envsel namespace via ctx.get('remote.envsel') instead of ctx.remote.envsel, which threw cannot 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 ~/.dsh with an explicit workspace-write policy rooted at the DSH home — the sandbox previously denied writes outside the session workspace, so set/pin/unpin failed. Selections now survive restarts (envsel-state.json / envsel-pinned.json).

Install

dsh plugin --profile web add @beihaizb/dsh-envsel