中文EN

dsh-edit-approval

tools装不上npmMIT

每次 edit 与 bash 调用前都会询问:编辑前展示红绿行级 diff,命令前展示描述与命令面板——同意一次或拒绝,两个 gate 各带独立总开关(Settings → General)。

下载量 / Downloads
1,029
测试时间 / Tested
2026-11-06
DSH 版本 / Version
0.2.2-rc.1

安装

dsh plugin --profile web add dsh-edit-approval

沙箱测试结果

阶段结果
1 安装✗
2 列装—
3 挂载—
4 启动—
第一条错误
dsh: initialized profile web at /home/node/.dsh/profiles/web

四阶段在隔离沙箱里跑:安装(有网)→ 列装 → 挂载 → 启动(后三步断网)。

README

dsh-edit-approval

为 DeepSeek Harness 提供先询问后执行的审批:每次 write / edit 调用都在文件真正落盘前先询问——弹出红绿行级 diff,同意一次 / 拒绝——每次 bash 命令执行前也先询问,两者各自的总开关位于侧栏「插件」面板里本插件的页面上。

![npm version](https://www.npmjs.com/package/dsh-edit-approval)

![npm license](https://github.com/SiriLee/dsh-edit-approval/blob/main/LICENSE)

[English](README.md) | 中文

刻意保持聚焦,只做一件事:两扇镜像对称的审批门——编辑与命令——让 agent 未经你同意就无法改动文件或执行命令。

审批门 · 拦截目标 · 默认 · 面板

编辑审批 · write / edit(str_replace_editor 需自行选入) · 开 · 红绿行级 diff——同意一次 / 拒绝

命令审批 · bash · 关 · 描述 headline + 原生命令行

两扇门共用 harness 自带的 serviceAsk seam:插件在 tools/pre-execute 返回 { kind: 'ask', reason },harness 将其路由进 Web 审批面板——host 端零 UI 改动——allowed-once 继续执行、rejected 拒绝调用;在 never 策略下插件直接委托,全权会话照常工作。

效果预览

所有写类调用先弹出红绿 diff 面板;开启命令审批后,每条命令先弹出面板:白色 headline 是 agent 的描述,灰色行是命令原文。两个总开关位于侧栏「插件」面板里本插件的页面上,走 harness 自带的表单暂存(截图为 v0.4.0)。

<table>

<tr>

<td align="center"><img src="assets/screenshots/edit-approval-panel.png" width="440" alt="编辑审批面板:红绿行级 diff"><br><sub>编辑审批面板——红绿行级 diff</sub></td>

<td align="center"><img src="assets/screenshots/bash-approval-panel.png" width="440" alt="命令审批面板:描述 headline 与命令行"><br><sub>命令审批面板——描述 + 命令</sub></td>

</tr>

<tr>

<td align="center"><img src="assets/screenshots/bundle-config-card.png" width="440" alt="侧栏「插件」面板里本插件的页面:编辑审批与命令审批开关及保存按钮"><br><sub>总开关在侧栏「插件」面板里本插件的页面上</sub></td>

<td align="center"><img src="assets/screenshots/approval-commands.png" width="440" alt="/approval-edit 与 /approval-bash 命令"><br><sub>/approval-edit 与 /approval-bash 命令</sub></td>

</tr>

</table>

安装

dsh plugin --profile web add dsh-edit-approval

装完重启 dsh web(--profile web)生效。

给贡献者:可从本地 checkout、pin 的 commit 或离线 tarball 安装——dsh plugin --profile web add /path/to/dsh-edit-approval、dsh plugin --profile web add github:SiriLee/dsh-edit-approval#<sha> 或 npm pack 后 dsh plugin --profile web add ./dsh-edit-approval-<version>.tgz。git 安装首次会失败:pnpm 默认禁止 git 依赖执行构建脚本,需先在 profile 的 pnpm-workspace.yaml 加 allowBuilds;之后 pnpm 会执行插件的 prepare 并装入 profile。npm pack 同样运行 prepare,tarball 内始终包含预构建 lib/(含 .d.ts)与 LICENSE。

使用

1. 编辑审批默认开启。 任何 write / edit 调用都在文件被触碰前先询问。面板只显示改动行——删除红色、新增绿色——带右对齐 NN| 行号 gutter,被跳过的上下文与 hunk 间隔以 … 省略号标记。

2. 同意一次 / 拒绝。 allowed-once 放行该调用;rejected 拒绝并反馈给模型。

3. 命令审批默认关闭——在本插件页面上或通过下面的命令开启。面板白色 headline 是描述(如 bash · push to remote);下方灰色行是命令原文,由 harness 原生渲染。

4. 命令行入口: /approval-edit on|off|status 与 /approval-bash on|off|status——与该面板写同一份文档,两者不可能不一致。

5. 白名单(仅配置文件): bashAllow 存放始终放行的命令前缀。匹配做了空白归一化(git push 命中 git push),无法用多余空格绕过。暂不提供 UI。

原理

插件监听 tools/pre-execute 瀑布(harness 在工具执行前的 seam),按工具名分派到两扇门之一——名称重叠时编辑门优先。

1. 编辑审批

对每个被拦截的写类调用:

1. 解析目标文件:经 ctx.fs 解析路径,使用 fs 工具所写的会话 cwd 原文(DSH 0.1.7 起 fs 工具不再对含 .. 的 cwd 做规范化,本预览同样不做)。

2. 读取当前内容,并按各工具自身的语义从参数重建"拟写入内容":write——全文;edit——单次唯一替换(或 replace_all);str_replace_editor——str_replace 唯一替换、insert 按行插入、create 取 file_text。

3. 计算行级 diff:用 jsdiff 的 structuredPatch(Myers),与 harness 写类结果卡片同一个参考实现、同一个 3 行上下文窗口——因此审批预览与批准后的结果卡片同源,大文件里改一行就只显示一行。

4. 返回 { kind: 'ask', reason }:首行是摘要(tool · file (op): N insertions, M deletions),其后是 diff 文本。harness 的 serviceAsk 将其经 ctx.approval 路由进 Web 审批面板。

2. 命令审批

纯判定,完全不碰 fs——既不读也不写:

  • 以下情况直接放行:门已关闭、工具不在 bashTools 中、命令为空、或该调用是沙箱提权(带 sandbox_permissions + justification,它们自带审批,不能重复询问)。
  • 白名单优先:空白归一化后的前缀命中即放行。
  • 否则返回 { kind: 'ask', reason },只有一行 headline——bash · <描述>(描述为空时就是 bash)。命令原文不写进 reason:harness 会在面板的命令行里原生渲染,避免重复。

3. 共享策略处理

会话审批策略(ask / never)始终生效。在 never 下(如 danger-full-access),本插件发出的每个 ask 都会被审批服务确定性拒绝,从而静默打断全权会话里的所有编辑与命令——所以两扇门都改为经 next() 委托,交由沙箱执行。插件绝不扩大权限,也不改动沙箱模式。

4. 审批面板

浏览器半边(dsh.client)在面板出现时增强它(按动画帧合并的 MutationObserver,所有副作用都在单个 ctx.effect 内,卸载 / HMR 时拆除):

  • 编辑面板:从纯文本 headline 重建为只有改动行——删除红色、新增绿色、右对齐 NN| gutter——并附 white-space: pre-wrap 补偿,多行 diff 再加一个折叠按钮。
  • 命令面板:保持 harness 原生外观,只加一个 dsh-ea-kind-command 标记,不重排样式、不重建——白色描述 headline 与灰色命令行就是 harness 渲染的样子。

配置

本插件的全部配置就是一个 profile 条目——bundle patch 插入的 dsh-edit-approval 行——分层为 schema 默认值 < 行配置 < 持久化用户层。patch 刻意不带 config:src/index.ts 里的 schema 默认值是唯一真源,profile patch 只需重述它要改的键:

# profile 的 cordis.patch.yml
- id: dsh-edit-approval
  name: dsh-edit-approval
  config:
    editMinDiffLines: 2
    editIncludeCreate: false
    bashEnabled: true

键 · 默认 · 位置 · 说明

editEnabled · true · 「插件」面板 · 编辑审批总开关

bashEnabled · false · 「插件」面板 · 命令审批总开关

editTools · ['write','edit'] · profile 文件 · 被拦截的写类工具名

editMinDiffLines · 0 · profile 文件 · 改动达到至少这么多行才询问;更小的改动静默放行

editIncludeCreate · true · profile 文件 · 新建文件是否询问

editIncludeDelete · true · profile 文件 · 清空 / 置空文件是否询问

bashTools · ['bash'] · profile 文件 · 被拦截的命令类工具名

bashAllow · [] · profile 文件 · 始终放行的命令前缀(空白归一化)

只有两个总开关是 live 字段——这正是它们成为"「插件」面板唯一展示、也是设置写入唯一可寻址"字段的原因:改动立即生效,无需重启。其余都是普通配置,在条目加载时读取,因此放在 profile 文件里。

开关被拨回 schema 默认值时是清除而非固化,所以 profile patch 只保留你真正改过的东西,日后的默认值变更仍能送达你。

str_replace_editor 默认不被拦截——它自 DSH 0.1.3 起不再是默认工具。针对它的 guard 分支仍然随包发布并有单测;把 str_replace_editor 加进 editTools 即可启用。

从 0.3.x 升级。 edit-approval 与 bash-approval 两个设置命名空间已不存在,键名改为上面的扁平字段。DSH 的设置服务会把旧 settings.yaml 的 section 导入同名条目,而这两个旧名字都不是 profile 条目 id,因此不会迁移。若你此前开着命令审批,请在 profile patch 里写上 bashEnabled: true(或在该面板拨一次)。

明确不做的事

  • 不绕过也不扩大沙箱——从不改动沙箱模式或授予权限;提权调用交给沙箱自己的审批。
  • 不拦截命令内部——在 bash 命令里发生的文件改动不由编辑门管辖(开启命令审批后由它覆盖)。
  • 不做部分应用——diff 是只读预览(+ / - 行标记),不支持"只应用其中几行"。
  • 不对工具本身会失败的调用提问——例如对已存在文件执行 str_replace_editor create、old_str / old_string 缺失或不唯一;这些直接放行,由工具自己报错。空的 old_string 编辑预览与工具行为有偏差

…(truncated)

以上内容来自 npm 上的 README,我们只做格式化,不改内容。

版本

npm 上共发布:17,最后更新 2026-09-28

链接

GitHub · Homepage · npm

同类插件