npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

dsh-tiered-approval

v0.1.0

Published

Tiered auto-review for DeepSeek Harness (DSH): static-rule safety net + LLM reviewer + human fallback. Auto-approve safe actions, auto-deny irreversible ones, ask a human for the rest. PURE VIBE CODING - not audited, use at your own risk.

Readme


[!WARNING]

本插件是纯 vibe coding 写的

代码、配置 schema、这份 README 都是 AI agent 生成的,几乎没有人工 review:未经过安全审计与 DeepSeek 官方无关不提供任何担保。它把关的是安全决策,请把它当起点,而不是信任边界——

  • 用之前先读一遍 lib/index.js(约 500 行);
  • 把每一条默认规则改成符合你自己威胁模型的样子;
  • 跑一遍 test/smoke.mjs(38 项),并补充你自己的用例;
  • 在你真正在意的事情上,永远保留人工兜底和静态安全网。

风险自负。review、审计、PR 都特别欢迎。


目录


这是什么

DSH 没有内置自动审批器,只有两个极端:每次越界都弹窗(烦),或全放权什么都不问(怕)。

这个插件填上中间地带:在每个工具调用真正执行前加一道三层裁决——静态规则先拦下不可逆的,LLM 审查员再看一遍拿不准的,剩下真正有疑问的才交回给你。

装完即生效,默认行为就是安全值,不需要你写一条规则。

为什么需要它

| 原生状态 | 体验 | 本插件 | | --- | --- | --- | | ask(审批策略) | 每个逃出沙箱的操作都弹确认 | 静态规则 + 审查员替你裁决,只剩真疑问 | | never / 全放权 | 什么都不问,出事故没兜底 | 不可逆操作被安全网直接拒绝,不弹窗也不花 token | | 权限预设(read-only / workspace-write / full-access) | 只换沙箱边界,审查强度不变 | 审查强度自动跟随预设(见 perMode) |

它如何工作

DSH 留了两个官方接缝(tools/pre-execute 门禁 + approval/request 应答者),本插件各占一个:

工具调用
   │
   ▼
tools/pre-execute 门禁 ── 能看到完整参数(命令文本、目标路径、升权模式、理由)
   │   第一层 静态规则(零成本、确定性)
   │     命中 deny 规则 ──► 直接拒绝,不弹窗(内置安全网)
   │     命中 allow 规则 ──► 打 "allow" 印记,放行
   │   第二层 LLM 审查员(策略跟随当前 Access 模式)
   │     裁决 allow ──► 打 "review-allow" 印记,放行
   │     裁决 deny  ──► 直接拒绝(理由返回给模型)
   │     裁决 ask   ──► 升权调用:放行到工具本体弹一次人工;其余:门禁直接问人工
   │     审查不可用/超时/解析失败 ──► 静默回退,不新增弹窗
   │   其余 ──► 保持默认放行,打 "none" 印记
   ▼
工具本体(例如 pwsh 升权时)──► 发起 approval/request 审批请求
   │
   ▼
approval/request 应答者 ── 依据印记 + 文本规则自动回答
   │   reason 命中 denyJustifications ──► rejected(优先级最高)
   │   印记 deny ──► rejected
   │   升权请求:
   │     印记 allow        且模式 ∈ answerer.allowModes       ──► allowed-once
   │     印记 review-allow 且模式 ∈ 当前模式的 review.allowModes ──► allowed-once
   │     reason 命中 allowJustifications 且模式 ∈ answerer.allowModes ──► allowed-once
   │   其余 ──► next() → 人工审批 UI(现状不变)

三个设计点:

  • 印记(stamp)approval/request 请求不带工具参数,危险与否只能在门禁里用完整参数判断——门禁把结论打在 callId 上,应答者凭印记兑现。
  • prepend 注册:web 部署里 dsh-host-apiproxy 有个挂起等人工的"终端"应答者,本插件必须排它前面,未命中的请求才能流回人工。
  • 一次性授权allowed-once 只管这一次调用,没有 allow-always / 记住授权。

高亮特性

  • 静态安全网优先 —— 试图逃出沙箱的破坏性命令(递归删除、格式化磁盘、强推 git、注册表删除、写系统目录)在任何模型调用之前被拒绝:不弹窗、不花 token;
  • LLM 审查员(上下文感知) —— 小模型对规则未裁决的调用做全参数审查(allow / deny / ask),并结合会话里最近一条用户消息判断命令是否对齐用户意图;复用会话自己的模型路由,不开子 agent、不写会话日志;
  • self-kill 守卫 —— taskkill / Stop-Process / killall / pkill 一类进程终止命令确定性拒绝(防 agent 杀掉自己的宿主;后台任务用 job_killkill <pid> 保留为逃生口);
  • L0 双保险 —— 静态 deny 除了瀑布最前的监听器,还注册了单调 tools.guard(),其他插件旁路不掉这条硬底线;
  • 跟随预设 —— 审查强度自动跟随 Access 选择器(Read only / Workspace write / Full access);Full access 下默认全量审查,因为沙箱已经不隔离了;
  • 全自主可切换 —— review.onUncertain: 'deny' 开启两态模式(审查不确定/失败一律拒绝,无人参与);默认 'ask' 保留人工兜底;
  • 快捷开关 —— 输入框直接 /auto-review on|off|rules|tiered|auto|status|reset 切档位、看统计,无需改配置(内存态,重启重置);
  • 不加弹窗 —— 未命中的请求行为与原生 DSH 完全一致;
  • 可插拔 —— 标准 cordis bundle,dsh plugin add 安装,卸载自动 dispose 全部监听器。

看它工作

真实日志(进程日志里的 [auto-approval] 行):

[auto-approval] deny pwsh <callId>: auto-review: escalated destructive command is refused without prompting (irreversible)
[auto-approval] review-allow pwsh <callId>: install dependencies
[auto-approval] allow escalation pwsh <callId> -> workspace-write
[auto-approval] reviewer call failed: provider exploded
[auto-approval] review inconclusive for pwsh <callId>; falling back

一条被拦住的命令(Remove-Item -Recurse + 升权,静态层直接拒绝——安装时它拦过我们自己的部署命令 😄):

→ pwsh(
    command="Remove-Item C:\Users\x -Recurse -Force",
    sandbox_permissions="danger-full-access",
    justification="clean up"
  )
→ Error: auto-review: escalated destructive command is refused without prompting (irreversible)

快速开始

最小配置就是默认配置——装完重启即生效,行为即"安全模型"一节:

# ~/.dsh/profiles/<profile>/cordis.patch.yml(手动挂载时)
- insert:
    - id: tiered-approval
      name: 'dsh-tiered-approval'

可复现验证三步:

  1. 插件清单页出现 tiered-approval
  2. 进程日志出现 [auto-approval] 决策行;
  3. 试一次"升权 + Remove-Item -Recurse"——被直接拒绝且不弹窗(静态安全网生效)。

之后按需调 config:(见「配置」),改完重启生效。

快捷开关(/auto-review)

不想改配置也能随时切审查档位——在输入框直接输入斜杠命令(和 /permission 一个玩法):

| 命令 | 效果 | | --- | --- | | /auto-review/auto-review status | 显示当前档位、审查模式、决策计数和最近决策 | | /auto-review on / /auto-review off | 打开 / 关闭 LLM 审查(off = 纯静态规则) | | /auto-review rules | 纯规则档(等价 off) | | /auto-review tiered | 三态档(默认):静态 → LLM → 人工兜底 | | /auto-review auto | 两态自主档:审查员不确定 / 失败一律拒绝,无人参与 | | /auto-review reset | 回到配置文件里的设置 |

  • 内存态:开关只对当前进程生效,重启后重置回配置;要持久化就改 config:
  • 优先级:开关 > 配置 > perMode 默认。
  • 档位映射:rules = review.mode: offtiered = on + onUncertain: askauto = on + onUncertain: deny

安装

本包是标准 bundlepackage.json 声明 dsh.bundle,携带自己的 cordis.patch.yml 层),按官方发布文档(docs/user/develop/basic/publish.md)安装。

方式一:官方 dsh plugin(推荐)

在包含本包目录的上层目录执行:

dsh plugin --profile web add ./dsh-tiered-approval

dsh plugin add 会把包链接进 profile 的 node_modules,并把本包追加到 dsh.profile.bundles(其 cordis.patch.yml 层自动挂载 tiered-approval 行)。前置条件:profile 目录里需要 pnpm 可用(dsh plugin 转发给 pnpm)。

npm 发布后,一行即可:dsh plugin --profile web add dsh-tiered-approval

方式二:从 GitHub 安装

dsh plugin --profile web add github:Elaina-real/dsh-tiered-approval

本包是编译好的 JSlib/ 已提交在仓库里),没有 TS 源码 + 构建步骤,所以不需要 prepare 脚本,也不需要 allowBuilds 放行——比 TS 源码包少一道安全门槛。

方式三:手动拷贝(无 pnpm 时兜底)

把整个目录拷到 ~/.dsh/profiles/<profile>/node_modules/dsh-tiered-approval(profile 用 hoisted pnpm 布局,拷贝即可被 loader 解析),并在 profile 的 cordis.patch.yml- insert: 挂载行。

验证与卸载

  • 验证dsh --profile web --dump-config 应出现 # == dsh-tiered-approval 层;或装完重启后看插件清单页 / 日志。
  • 注意:插件代码在 node_modules 里,HMR 不追踪 node_modules——改代码必须重启;改 cordis.patch.yml 配置可能热生效,但别依赖。
  • 卸载:见下一节。

卸载 / 禁用

  • 临时禁用:bundle 行加 disabled: true(或在 profile 的 patch 里覆盖 tiered-approval 行),重启。
  • 彻底卸载(bundle 方式)dsh plugin --profile web remove dsh-tiered-approval,重启。所有监听器随 cordis fiber 自动 dispose。

配置

# ~/.dsh/profiles/<profile>/cordis.patch.yml
- insert:
    - id: tiered-approval
      name: 'dsh-tiered-approval'
      config:
        builtinDeny: true                 # 内置破坏性命令安全网总开关(默认开;建议永远别关)
        builtinDenyRules: []              # 内置危险命令规则列表(默认 = 代码内置那组;可在这里增删改,无需改代码)
        log: true                         # 记录每一次自动决策

        deny: []                          # 追加硬拒绝规则(命中即拒、不弹窗)
        # 例如:
        # - tool: pwsh
        #   where:
        #     command: ['git\\s+push.*(--force|-f\\b)']
        #   reason: '禁止强推'

        allow: []                         # 自动放行规则(配合应答者生效)
        # 例如(门禁判定安全,且升权模式被允许时自动批准):
        # - tool: pwsh
        #   where:
        #     command: ['pnpm\\s+install|npm\\s+install']
        #   escalating: true

        answerer:
          allowModes: ['workspace-write']            # 规则层:默认不含 danger-full-access
          allowJustifications: []                    # 理由命中 ⇒ 自动批准
          denyJustifications: []                     # 理由命中 ⇒ 自动拒绝(优先)
          # 例如:
          # denyJustifications:
          #   - 'drop\\s+database'
          #   - 'DROP\\s+TABLE'
          #   - '删除.*(数据库|生产|整个)'

        review:                                      # LLM 审查层(默认开)
          mode: 'on'                                 # 'off' = 纯规则版
          # provider: 'deepseek-official'            # 显式路由(必须与 model 成对)
          # model: 'deepseek-v4-flash'
          skipTools: [read, read_image, glob, grep, web_search,
                      job_output, job_list, job_kill, ask_user_question,
                      todo_write, list_agents, interrupt_agent]
          skipNested: true                           # 跳过 run_code 子分发
          allowModes: ['workspace-write', 'danger-full-access']   # 审查员可批准的模式
          onUncertain: 'ask'                         # 'ask'=不确定交人工(默认);'deny'=全自主两态,直接拒绝
          timeoutMs: 20000
          maxTokens: 512
          maxInputChars: 12000
          perMode: {}                                # 按沙箱模式覆盖(见下)

规则字段(deny / allow 共用)

| 字段 | 说明 | | --- | --- | | tool | 工具名,* 匹配所有工具(pwshbashwriteeditreadglobgrep…) | | where | 参数匹配表:键是参数的点路径,值是正则列表;所有列出的键都命中才匹配 | | escalating | true ⇒ 只匹配带了 sandbox_permissions(升权)的调用 | | reason | 拒绝时的说明(作为工具错误返回给模型 / 写进日志) |

正则大小写不敏感;YAML 里反斜杠要写双份(\\s)。所有正则加载期校验:写错插件直接拒绝加载,不会静默不匹配。

跟随 Access 选择器(perMode)

审查策略自动跟随会话当前的沙箱模式——界面 Access 下拉(Read only / Workspace write / Full access)会把 sandbox/mode 写进会话,插件每次调用都按当前模式重新解析策略:

review:
  perMode:
    'read-only':                  # 只读下保持审查(命令仍会执行,只是改不了文件)
      mode: 'on'
    'workspace-write':            # 标准模式,默认即可
      mode: 'on'
    'danger-full-access':
      # 内置安全默认:若从未自定义过全局 skipTools,Full access 下全量审查
      # (skipTools: [])——沙箱不隔离了,审查是静态规则之外的最后防线。
      # 想放开就在这写:
      # skipTools: [read, glob, grep]
      mode: 'on'

| 当前 Access | 默认审查行为 | | --- | --- | | Read only | 开;跳过只读/搜索/任务控制类工具 | | Workspace write | 开;跳过只读/搜索/任务控制类工具(同全局默认) | | Full access | 开且全量(什么都不跳过);全局 skipTools 自定义过则跟随全局 |

[!WARNING] Full access 预设同时把审批策略设为 never(无人工弹窗)。此时审查员裁决 ask 不会弹窗,而是变成确定性拒绝(fail-closed)。想要人工兜底,就别把会话切成 Full access。

LLM 审查层说明

  • 上下文感知:审查输入帧除了工具名 + 完整参数 + 沙箱模式/工作区根,还带会话里最近一条真人消息source.kind === 'user',注入的 skill/通知类上下文会跳过),让审查员判断命令是否对齐用户意图。
  • 路由:默认取第一个已注册 provider 的第一个模型;想指定就配 review.provider + review.model(必须成对)。
  • 成本:每个规则未裁决的调用 = 一次小模型调用(输出 ≤ maxTokens,输入帧截断到 maxInputChars);skipToolsskipNested 防止审查调用被放大。
  • 故障行为(默认 onUncertain: 'ask'):审查员不可用 / 超时 / 输出畸形 ⇒ 静默回退(记日志,不新增弹窗);静态安全网照常兜底。只有审查员明确裁决 ask 才弹人工。
  • 全自主两态onUncertain: 'deny'):审查员 ask 与审查失败都变成确定性拒绝(fail-closed),全程无人参与——适合你已经信任模型判断的场景;代价是审查员拿不准的调用会被拒绝而不是问你。
  • 收紧:把 review.allowModes 改成 ['workspace-write']danger-full-access 升权就回到人工审查。

安全模型与默认值

| 情况 | 默认行为 | | --- | --- | | 工作区内正常操作(读写/搜索/构建) | 静态规则放行;未裁决的交给 LLM 审查员 | | 升权到 workspace-write(如 read-only 会话) | 规则或审查员判定安全 → 自动批准 | | 升权到 danger-full-access | 规则层:默认不自动批准;LLM 层:审查员允许则自动批准(review.allowModes 默认含它) | | 升权 + 破坏性命令(递归删除、格式化、强推、注册表…) | 静态层直接拒绝——不弹窗、不调模型 | | 升权写入系统目录(C:\Windows/etc…) | 静态层直接拒绝——不弹窗 | | 进程终止命令(taskkill / Stop-Process / killall / pkill) | self-kill 守卫静态拒绝(后台任务用 job_killkill <pid> 是逃生口) |

规则版与 LLM 版自由混用:review.mode: 'off' = 纯规则版;开着 LLM 层时静态安全网仍然先执行(不可逆操作从不消耗审查 token)。

权限与数据

| 内容 | 说明 | | --- | --- | | 读取 | 每个工具调用的完整参数(命令文本、路径、升权理由等)——在门禁内读,仅用于裁决,不落盘 | | 发送给模型 | 开启 LLM 审查时,把参数帧(工具名、参数、沙箱模式/工作区根、最近一条用户消息)发给你配置的模型 provider(默认与会话同款路由)——参数和用户消息里可能含敏感文本,请知情 | | 网络 | 无独立网络访问;只通过 DSH 的 ctx.llm 服务发模型请求 | | 凭据 | 不读取、不存储任何凭据;~/.dsh/.credentials.yaml 由 DSH 凭据服务管理,本插件不触碰 | | 文件写入 | 无(仅日志由 dsh 进程统一输出) | | 会话日志 | 不写 session 事件;仅通过插件 logger 输出 [auto-approval] 行 | | 卸载 | 全部监听器随 fiber dispose,无残留状态 |

兼容性

| 项 | 说明 | | --- | --- | | DSH 版本 | 针对 @deepseek-ai/dsh 0.1.0-rc.6 开发与验证 | | 依赖 | @deepseek-ai/cordis ^4.0.1、@deepseek-ai/schemastery ^3.18.1、@deepseek-ai/dsh-llm ^0.1.0-rc.6、@deepseek-ai/dsh-timeout ^0.1.0-rc.6 | | 平台 | Windows(pwsh 规则集,实测);POSIX 走 bash 规则集,理论上兼容(未实测) | | 最后验证 | 2026-08(npm test 全绿;冒烟测试 38 项) |

mainline 迭代很快,兼容性结论可能过期;升级 DSH 后请重跑 npm test 并试一次门禁行为再依赖。

边界与限制

  • 本插件是纯 vibe coding 写的——见顶部警告。 未审计、非官方、无担保。
  • 应答者的文本规则(allowJustifications / denyJustifications)只匹配模型写的一句理由——真正的判断在门禁(静态规则 + LLM 审查员),那里才有完整参数。
  • LLM 审查是概率性的,不是证明;规则是人写的,可能漏掉新姿势;来自文件/网页/工具输出的 prompt injection 可能把 agent 往越界方向带,命令级审查员不一定看得出来。
  • run_code 子分发经过门禁(印记覆盖),但 LLM 审查默认跳过嵌套调用(skipNested: true),只审查外层 run_code 本身。
  • 委派的子 agent 不受影响:DSH 默认把子 agent 的审批策略钉死为 never

日志与排查

log: true(默认)时,每次自动决策都会写进 dsh 进程日志:

  • [auto-approval] deny ... —— 静态或审查拒绝
  • [auto-approval] review-allow / review-deny / review-ask ... —— 审查员裁决
  • [auto-approval] allow escalation ... -> <mode> —— 自动批准了一次升权
  • [auto-approval] reviewer call failed ... / review inconclusive ... —— 审查层故障(已静默回退)

排查时 grep [auto-approval],看是哪一层、哪条规则/理由做的决定。

| 症状 | 排查 | | --- | --- | | 插件清单里没有 tiered-approval | 重启服务;确认包在 node_modules、patch/bundle 行正确;看启动日志是否报 "plugin failed to load"(如配置 schema 校验失败) | | 升权不再自动批准,或弹窗变多 | 检查当前 Access 预设(Full access 下 ask 是确定性拒绝);确认 review.modeallowModes | | 规则没生效 | 配置正则加载期已校验(非法会拒绝加载);确认 tool 名、where 键路径、YAML 转义(\\s) | | 审查延迟高 | 加了 skipTools 仍慢的工具;或 review.provider/model 指向慢模型;看 timeoutMs | | 想彻底回滚 | 按「卸载 / 禁用」移除 bundle 或手动行 + 重启;删除包目录即可 |

测试

包内带 test/smoke.mjs —— 38 项断言驱动 apply()(假 ctx:假 llm 服务返回预置裁决、假 sandboxPolicy),覆盖静态层、审查员 allow/deny/ask/故障、skipTools / skipNestedperMode 跟随预设、应答者的升权规则和配置默认值。

独立运行(devDependencies 已声明,不需要 DSH profile):

npm install
npm test        # 期望 "ALL PASS"

推送到 GitHub 后,.github/workflows/test.yml 会在每次 push / PR 上自动跑冒烟测试(Node 20 和 22)。

冒烟测试 ≠ 安全审计——用之前先为你的工作流补用例。

贡献

  • Issues:bug、建议、看不懂的报错、文档疑问——开一个 就行;
  • PRs:欢迎,尤其是 review / 审计——一个 vibe coding 产物最缺的就是人眼;
  • 安全相关问题:开 issue 时标注 security,或先私下联系作者。

License

MIT —— 但请看顶部的 vibe coding 警告:风险自负。

如果它帮你少点了很多次鼠标,⭐ 一下 就是最好的支持。