# dsh-auto-pass [English](README.md) | 中文 > **本项目只解决「自动审批通过」,不解决无人值守问题。** > > 本项目 fork / 参考自 [simon300000/dsh-auto](https://github.com/simon300000/dsh-auto/)。 `dsh-auto-pass` 为 DeepSeek Harness 的 WebUI 增加 `自动审批` 权限档位。每个需要审批的动作都会先交给一次**单轮模型审查**——一次普通的模型调用,不起子代理、不带工具、没有会话转录,只喂归一化后的动作与你最后一条直接消息——插件只自动放行审查通过(allow)的请求。模型拒绝、宿主安全降级和审查失败一律交回 DSH 原生人工审批链,由用户决定。**唯一的例外是设置里显式打开的「黑名单直接拒绝」**(默认关闭):打开后命中黑名单的调用直接判为拒绝、不弹审批卡。 在此之上还有两层「权限记忆」:**白名单**(以后直接放行,不再叫模型)与**黑名单**(以后直接转人工,不再叫模型),白/黑名单分**项目**与**全局**两级。规则来源有三种:你在时间线上手动升级/降级、审查模型在审查时顺带给出的建议规则,以及**达阈值后自动写入的规则**——同一个项目下同一权限连续放行(默认 3 次,插件自动放行与你本人的放行都算)达到阈值时,插件**直接把匹配条件写进白名单**(有工作区写本项目,没有写全局),**不再询问**;连续被拒(默认 3 次,你的手动拒绝算,无人推翻的模型拒绝也算)达到阈值时仍会问你是否加入黑名单(本项目 / 全局 / 不加入):两侧都优先用本次审查回复里顺带的建议条件,没有可用建议就**默认写成这次动作的权限指纹**(归一化签名,见下)。黑名单选「不加入」后这个动作不会再被计数、也不会再被询问。 ## 截图 选择 `自动审批` 权限档位(DSH 0.1.5-rc.1,中文界面): ![中文界面的 自动审批 权限档位](docs/images/auto-approve-permission.zh.png) 「审批设置」面板——连续放行 / 连续被拒两个阈值,以及**全局**与**项目**两级的白名单、黑名单(对话区标签页): ![审批设置面板:两侧阈值与项目/全局两级的白名单、黑名单](docs/images/auto-approve-policy.zh.png) 「审批时间线」面板——每次审批一条记录,顶部可按 全部 / 白名单 / 黑名单 / 自动 / 人工 筛选(右侧栏): ![审批时间线面板:记录列表与快捷筛选](docs/images/auto-approve-timeline.zh.png) ## 工作方式 ```mermaid flowchart TD action["动作"] --> sandbox{"在 workspace-write
允许范围内?"} sandbox -- 是 --> execute["直接执行"] sandbox -- "否:申请提权" --> review["🧐 自动审批"] review -- 允许 --> approved["仅放行本次动作"] review -- "拒绝 / 审查失败" --> deferred["交回用户审批(ask)"] exact["解析出权限签名"] --> lists{"命中白名单?"} lists -- 是 --> approved lists -- "命中黑名单(默认)" --> deferred lists -- "命中黑名单 + 开启直接拒绝" --> rejected["直接拒绝(rejected)"] lists -- 都没有 --> review ``` 选择 `自动审批` 后,`workspace-write` 允许范围内的普通操作直接执行,不需要任何审批。图中展示的是沙箱提权流程;其他工具审批规则也可能触发自动审批。**审批请求只在工具真的申请提权时才会产生**(`sandbox_permissions` + `justification`),所以从不提权的调用根本到不了插件。 - 只有会话**当前**权限档位是 `自动审批` 时,插件才接管这次审批请求;其他权限档位继续使用 DSH 原有审批链。插件抢在人工审批应答器之前接管,因此不依赖 bundles 顺序(上面那张权限预设表的覆盖仍然要求本 bundle 装在 `dsh-web-app` 之后)。 - 每次审查就是**一次普通的模型调用**,`timeoutMs`(默认 90 秒)覆盖这一次调用(含流式读取)。审查模型没有子 Agent、没有工具、读不了文件,也看不到会话历史,所以它无从调查,只能凭给到的信息判断。 - 提示词是两段 JSON:① 归一化后的动作(工具名、命令/路径、cwd、是否申请提权);② 极简证据(你最后一条**直接**用户消息 + 最近一次 `ask_user_question` 的回答,各自截断到 `maxEvidenceChars`,默认 400 字)。只有这两者能构成授权;其余东西根本不在提示词里。 - 审查的口径是「**无害的动作不必打扰你**」:范围明确、没有破坏性、可逆、与你的请求一致 → 放行;**请求提权(`sandbox_permissions`)本身不是拒绝理由**——受限沙箱下跑测试这类命令本来就靠提权才能起子进程,所以 `pnpm test` 带 `danger-full-access` 也应当自动放行。仍然一律拒绝的只有:删除/覆盖、外发与强推、读凭据与密钥、sudo / 改系统或注册表 / 命令本身要写工作区之外、来路不明的代码、关闭安全设施。 - 回复只强制要求 `outcome`,且必须是**一行 JSON**(外面包一层 Markdown 代码围栏也能容忍)。简写 `{"outcome":"allow"}` 默认表示 low 风险、unknown 授权;deny 缺少其他字段时默认表示 high 风险、unknown 授权。完整结果还可以包含 `risk_level`、`user_authorization`、`rationale`,以及可选的 `rule` 建议。插件**只会降级、绝不升级**:critical 风险一定变成拒绝,用户授权低于 medium 的 high 风险也一定变成拒绝。输出不合法、动作拿不到或过长、没有可用的审查模型路由、超时以及任何基础设施失败,都**不会**变成自动拒绝,而是把请求交回用户。 - 模型拒绝不会被重新审查,也**不会**变成自动拒绝:插件调用下一个审批应答器,让请求继续走 DSH 原生审批链,由用户决定。插件自动给出的结论只有两种:审查通过时的 `allowed-once`,以及**设置里打开「黑名单直接拒绝」后**命中黑名单时的 `rejected`(默认关闭 = 黑名单也只转人工)。转人工时审查意见还会写进审批请求的 `reason`,审批卡首行就能看到为什么转人工。 - **名单优先于模型审查**:命中黑名单直接转人工(开了直接拒绝则是直接判拒)、命中白名单直接放行,两者都不调用模型。黑名单永远压过白名单;项目级规则优先于全局级。命中名单的那一次按设计**不参与计数**。 - **权限指纹**由「工具名 + 归一化关键参数」得出,与调用 id、时间无关:命令类工具取命令文本(折叠空白),文件类工具取路径参数,其余取按键排序的参数 JSON。归一化只抹掉**不改变「在授权什么」**的东西——`description`/`justification` 这类每次都会被改写的说明、管道之后的部分(`| Select-Object -Last 20`)、结尾的输出重定向(`2>&1`),以及工作目录的写法差异;**提权标记等真会改变授权范围的参数一律保留**,所以「提权重试」不会被当成普通调用,换个参数(例如换个测试文件)也仍是另一条权限。指纹既是「相似权限」的判定单位,也是名单规则的匹配单位、连续计数的计数键,还是时间线上「加入名单」默认填的那一条(界面上叫「权限指纹」,匹配条件里对应 `signature`)。**这个值在界面上只能看、不能手改**:指纹由插件算出来,手填必然写出命不中的规则——别的条件也切不成它(指纹只能由时间线上的某条记录生成)。界面上给你看的是它的**可视化**,而不是那串机器码:原始串里全是 NUL 分隔符,浏览器会把每个 NUL 画成一个方框,**选中那段文字复制还会把分隔符吃掉**(粘出来是 `pwshcmd:pnpm testx:{…}` 这种废串),所以要整串复制就用旁边那个「复制指纹」按钮(走剪贴板 API,一个字符不少)。规则列表与表单里是一行紧凑(`bash · npm test · sandbox_permissions=danger-full-access`),记录详情里拆成「工具 / 命令或参数 / 额外参数」三行,原始串挂在 tooltip 上。 - 这些归一化**同时作用于计数与规则匹配**:同一条命令换个输出截断、换句说明算同一个指纹(否则「连续 N 次」永远攒不到阈值),而**换参数、加提权仍然是另一条权限**——通用化没有放宽授权面。前缀类条件(命令前缀 / 路径前缀)另外还会折叠空白与忽略大小写。 - **连续放行自动升级**统计「最终获准执行」的次数(插件自己放行的、以及你在审批卡上点「允许一次」的都算),连续被拒同理(只有**没人推翻**的拒绝才算)。信号取自**最终结果**而不是模型判定:模型判了 deny 但你在审批卡上放行的,算作一次放行。同一项目下同一动作达到阈值(默认 3,面板可改)后:**连续放行那一侧直接把规则写进白名单**(有工作区写本项目,没有写全局),**不问用户**;**连续被拒那一侧仍然问你**(本项目 / 全局 / 不加入),确认后才写规则。没有可用的模型建议时默认写成这次动作的**权限指纹**(同一条命令换个输出截断仍是同一条,不会像逐字签名那样加个 `-Last 30` 就失效);想覆盖同一命令的其他参数,在表单里把匹配条件切到「命令前缀」即可。黑名单选「不加入」后不再为这个动作计数、也不再询问。 - 拿不到精确动作(例如审批请求先于 `tool/call` 到达,PTC 派发的工具也会这样)时**不建立签名**。这类请求既不参与名单匹配,也不参与计数——否则它们会塌缩成同一个空签名,几次放行后把「所有解析不出参数的调用」一起放行。 - 「拒绝理由追问」与「黑名单阈值确认」共用**一个串行队列**,同一时刻只会挂一张问题卡:先问理由、后问规则(白名单那一侧不挂卡,规则在旁路直接写入)。两者都是旁路,既不改变也不拖住审批结论。 主 session 会记录审批事件和一行简短插件通知(**可在设置里关掉**,默认开启)。通知在审批**结束之后**才注入,所以同时带上审查结论与**最终结果**,例如 `[自动] 自动审批 已自动批准 bash · 命中:白名单 · low/medium · 0 步 · 最终结果:已批准 · 理由:…`——转人工的请求因此能看到你最终是批准还是拒绝。正文上限 240 字符;审查提示词、它给出的建议规则、命中规则全文都不进模型上下文。若你为一次拒绝写了理由,它作为**第二行**通知单独注入(`[人工] 人工拒绝理由:…`)。Console 只记录每次审查的路由、风险、授权、token 用量与结果,不默认输出完整 prompt 或文件内容;每次审查的 token 用量也会写进审批记录、在时间线里显示。 ## 审批面板:审批设置 + 审批时间线 每次审批都会记一条记录。两个面板刻意分开,避免对话区被审批噪声占满:**对话区标签页放「审批设置」,右侧栏放「审批时间线」**。面板数据来自插件自己的本地路由(`/api/dsh-auto-pass/log`、`/config`、`/policy`、`/rule`、`/rule/draft`、`/rule/revert`,只在 localhost 上提供)。 「审批设置」包含:连续放行与连续被拒两个阈值(改完即生效,写入策略文件的全局段),以及**全局**与**项目**两级的白名单/黑名单列表(每条规则显示标签、来源(手动/模型/记忆)、匹配条件,可**编辑**(改标签或匹配条件,按 id 原地更新)或单独删除;**同一条规则不会出现两份**——工具 + 匹配条件相同的再添加就是**更新**那条,新规则若已被已有规则完全覆盖则**不重复写入**并如实提示,新规则若覆盖了已有的窄规则会把窄规则**合并掉**)。设置页(设置 → 插件)的插件卡片——「审批设置」面板底部也是同一张卡片——放面板显示位置与**四个开关**:**注入审批结果到上下文**(关闭后结果那行不再写进模型上下文,审批时间线不受影响)、**黑名单直接拒绝**(命中黑名单直接把调用判为拒绝)、**自动打开审批时间线**(只有**刚发生**的审批(1 分钟内)才自动展开时间线;切会话 / 刷新后翻到的历史记录不弹。右侧栏**整栏收起**时展开;**你手动把时间线 tab 关掉了**(侧栏里已经没有它,但侧栏本身没收起)也算「该展开」,下一次审批会把它重新打开;时间线已经显示在眼前、或**时间线 tab 还开着**而右侧栏停在其他工具上时都不打扰——切到别的侧边工具后新审批不会把你切回去。后两种情况改由右侧栏 tab 上的**未读角标**提示:数字 = 本轮页面里你还没看过的审批记录条数,时间线一显示就清零。**这个开关按工作区区分**:「审批设置」面板里改的是**本工作区**(写进该项目的 `.dsh-auto-pass/policy.json`),设置页卡片里改的是**所有工作区的默认值**)、**拒绝后追问理由**(你拒绝一次审批后,插件问一句拒绝理由并注入模型上下文;第一项就是本次的模型审批意见,点一下即可,也可以自己写或选「不留言」)。四者都写进 DSH 设置命名空间 `dsh-auto-pass`、改完立即生效、跨重启保留。能管理项目规则的前提是能确定当前项目目录——插件会先问宿主会话列表,拿不到就退回本会话最新一条审批记录里的 `cwd`。 「审批时间线」顶部有**快捷筛选**——`全部` / `白名单` / `黑名单` / `自动` / `人工` 五个 chip,每个 chip 后面是它在本次会话里的条数(面板只看**本次会话**;2026-09-18 移除了「本次会话 / 全部会话」切换,记录里的会话字段仍保留);白名单、黑名单看这次审批是否命中名单规则,自动只看**插件自己放行的**、人工只看**你最终拍板的**——后两类都排除命中名单的记录,所以**四类互不重叠,四个条数相加正好是总数**;白/黑/自动/人工可**多选叠加**(点亮多个时显示满足任一条件的记录),点 `全部` 清空筛选。列表**按日期分组**(今天 / 昨天 / MM-DD),每条记录左侧是时间线轨道(竖线 + 按结论着色的圆点:绿 = 自动批准、黄 = 待人工或黑名单拒绝、灰 = 已人工定夺)。折叠的行头**两行**:第一行 `时:分:秒 · 工具 · 来源 chip · 自动写入标识 · 结论徽标`,第二行是审批意见——不展开也能看出这次为什么放行或转人工。达阈值**自动写入白名单**的那条记录在第一行还有一个短标识 **`+白名单`**(条件来源——`模型建议` = 用本次审查里模型顺带给的规则、`权限指纹` = 回落到本次动作的权限指纹——连同作用域与规则标签一起**悬停可见**;已有规则覆盖、一条都没写入时改显示 **`白名单已覆盖`**);匹配条件有三种:命令前缀、精确签名、路径前缀(这次动作用不上的那种会直接禁用,免得生成命不中的规则);路径前缀支持**单层**通配(`D:/work/x/src/*.js`,只匹配该目录下的文件),跨目录的 `**` 会被拒绝。展开任意一条记录,**顶上一块「结论条」先给结论**(`自动批准 · 低风险` / `转人工 · 极高风险`,成功/警告底色),同一行还跟着风险、授权、命中名单、连续放行/被拒的 chip;接着是「依据」三行(审批意见、审批原因、你写的人工拒绝理由)与一张**规则卡**(这次写进哪条名单、条件从哪来、被顶掉的旧规则、「撤销这次加入」);**技术字段全部收在底部默认收起的「排查信息」里**,分**两组**——`这次动作`(权限指纹(可一键复制整串)/ 命令 / 额外参数 / 动作参数 / 轮次步数)与 `审查与用量`(模型建议规则 / 决策来源 / 审查模型 / Token / 耗时 / 时间);重复与恒空的行不再展示(「工具」并进指纹行、「签名摘要」与「工具 + 命令」同义、「已自动升级」新记录不会有、Reviewer 的步数在单轮审查下恒为 0)。详情底部是两张**折叠卡**,**卡头本身就是开关**(点标题展开 / 收起):**「加入名单」**(表单默认收起)与**「排查信息」**。表单打开后是**三行带可见标签的编辑项**(匹配条件 / 匹配值 / 规则标签)+ 一行**作用域**(本项目 / 全局)+ 两个动作按钮:**「以后直接放行」「以后直接转人工」**——作用域选一次即可,两个动作共用它。规则内容默认填审查模型在本次审查里给出的**建议规则**(模型产出,可覆盖同类动作,例如 `command_prefix: pnpm test`),记录里没有**可用的**模型建议时(例如审查未完成就转人工,或模型给的「精确签名」跟这次动作对不上)默认填该次动作的**精确签名**——最窄,也正是详情里「权限签名」那一行;**这块表单可以直接改**——匹配条件(命令前缀 / 精确签名 / 路径前缀)、匹配值、规则标签都由你定,四个按钮按你填的内容写入,不再经过模型。切换匹配条件时会向宿主 `/rule/draft` 起一次额外的模型调用、**按新条件**重新生成一个值填进表单(失败或期间又换了条件就保留本地推导的值),只生成不落盘。模型建议若明显写错(实测出现过把「精确签名」写成 `danger-full-access` 这种一句描述的),插件会判定它**不覆盖这次动作**、直接丢弃(包括不拿它当表单默认值)、回落到本次精确签名,不会写进名单。**被顶掉的规则会点名,而且能撤销**:你加入的规则若把之前确认过的更窄规则盖住(例如一条命令前缀盖住了某次动作的精确签名),插件会删掉那些窄规则——同一个名单里不留两条互相覆盖的规则——并在结果提示、记录与日志里列出它们的名字;那条记录的详情里还有一个「撤销这次加入」,点一下就把这次写入的规则删掉、把被顶掉的规则原样放回(已经撤销过、或那条规则之后又被改过时,插件拒绝撤销并说明原因)。**连续放行达阈值时自动写进去的规则同样带这个撤销入口**,详情里会标明它是自动加入、没有问过你。设置面板里手动改规则同样会列出被合并掉的窄规则,但那里没有撤销入口。 - 放置位置沿用 [`dsh-context`](https://github.com/bowenliang123/dsh-context) 的模型:对话区里和「对话/轨迹」并排的标签页(`conversation.view`)放审批设置、右侧栏标签页(`sidebarRightTabs`)放时间线,或两处都放。`placement: all`(默认)两处都注册,对话区标签页立刻可见;`auto` 表示优先右侧栏、右侧栏座位不可用时退回对话标签页——因此不装任何第三方侧边栏插件也能用。只想留一处就用 `tab` / `sidebar`。 - 设置页卡片(`settings.plugin.item`,位于 设置 → 插件)可即时切换位置,选择写进 DSH 设置命名空间 `dsh-auto-pass`、跨重启保留,并优先于 `placement` 配置值。**注意**:设置页只为宿主侧注册过设置命名空间的插件渲染卡片,所以插件的 host 半会注册这个命名空间(客户端卡片的 key 必须与它同名)。 - 每行第一行显示时分秒、工具名、来源 chip(命中名单 + 决策来源;命中规则名悬停可见)、结论(`自动批准` / `转人工` / `直接拒绝` / `审查未完成`)与结果徽标,第二行是审批意见摘要;「第几轮第几步」收在详情的排查信息里。展开后先是一条**结论条**(结论 + 风险/授权/命中名单/连续计数 chip),再是**依据**(审批意见 / 审批原因 / 你写的人工拒绝理由)与本次写入的**规则卡**(含撤销);技术字段收在底部**「排查信息」**折叠卡里——**权限指纹**(升级/降级表单里 `signature` 条件写进名单的就是这一串,可一键复制)、指纹摊开的命令/额外参数、动作参数、轮次/步数、模型建议规则、决策来源、审查模型、token 用量、耗时与时间。详情底部的**「加入名单」**折叠卡是升级/降级表单的入口(默认收起)。面板只看本次会话(「全部会话」视图已移除,记录里的会话字段保留)。 - 记录以 JSON 落盘、跨重启保留,并且**按工作区分文件**:`$DSH_HOME/dsh-auto-pass/records/<工作区>.json`(默认 `~/.dsh/dsh-auto-pass/records/`,没有 cwd 的记录进 `unknown.json`),每个工作区各自保留最新 1000 条,先写临时文件再改名;面板把各工作区合并成一条时间线读。升级到本版本时会自动把旧的单文件 `$DSH_HOME/dsh-auto-pass/approvals.json` 按工作区拆开(全部写成功才删原文件,重复 id 只留一条)。`logFile` 显式指定路径可退回单文件模式,`maxRecords` 改每个工作区的上限。记录只存本地审批数据,并且只在 localhost 上提供。 - 策略与计数分三类文件:全局策略 `$DSH_HOME/dsh-auto-pass/policy.json`(两侧阈值 + 全局名单)、项目策略 `<会话 cwd>/.dsh-auto-pass/policy.json`(项目名单),以及**按工作区分文件**的连续计数 `$DSH_HOME/dsh-auto-pass/counters/<工作区>.json`(与审批记录同一套 slug,没有 cwd 的进 `unknown.json`)。所以项目目录只在你真的给它写了项目规则之后才会多出一个 `.dsh-auto-pass/` 目录(该目录已列进本仓库的 `.gitignore`,建议你也忽略它)。每个计数文件**最多 500 条**(计数键里含参数 JSON,不设上限会一直膨胀):超限时先淘汰最久未用的活动条目、`dismissed` 条目最后才动,两侧都归零且未被「不加入」标记的死条目在启动时直接清理;**每次审批只重写本工作区那个计数文件**,不再动全局策略文件。写盘失败只告警:项目规则写不进去会自动降级写全局,绝不因为策略落盘失败而改变审批结论。 ## 安装 包名为 `dsh-auto-pass`,且此 bundle 必须安装在 `dsh-web-app` 之后。从 GitHub 安装: ```sh dsh plugin --profile web add github:sujingkpo/dsh-auto-pass ``` 也可以从本地检出安装: ```sh dsh plugin --profile web add link:/path/to/dsh-auto-pass ``` 重启 WebUI 后,在会话的 Permissions 选择器中选择 `自动审批`,也可以在 General Settings 中设为默认权限档位。该档位跑在 `workspace-write` 沙箱里、保持 `approval: ask`——插件是在 DSH 的审批 waterfall 里面应答,而不是取代它。 ## 配置 下面这份是随包 `cordis.patch.yml` 里那段配置中**适合写在配置文件里**的键;除审查模型路由(provider/model 必须成对)外都可以省略,列出的值就是插件的默认值。其余偏好都在界面里改(见本节末尾)。 ```yaml - id: dsh-auto-pass name: dsh-auto-pass config: language: auto reviewerProvider: deepseek-official reviewerModel: deepseek-v4-flash reviewerReasoningEffort: high timeoutMs: 90000 maxEvidenceChars: 400 maxActionChars: 16000 maxOutputTokens: 2048 logFile: '' maxRecords: 1000 policyFile: '' ``` ### 参数说明 - `language` —— 审查结论用哪种语言:`auto`(默认)按你**直接发送**的消息里累计的汉字判断(≥ 4 个选中文,否则英文;Agent 指令、助手消息、工具结果不参与判断),也可以写死 `zh` / `en`;非法值只告警并回退 `auto`。安全策略正文两种模式下都是同一份中文提示词,不因翻译改变审查语义。 - `reviewerProvider` / `reviewerModel` —— 用哪个提供方的哪个模型做审查,**必须成对写**;两个都不写就用父会话当前的 provider/model,连路由都拿不到时这次审批直接转人工。 - `reviewerReasoningEffort` —— 传给审查模型的推理档(例如 `high`);必须是**非空字符串**,省略则用模型自己的默认档。 - `timeoutMs` —— 单次审查的总时限(毫秒,默认 90000),覆盖这一次模型调用(含流式读取);超时即转人工。 - `maxEvidenceChars` —— 喂给审查模型的证据(你最后一条直接消息、最近一次 `ask_user_question` 的回答)**各自**截断到多少字,默认 400。 - `maxActionChars` —— 归一化后动作 JSON 的字符上限(默认 16000);超限**不调用模型**、直接转人工。 - `maxOutputTokens` —— 单次审查回复的 token 上限(默认 2048)。 - `logFile` —— 审批记录文件;**留空**=按工作区分文件(`$DSH_HOME/dsh-auto-pass/records/<工作区>.json`),显式给路径=退回单文件模式(所有工作区写同一个文件,调试用)。 - `maxRecords` —— **每个工作区**各保留多少条审批记录,默认 1000。 - `policyFile` —— 全局策略文件路径(**只放**两侧阈值与全局名单);留空=`$DSH_HOME/dsh-auto-pass/policy.json`。连续计数另存、**按工作区分文件**(不受这个键影响):`$DSH_HOME/dsh-auto-pass/counters/<工作区>.json`,文件名与审批记录同一套 slug,没有 cwd 的进 `unknown.json`。每个计数文件**最多 500 条**:超出时先淘汰最久未用的活动条目、`dismissed`(「不加入」)条目最后才动,两侧都是 0 且未被 `dismissed` 的死条目在启动时清掉。升级时会把老全局文件里带 `cwd` 前缀的计数拆进这些文件,全部写成功才从全局文件里删掉。 数值类键必须是**正整数**、`logFile` / `policyFile` 必须是字符串,写错会在插件加载时直接报错;只写 `reviewerProvider` 或只写 `reviewerModel` 同样直接报错。 另有几个键**只适合在界面里改**:`placement`(面板位置)、`notice` / `denyDirect` / `autoOpenTimeline` / `askRejectReason`(四个行为开关),以及 `autoApproveAfter` / `autoDenyAfter`(连续放行 / 连续被拒的缺省阈值)。它们不必写进配置文件;写进去也生效,但**设置里的值优先**,而面板里改过的阈值存在策略文件里。 `notice`(默认 `true`)控制是否把审批结果那行注入模型上下文,`denyDirect`(默认 `false`)控制命中黑名单时是否直接拒绝,`autoOpenTimeline`(默认 `true`)控制「**刚发生**的审批(1 分钟内)」是否自动打开它——右侧栏整栏收起、或你手动关掉了时间线 tab 都会打开;切会话 / 刷新后翻到的历史记录不弹,时间线已显示、或时间线 tab 还开着而侧栏停在其他工具上时也不打扰(后两种改由右侧栏 tab 上的未读角标提示);**它是唯一按工作区区分的行为开关**——设置页那份是所有工作区的默认值,每个工作区可以在「审批设置」面板里单独设一份(落在该项目的 `.dsh-auto-pass/policy.json` 的 `prefs` 里),`askRejectReason`(默认 `true`)控制**你拒绝一次审批后是否追问一句拒绝理由**(第一项就是本次的模型审批意见,点一下即可;也可以自己写,或选「不留言」)——你给的理由会作为**单独一行**注入,**即使 `notice` 关着也照样注入**,两个开关互不连带。四者都能在设置页的插件卡片或「审批设置」面板里改,设置里的值优先于这里的默认值;因为每次审批都会重新读设置,改完立即生效、不需要重启。 profile 覆盖会替换同一 bundle 行的完整 `config`,因此应重复写出所有需要保留的值。 审查的 system 提示词在 `prompts/review.md`,规则建议用的匹配条件提示词在 `prompts/rule.md`;两者都是普通 Markdown,插件加载时读取。修改配置、策略或插件代码后需要重启 DSH。 ## 许可证 [MIT](LICENSE)