dsh-plugin-tool-management 0.2.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,46 @@
1
+ // 审批策略探测(宿主端):确认门在「完全权限」会话里该怎么行为。
2
+ //
3
+ // 背景:DSH 的审批策略是「会话级 fold + 全局默认」两级(dsh-user-approval:
4
+ // effectivePolicy(session) = overrideOf(session) ?? config.policy ?? 'ask'),
5
+ // 「完全权限」预设写的是**会话级** approval/policy fold(dsh-permission-presets
6
+ // 调 approval.setPolicy(agent, 'never'),预设自述 "without approval prompts")。
7
+ //
8
+ // 口径(2026-09-13 用户裁定,方案 B):**never = 用户在预设层面已预先批准一切确认门**。
9
+ // 因此插件的三个确认门在 never 会话里直接放行(并写插件审计日志留痕),不再把 ask
10
+ // 交给审批层——宿主 ApprovalService.decide() 对 never 直接返回 rejected(fail-closed),
11
+ // 确认卡永远不会弹出,模型只会收到一句无信息量的「用户拒绝」。这也与 DSH 官方子代理
12
+ // 工具(dsh-tool-subagent 无 ask 门)在完全权限下的行为一致。
13
+ // 注意这是**插件自定策略**,与宿主 decide() 的 never=自动拒 相反,属有意选择:
14
+ // 插件确认门的语义是「问用户」,而用户已在会话层面声明「不要再问我」。
15
+ //
16
+ // 读取链的关键约束:**必须用 ctx.get('approval'),不能用 ctx.approval**。
17
+ // 本插件的 inject 未声明 approval,cordis 的上下文代理会沿 fiber 链找 provider,
18
+ // 找不到就抛 `cannot get property "approval" without inject`;旧实现把它写在
19
+ // try/catch 里,异常被吞成 false,于是 never 会话里永远走 ask 分支(2026-09-13
20
+ // 19:52 会话实测到的 bug)。dsh-tools 自己拿这条缝也是 `this.ctx.get("approval")`
21
+ // (dsh-tools/lib/index.js `serviceAsk`),且它的 inject 同样只有 systemPrompt
22
+ // ——可作对照。回归测试见 test/approval-policy.test.mjs。
23
+ /**
24
+ * 判断本次工具调用的会话是否处于 never 审批策略(= 完全权限,确认门应直接放行)。
25
+ *
26
+ * 任一步不可用(无 approval 服务、无 agent/session、读取抛错)都返回 false:
27
+ * 探测失败一律退回正常问询流程,绝不代替审批层做放行决定。
28
+ */
29
+ export function isApprovalNever(ctx, exec) {
30
+ try {
31
+ const get = ctx?.get;
32
+ if (typeof get !== 'function')
33
+ return false;
34
+ const approval = get.call(ctx, 'approval');
35
+ if (!approval)
36
+ return false;
37
+ const session = exec?.agent?.session;
38
+ if (session !== undefined && typeof approval.effectivePolicy === 'function') {
39
+ return approval.effectivePolicy(session) === 'never';
40
+ }
41
+ return approval.config?.policy === 'never';
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }