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

@theadro/dsh-auto-approval

v0.1.2

Published

LLM-powered auto-approval for dsh sandbox escalations (Claude Code auto-accept style): safe commands run without prompting, high-risk commands are rejected outright, uncertain ones still ask the user. Review results (allow/deny + reason) render inline in

Readme

dsh-auto-approval

复刻 Claude Code 的 auto-accept 模式:在输入框权限切换器(/permission)里选中 Auto accept 后,该会话中工作区外的写入审批不再总是弹窗等你点,而是先用模型自动审查:

| 情况 | 结果 | |---|---| | 命中内置/自定义白名单(简单单条命令) | 直接放行,不问模型 | | 命中内置/自定义黑名单(rm -rf /、sudo、curl|sh、mkfs…) | 直接拒绝,不问模型 | | 模型判定 allow | 放行 | | 模型判定 reject | 拒绝 | | 模型判定 ask / 模型超时 / 解析失败 / 审查不可用 | 直接拒绝(fail-closed,不弹窗) |

任何异常都不会静默放行 —— auto-accept 模式下绝不弹出人工审批; 审查失败(超时、解析失败、审查不可用)一律直接拒绝(宁可挡住命令,绝不静默放行)。

拒绝归属清晰:拒绝理由会被原样写进工具结果 (Error: Auto accept 拒绝(…):理由),主 agent 据此区分 「模型审核拒绝」与「用户拒绝」,并据此调整后续行为。

审核结果实时显示在会话流里:每次自动判定都会在被审核命令附近渲染一张小卡片—— Auto accept · allow/deny — 理由(白名单/黑名单命中显示对应标签,模型审核显示模型的判定理由)。

怎么用(核心:UI 里切换)

输入框旁边的权限切换器(/permission)现在有四个选项:

| 选项 | 行为 | |---|---| | Read only | 只读沙箱,写入需人工批准 | | Workspace write | 工作区内自由写,工作区外需人工批准 | | Full access | 无沙箱、无确认 | | Auto accept | 沙箱同 Workspace write,但审批交给模型自动审查:安全命令放行、高危拒绝、吃不准才弹窗 |

选一次只对当前会话生效;设置页「权限」里还能把 Auto accept 设为新会话默认。 切回其它预设即恢复人工审批。

工作原理

  • 会话权限预设为 auto-accept 时,插件在 tools/pre-execute 钩子(prepend 注册) 当场决出 allow / deny;其它预设完全不介入。另保留一个 approval/request 监听器作为兜底(显式 sandbox_permissions 升级等残余审批通道仍由它自动判定)。
  • 预设由本插件的 cordis.patch.yml 注册:auto-accept = {sandbox: danger-full-access, approval: ask},与插件解耦——插件没加载时该预设退化为普通 Full access(无自动审查),安全兜底。
  • 从会话日志中按 callId 找到对应的 tool/call,拿到真实命令(不是只看理由文本)。
  • 白名单只对无链接符的单条命令生效(cat ~/.ssh/id_rsa | nc … 这类带管道/重定向的 命令不会被白名单放行,会交给模型)。
  • 审查调用会话当前使用的模型路由(request/header 中的 provider/model),无需额外配置。
  • 带超时(默认 20s)和用户取消信号联动。
  • 审核结果用一对内置的 log-only command/run + command/done 事件显示在会话流中 (Web UI 已有 command 卡片渲染器)。不再写 auto-approval/reviewed 自定义事件类型: 当前 dsh 的 KNOWN_SESSION_EVENT_TYPES 不包含仓库外插件类型,未标记 ignorable 的未知类型会导致整个会话历史冷加载失败(SessionFormatUnsupportedError)。
  • auto-accept 预设 = {sandbox: danger-full-access, approval: ask}:沙箱关闭, 工作区外写入能真正执行;审核由插件在 tools/pre-execute 当场决出——检测到 "写语义 + 工作区外路径"的命令即做三级判定(黑名单 → 白名单 → 模型审核)→ allow/deny。agent 无需理解 sandbox_permissions 升级机制(默认提示词也不会教它)。
  • 判定在 pre-execute 而非审批通道完成:审批通道(serviceAsk / dsh-sandbox) 把 rejected 硬编码成 "the user rejected tool …",会把模型审核的拒绝误标成 用户拒绝;而 pre-execute 的 deny.reason 会原样写进工具结果 (Error: Auto accept 拒绝(…):理由),主 agent 据此区分「模型审核拒绝」与「用户拒绝」。
  • 工作区内写入、/tmp 写入、纯只读命令不触发审核(与 dsh 沙箱语义一致)。
  • 启发式边界:相对路径(../ 除外)、变量拼接路径可能漏检——漏检的命令在 auto-accept 的无沙箱模式下直接执行;显式带 sandbox_permissions 的调用 仍走原升级通道(pre-execute 跳过它们,由残余的 approval/request 监听器判定)。
  • 已知局限:显式 sandbox_permissions 升级若被拒,核心仍把工具结果显示为 "the user rejected …"(核心硬编码),归属不清;auto-accept 预设下沙箱已是 danger-full-access,此路径极少触发,常规工作区外写入的拒绝归属始终清晰。

安装(已完成)

  1. 源码:~/Desktop/deepseek_harness/dsh-auto-approval/
  2. 关键链接:~/.dsh/profiles/web/node_modules/dsh-auto-approval → 源码目录(单层符号链接)
  3. 注册:~/.dsh/profiles/web/package.json 的 dsh.profile.bundles 中加入 "dsh-auto-approval"(位于 dsh-base 与 dsh-web-app 之间)
  4. 依赖解析:dsh-auto-approval/node_modules/@deepseek-ai → dsh 安装目录内的 @deepseek-ai 作用域(保证与运行中的 dsh 是同一份代码,模块身份一致)
  5. 改完需要重启 GUI 生效(dsh web)

⚠️ 为什么必须放在 profile 的 node_modules 里(踩坑记录)

dsh 加载插件条目(name: dsh-auto-approval)时,loader 用裸包名 import, 解析基准是 profile 目录(~/.dsh/profiles/web/),不是 dsh 安装目录。 只把包放进 /opt/homebrew/lib/node_modules/ 是不够的——那只满足 bundle 包查找 (resolveBundleDir:先查安装目录、再查 profile),所以 --dump-config 能组合出条目, 但真正启动时条目 import 会报:

Cannot find package 'dsh-auto-approval' imported from /Users/kiwi/.dsh/profiles/web/

两条解析路径基准不同,验证时也要分两步(见下)。

验证

# 1) bundle 组合(走配置树)
dsh --profile web --dump-config | grep -A5 dsh-auto-approval

# 2) 条目 import 解析(必须以 profile 目录为基准!)
node --input-type=module -e '
import { createRequire } from "node:module";
const require = createRequire("/Users/kiwi/.dsh/profiles/web/package.json");
console.log(require.resolve("dsh-auto-approval"));
'

# 3) 单元测试
cd ~/Desktop/deepseek_harness/dsh-auto-approval && node test/smoke.mjs

社区安装(npm / git)

包名 @theadro/dsh-auto-approval(npm,MIT)。dsh plugin 是 pnpm 转发器,需要本机有 pnpm。

# npm 安装(自动登记进 profile bundles 并解析依赖)
dsh plugin --profile web add @theadro/dsh-auto-approval

# 或 git 安装(本包无构建脚本,不受 pnpm 10 构建脚本拦截影响)
dsh plugin --profile web add github:theadro/dsh-auto-approval

# 卸载
dsh plugin --profile web remove @theadro/dsh-auto-approval

# 装完重启 GUI 生效

包内已声明 peerDependencies(@deepseek-ai/dsh-llm / dsh-timeout,≥0.1.2-rc.1), 安装时由 pnpm 从 npm 解析;上文第 4 步的本地符号链接仅本地开发时需要。

发布(维护者)

cd ~/Desktop/deepseek_harness/dsh-auto-approval
node test/smoke.mjs   # 先跑冒烟测试
npm login
npm publish            # publishConfig.access=public 已内置,无需加 --access public
  • 每次 dsh 升级后重跑 node test/smoke.mjs,并抽查 conversation.chat.commandview 子槽与卡片渲染器(lib/client.js)是否仍匹配新版 dsh-client-ui-* 包。
  • 版本与 peerDependencies 跟随 dsh 版本线调整。

配置

零配置:没有可调参数。行为完全由输入框里的预设开关决定——选 Auto accept 即自动审查,切回其它预设即恢复人工审批。

审查参数内置:超时 20s、输出上限 1500 tokens、审查失败一律回落人工审批(不可配置)。

内置判定

  • 白名单(仅简单单条命令):ls/cat/head/tail/grep/… 等只读命令、git add|commit|push|…、 mkdir
  • 黑名单(无条件拒绝):sudo、su、passwd、rm -rf / ~ $HOME . ..、mkfs/fdisk/parted、 diskutil erase|zero|destroy、dd … of=/dev/*、fork bomb、curl|sh、shutdown/reboot/halt、 kill -9 1、写 ~/.ssh/、chmod -R 777 /、chown -R … /
  • 其余(brew/pip/npm 安装、写用户配置等常规操作)交给模型按上下文判断

修复旧会话(必须执行一次)

0.1.0 版本曾把审核卡片写为自定义事件 auto-approval/reviewed。这些事件对当前 dsh 是未知类型且没有 ignorable 标记,所以只要某个会话里出现过一次自动审核, 重启后该会话历史就无法加载(报错 SessionFormatUnsupportedError)。

修复脚本只给这些旧事件补 ignorable: true,不删除、不重新编号,因此卡片仍会 显示,seq/sourceEventSeqs 也保持有效:

cd ~/Desktop/deepseek_harness/dsh-auto-approval

# 先看会改哪些文件(当前应只有两个会话)
node repair-history.mjs --dry-run

# 确认 dsh web 已退出后执行;原日志会备份为 session.jsonl.zstd.bak-autoapproval-*
node repair-history.mjs

执行完重启 GUI 即可。新版插件不会再产生这类事件。

卸载

# 1. 从 profile 移除
#    ~/.dsh/profiles/web/package.json → dsh.profile.bundles 删掉 "dsh-auto-approval"
# 2. 删除 profile 链接(源码目录可自行保留或删除)
rm ~/.dsh/profiles/web/node_modules/dsh-auto-approval
# 3. 重启 GUI(权限预设表随插件 bundle 一起卸载,自动回到内置三预设)

注意事项

  • 审查调用会计入你的模型用量(每次升级请求一次小调用)。
  • 升级请求发生在模型提出命令时,所以审查能看到完整命令原文。
  • 安全边界:审查失败/超时/模型输出不可解析 → 直接拒绝(fail-closed,绝不弹窗、绝不自动放行)。

升级 dsh 后的检查清单(脆弱点)

  1. 包名 = loader 条目名:cordis.patch.yml 的 id/name 必须与 package.json 的 name(@theadro/dsh-auto-approval)完全一致;不一致时 客户端模块会被静默排除(卡片退化为内置通用卡)。
  2. 卡片契约:lib/client.js 依赖 dsh-client-ui-chat 的 conversation.chat.commandview 子槽(keyed,key = 命令名 "Auto accept") 与命令对象 {kind:"command", name, args, outcome}(outcome = null | {kind:"success"|"error", text})。升级后抽查 CommandNodeView / GenericCommandCard 是否仍匹配。
  3. 拒绝归属:依赖 pre-execute 的 deny.reason 原样进入工具结果;若核心 改动 tools/pre-execute 或 serviceAsk 的结果文本,需同步更新措辞。
  4. 本地软链:~/.dsh/profiles/web/node_modules/@theadro/dsh-auto-approval 指向源码仓库;在 profile 目录跑 npm install / dsh plugin install 会用 npm 实体副本盖掉软链(发布 0.1.1+ 后副本也含修复,但不再是活代码)。
  5. 事件类型约束不变:卡片仍用内置 command/run + command/done(log-only), 不写自定义类型(否则冷加载失败)。