Skip to content

审批提醒从未触发:疑似宿主侧 approval/request 监听未收到事件 #2

Open

Description

@raphael-y7

环境

  • DSH 0.2.0-rc.2(桌面端,Windows)
  • dsh-ding v1.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 并不是一个普通的全局事件:

  1. 它由审批 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")))
  2. 它被列入 @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。

  3. 同一市场的另外两款通知插件 dsh-notify-me 与 dsh-plugin-notify-sound,它们的审批提醒都不消费这个宿主事件,而是观察客户端 store 的 pendingInteraction / sessionStatus。

综合上述,最可能的解释是:宿主半边注册的这个监听器从未被调用,notifyApproval 也就从未执行。

需要说明:这一步没有在运行时直接观测到(那需要在回调入口加一行日志)。上面第 1–7 条是实测数据,本节的因果解释是基于宿主源码结构与同类实现的推断。

建议

  1. 先坐实:在 approval/request 回调入口加一行日志,复现一次审批,确认回调是否被调用;若未被调用,再确认该事件是否需要按 agent 作用域注册或改走 ctx.remote。
  2. 修复:参照 dsh-notify-me 的做法,把审批检测挪到客户端半边,观察 pendingInteraction / sessionStatus 的待审批状态,而不是依赖宿主侧的 approval/request。
  3. 排查提示:插件高级设置里的「审批」测试按钮会直接调用 notifyApproval(playTest 分支,且强制 quietOnViewing: false)。它响只能证明 notifyApproval 与 notify.ps1 可用,不能证明监听器工作——两者要分开验证。

影响

审批是阻塞型事件:没有提醒时,任务会停在审批上而用户不知道,直到主动切回窗口查看。

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions