Repository navigation
Description
环境
- DSH
0.2.0-rc.2(桌面端,Windows) dsh-dingv1.0.6(npm 安装)- 已启用
@deepseek-ai/dsh-experimental-auto-review(权限模式 Auto review),因此绝大多数审批来自 reviewer 拒绝后转人工
现象
需要用户审批的场景没有任何提醒:提示音和 Windows 通知都没有。
同一插件的另外三类提醒在同一时间段内都正常工作:完成、提问、长任务运行中。
用户最初的主观感受是「有些时候审批不响」,实测数据表明是从未响过。
证据
1. 通知脚本自身的诊断日志
notify.ps1 每次运行都会往 %TEMP%\dsh-ding-notify.log 写一条 run: title=[…] 记录(脚本自带的排查手段)。该文件覆盖 18:16:59–19:02:01 共 16 条运行记录:
| 通知类型 | 次数 |
|---|---|
DSH 完成 |
7 |
DSH 运行中 |
5 |
DSH 提问 |
4 |
DSH 审批 |
0 |
2. 同一窗口内确实存在审批请求
会话日志(~/.dsh/sessions/**/session.v4.jsonl.zstd)在上述窗口内有 5 条 approval/asked,每条都配对了 approval/decided,即审批流程完整走完,reason 均以 Auto review denied tool "…" 开头。
作为对照,同一时间窗口内另外三类提醒共触发 16 次,说明插件进程、通知脚本与播放链路都活着。
3. 排除全局节流(minIntervalMs)
lib/index.js 的 lastFired(第 852 行)是四类提醒共用的节流,默认 minIntervalMs: 3000。把窗口内每次 approval/asked 与最近一次通知脚本运行时刻对齐,间隔为 48 秒 ~ 265 秒,没有一次落在 3 秒窗口内。
(更早的 10 条审批发生在 12:44–18:15,早于通知日志起点,无法对照,未计入。)
4. 排除「当前会话免打扰」(quietOnViewing)
notifyApproval(第 391 行)的早退条件之一是 state.quietOnViewing && state.foreground && agent?.id === state.activeSession。审批分布在多个不同会话,而「当前查看的会话」同一时刻只有一个值,无法解释全部审批都不响。
5. 排除配置
- 插件自带
cordis.patch.yml的config里没有approvalNotify键 → 代码config.approvalNotify !== false取默认true - profile 的用户补丁没有覆盖它
- profile 的
data/目录不存在,即从未写过data/dsh-ding.json,设置保持默认
6. 排除 !agent?.id 早退
lib/index.js:943 有 if (!agent?.id) return next();。宿主 @deepseek-ai/dsh-agent 的 enter() 强制校验 agent.id === agent.session.id,不匹配直接抛错,因此审批事件里的 agent.id 不可能为空。
7. 排除脚本与播放链路故障
同一个 notify.ps1 在同一窗口为完成/提问/运行中三类成功播放了声音并弹出了通知(日志中有 sound: MCI playing … 与 toast: shown …)。
根因分析(推断,未在运行时直接观测)
lib/index.js:940 是这样注册审批监听的:
ctx.on("approval/request", async (req, next) => { … });在 0.2.0-rc.2 上,approval/request 并不是一个普通的全局事件:
-
它由审批 seam 在 agent 作用域上派发。
@deepseek-ai/dsh-user-approval中:const answer = Promise.resolve().then(() => this.ctx.waterfall(scopeTarget(req.agent, req.agent), "approval/request", req, () => Promise.resolve("unavailable")))
-
它被列入
@deepseek-ai/dsh-api-remotes的API_REMOTE_FORWARDED_EVENTS:{ event: 'approval/request', mode: 'waterfall' },需要经跨端转发;客户端审批 UI(@deepseek-ai/dsh-client-ui-approval)用的是ctx.remote.$on("approval/request", …),不是ctx.on。 -
同一市场的另外两款通知插件
dsh-notify-me与dsh-plugin-notify-sound,它们的审批提醒都不消费这个宿主事件,而是观察客户端 store 的pendingInteraction/sessionStatus。
综合上述,最可能的解释是:宿主半边注册的这个监听器从未被调用,notifyApproval 也就从未执行。
需要说明:这一步没有在运行时直接观测到(那需要在回调入口加一行日志)。上面第 1–7 条是实测数据,本节的因果解释是基于宿主源码结构与同类实现的推断。
建议
- 先坐实:在
approval/request回调入口加一行日志,复现一次审批,确认回调是否被调用;若未被调用,再确认该事件是否需要按 agent 作用域注册或改走ctx.remote。 - 修复:参照
dsh-notify-me的做法,把审批检测挪到客户端半边,观察pendingInteraction/sessionStatus的待审批状态,而不是依赖宿主侧的approval/request。 - 排查提示:插件高级设置里的「审批」测试按钮会直接调用
notifyApproval(playTest分支,且强制quietOnViewing: false)。它响只能证明notifyApproval与notify.ps1可用,不能证明监听器工作——两者要分开验证。
影响
审批是阻塞型事件:没有提醒时,任务会停在审批上而用户不知道,直到主动切回窗口查看。
Activity