返回目录
其他 插件

dsh-auto-approval

SipengXie2024/dsh-auto-approval

LLM-gated auto approval for DeepSeek Harness: a model judges every approval ask first, low-risk operations pass without prompting (fail-closed)

Stars
0
Forks
0
Issues
0
更新
今天

PROJECT TOPICS

项目标签

PROJECT README

README

dsh-auto-approval

English: A guardian-style auto-approval plugin for DeepSeek Harness (dsh), modelled after Codex's "Approve for me" reviewer. Every operation that would normally pop an approval prompt is first judged by an LLM subagent that reads the session transcript (framed as untrusted evidence), may verify local state through three read-only tools (read_file / list_dir / stat_path), and answers a four-field verdict (risk_level × user_authorization × outcome × rationale). Low-risk operations proceed silently; anything doubtful still asks. Fail-closed by design: judge errors, timeouts, step-cap hits, and unparseable replies always fall back to the human prompt. See 安装与使用 below (Chinese).


一个给 DeepSeek Harness(dsh)加「Auto 审批模式」的插件,判定机制对齐 Codex 的「Approve for me」(内部代号 guardian)。

dsh 自带四种权限模式(Read-only / Workspace / Write / Full Access),但「要不要弹窗问用户」这件事只有 ask / never 两档。这个插件加了第五种姿态:每次要弹窗的操作,先由一个 LLM 裁判判定风险——明确安全的直接放行,拿不准的照常问你

v0.3 起裁判不再是「看一眼请求就表态」的单次补全,而是一个 guardian 式的有界子代理:

  • 读得到会话上下文:会话 transcript 渲染为文本注入(预算压缩,框定为不可信证据),裁判据此判断「用户到底有没有授权这件事」;
  • 查得了本地状态:裁判可调用三个插件自实现的只读工具(read_file / list_dir / stat_path)查证——比如「要删的路径其实不存在」就是放行 Remove-Item 的直接证据;
  • 按声明式安全策略下结论:输出四字段 verdict(risk_level 风险四级 × user_authorization 授权四级 × outcome 放行/拦下 × rationale 理由),决策表:低风险放行、高风险须授权充分且作用域窄、critical 一律拦;
  • 宿主兜底:模型输出 critical+allow 或「高风险+授权不足+allow」这类自相矛盾的组合,宿主机械翻转成 deny(单向收紧,绝不反向放宽)。

工作原理

工具调用需要审批
      │
      ▼
ApprovalService.request()           ← 记 approval/asked 审计事件
      │
      ▼
approval/request 瀑布(本插件 prepend 在链首)
      │
      ├─ Auto 关 → next() → 内置 answerer 弹窗
      ▼
  guardian 裁判(有界 fork 循环,默认 ≤4 步)
  输入:安全策略 + 会话 transcript(不可信证据框定)
        + 工具名 + 完整参数 JSON + 申请理由 + 工作区路径
  可选:read_file / list_dir / stat_path 查证本地状态
      │
      ├─ verdict.outcome = "allow" → 返回 allowed-once,不弹窗,直接执行
      └─ 其他一切 → next() → 照常弹窗
         (deny / 解析失败 / 流错误 / 步数打满 / 90s 超时)

三个关键实现细节:

  • 必须 prepend:approval/request 瀑布里,dsh 内置的 web answerer(dsh-host-apiproxy)在启动时注册,认领请求时不调 next()——正常 append 的监听器永远轮不到执行。本插件以 ctx.on('approval/request', fn, true) 插到链首。
  • 参数是旁路缓存的:ApprovalRequest 只带 toolName / callId / reason,不带工具参数。插件另挂 tools/pre-execute 观察者,按 callId 缓存每个调用的参数快照,判定时拼进 prompt。
  • transcript 绝不回放原生消息:会话历史渲染成带 >>> TRANSCRIPT START/END 框定的纯文本,作为单条消息注入。回放原生 Message[] 会让注入内容以第一人称指令身份出现,信任分层就失效了。信任规则同 Codex:只有 user 消息能建立授权,assistant 文本与工具输出一律当不可信证据。

审计不受影响:approval/asked + approval/decided 由 ApprovalService 自己记录,无论谁认领。

安全边界

  • 不改变沙箱:Read-only 模式下该被沙箱拦的操作照样被拦;Auto 只接管「本来要问你」的那一步。
  • fail-closed:裁判报错、超时(默认 90s)、返回无法解析的内容、步数打满没给终答、或明确判 deny——全部落到你熟悉的弹窗。
  • 查证工具只读且不递归触发审批:三个工具是插件用 node:fs 自实现的,不经过 dsh 工具运行时,读不了网络、跑不了命令;相对路径解析到工作区根,符号链接读取前先披露。
  • 判定期间无 UI 提示:裁判在跑的时候界面没有任何动静,最坏情况(超时)弹窗比平时晚 90 秒出现。这是已知取舍,不是卡死。
  • 判定每次调用消耗额外 token(默认用当前会话模型;可路由到便宜的小模型,见下)。

安装与使用

从 Release 安装(推荐)

# 下载 release 里的 dsh-auto-approval-<version>.tgz,然后:
dsh plugin --profile web add dsh-auto-approval-<version>.tgz
# 重启 dsh

从源码构建

git clone https://github.com/SipengXie2024/dsh-auto-approval.git
cd dsh-auto-approval
npm install
npm run check    # tsc --noEmit + vitest
npm run build    # tsc(host)+ tsdown(client 闭包工厂 bundle)
npm pack         # 产出 dsh-auto-approval-<version>.tgz
dsh plugin --profile web add dsh-auto-approval-<version>.tgz
# 重启 dsh

使用

  • 输入框工具排(权限模式开关旁)有 Auto 药丸,点一下开关;
  • 「设置 → Auto 审批」页有完整面板:开关、见证/放行/判拦/判定失败四项统计、带风险徽标(如 [high·auth:low·3步])和理由的判定记录、清空按钮;
  • 默认开启(config enabled: true)。想默认关:在 profile 的 patch 里给 auto-approval 行加 config: { enabled: false }

配置项

注册为 settings 命名空间 auto-approval,全部键可在 settings.yaml 写同名段热覆盖(patch 层 config 作为底,settings 文档盖在上面,保存即生效,无需重启):

# settings.yaml
auto-approval:
  judgeProvider: ccswitch
  judgeModel: haiku        # 便宜小模型当裁判
  policyText: |
    # 自定义安全策略(整段替换内置策略,英文成文效果最好)
    ...
默认 说明
enabled true 启动时是否开启 Auto(仅作 boot 默认;运行时开关归面板/药丸)
judgeTimeoutMs 90000 整个判定(含查证轮次)的总时限,超时转人工
judgeMaxTokens 512 裁判单步输出预算
judgeMaxSteps 4 判定最多 LLM 调用次数(首答 + 查证轮),打满没终答转人工
judgeProvider '' 裁判 provider 覆盖;空 = 跟随会话默认模型
judgeModel '' 裁判 model 覆盖;须与 judgeProvider 成对设置
policyText '' 非空则整段替换内置安全策略(输出契约与信任分层不受影响)

适用与局限

  • 弱模型当裁判的前提是支持 function calling:不支持工具调用的模型会直接给终答——等价于 v0.2 的单发判定,查证能力退化但判定链路照常工作;把工具名当正文输出的,按解析失败转人工。
  • 判定偏保守是设计使然:只有 verdict 明确 allow 才放行,且宿主还会兜底翻转自相矛盾的高危放行。在低权限模式下,会触发审批的操作大多是提权类,天然落在「转人工」区间——Auto 的价值是筛掉重复的低危确认,不是替你点掉所有弹窗。
  • 插件作用于整个进程:对本进程所有会话(含子 agent)的审批生效。
  • 裁判读文件不设工作区围栏(绝对路径可读任意本地文件,对齐 Codex)。判定输出只进面板日志,没有外传出口;若你的威胁模型在意这点,请不要在共享机器上开 Auto。

相关

  • 判定机制对齐:Codex 的 Approve for me(guardian reviewer;策略模板与输出契约改写自其 Apache-2.0 源码,出处标注在 src/prompt.ts 模块头);
  • 工程骨架参照 dsh-memory-hermes 的打包做法(tsc + tsdown 闭包工厂 client bundle + dsh.bundle.patch)。

License

MIT

CLASSIFICATION EVIDENCE

分类依据

项目类型插件
功能分类其他
规则置信度

系统优先读取 GitHub Topics,再与站内分类词典和词根规则比对。