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

@log.li/dsh-automode

v0.16.1

Published

CC-style auto mode for DeepSeek Harness: deterministic deny/allow rules + pre-execute gate + model-agnostic two-stage classifier. Two-state (allow/reject) classifier since 0.8.0. TypeScript rewrite merging dsh-auto-mode v0.4.1 with Nuo-cl/dsh-auto-mode na

Downloads

2,984

Readme

dsh-automode ⚡

面向 DeepSeek Harness 的 Claude Code 风格自动模式:让 agent 放手自主执行,同时由确定性护栏 + 低成本复审模型把危险操作挡在执行之前。

🌐 简体中文: README.zh.md · English: README.md

npm npm downloads license GitHub stars GitHub last commit TypeScript DSH plugin


dsh-automode 是护栏插件,介于 agent 与 harness 之间,在每次工具调用执行前拦截——硬 deny 规则与 curated allowPaths 确定性裁决(零 LLM 开销),其余交给两阶段分类器。安全操作全自动放行;危险操作被拦截、改写或转交给你。

✨ 核心特性

  • 🛡️ 确定性第一道防线 —— 正则 deny 频带在任何 LLM 调用之前硬拒外泄、密钥与系统路径;前缀 glob allow 规则零成本放行常规命令。
  • ⚡ 零确认白名单 —— config.allowPaths 即全信任:其中文件操作与 bash 写命令完全跳过分类器,提权调用经 approval 桥接自动放行(v0.10.0)——不弹窗、不来回。
  • 🧠 省成本的两阶段分类器 —— 约 1 token 的粗筛预判,仅命中项进入结构化复审;相同动作 5 分钟内复用判决缓存。
  • 🔁 熔断器 + 人工兜底 —— 连续 3 次(或累计 20 次)DENY 暂停自动模式并转人工;一次人工决定即恢复并清零。
  • 📜 完整审计轨迹 —— 每次 allow / deny / bridge 决定都追加到 ~/.dsh/auto-mode/decisions.jsonl。
  • 🔌 原生预设 —— 权限选择器一键开启或 /auto;与只读 / workspace-write / danger-full-access 并存。

⚠️ 它不是沙箱。插件运行在 DSH 进程内,蓄意恶意的插件可以做你用户账户能做的任何事。它用于降低不安全的自主工具使用,而不是 OS 安全边界。

📚 目录

安装

dsh plugin add @log.li/dsh-automode

从本地 checkout:

dsh plugin add ./path/to/dsh-automode

安装后重启 dsh web。权限选择器(聊天框左下角)会显示 Auto mode,与只读 / workspace-write / danger-full-access 并列。

可选:权限选择器里的 ⚡ 图标

auto-mode 预设声明了一个 icon,但原生 DSH 把三个内置 glyph 写死在客户端里,会静默忽略预设的 icon —— 所以只有额外打上随包提供的补丁,闪电才会显示:

# <profile> 是你的 DSH profile 名(通常是 web)。用哪个 profile 下的副本都行:
# 脚本自己会扫描所有 profile 与全局安装。
node ~/.dsh/profiles/<profile>/node_modules/@log.li/dsh-automode/patches/dsh-permission-preset-icon.mjs

# 或者从 checkout 里跑:
node patches/dsh-permission-preset-icon.mjs --dry-run   # 先看它会改什么
node patches/dsh-permission-preset-icon.mjs

然后重启 dsh web。

先弄清你在接受什么。 这个补丁改的是 node_modules 里的文件(宿主预设 schema 与客户端 bundle),所以它以独立脚本形式提供、而不在安装时自动执行:

  • 它只是外观。 闪电渲染与否,auto-mode 行为完全一致。不在意就别跑。
  • 每次 npm update @deepseek-ai/dsh 或重装插件都会把它冲掉 —— 之后重跑一次即可。它不会「打一半」:先做全量锚点预检,锚点对不上的文件会被明确报告(ANCHORS NOT FOUND)并逐字节保持原样。
  • 回滚就是抄回备份。 每个被改写的文件旁边都先留一份 <文件名>.pre-dsh-automode-icon.bak;重跑是空操作(报 already patched)。
  • 它针对 DSH 0.1.7-rc.2 这一代。 更早的 0.1.x 行会被标注后跳过(那几代的权限选择器在另一个包里,锚点不可能命中)。更新的版本仍会按锚点尝试——失配则文件逐字节不动、报告点名是哪一处锚点没中。将来 DSH 若原生支持预设 icon,删掉脚本即可。
  • npm run test:patch(已并入 npm test)用合成 fixture 覆盖 apply / 幂等 / dry-run / 锚点失配 / 外来注入拒绝 / 参数错误;本机存在 0.1.7 安装时,还会拿真实产物的副本跑一遍(两个补丁产物都过 node --check)。

命令

/auto           # 把本会话切换到 auto 模式
/auto-status    # 显示诊断:preset、审批策略、熔断器状态

工作原理

工具调用到达
  │
  ├─ [pre-execute 门](所有工具,第一道防线)
  │    ① 只读工具 → 放行(除非命中 deny)
  │    ② deny 规则(正则)→ 硬拒绝
  │    ③ allow 规则(前缀 glob)→ 放行
  │    ④ 工作区内文件操作 → 放行(allowInsideWorkingDirectory)
  │    ⑤ 升级意图 → 分类器预审
  │    ⑥ 其余 → 放行
  │
  └─ [approval 瀑布]
       ① 散文 deny 规则 → 拒绝
       ② 散文 allow 规则 → 放行
       ③ 只读 allowlist → 放行
       ④ 裁决缓存命中 → 复用(不二次调用 LLM)
       ⑤ 分类器(两阶段:one-token 预筛 → 结构化裁决)
       ⑥ 失败 → fail-closed

Auto mode 工具调用拦截管线

🖱️ 可交互版本:docs/auto-mode-flow.zh.html —— 平移缩放、关系追踪、暗色模式。图表源数据:docs/auto-mode-flow.zh.workflow.json。

pre-execute 门拦截所有工具调用(包括工作区沙箱内、本来不会触发 approval 瀑布的那些)。approval 瀑布只对真正需要沙箱升级的调用运行。pre-execute 门仅对 auto-mode 会话生效;在其他 preset(read-only / workspace-write / danger-full-access)下它是 no-op,不会与你所选沙箱冲突。

规则

规则体系分两层:

硬边界(确定性,永不进分类器)

  • deny — 正则模式,硬拒绝。首个匹配生效。在所有检查之前求值。用于加密外泄、密钥、敏感目标、危险命令。频带只匹配「操作」(v0.15.1):bash 扫命令原文、文件工具扫目标路径;参数是散文的工具(如 subagent 的 prompt、脚本正文)只受「操作形」内置模式约束——提到某个敏感话题不等于处理它,因此提及 .env/密钥/凭据主题的文档与审查不再被硬拒,而真正的凭据库文件名与内联密钥材料仍硬拒。
  • allow — 前缀 glob 模式,不调用任何 LLM 直接放行。在 deny 之后求值。用于你完全信任的常规命令。

分类器引导(散文,喂给 LLM)

  • rules.deny — 软拒绝描述。分类器把它们视为常驻拒绝。可被用户直接意图或匹配到的 allow 规则覆盖。
  • rules.allow — 软放行例外。分类器把它们视为常驻放行,会覆盖匹配的软拒绝规则。
  • rules.environment — 上下文事实(受信仓库、基础设施、云存储桶)。分类器据此判断某动作是否在用户环境内。

所有 rules.* 数组都支持 $defaults:用 ["$defaults", "my custom rule"] 保留内置规则并添加你自己的;省略 $defaults 则整个用你的替换内置列表。

配置

配置写在 profile 的 cordis.patch.yml。一切都有默认值,裸 {} 配置也合法。下表是完整参考;最小示例(allowPaths 覆写)见 信任额外目录。

关键选项

| 选项 | 默认 | 说明 | |---|---|---| | deny | 内置列表 | 正则模式,硬拒绝。首个匹配生效。 | | allow | 内置列表 | 前缀 glob,不调用 LLM 放行。 | | readOnlyTools | read, glob, grep, list, search | 默认放行的工具(除非命中 deny)。 | | allowPaths | [] | 全信任的外部目录:目标落在其中的文件操作与 bash 写命令跳过分类器;v0.10.0 起提权调用也自动放行(approval-bridge)。见 信任额外目录。 | | allowInsideWorkingDirectory | true | 工作区内文件操作不经分类器。 | | classifier.provider / classifier.model | ''(跟随会话) | 覆盖分类器 LLM 路由。解析顺序:classifier.{provider,model} → 会话当前模型 → agent 配置模型。 | | classifier.reasoningLevel | off | 分类器推理强度(off 关闭推理)。若路由拒绝该 effort,调用会重试不传 effort。 | | rules.deny | ['$defaults'] | 分类器软拒绝散文。 | | rules.allow | ['$defaults'] | 分类器软放行散文。 | | rules.environment | ['$defaults'] | 分类器环境事实。 | | failClosed | true | 分类器失败时拒绝,vs. 回退到审批链。 | | preExecuteGate | true | 启用 pre-execute 门(仅 auto-mode 会话生效)。 | | timeoutMs | 45000 | 分类器 LLM 调用的单次硬超时。 | | classifyContextChars | 6000 | 给分类器的任务对齐上下文字符预算。 | | maxArgsChars | 4000 | 裁决缓存 key 用的命令签名字符预算。 | | breakerConsecutive | 3 | 连续分类器 DENY 触发熔断。 | | breakerTotal | 20 | 总分类器 DENY 触发熔断。 |

信任额外目录(allowPaths)

allowPaths 是用户 curated 的全信任列表:目标解析后落在其中任一目录内的文件操作与 bash 写命令,完全跳过安全分类器(日志记为 pre-execute-allow / curated allowPath;工作区内目标带提权请求的另行记为 workspace in-tree escalation,v0.14.0)。随插件发布的默认只保留通用 /tmp/——个人目录改在 profile 的 cordis.patch.yml 配置。loader patch 会整体替换目标行的 config,所以下面的最小覆写只设 allowPaths(其余字段回退到插件代码默认值):

# ~/.dsh/profiles/<profile>/cordis.patch.yml
- id: auto-mode
  config:
    allowPaths:
      - /tmp/
      - /Users/<you>/Library/CloudStorage/OneDrive-<tenant>/Projects/<proj>/Proposal/

只有被识别的写命令才会被信任;路径在 symlink 解析后匹配,/Users/<you>/OneDrive - … 软链与真实 Library/CloudStorage/… 路径都可用,且 ~/$HOME 前缀会在匹配前展开(v0.13.0)。不可恢复删除(rm、shred、unlink)绝不会进入白名单;而经 trash(freedesktop 回收站)执行的可恢复删除可以(v0.13.0)——其目标会被提取,且每一个都必须解析到 allowPath 内,硬 deny 频带仍最先拒绝针对系统路径的 trash/mv。白名单目录内的 git add/commit/push 会把仓库根解析为写目标,因此对位于 allowPath 下的仓库做提交/推送也会跳过分类器(v0.11.1)。下面的裁决缓存修复仍然重要:即便没有 allowPath,你一旦显式授权某个动作,分类器也会带着你的意图重跑,而不是回放旧的缓存拒绝。

复合写命令(v0.11.0)。临时文件→替换的导出三步曲(如 DIR=…; cp a b_tmp && (trash b; true) && mv b_tmp "$DIR/b")现在会按段解析(含 VAR=… 赋值跟踪与 $VAR 展开),其目标仍能命中 allowPaths。cd <dir> 是受跟踪的良性导航命令——它更新有效工作目录(使后面的 git add/commit/push 据此解析仓库根),且不使快速路径失效(cd - 仍不可预测,回退分类器)。快速路径仍有守卫:复合命令若含副作用命令(kill、pkill、rm、sh、bash、网络/守护进程管理等)、命令替换(`…`、$(…)、<(…))、文件重定向(>file、>>file、2>file)或写/良性集之外的任何命令,一律回退分类器,与之前行为一致。fd-dup 重定向(2>&1、>&2、>&-)不是文件写入,不使快速路径失效——所以 git push … 2>&1 | tail 仍可被白名单判定。复合内的只读工具(echo、ls、cat、head 等)随白名单快速路径搭车执行——一旦所有写目标都在白名单内,其副作用不再单独过分类器。写目标按该段当时的 cwd 解析,因此 cd 会被信任证明如实采纳:cd 进信任根内的相对写入仍走快速路径,而 cd /elsewhere && cp a rel/path 不再因为把 rel/path 按会话目录解析而蒙混过关(v0.15.3——此前这种不一致可被桥接为 danger-full-access);展开后仍含未解析 $VAR 的目标(如命令内从未赋值的 $TMPDIR)则整条不再走快速路径,而不是去证明一个字面量路径。mkdir 自 v0.15.3 起不再搭车:它会创建目录,因此其目标同样加入信任证明(全部须在信任根内)——此前 git commit … && mkdir -p /elsewhere 可以仅凭仓库根就被自动信任。rm 仍强制回退分类器;而 v0.13.0 起,trash 出现在复合命令中时其可恢复删除目标会加入目标集,与普通写目标一样接受白名单判定(全部须在信任根内,否则整体回退分类器)。改写历史的 git 命令(reset --hard、clean、rebase、merge)刻意不进入白名单信任。

零确认提权(v0.10.0)。allowlist 路径意味着全信任:请求放宽沙箱(sandbox_permissions: danger-full-access)进入 allowlist 路径的调用现在无需任何确认、不经分类器直接放行——pre-execute 门已确定性证明所有目标都在 allowPath 内,该结论通过调用的 callId 传给 approval answerer(审计日志呈现 curated allowPath → approval-bridge → decision allowed-once;工作区内提权则呈现 workspace in-tree escalation,v0.14.0)。deny 频带仍最先执行(~/.ssh/ 等 deny 路径即便在 allowPath 内也硬拒),熔断器也不会被绕过——跳闸期间 allowlist 调用仍走人工。

不是文件沙箱豁免。allowPaths 只跳过本插件的评审——DSH 文件沙箱(会话文件策略)是独立一层,仍然生效。写 workspace 外的 allowlist 目录会被沙箱拦截,除非调用带 sandbox_permissions: danger-full-access;而该提权对 allowlist 路径经 approval 桥接零评审自动放行——所以第一次尝试就直接带上提权即可。

每个 auto-mode 会话也会通过系统提示段(auto-mode:allowlist)获得这份知识:模型知道 per-profile 的 allowPaths 配置在哪、怎么改——动作被拦截时可以给出精确的配置修改建议,且只有在你明确确认后才会实际改动。v0.15.3 起该段还携带提权规则(原先只写在本 README 里):目标在白名单内时,首次尝试就带 sandbox_permissions: danger-full-access + 一句 justification——approval 桥接零评审放行,不会排队等人工;不要裸跑、等沙箱拒绝后再升级,也不要因为怕弹窗而回避提权(信任目标不会弹窗)。

权限预设图标

auto-mode 预设默认在权限选择器里显示 ⚡ 图标。想换 logo,就覆盖预设上的 icon(cordis.patch.yml 的 permission 行,不是 auto-mode 自身配置)——一个画在盾牌轮廓内的 SVG 路径:

- id: permission
  config:
    presets:
      auto-mode:
        sandbox: workspace-write
        approval: ask
        name: Auto mode
        description: ...
        icon: '<你的-svg-path-d>'   # 默认 bolt:'M9.15 3.4L5.85 8.55H7.95L7.05 12.6L10.45 7.25H8.25L9.15 3.4Z'

图标只是外观——无论是否渲染,行为完全一致。它只在支持读取预设 icon 的 DSH 上显示(原生 DSH 会忽略;随包提供的 patches/dsh-permission-preset-icon.mjs 可开启 —— 见安装)。渲染位置是选择器菜单与当前值触发器;设置页的「新会话默认预设」那一行只显示文字。不设 icon 即用默认 bolt。

两阶段分类器

分类器用两阶段把 LLM 成本降到最低:

  1. One-token 预筛(~1 token):让 LLM 只回一个数字(0 = 安全,1 = 需审查)。使用宽松的 token 预算和鲁棒的数字解析,避免 reasoning 模型被饿死,并把 classifier.reasoningLevel 作为推理强度传入(off = 不推理)。大多数常规动作返回 0 直接跳过阶段 2。预筛的输入是「动作」而不是「叙述」(v0.15.1):命令原文(bash)或目标路径(文件工具)在前,agent 的 justification 只作附注——否则一段写得自信的理由就能让一个会离开本机的命令以 0 免审通过。
  2. 结构化裁决:仅当阶段 1 标记时才运行。返回完整 verdict 及理由。

这意味着大多数工具调用只产生 ~1 token 的分类器开销,只有边界情况才 incur 完整分类器成本。

闸门判的是授权,不是价值。它不判断一个动作「值不值得做」,只判断你有没有要求它。你才是最终决断者。

  • 只读与可恢复操作一律 ALLOW:GET/HEAD 请求、检视/列举/搜索/状态查询,以及可以安全撤销的本地改动(编辑、临时文件、构建、测试、git 跟踪文件)。
  • 你要求过的、有风险的动作可以放行 —— 包括会离开本机的效果:发版、发布、部署、推送、对外发消息、写别的系统。风险本身不是拒绝你的理由。
  • 只有一条硬底线对任何人都不开:执行下载来的代码、破坏或移动系统路径、删 docker 卷/容器/镜像、读密钥材料/凭据库/env 文件、把密钥材料写进命令、改 shell 启动文件或 agent 权限配置。这些还会在任何模型介入之前被确定性拦下(见上文 deny 频带)。
  • double-check 闭环:当动作会影响其他人或系统、而你自己的消息没有明确覆盖这一个动作时,闸门拒绝,并要求 agent 把原样命令拿给你确认(ask_user_question)。你的回答就是直接授权,之后该动作可以放行。
  • <recent_user_intent> 只计入直接的人类消息——但有一个刻意例外:用户经 ask_user_question 工具给出的答案也是经由工具的直接人工授权,会被并入意图窗口 —— 连同你回答的那个问题一起(问题明确标注为 agent 所写,好让一句简短的「可以」仍能与你当时看到的命令对上),并进入裁决缓存签名,使「工具型授权」与「打字授权」一样能让旧的 DENY 缓存失效。agent 的 justification、仓库文本与工具输出永远不是授权:否则「用户意图」就退化成「谁最后说话谁算」。

熔断器

当分类器在会话内连续拒绝 3 个动作、或累计 20 个时,熔断器跳闸,auto 模式暂停。approval 瀑布转交人工 answerer。任何一次真实人工决策(允许或拒绝该动作)都会恢复 auto 模式并清零所有计数器——人工参与即打破熔断器要抓的静默连拒循环。若用户取消请求、或没有可用 answerer,熔断器保持跳闸。

在熔断器跳闸的瞬间,插件会注入一段提示,告诉模型在下一次尝试就直接请求 danger-full-access 沙箱升级(立即弹出人工批准窗口),而不是"先以当前权限试一次 → 命中 denied → 再升级"的多余往返。v0.15.3 起该提示还限定了为何会走人工:走人工是因为 auto 模式已暂停,而不是提权本身总要人工——正常状态下白名单内目标的提权是零评审自动放行。

分类器失败(超时、解析错误、空响应)不计入熔断器。但缓存命中的拒绝会计入——完全相同的已拒动作重试(verdict cache 命中)同样增加连续与总计计数,因此重复提权尝试能真正触发熔断器并到达人工审批,而不是永远空转。

拒绝引导与诊断

分类器为两态(allow / reject),无 ask 层——不确定的动作直接拒绝(fail-closed):拒绝可重试或升级到用户,误放不可逆,宁拒勿放。

routine 类别(install/build/test/文件编辑/git add/commit/status)只是倾向基准,不是免检通行证——分类器必须判断具体命令与参数,不能只看类别标签(例如管道下载执行远程代码、未知包安装带任意 postinstall 脚本、写入 secrets、不可逆删除、推送未知 remote)。

拒绝时,提示会回显审查者的拒绝理由 + 模型自身在工具调用里写的操作解释(justification),让模型看清被拒的是什么、如何改造成更安全的形式。随后指示模型尝试更安全方案;若没有更安全方案存在,则停止重试并询问用户明确许可——被拒绝的动作会一直失败,只有用户明确批准,后续尝试才可能通过(分类器经 <recent_user_intent> 权衡用户的最近显式意图)。

每次分类器流失败(抛异常或 error finish chunk)都会写入 DSH 日志(带解析后的路由、effort、底层错误 code/message、模型原始输出),并作为 classifier-fail 事件写入 decisions.jsonl——反复出现的 classifier returned no verdict 直接从审计记录即可诊断。若路由拒绝配置的 reasoningEffort(例如只支持 off 的路由收到 low),调用会先重试不传 effort 再判定失败。模型侧看到的拒绝提示现在会区分配置性问题(未配路由 / 路由拒绝配置的 effort——v0.14.0:修复 classifier.provider/model 或模型元数据,重试无用)与瞬时问题(429 / 5xx / 超时——稍后重试)。

裁决缓存

分类器 verdict 按会话的 tool + 命令 + 用户意图 签名缓存。用户最近直接指示——打字消息与 ask_user_question 答案——会被 hash 进签名,因此一次新的显式授权(新的人类消息或工具型授权)会使旧的缓存 verdict 失效、分类器带着新意图重跑——用户的授权绝不会被缓存的 DENY 吞掉。在同一意图窗口内,重复动作仍会复用缓存 verdict,不再二次 LLM 调用。pre-execute 门与 approval 路径现在用同一份命令原文签名——approval 路径按 callId 从会话恢复该工具调用的真实参数(审批 payload 不携带参数),因此提权调用会命中门的裁决,而不是被第二次分类(v0.13.0)。文件工具(write/edit,无 command 字段)按目标目录签名(v0.14.1):同一目录的批量写入共享一次裁决,不同目录即使理由逐字相同也不会碰撞——敏感文件名仍由 deny 频带兜底(每调用照跑)。缓存条目 5 分钟后过期。

日志

所有决策写入 ~/.dsh/auto-mode/decisions.jsonl(JSONL 格式,append-only,跨重启保留)。每条记录包含:

  • at — ISO 时间戳
  • event — decision / pre-execute-deny / pre-execute-allow / pre-execute-fileop / pre-execute-bashop / pre-execute-fail-open / classifier-fail / breaker / resume / boot
  • outcome — allowed-once / rejected / cancelled
  • tool — 工具名
  • tier — deny / allow / classify:monitor / classify:cache / classify:fail / ...
  • callId — 被裁决的精确工具调用(approval 路径 decision 事件,v0.14.0)——可与其 pre-execute 记录精确 join,做两阶段审计
  • detail — 人类可读理由(deny 命中现附命令/目标上下文,v0.14.0)
  • sessionId — 会话标识

用复盘脚本分析日志、检测 allow→reject 矛盾对回归特征、识别规则优化机会(v0.14.0):

node scripts/audit.mjs                  # 报告 + 矛盾对哨兵
node scripts/audit.mjs --fail-on-pairs --limit 500  # 存在矛盾对即 exit 1——CI/cron 建议配 `--limit` 滚动窗口

贡献者(Contributors)

感谢所有为 @log.li/dsh-automode 做出贡献的人:

| 贡献者 | 贡献 | |---|---| | @WSL043 | 💻 权限兼容层 namespace-probe 思路(PR #2,共同署名) | | @xiaolinziwang | 🐛 bug 报告(issue #1) |

当 auto 模式激活时,插件会"影子化"审批策略的系统提示,让模型看到 "auto" 而不是 "ask"。这告诉模型:工具拒绝来自自动化审查者,而非人类。模型会相应调整重试策略(尝试更小/更安全动作,而不是问用户)。

架构

src/
  index.ts         主入口:preset 管理、审批 answerer、熔断器复位、命令、系统提示影子化
  config.ts        配置 schema + $defaults 机制 + 内置规则列表
  bands.ts         确定性频带引擎(deny 正则 + allow glob)
  pre-execute.ts   pre-execute 门(第一道防线;真实路径信任、分类器预审、熔断跳闸提示)
  classifier.ts    两阶段分类器(+ 鲁棒解析、推理强度、诊断)
  rules.ts         分类器散文规则匹配
  prompt.ts        分类器提示构造(<recent_user_intent> + 意图加权)
  cache.ts         裁决缓存(跨强制点共享)
  breaker.ts       熔断器(3 连续 / 20 总)
  log.ts           共享 appendDecision JSONL 日志器

兼容性与贡献

支持的 dsh 版本:0.1.0-rc.6 – 0.1.x(peer 范围 >=0.1.0-rc.6 <0.2.0)。权限事实(预设 / 沙箱 / 审批策略)经两条自动探测的读取路径获取:

| dsh 版本 | 权限读取路径 | |---|---| | 0.1.0-rc.6 – 0.1.4.x | session.events 事件日志(effectivePermissionPreset 等) | | ≥ 0.1.5-rc.1 | 持久的 permissions 会话投影(ctx.sessionProjections.stateOf) |

dsh 0.1.5-rc.1 移除了 session.events 访问器——没有投影路径时,每个 auto-mode 回合都会在组装系统提示时报 Cannot read properties of undefined (reading 'length')(v0.11.2 修复)。dsh ≥ 0.2.0 尚未验证——只有对新内核实测通过后才应上调 peer 范围。

DSH session format v4(dsh ≥ 0.1.7-alpha.1)退役了 catch-all 的 plugin 消息来源标识,并拒绝所有 durable 消息槽位上的该形态。注入消息改用本插件自有的 source kind——与 v3 → v4 会话日志迁移把老记录归一到的标识一致,因此两代格式都接受,无需版本探测(v0.15.4 修复)。

同一次格式变更还把工具结果从「用户消息包裹」改成了原生 tool 消息。还原用户意图时两种形态都读,因此你对 ask_user_question 的答复在两代格式上都算授权(v0.16.1 修复)。

  • 仅在 macOS 上验证。已针对 macOS 文件系统、DeepSeek Harness(DSH) 运行时与开发时使用的 DSH 版本做过测试。路径语义——包括 macOS 的 /tmp → /private/tmp 软链(由 realpath 最近祖先解析处理)与工作区路径信任——尚未在 Linux / Windows 上验证,deny 模式与路径匹配在这些平台上可能有差异。
  • 发现 bug,或其它平台上有问题? 欢迎提交 issue 或 PR:github.com/log-li/dsh-automode。

许可证

MIT