XIMOYA/dsh-danger-reflection ↗★ 0

dsh-danger-reflection

Danger Reflection (危险反思): a DeepSeek Harness permission preset that replaces the human approval prompt for sandbox escalation with a same-model review that replays the whole conversation. 适合希望减少人工介入、通过模型自我反思来处理沙箱提权审批的用户。

패키지
dsh-danger-reflection
호환성
미검증
버전
1.0.0
라이선스
NOASSERTION
최근 업데이트
2026. 10. 2.

설치

$npx -p @deepseek-ai/dsh dsh plugin --profile web add github:XIMOYA/dsh-danger-reflection

配置

配置写在插件自身的 bundle patch(cordis.patch.yml)里。

字段默认值含义
presets["danger-reflection"]哪些权限等级(preset key,不是显示名)需要反思
onDenyreject模型判定拒绝时:reject 直接拒绝(模型的反思就是最终结论);ask 转交给人类应答者再要一次意见
onFailureask审查没能作出判定时(模型报错、超时、输出不合协议):ask 把问题交还给人类;unavailable 以「审查无法作答」结束(fail-closed);allow 无判定直接放行
timeoutMs120000单次审查调用超时
maxContextChars400000重放上下文的上限;超出时保留最近的消息
maxOutputTokens8192审查调用的 token 上限。给得宽是故意的:推理模型会先花这块预算做隐藏推理,DSH 的 DeepSeek 适配器默认 effort 是 high,上限给小了就会在说出判定之前被截断(2048 实测踩过)
temperature0审查采样温度(0 有意义)
reviewPrompt内置审查员的判断规则,可整个替换
announcetrue是否把审查结果作为消息放进对话(见上)
audittrue是否记录审计(JSON Lines)
auditPath""显式指定审计文件绝对路径;留空则由宿主推导到 /danger-reflection/audit.jsonl
verbosefalse是否把每次「拒绝」也写进日志(「放行」始终以 warn 记录)

审计记录

因为这是一个「不需要人类确认就放行」的功能,默认会留一条审计线索。位置由宿主的 profile 上下文推导(/danger-reflection/audit.jsonl),不依赖环境变量——组合插件的主进程不保证导出 DSH_HOME。文件里每行一个 JSON 对象:

  • {"kind":"loaded",...}:插件加载时写入一次,带 sourceHash —— 即当前正在运行的 lib/index.js 的 SHA-256 前 16 位。用它可以把某次决定归因到确切的代码版本,而不是「当时插件目录里碰巧是什么」。
  • {"kind":"review",...}:每次反思一行,含会话、工具名、调用 id、审批理由、原始命令参数、模型判定、理由、最终动作(allow / deny / 失败策略)、announced 与 notice(对话里实际发出的通知全文)、provider/model、耗时。

审计写入是「尽力而为」的:写失败只会记一条警告,绝不会影响判定结果。

默认策略是 fail-closed:只有模型明确说出 allow 才会放行。任何含糊、超时、报错、协议不符,都会回到人类手上,绝不会静默放行。

失败 ≠ 拒绝

这条是刻意做进设计里的,不是措辞问题。

DSH 的审批结果词汇是封闭的四个值:allowed-once / rejected / cancelled / unavailable——没有「失败」这一格。所以审查没作出判定时,必须在这四个里挑一个,而 rejected 是错的那个:调用方(dsh-sandbox)会把它渲染成

the user rejected escalating this command to "danger-full-access"

也就是说,它会把一个没人做过的判断说成事实——既替模型认了罪,也替你认了罪。正确的落点是 unavailable,调用方渲染为「审批通道无法作答」,这才是实际发生的事。

因此 onFailure 不接受 reject(写了会在加载时明确报错并告诉你该用哪个),而且插件里所有地方都做了区分:

  • 通知的标题只讲模型判了什么,✅ 模型判定:放行 / 🛑 模型判定:拒绝 / ⚠️ 未得出结论,不看最终动作;
  • 通知的结尾只讲实际发生了什么,未获放行 / 已转交人工确认 / 未获放行:审查没有作出判定;失败路径不会出现「被拒绝」字样;
  • 审计记录里 verdict 与 decided 分开记,decided: false 明确表示「没有判定」,action 用 unavailable 而不是 reject。

顺带一提,allow 只被描述成它实际做的事(无判定也放行),不会被包装成一条判定——失败在两个方向上都不能冒充结论。


使用

  1. 在输入框下方的权限等级选择器里选 危险反思(也可以用 /permission danger-reflection)。
  2. 之后当某条命令需要更宽权限时,模型会先自我反思,而不是弹窗问你。
  3. 想留档就打开审计记录(默认已开,见上)。

权限等级是按会话生效的。切换只影响当前会话。

改了插件代码之后需要重启 DSH(首次安装后也需要一次),然后刷新页面。 原因有两层:

  1. 宿主侧模块代码:DSH 的 HMR 默认 root: [],模块监视是 opt-in 且必须在启动前配置好,所以 lib/index.js 的改动不会热加载。
  2. 浏览器侧半边:宿主把包元数据按 Loader specifier 缓存至重启,新出现的 dsh.client 声明要重启后才会被扫描并提供;而客户端插件在没有 pnpm run dev:web 的情况下也不会热更新。

安装/启用插件、以及 cordis.patch.yml 里的配置改动都是即时生效的,只有代码不是。

本插件已经替你把第 1 层配好了:profile 的 cordis.patch.yml 末尾加了一段带 # BEGIN/END DANGER REFLECTION (managed) 注释的 hmr 行,把插件源码目录加入 root。重启一次之后,改 lib/index.js 就会实时生效。想恢复默认就删掉那一段(原始文件已备份为 cordis.patch.yml.bak-danger-reflection)。第 2 层没有等价开关,改 lib/client.js 仍需重启 + 刷新。