前言¶
在 DeepSeek Harness(DSH)里,会话权限可以选「自动审批」(预设 auto)。不少开发者会长期用这个档位,希望 Agent 在可控范围内自动过审。实际使用中有一个现象:选过 auto 后正常退出 DSH,再打开同一会话,权限却变成了「完全权限」(danger-full-access,审批策略 never)。这不是偏好没保存,而是退出流程里有一次向更高权限的持久写入。若 DSH 版本仍带未修复的上游逻辑,每次关应用都会重演。本文介绍社区插件 dsh-auto-preset-guard(维护者 SternChiri,分类 admin-security),说明它针对什么问题、如何安装,以及和上游修复的关系。
这是什么¶
dsh-auto-preset-guard 是一条常驻的 DSH host 插件行:在运行期包裹 permissionPresets 服务,不修改安装目录里的任何包,升级 DSH 不会把改动覆盖掉。
它解决两类与 @deepseek-ai/dsh-experimental-auto-review 相关的副作用:
- 应用退出时,集成在 effect disposer 里会把当前仍是
auto的会话批量set成danger-full-access;set()会往会话日志追加事件,因此重启后看到的是被改写后的权限。 - 会话日志里存着
auto、但自动审批集成未激活时,pinInitialPermission可能抛出permission: cannot restore preset "auto" without its active integration,会话无法重新打开。
上游已在提交 4923f3cb(「fix(auto-review): preserve Auto during application shutdown」)中通过判断 ctx.root.fiber.state 区分「应用退出」与「运行中卸载插件」;该修复从 0.2.2-alpha.2 起进入主线,0.2.1-rc.* 仍可能执行无条件的迁移循环。本插件面向尚未升级或仍需兜底的环境。
背景:退出时为何会升到完全权限¶
auto-review 在 disposer 中的逻辑大致如下(摘自仓库说明):
for (const session of ctx.sessions.list()) {
if (permissionPresets.current(session) !== AUTO_PRESET) continue
permissionPresets.set(session, 'danger-full-access')
}
设计意图是:运行中卸载自动审批集成时,把仍停留在 auto 的会话迁到完全权限,避免留下无法服务的预设。同一 disposer 在应用退出时也会执行,而退出时本应保留用户选择。cordis 的卸载顺序是 root 先进入 UNLOADING,再跑子插件 disposer;因此在 disposer 阶段读取 root fiber 状态,可以区分「正在关应用」与「root 仍为 ACTIVE 的活体卸载」。未修复版本无法区分,导致每次退出都写入迁移。
核心功能¶
插件只做两件事,且仅在服务实例上安装一次包裹(Symbol.for 标记);dispose 时故意不解包,避免在本行先于 auto-review 卸载时把原方法还原、让关机迁移重新生效。
| 行为 | 说明 |
|---|---|
关机窗口内忽略 set(session, 'danger-full-access') |
当 root fiber 不是 ACTIVE(如 PENDING、LOADING、FAILED、DISPOSED、UNLOADING),且会话当前预设为 auto 时,不写入会话日志 |
放宽 pinInitialPermission 对「auto 缺集成」的处理 |
会话按存储身份正常打开,不为此追加降级事件 |
运行中卸载 auto-review 时 root 仍为 ACTIVE,上游迁移仍会执行——插件不干预这一路径。若宿主无法识别(root.fiber.state 不是数字),所有调用保持原样。
安装与启用¶
npm 上的 0.1.0 与 GitHub main 上 v0.1.0 tag 等价。要求 Node ^22.19 || >=24,DSH >=0.2.0 <0.3.0(见 package.json)。
下面介绍两种等价安装方式,命令来自仓库 README:
# 从 npm
dsh plugin --profile desktop add dsh-auto-preset-guard
# 从 GitHub
dsh plugin --profile desktop add "github:SternChiri/dsh-auto-preset-guard"
若 desktop profile 的 .npmrc 指向镜像源(例如 registry.npmmirror.com),刚发布的版本可能尚未同步,可先把该源的 registry 改回 https://registry.npmjs.org 再安装。
装完后重启 DSH。package.json 声明了 dsh.bundle.patch,reconciliation 会自动在 bundle 中插入 host 行(id: dsh-auto-preset-guard)。
卸载:
dsh plugin --profile desktop remove dsh-auto-preset-guard
关掉或移除本插件后,若当前 DSH 仍带未修复的裸循环,退出时仍会把 auto 迁到完全权限。是否继续安装,取决于你的 DSH 版本是否已含上游修复。
典型用法与验证¶
日常用法无需额外配置:插件无 UI、无设置项,安装并重启后即对 permissionPresets 生效。
手工验证「重启后仍保留 auto」:在会话中选自动审批,完全退出 DSH 再打开同一会话,确认预设仍为 auto 而非完全权限(在仍受 bug 影响的 DSH 版本上,未装本插件时应能复现相反行为)。
仓库 test/ 提供不启动 DSH 即可跑的脚本,直接驱动安装目录内的 cordis 运行时:
node test/verify.mjs
node test/proxy-check.mjs
verify.mjs 覆盖:运行期卸载集成仍会把 auto 迁到完全权限;root 进入 UNLOADING 后迁移零写入且身份仍为 auto;缺集成的会话打开不抛错;其它发布错误照常抛出。proxy-check.mjs 验证 auto-review 在 apply 时捕获的 permissionPresets 引用仍能派发到包裹后的方法。
运行时位于非常规路径或 asar 内时,可指定:
DSH_CORDIS=/path/to/node_modules/@deepseek-ai/cordis/lib/index.js node test/verify.mjs
调试被拦下的写入:
DSH_AUTO_PRESET_GUARD_DEBUG=1
(在运行 DSH 或上述测试前于环境中设置。)
适用场景与注意¶
适合谁
- 使用 DSH 0.2.1-rc.* 或尚未包含
4923f3cb修复的版本,且依赖「自动审批」预设的用户。 - 需要打开历史会话里存为
auto、但当前环境暂时没有自动审批集成的情况(避免pinInitialPermission直接失败)。
已知边界(摘自 README)
- 只拦截
auto → danger-full-access这一种写入,其它预设变更一律放行。 - 仅在本插件行处于 active 时生效;DSH 仍有裸循环而本插件被禁用时,退出照样迁移。
- 不修改沙箱值、持久终端或会话数据本体。
- 依赖 cordis 卸载顺序,属于运行时实现细节;上游修复落地后,可原样卸载本插件,无需额外清理。
安全与信任
DSH 插件以当前 DSH 进程权限运行,安装前请阅读 GitHub 仓库 源码与 MIT 许可证。社区目录 SkillHub 插件页 为独立站点,与 DeepSeek / 幻方无官方从属关系;安装命令与行为说明以仓库 README 为准。
结尾¶
dsh-auto-preset-guard 在不动上游包的前提下,用运行期包裹保留退出前的「自动审批」选择,并避免因缺集成而无法打开存为 auto 的会话。若你已升级到 0.2.2-alpha.2 及以后且行为正常,可优先考虑依赖上游修复;否则可按上文命令装入 desktop profile 并重启验证。
- 目录页:https://www.skillhub.cn/plugins/SternChiri/dsh-auto-preset-guard
- GitHub:https://github.com/SternChiri/dsh-auto-preset-guard