🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

交互提醒 waterc07/dsh-interaction-notify

DeepSeek Harness
waterc077 天前有提交已提供中文文档扫描:含敏感能力

智能体等你回答或授权时弹窗响铃提醒你

29.5/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/11/2 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add waterc07/dsh-interaction-notify
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:仅索引
是什么[目录]—
dsh 原生插件 · other
暂无时间戳·判据 →
装得上吗[实装验证]—
本站尚未做安装检查
暂无时间戳·判据 →
安全吗[自动扫描]—
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
数据截至 2026/11/04·判据 →
还在维护吗[仓库]✓
活跃:最近一次提交在 7 天前
暂无时间戳·判据 →
图例:✓ 通过! 需注意— 未判定 / 无数据· 「未判定」= 本站尚无数据,不代表插件有问题
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →

可信度证据

安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件
查看扫描证据(共 17 处,展示前 17 条)
  • 写入本地文件
    lib/index.js:287
    await mkdir(diagDirectory(paths), { recursive: true })
  • 写入本地文件
    lib/index.js:289
    await writeFile(target, serialized, { encoding: 'utf8', mode: 0o600 })
  • 读取本地文件
    lib/config.js:132
    const parsed = JSON.parse(await readFile(stateFile(paths), 'utf8'))
  • 读取本地文件
    lib/config.js:142
    const parsed = JSON.parse(readFileSync(stateFile(paths), 'utf8'))
  • 写入本地文件
    lib/config.js:179
    await mkdir(dirname(target), { recursive: true })
  • 写入本地文件
    lib/config.js:181
    await writeFile(temporary, `${JSON.stringify(normalized, null, 2)}\n`, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    lib/config.js:182
    await rename(temporary, target)
  • 执行外部命令来自配置/变量
    lib/deliver.js:111
    child = spawn(
  • 写入本地文件
    lib/deliver.js:176
    await mkdir(temporaryDirectory, { recursive: true })
  • 写入本地文件
    lib/deliver.js:177
    await writeFile(payloadPath, `${JSON.stringify(payload)}\n`, { encoding: 'utf8', mode: 0o600 })
  • 删除本地文件
    lib/deliver.js:184
    await rm(payloadPath, { force: true }).catch(() => { })
  • 写入本地文件
    lib/notifier.js:72
    await mkdir(dirname(target), { recursive: true })
  • 写入本地文件
    lib/notifier.js:73
    await appendFile(target, `${JSON.stringify(entry)}\n`, { encoding: 'utf8', mode: 0o600 })
  • 读取本地文件
    lib/notifier.js:74
    const text = await readFile(target, 'utf8')
  • 写入本地文件
    lib/notifier.js:79
    await writeFile(temporary, compacted, { encoding: 'utf8', mode: 0o600 })
  • 写入本地文件
    lib/notifier.js:80
    await rename(temporary, target)
  • 读取本地文件
    lib/notifier.js:86
    const text = await readFile(logFile(paths), 'utf8')
扫描于 2026/11/4(1 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

社区实装还没有人打卡 · 装过的第一个就是你
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

DeepSeek Harness 插件:agent 提问/请求授权/计划批准时弹出 Windows 系统通知与提示音,点击通知回到窗口。

README

由 DeepSeek 最新模型翻译生成
dsh-interaction-notify DeepSeek Harness 交互提醒:智能体停下来等你时,弹 Windows 系统通知、响一声提示音,点通知回到 DeepSeek Harness 窗口。 后台跑长任务时不必一直盯着窗口:要你回答、要你授权工具、要你批准计划的时候,会有一条系统通知 + 提示音把你叫回来。这是 host-only 的 DSH 插件:没有浏览器半,也不注入任何页面脚本,系统通知与窗口激活都由宿主进程完成。 功能特性 一次触发最多产生三个可感知的信号: | 信号 | 说明 | | 系统通知(Toast) | 出现在 Windows 通知中心,应用身份为「DeepSeek Harness 提示」(由开始菜单快捷方式注册);标题/正文就是当前要你处理的内容 | | 提示音 | 默认播放内置的 assets/notify.wav(C5→E5 双击音,默认音量 55);可切换为 Windows 系统音或静音 | | 任务栏闪烁 | 让 DSH 主窗口在任务栏闪 5 次,作为不打断当前操作的第三重提示 | 其它行为: - 同一交互只提醒一次:按审批 id 或工具 callId 去重(内存中保留最近 200 个 id)。
展开完整文档(README 剩余 1 节)
dsh-interaction-notify

DeepSeek Harness 交互提醒:智能体停下来等你时,弹 Windows 系统通知、响一声提示音,点通知回到 DeepSeek Harness 窗口。

后台跑长任务时不必一直盯着窗口:要你回答、要你授权工具、要你批准计划的时候,会有一条系统通知 + 提示音把你叫回来。这是 host-only 的 DSH 插件:没有浏览器半,也不注入任何页面脚本,系统通知与窗口激活都由宿主进程完成。

功能特性

一次触发最多产生三个可感知的信号:

| 信号 | 说明 |
| 系统通知(Toast) | 出现在 Windows 通知中心,应用身份为「DeepSeek Harness 提示」(由开始菜单快捷方式注册);标题/正文就是当前要你处理的内容 |
| 提示音 | 默认播放内置的 assets/notify.wav(C5→E5 双击音,默认音量 55);可切换为 Windows 系统音或静音 |
| 任务栏闪烁 | 让 DSH 主窗口在任务栏闪 5 次,作为不打断当前操作的第三重提示 |

其它行为:

- 同一交互只提醒一次:按审批 id 或工具 callId 去重(内存中保留最近 200 个 id)。
- 防刷屏:非审批类通知受 minIntervalMs(默认 1200ms)最小间隔限制,间隔内的新提醒直接丢弃、不排队;审批请求永不节流(安全相关,只去重)。
- 不打扰正在看的你:默认 quietWhenFocused: true,DSH 已经在前台时整条提醒(含声音)都会跳过,日志记为 skipped: focused。
- 内容克制:通知只包含一句标题 + 一句话摘要(问题/工具名/reason),不包含完整会话内容,也不上传任何数据。
- 配置可热更新:通过本机 HTTP 路由修改后立即生效,无需重启。
- 无第三方依赖:插件只用 Node.js 内置模块 + Windows PowerShell 5.1。

三种触发场景

| 场景 | 宿主事件 | 通知标题 | 通知正文 |
| 提问 | tool/call,工具名为 ask_user_question | 需要你的回答 | 第一个问题(去除换行、截断 140 字);多个问题时追加 (共 N 个问题);没有问题时为 请打开对话回答问题 |
| 授权审批 | approval/asked | 需要你的批准 | 工具「<toolName>」需要你授权;有 reason 时追加 :<reason>(截断 120 字) |
| 计划批准 | tool/call,工具名为 exit_plan_mode | 计划已就绪,等待你的批准 | 点击查看计划并批准,或给出修改意见 |

三类可分别用配置里的 events.question / events.approval / events.plan 单独关闭。

前置条件

- Windows 10 / 11(依赖 Toast 通知、开始菜单 AppUserModelID、user32 窗口 API)。
- DeepSeek Harness 桌面端(由宿主进程加载 Cordis 插件)。本插件没有浏览器半,package.json 里也没有 dsh.client。
- Windows PowerShell 5.1(%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe)。notify.ps1 使用 WinRT 的 Windows.UI.Notifications 类型,PowerShell 7(pwsh)无法加载,因此固定调用 5.1。
- 通知权限:Windows 设置 → 系统 → 通知,确认总开关打开,并允许「DeepSeek Harness 提示」(回退到 PowerShell 身份时还需允许 Windows PowerShell)。无需修改全局 PowerShell 执行策略——插件调用脚本时自带 -ExecutionPolicy Bypass。
- Node.js(仅构建/测试与安装脚本使用;运行时由 DSH 自带的 Node 执行插件)。本项目在 Node.js v25.9.0 上验证,建议使用较新的 LTS 版本(22+)。

安装

插件需要 lib/ 加载产物、profile 依赖声明、node_modules 软链接,以及注册通知身份的开始菜单快捷方式。推荐用仓库自带的 scripts/install.mjs 一次完成。

方式一:使用安装脚本(推荐)

先在 PowerShell 里确定 DSH 家目录(未设置 $env:DSH_HOME 时默认为 $env:USERPROFILE\.dsh):

$dshHome = if ($env:DSH_HOME) { $env:DSH_HOME } else { Join-Path $env:USERPROFILE '.dsh' }
$pluginDir = Join-Path $dshHome 'plugins\dsh-interaction-notify'
New-Item -ItemType Directory -Force -Path (Join-Path $dshHome 'plugins') | Out-Null

从 GitHub 克隆(也可下载 zip 解压到该目录)
git clone https://github.com/waterc07/dsh-interaction-notify.git $pluginDir
Set-Location $pluginDir

1) 先预览会改什么:不写任何文件
node scripts\install.mjs --profile desktop --dry-run

2) 正式安装(幂等,重复运行只补缺失项)
node scripts\install.mjs --profile desktop

install.mjs 会做四件事:

1. 在目标 profile 的 package.json 里写入依赖 "dsh-interaction-notify": "link:../../plugins/dsh-interaction-notify";
2. 把 dsh-interaction-notify 追加到 dsh.profile.bundles(最高优先级层);
3. 建立 node_modules\dsh-interaction-notify junction,让 profile 不执行 pnpm install 也能解析到插件;
4. 调用 scripts/setup-shortcut.ps1 创建带 AppUserModelID 的开始菜单快捷方式(点击通知回到窗口依赖它)。

要点:

- 写 profile 清单前会先生成一份带时间戳的备份(package.json.bak-dsh-interaction-notify-<时间戳>)。
- 脚本不会写入 DSH 安装目录:exe 解析顺序为 --exe > $env:DSH_EXE / 常见安装位置 > 正在运行的 DeepSeek Harness 进程 > 开始菜单快捷方式。找不到时用 --exe 指定:

node scripts\install.mjs --profile desktop --exe "<DSH 安装目录>\DeepSeek Harness.exe"

- 快捷方式步骤是「尽力而为」:setup-shortcut.ps1 缺失或失败只打印警告、不中断安装;但点击回窗口会失效,补跑即可。
- 其它参数:--profile <名称>(默认 desktop)、--dry-run、--uninstall、--help。
- profile 必须已经存在(先启动过一次 DSH 桌面端);否则脚本会提示先启动一次。

方式二:手动注册(不使用安装脚本)

1. 把仓库克隆/解压到 $dshHome\plugins\dsh-interaction-notify。
2. 编辑 profile 清单 $dshHome\profiles\<profile>\package.json:

{
"dependencies": {
"dsh-interaction-notify": "link:../../plugins/dsh-interaction-notify"
},
"dsh": {
"profile": {
"bundles": ["dsh-interaction-notify"]
}
}
}

已有 dependencies / bundles 时按同样格式追加,不要覆盖原有条目。
3. 建立 junction(profile 的 node_modules 不存在时先创建):

$profileDir = Join-Path $dshHome 'profiles\desktop'
New-Item -ItemType Directory -Force -Path (Join-Path $profileDir 'node_modules') | Out-Null
cmd /c mklink /J "$profileDir\node_modules\dsh-interaction-notify" $pluginDir

4. 创建开始菜单快捷方式(注册通知身份 + 点击回调):

powershell -NoProfile -ExecutionPolicy Bypass -File scripts\setup-shortcut.ps1
-Action install -ExePath "<DSH 安装目录>\DeepSeek Harness.exe" -PluginRoot "$pluginDir"

5. 完全退出并重新打开 DSH(见下节)。

安装/升级后必须重启

profile 与 bundle 列表只在 DSH 启动时读取,因此安装、升级、卸载后都要完全退出并重新打开 DeepSeek Harness;刷新页面不算。

重启后自检:调用一次测试通知(见下一节)能弹通知 + 响铃,说明宿主半已加载。

使用与配置

触发是自动的:智能体调起提问 / 授权 / 计划批准时就会提醒。若想验证安装,可主动发一条测试通知。

配置文件与默认值

设置持久化在 $DSH_HOME\dsh-interaction-notify\state.json(默认 $DSH_HOME 为 $env:USERPROFILE\.dsh),原子写入、权限 0600;文件缺失或损坏时自动回退默认值。

| 字段 | 取值 | 默认 | 说明 |
| enabled | true / false | true | 总开关;false 时任何事件都不投递 |
| events.question | true / false | true | 是否在 ask_user_question 时提醒 |
| events.approval | true / false | true | 是否在审批请求时提醒(只去重,不受最小间隔限制) |
| events.plan | true / false | true | 是否在 exit_plan_mode 计划批准时提醒 |
| sound | "chime" / "system" / "silent" | "chime" | 内置音效 / Windows 提示音 / 静音(静音仍会弹通知) |
| volume | 0–100 的整数 | 55 | 内置音效的播放音量 |
| quietWhenFocused | true / false | true | DSH 已在前台时不打扰(整条提醒跳过,日志记 skipped: focused);POST /test 不受此限 |
| clickToReturn | true / false | true | 是否在通知上显示「回到 DeepSeek Harness」按钮;关闭后不显示该按钮,通知与声音不受影响 |
| minIntervalMs | 毫秒数,≥ 0 | 1200 | 非审批类通知的最小间隔;间隔内的新通知直接丢弃、不排队。审批类永不节流 |

POST /set 只改请求里出现的字段(深合并),未提及的字段保持原值;非法值回退默认。用 POST /set 修改立即生效;如果直接用编辑器改 state.json,需要重启 DSH 才生效(运行中的实例只在启动时读取一次,之后用 /set 写回时也会以内存中的值为准)。

环境变量

| 变量 | 用途 |
| DSH_HOME | DSH 家目录;决定插件数据目录、profile 位置,未设置时为 $env:USERPROFILE\.dsh |
| DSH_EXE | scripts/install.mjs 自动解析用的桌面端 exe 路径(可用 --exe 覆盖) |
| DSH_INSTALL_ROOT | scripts/install.mjs 的只读保护目录(默认由解析到的 exe 所在目录推导),防止脚本写入 DSH 安装目录 |

如何关闭提醒

- 临时全部关闭:POST /set 传 { "enabled": false }(立即生效,无需重启)。
- 只关某一类:{ "events": { "plan": false } }。
- 只要声音关掉、通知保留:{ "sound": "silent" }。
- 完全移除插件:用 install.mjs --uninstall(见下文)。

HTTP 接口(改配置 / 测试 / 看日志)

宿主注册了以下路由,全部只接受本机 loopback + 同源请求(否则 403),无需鉴权头,PowerShell 直接调用即可。请求体上限 256 KiB。

| 路由 | 方法 | 说明 |
| /api/dsh-interaction-notify/state | GET | { config, platform, rev, stats } |
| /api/dsh-interaction-notify/set | POST | 部分配置 → { config, rev } |
| /api/dsh-interaction-notify/test | POST | 立即投递测试通知 { title?, body?, kind?, sound?, volume? } → { ok, code?, error?, stats }(绕过静默/去重/节流,仍尊重 sound) |
| /api/dsh-interaction-notify/log | GET | { lines: [...] } 最近 200 行通知尝试日志 |
| /api/dsh-interaction-notify/diag | POST | { name, payload } → 落盘 diag\<name>.json,返回 { ok, path }(文件名会被清洗) |

桌面端的 Web 服务使用随机端口且只监听 127.0.0.1,不要写死端口。最方便的办法是在 DSH 窗口内打开开发者工具执行 location.origin,得到形如 http://127.0.0.1:<port> 的值;用 dsh web 命令启动时 stdout 也会打印服务地址。

$base = 'http://127.0.0.1:<port>' # 换成上一步得到的 origin

当前配置、平台、统计 Invoke-RestMethod "$base/api/dsh-interaction-notify/state" | ConvertTo-Json -Depth 6

改配置(只传要改的字段) Invoke-RestMethod "$base/api/dsh-interaction-notify/set" -Method Post -ContentType 'application/json'
-Body (@{ sound = 'system'; volume = 70; quietWhenFocused = $false } | ConvertTo-Json)

只关掉「计划批准」这一类提醒 Invoke-RestMethod "$base/api/dsh-interaction-notify/set" -Method Post -ContentType 'application/json'
-Body (@{ events = @{ plan = $false } } | ConvertTo-Json)

立即弹一条测试通知(会真的响) Invoke-RestMethod "$base/api/dsh-interaction-notify/test" -Method Post -ContentType 'application/json'
-Body (@{ title = '测试'; body = '来自 dsh-interaction-notify'; kind = 'test' } | ConvertTo-Json)

看最近的通知尝试日志 (Invoke-RestMethod "$base/api/dsh-interaction-notify/log").lines

卸载

在插件目录下执行:

node scripts\install.mjs --profile desktop --uninstall

卸载会移除:依赖声明、dsh.profile.bundles 条目、node_modules junction、开始菜单快捷方式(%APPDATA%\Microsoft\Windows\Start Menu\Programs\DeepSeek Harness 提示.lnk)。state.json、日志与插件目录默认保留;需要彻底清理时手动删除 $DSH_HOME\dsh-interaction-notify\ 和插件目录。

工作原理

宿主监听

插件是标准的 Cordis 宿主插件:export const inject = ['webServer'],在 apply(ctx) 里用 ctx.effect(...) 一次性注册 HTTP 路由,并订阅根上下文的 session/event:

ctx.on('session/event', (session, event) => notifier.handleEvent(session, event))

session/event 在根上下文注册可收到全部会话的已提交事件。检测层(src/detection.js)是纯函数,只认三种事件:

- approval/asked → approval;
- tool/call 且 data.name === 'ask_user_question' → question;
- tool/call 且 data.name === 'exit_plan_mode' → plan。

其它事件、缺字段或脏数据一律返回 null,绝不抛错。

通知投递

src/notifier.js 负责去重、节流、按 events. 过滤、统计与写尝试日志,然后调用 src/deliver.js。deliver 运行在 DeepSeek Harness.exe 的 Node 环境里,没有 Electron 通知 API,因此:

1. 把标题/正文/声音/音量等写成一个临时 JSON payload(放在 $DSH_HOME\dsh-interaction-notify\tmp\,用完即删);
2. 启动 %SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -NonInteractive -ExecutionPolicy Bypass -File assets\notify.ps1 -PayloadFile <payload>;
3. 单次投递硬超时 25 秒,失败只记日志与统计,绝不影响产生事件的会话;非 Windows 平台直接返回 { ok: false, skipped: 'unsupported-platform' }。

assets/notify.ps1 负责整个可见侧:

- Toast:通过 WinRT ToastNotificationManager 弹出,通知音被显式静音(),避免和自定义声音重复;有「回到 DeepSeek Harness」按钮(clickToReturn 时)。
- 声音:chime 用 WPF MediaPlayer 播放 assets/notify.wav,volume 映射为播放器音量(不可用时回退 SoundPlayer);system 播放 SystemSounds.Asterisk;silent 不发声。
- 任务栏闪烁:找到进程名为 DeepSeek Harness 的主窗口,调用 FlashWindowEx 闪 5 次。

点击通知回到窗口

Windows 只把前台权限交给「被点击的那个进程」,所以点击路径是:

点击通知 / 通知按钮 → 与 AppUserModelID(com.deepseek.harness.notify)关联的开始菜单快捷方式 → wscript.exe 隐藏启动 assets/activate.vbs → assets/activate.ps1:找到已存在的 DSH 主窗口
· 已在前台且未最小化 → 什么都不做
· 最小化 / 被隐藏 → ShowWindow 恢复 + SetForegroundWindow 置前(前台锁拒绝时用 AttachThreadInput + 合成 Alt 键兜底)
· 应用已完全退出 → 用快捷方式里记录的 exe 路径重新启动

这也是为什么不能靠「重新拉起一个 exe 进程再 window.focus()」:第二个进程拿到前台权限后立刻退出,原进程的聚焦会被 Windows 前台锁拦掉。快捷方式由 scripts/setup-shortcut.ps1 创建,install.mjs 会调用它。

如果开始菜单快捷方式缺失,notify.ps1 会回退到 Windows PowerShell 自己的身份:通知可能仍然弹出,但点击不会回到 DSH;如果快捷方式存在但 AppUserModelID 写入失败,通知可能完全不显示。这两种情况都可以重跑安装脚本或 setup-shortcut.ps1 修复。

设置、统计与日志

- 设置:$DSH_HOME\dsh-interaction-notify\state.json(原子写,0600)。
- 统计:内存中的 attempted / delivered / skipped / failed / lastAt / lastError,可通过 GET /state 读取。
- 尝试日志:$DSH_HOME\dsh-interaction-notify\notifications.log,每次尝试一行 JSON({t, kind, id, ok, code?, skipped?, error?});超过 400 行时压缩为最近 200 行;GET /log 返回最近的 200 行。
- 诊断转储:POST /diag 写到 $DSH_HOME\dsh-interaction-notify\diag\<name>.json。

目录结构

dsh-interaction-notify/
├─ package.json 插件清单(宿主半;无 dsh.client) ├─ cordis.patch.yml 插入 profile 的 bundle 补丁 ├─ CONTRACT.md 模块接口与行为契约(设计文档) ├─ README.md 本文件 ├─ LICENSE MIT ├─ .gitignore ├─ src/ 源码 │ ├─ index.js Cordis 入口:事件监听 + HTTP 路由 │ ├─ detection.js 纯函数:会话事件 → 交互描述 │ ├─ notifier.js 去重/节流/统计/日志 → 调用 deliver │ ├─ deliver.js Windows 投递:payload + 调用 notify.ps1 │ └─ config.js 设置默认值/校验/深合并/原子写 ├─ lib/ src/ 的构建产物(scripts/build.mjs 直拷,随仓库提交) ├─ assets/ │ ├─ notify.ps1 弹 Toast + 播放声音 + 任务栏闪烁 │ ├─ activate.ps1 点击后聚焦/唤醒 DSH 窗口 │ ├─ activate.vbs wscript 隐藏启动 activate.ps1 的入口 │ └─ notify.wav 内置提示音 ├─ scripts/ │ ├─ build.mjs src → lib 复制 │ ├─ install.mjs 安装/卸载到 profile(幂等 + 备份) │ ├─ setup-shortcut.ps1 创建/删除带 AUMID 的开始菜单快捷方式 │ └─ make-chime.mjs 重新生成 assets/notify.wav └─ test/ ├─ detection.test.mjs ├─ config.test.mjs ├─ notifier.test.mjs ├─ routes.test.mjs ├─ e2e.test.mjs ├─ REPORT-final.md 测试证据 └─ lib/harness.mjs 测试桩(假宿主/假投递/临时 DSH_HOME)

开发与构建

以下命令都在插件目录下执行(克隆位置,如 $env:USERPROFILE\.dsh\plugins\dsh-interaction-notify):

改过 src/ 后必须重建:宿主加载的是 lib/
node scripts\build.mjs

跑全部测试(node:test,无第三方依赖)
node --test "test/.test.mjs"

只跑单个文件
node --test "test/detection.test.mjs"

重新生成内置提示音(确定性,重复生成字节一致)
node scripts\make-chime.mjs

- lib/ 是构建产物,必须与 src/ 保持一致;只改 src/ 不重建,重启后跑的仍是旧代码。
- 构建就是直拷(ESM,无打包器、无网络),node scripts\build.mjs 输出 5 个文件。
- 调试时建议用独立配置档,避免影响正在使用的桌面端:
dsh --profile notifydev web --port 5599

(dsh 命令可来自 DSH 安装目录的 resources\runtime\cli\bin\dsh.cmd。)
- 测试的 createPlugin({ deliver }) 支持注入假投递;真实 deliver 使用 Windows PowerShell,测试永远不会弹通知或响铃。

测试

测试使用 Node 内置的 node:test,覆盖:

| 文件 | 覆盖内容 | 用例数 |
| test/detection.test.mjs | 三种事件 → 通知描述的纯函数契约、脏数据不抛错 | 13 |
| test/config.test.mjs | 默认值、normalize/mergeConfig、原子写、损坏文件回退 | 16 |
| test/notifier.test.mjs | 去重、节流(审批不节流)、开关、统计、日志裁剪、deliverNow | 26 |
| test/routes.test.mjs | 路由鉴权(loopback + 同源)、405/400、body 上限、/set、/test、/log、/diag | 20 |
| test/e2e.test.mjs | 真实 session/event → 假投递的端到端链路、dispose | 15 |

共 90 个用例。测试全部注入假 deliver,并把 $DSH_HOME 指向系统临时目录,因此不会产生真实通知、不会写真实状态;详细证据见 test/REPORT-final.md。

ℹ tests 90
ℹ pass 90
ℹ fail 0

已知限制

- 只有宿主半:没有图形化设置界面,改配置用 HTTP 接口或直接编辑 state.json。
- 点击只回到 DSH 窗口本身,不定位到具体会话或消息(通知是应用级的)。
- 依赖 Windows 10/11 的 Toast 与开始菜单 AppUserModelID 机制;macOS/Linux 上宿主半安全降级(不投递、不报错)。
- 通知投递是「尽力而为」:单次 25 秒超时、失败只记日志,绝不影响会话;通知能否显示还受 Windows 通知权限与「专注助手 / 请勿打扰」控制。
- quietWhenFocused 通过前台进程名判断;DSH 窗口在前台但被其它置顶窗口遮住等边缘情况可能误判。
- 若开始菜单快捷方式被删除或被安全软件改写,点击回窗口会失效(通知可能仍正常弹出),重跑安装脚本可修复。
- 插件依赖 DSH 的 session/event 事件与内建工具名(ask_user_question / exit_plan_mode);若 DSH 后续调整这些协议,需要同步更新 src/detection.js。

故障排查

完全收不到通知

1. GET /state 看 enabled、events.* 是否被关掉,stats.skipped/stats.failed 是否在增长。
2. quietWhenFocused 默认为 true:你是不是正看着 DSH?用 POST /test 验证(它绕过该规则),或把配置改为 false。
3. Windows 设置 → 系统 → 通知:总开关、专注助手/请勿打扰,以及「DeepSeek Harness 提示」的允许开关。
4. 检查快捷方式是否存在:Test-Path "$env:APPDATA\Microsoft\Windows\Start Menu\Programs\DeepSeek Harness 提示.lnk"。不存在就重跑 install.mjs 或 setup-shortcut.ps1。
5. GET /state 的 platform 必须是 win32;非 Windows 返回 skipped: unsupported-platform。

有通知但没声音

1. sound 不是 "silent",volume 不是 0。
2. Windows 音量合成器里检查 Windows PowerShell 的音量(notify.ps1 在它下面播放)以及系统总音量/静音键。
3. chime 使用 assets/notify.wav;文件丢失时会退化为系统提示音。可用 node scripts\make-chime.mjs 重新生成。
4. 系统声音方案被禁用时 sound = "system" 也可能没声,换回 chime 验证。

点击通知回不到窗口

1. 检查开始菜单快捷方式是否存在(同上);缺失时 notify.ps1 会回退到 PowerShell 身份,点击不会回到 DSH。
2. 快捷方式目标应为 wscript.exe "...\assets\activate.vbs" "<DSH exe>",工作目录为插件根。
3. 手动双击该快捷方式,观察 DSH 窗口是否置前,以区分是快捷方式问题还是窗口状态问题。
4. 记住限制:只回到 DSH 窗口,不跳到具体会话;应用被完全退出时会重新启动。

日志与诊断

| 内容 | 位置 |
| 通知尝试日志 | $DSH_HOME\dsh-interaction-notify\notifications.log |
| 最近 200 行日志 | GET /api/dsh-interaction-notify/log |
| 诊断转储 | POST /api/dsh-interaction-notify/diag → $DSH_HOME\dsh-interaction-notify\diag\<name>.json |
| 设置 | $DSH_HOME\dsh-interaction-notify\state.json |
| 单次通知的临时 payload(正常会被删除) | $DSH_HOME\dsh-interaction-notify\tmp\ |

日志里 skipped 的常见值:focused(DSH 在前台,按 quietWhenFocused 静默)、unsupported-platform(非 Windows)。error / code 非空说明 PowerShell 投递失败,通常会带出具体原因。

安全说明

- 插件不联网、不上报、无第三方依赖;通知内容只来自本地会话事件。
- HTTP 路由只接受 loopback + 同源请求(含 DNS rebinding 防护),请求体限制 256 KiB。
- 设置、日志、payload 文件权限 0600,payload 用完即删。
- 开始菜单快捷方式只指向仓库内的 assets/activate.vbs 和用户指定的 DSH exe,不包含任何凭据。

许可

MIT © 2026 waterc

接口与内部行为约定见 CONTRACT.md。
预览分享卡片长什么样 ↓waterc07/dsh-interaction-notify
分享 · DeepSeek Harness Hub
waterc07/dsh-interaction-notify

智能体等你回答或授权时弹窗响铃提醒你

这个插件是你维护的吗?
作者本人可认领并核对本条目;认领通过后,详情页会显示「作者已认领」标记。
认领条目 →
回到顶部