mirage
strukto-ai
The World's First Unified Virtual Filesystem For AI Agents
PROJECT TOPICS
INSTALL REFERENCE
dsh plugin --profile web add github:SiriLee/dsh-edit-approval
该命令指向仓库当前默认分支;尚无绑定当前 commit 的完整验证结果。
PROJECT README
Per-edit approval for DeepSeek Harness: intercepts write / edit / str_replace_editor and shows a red/green line-level diff before the file is touched — approve once or reject, with a master switch in Settings → General.
Status: published to npm (
v0.2.2) via GitHub Actions Trusted Publishing + Sigstore provenance. Targets the web profile (dsh --profile web).
| Feature | Description |
|---|---|
| Pre-write approval | Intercepts write / edit / str_replace_editor on the tools/pre-execute seam and asks before any file is modified |
| Red/green line diff | Line-level diff (added / removed / context) computed per tool semantics; rendered per-line in the approval panel, with unchanged runs collapsed to … |
| Panel collapse | Long diffs can be collapsed via the button at the strip's right end to reveal the agent's output; CSS-only hide/show, expanding restores the exact view |
| Approve once / reject | Two actions, mirroring the Claude Code edit-approval flow; rejection reports back to the model |
| Master switch | Settings → General "Edit approval" row, backed by the /approval-edit on\|off\|status host command (same source) |
| Policy-aware | Respects the session approval policy: ask intercepts, never (full access) runs edits through untouched |
| Thresholds | minDiffLines, includeCreate, includeDelete for fine-grained control |
| Master switch in Settings → General | The /approval-edit command and its arguments |
|---|---|
![]() |
![]() |
| Approval panel — red/green line diff |
|---|
![]() |
The plugin listens on the tools/pre-execute waterfall (the seam the harness
runs before a tool executes) and matches a whitelist of registered tool names:
write, edit, str_replace_editor. For each intercepted call it:
ctx.fs, applying the same session-cwd rule
the fs tools use (a relative .. path canonicalizes the cwd).write — full text; edit — single unique replace (or replace_all);str_replace_editor — str_replace unique replace, insert line
insertion, create uses file_text.{ kind: 'ask', reason } with a header line (tool · file (op): N insertions, M deletions) plus the diff text. The harness's own
serviceAsk routes that through ctx.approval into the web approval panel
— the host needs zero UI changes. allowed-once proceeds, rejected
denies the call; every other case delegates via next().The browser half (dsh.client) rebuilds the panel's plain-text headline into
red/green per-line blocks, adds a white-space: pre-wrap compensation for the
headline's CSS, installs the collapse button on multi-line diffs, and registers
the Settings → General master-switch row. All side effects live in a single
ctx.effect (torn down on plugin unload / HMR), and a per-animation-frame
MutationObserver enhances approval panels as they appear.
The harness's session approval policy (ask / never) keeps applying:
| Session policy | Plugin behavior |
|---|---|
ask (e.g. workspace-write preset) |
Intercepts and shows the approval panel |
never (e.g. danger-full-access preset) |
Delegates — edits run without prompting, the sandbox keeps enforcing |
Under never, every ask this plugin emitted would be deterministically
rejected by the approval service, silently breaking every edit in a full-access
session. The plugin therefore stops asking and lets the sandbox enforce. It
never expands access or changes the sandbox mode.
Published to npm — the registry path is the recommended one. Restart dsh web
(--profile web) after installing.
dsh plugin --profile web add dsh-edit-approval
cd dsh-edit-approval
npm install # devDeps come from the npm registry; no harness checkout needed
npm run build # full tsc build, including .d.ts
dsh plugin --profile web add /path/to/dsh-edit-approval # link install
dsh plugin --profile web add github:SiriLee/dsh-edit-approval#<commit-sha>
First run fails: pnpm blocks git dependencies from running build scripts. Follow
the CLI hint to add an allowBuilds key to the profile's pnpm-workspace.yaml
(e.g. $DSH_HOME/profiles/web/pnpm-workspace.yaml), then retry. pnpm then runs
the plugin's prepare (full build) and installs it into the profile.
npm pack # produces dsh-edit-approval-<version>.tgz
dsh plugin --profile web add ./dsh-edit-approval-<version>.tgz
npm pack runs prepare, so the tarball always carries a prebuilt lib/
(including .d.ts) and the LICENSE; dsh plugin add runs no build scripts.
Runtime configuration lives in the edit-approval settings namespace, layered
as schema defaults < cordis row config < user settings page (persisted).
The cordis row ships without config on purpose; a profile patch overrides
deployment defaults by restating only the keys it changes:
# profile's cordis.patch.yml
- id: dsh-edit-approval
name: dsh-edit-approval
config:
minDiffLines: 2
includeCreate: false
| Key | Default | Description |
|---|---|---|
enabled |
true |
Master switch (users can turn it off) |
tools |
['write','edit','str_replace_editor'] |
Whitelist of intercepted registered tool names |
minDiffLines |
0 |
Ask only when the change touches at least this many lines; smaller changes pass silently |
includeCreate |
true |
Whether creating a new file asks for approval |
includeDelete |
true |
Whether clearing/emptying a file asks for approval |
bash/pwsh
commands are out of scope.+ / - line markers — a read-only preview, not
interactive per-line selection; "apply partially" is not supported.str_replace_editor create against an existing file,
a non-unique or missing old_str / old_string. An empty old_string edit
preview deviates from the tool (treated as not-found) — the deviation is safe,
it never falsely blocks.navigator.language, not ctx.locale — a deliberate
simplification for a self-contained bundle.str_replace_editor (underscores), distinct
from the npm package name @deepseek-ai/dsh-tool-str-replace-editor.^22.19.0 || >=24.0.0.dsh --profile web); peer @deepseek-ai/*
packages are resolved by the harness at runtime.[!WARNING] This project and DSH are both in developer preview. Pin exact versions in reproducible environments and review the behavior notes above.
npm install # devDeps from the npm registry
npm run typecheck # tsc on both compilation surfaces (host + client)
npm test # vitest: diff / guard unit tests + real-cordis integration + jsdom panel-collapse (54 cases)
npm run build # full build: tsc → lib/ (with .d.ts) + lib/client.js bundle
npm run build:portable # optional lightweight esbuild build, no typecheck
node scripts/verify-host.mjs # verify the BUILT host artifact end-to-end
prepare runs the full build, so git installs and npm pack/npm publish
always produce a complete lib/ (with .d.ts) and the LICENSE.
Releases go out through GitHub Actions Trusted Publishing (OIDC, no stored
NPM_TOKEN). See docs/npm-trusted-publishing-guide.md.
npm version patch && git push origin main --tags # triggers .github/workflows/publish.yml
The workflow verifies the tag matches package.json, runs typecheck + tests +
a full build + artifact verification, publishes with Sigstore provenance, and
creates a GitHub Release. CI (.github/workflows/ci.yml) runs the same checks
on every push / PR. The publish step is idempotent — a version already on npm
is skipped.
src/index.ts host plugin: tools/pre-execute interception + /approval-edit command + settings
src/diff.ts line-level diff (pure functions: LCS, head/tail trim, render, counts)
src/guard.ts decision logic (pure functions: tool matching, thresholds, create/delete, ask/pass)
src/client/index.ts client plugin: red/green diff rendering + master switch + lifecycle
src/client/settings-row.tsx Settings → General toggle row
tests/ vitest suites (diff / guard / integration / client collapse)
scripts/ build + artifact verification
cordis.patch.yml bundle patch (mounts the host plugin row)
package.json dsh.bundle + dsh.client manifests, peerDependencies
CLASSIFICATION EVIDENCE
系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。当前命中: approval。