Skip to content

Releases

v0.2.0 — computed fields, so a card can show what the arguments cannot

Choose a tag to compare

@YunpengDon YunpengDon released this 04 Oct 14:36

Added

  • fields[].value accepts a function: (exec) => string | Promise<string>, resolved by the host before the request is built. A literal string works too, and a field without a value keeps reading its own argument as before.
  • diff.before / diff.after / diff.path accept a function as well as a parameter name, so a proposal can diff what is on disk against what the call would write. A string path that is not a parameter name is now used as a literal path.
  • service.list() reports computed for every mount, so /dsh-hitl/status answers "which mounts need the host to compute a field".

Changed

  • A failing resolver degrades instead of blocking. A throw or a timeout — bounded by resolveTimeoutMs, 5 s by default — turns that one field into a one-line notice; the card still opens and the human still decides. If the resolution machinery itself breaks, the proposal falls back to the call's raw arguments rather than denying the call.
  • diff is validated at mount time. A malformed one is reported and dropped instead of silently rendering as a markdown box.
  • Each side of a diff is cut past maxDiffLines (2000 lines) with a notice, so a whole-file diff cannot become an unbounded SSE frame.
  • Both READMEs document computed fields; the appendix line counts and case counts are updated.

Install

# From npm
dsh plugin --profile <your profile> add dsh-hitl

# Straight from GitHub
dsh plugin --profile <your profile> add github:YunpengDon/dsh-hitl

167 zero-dependency cases pass.

Documentation: English · 中文 · Website

v0.1.2 — a 94.5 kB package, staged releases, two pipeline fixes

Choose a tag to compare

@YunpengDon YunpengDon released this 04 Oct 07:29

A smaller package, an off-package tour, and two pipeline fixes.

Changed

  • The published package is about six times smaller: 599.8 kB → 94.5 kB packed (851.9 kB → 314.4 kB unpacked, 29 → 21 files). The READMEs no longer embed the screenshots — they link the landing page, whose own repository carries the images at full resolution in both languages. docs/ stays in this repository as source material and is deliberately not shipped.
  • Releases are staged, not published. Pushing a v* tag runs .github/workflows/release.yml: it self-checks, verifies the tag against package.json, and runs npm stage publish over OIDC trusted publishing. The version then waits in npm's staging area until a maintainer approves it with 2FA — a tampered workflow can upload, but it cannot publish.

Fixed

  • modify.mode: allow-and-inform no longer parks revisions in a leaking map. The user's edit was held in a Map keyed by callId, so a call that was allowed and then never reached tools/post-execute — an aborted turn, a process torn down mid-execution — left its entry behind for the life of the process. It is a WeakMap keyed by the execution object now, so the entry dies with the call that owns it, and a call without an id is labelled by tool name in the dropped-context warning instead of printing undefined.
  • whenUnavailable: 'wait' without a countdown warns at mount time. It is legal, but it blocks an unattended call for as long as its session lives; the mount still installs, and the warning is the whole point.

Install

# From npm
dsh plugin --profile <your profile> add dsh-hitl

# Straight from GitHub
dsh plugin --profile <your profile> add github:YunpengDon/dsh-hitl

153 zero-dependency cases pass.

Documentation: English · 中文 · Website

v0.1.1 — slimmer package, npm install documented

Choose a tag to compare

@YunpengDon YunpengDon released this 04 Oct 04:21

Slimmer package, and a canonical install from npm.

Changed

  • The tarball is half the size. The README's 2360px retina captures were 1.3 MB of a 1.2 MB package — every install paid for the documentation. They are now exported at 1000px (still wider than the ~860px GitHub and npm render at, and still lossless PNG): 1.2 MB → 599.8 kB packed, 1.6 MB → 851.9 kB unpacked, with no format change and no link change.
  • English copy finished. Six sample values inside the English README's config snippets (title: '这条命令要执行吗?' and friends) were still Chinese; each document now shows its own language.
  • npm documented as the canonical install, with the GitHub and local-directory installs beside it.

Install

# From npm
dsh plugin --profile <your profile> add dsh-hitl

# Straight from GitHub
dsh plugin --profile <your profile> add github:YunpengDon/dsh-hitl

Unchanged

No runtime code changed in this release: index.js, client.js and lib/ are identical to v0.1.0. The 151 zero-dependency cases still pass, and prepublishOnly runs them before any publish can land.

Documentation: English · 中文

v0.1.0 — human-in-the-loop gate for DSH tool calls

Choose a tag to compare

@YunpengDon YunpengDon released this 04 Oct 03:43

Human-in-the-loop for any DeepSeek Harness tool: mount a tool behind a decision card so a human approves, edits, or rejects the call before it runs.

Highlights

  • Mount in one line — a cordis.patch.yml entry, or ctx.hitl.protect('bash', { ... }, ctx) from another plugin.
  • A decision card before execution — title + pending proposal (side-by-side diff / text / rendered markdown) + 【Approve】【Modify】【Reject】, with an optional rejection-feedback box whose words reach the agent with the rejection.
  • Modify becomes a revision request — editing the proposal flips the primary button, and the edited text goes back to the agent instead of silently rewriting the call (DSH cannot rewrite arguments before execution).
  • Countdown with three endings — approve / reject / report the timeout to the agent. A timeout is nobody's decision, so the panel lingers a few seconds saying what happened instead of vanishing.
  • Subagent pass-through — a tool call inside an in-process subagent (spawn / fork) is gated too, and the request is filed both under the child Session and under the Session you are reading: the card appears where you are, labelled 「from subagent Session …」 with a jump button.
  • A frame-level fallback notice — on the plugins page, inside the settings modal, or with no Session selected, a top-layer notice keeps the decision reachable (approve / reject / jump, plus the count and remaining time).
  • Bilingual panel — follows the application language (zh / en) and switches live; mounting plugins keep their own copy.

Install

dsh plugin --profile <your profile> add github:YunpengDon/dsh-hitl

Zero dependencies, zero build: index.js (host half) + client.js (browser half) + lib/, all plain JS. Refresh the page once after installing (the decision token is injected per page load).

Checks

151 zero-dependency cases via npm test — protocol frames and uplink validation, the countdown/hold state machine, default proposal derivation, matcher compilation, the browser half's pure logic (markdown, diff, clock, filing, seat visibility), and a guard that keeps the two READMEs and their screenshots honest.

Documentation: English · 中文