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

任务通知器 xubin0628/dsh-task-notifier

DeepSeek Harnessv1.1.0
xubin062833 天前有提交已提供中文文档扫描:未发现敏感能力

任务完成或需批准时用横幅、提示音和系统通知提醒你

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

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

自动兼容检查有告警:npm 同名包「dsh-task-notifier」归属 moranyue/dsh-task-notifier,装到的可能不是本插件。
安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add xubin0628/dsh-task-notifier
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · other
装得上吗
本站已在 dsh 0.2.1-rc.5 下真实安装成功
非静态推断
L5 · 运行时冒烟等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
更新放缓:最近一次提交在 33 天前
档位由哪些信号合成

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

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安装兼容性检查⚠ 装前注意

npm 同名包「dsh-task-notifier」归属 moranyue/dsh-task-notifier,装到的可能不是本插件

展开查看检查明细 ↓

以下结论由程序自动检查 npm 包、engines 声明与入口文件得出,未做人工实机验证——能装不等于用着没问题。

✓npm 包dsh-task-notifier @ 1.1.0
✓Node 引擎未声明 engines.node
✓dsh CLI 依赖未声明 dsh 版本约束
✓入口文件main/exports/bin 已声明

验证方式:npm registry 存在性 + package.json 静态校验 · 最后检查 2026/10/12 17:40:16

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

静态扫描未发现敏感能力:最多只发网络请求、读取自身元数据或只读文件,未发现执行命令、文件写入或敏感信息读取。

发起外部网络请求
查看扫描证据(共 1 处,展示前 1 条)
  • 发起网络请求
    lib/client.js:345
    fetch("/dsh-notifier/seen?who=settings-page", { cache: "no-store" }).catch(() => {})
扫描于 2026/11/4(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

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

给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

功能亮点

  • 任务完成提醒
  • 需批准时提醒
  • 横幅提示音系统通知

DSH 任务通知插件:任务完成 / 需要批准 / 需要回答 / 出错时的横幅、提示音与系统通知,并在设置里提供「通知」页自由配置

README

由 DeepSeek 最新模型翻译生成
dsh-task-notifier DSH 任务通知器:任务完成 / 需要你批准 / 需要你回答 / 出错时,用「应用内横幅 + 提示音 + 系统通知」提醒你。 通知哪四件事 | 事件(DSH 公开事件) | 触发条件 | 横幅标题 | | agent/status | 会话从 running 变回 idle,且不是在等你输入 | 任务完成 | | approval/request | 有工具调用需要你批准(沙箱/权限) | 需要你的批准 | | user-questions/request | 有工具在等你回答问题 | 需要你的回答 | | agent/error | 某一步或某一轮出错 | 执行出错 | 两个 waterfall 事件(approval / user-questions)只做通知,然后原样 next() 交回默认流程,不改变也不拦截既有批准语义;同一轮已经报过错时不再补一条「完成」,避免双响。 「卡在等你输入」不当作任务完成:智能体停下来等你批准 / 等你回答时,agent/status 也会落到 idle,但那不是跑完了 —— 这种暂停已经由 approval / question 通知过一次,再补一条「任务完成」会让同一次暂停被通知两遍且结论相反。
展开完整文档(README 剩余 1 节)
dsh-task-notifier

DSH 任务通知器:任务完成 / 需要你批准 / 需要你回答 / 出错时,用「应用内横幅 + 提示音 + 系统通知」提醒你。

通知哪四件事

| 事件(DSH 公开事件) | 触发条件 | 横幅标题 |
| agent/status | 会话从 running 变回 idle,且不是在等你输入 | 任务完成 |
| approval/request | 有工具调用需要你批准(沙箱/权限) | 需要你的批准 |
| user-questions/request | 有工具在等你回答问题 | 需要你的回答 |
| agent/error | 某一步或某一轮出错 | 执行出错 |

两个 waterfall 事件(approval / user-questions)只做通知,然后原样 next() 交回默认流程,不改变也不拦截既有批准语义;同一轮已经报过错时不再补一条「完成」,避免双响。

「卡在等你输入」不当作任务完成:智能体停下来等你批准 / 等你回答时,agent/status 也会落到 idle,但那不是跑完了 —— 这种暂停已经由 approval / question 通知过一次,再补一条「任务完成」会让同一次暂停被通知两遍且结论相反。所以 approval/request 与 user-questions/request 会把该会话标记为 awaitingUser,直到你回复(agent/inbox/claimed)或该会话重新 running 才清除;被标记期间的 running → idle 不发「完成」。/status 会把这个集合列出来,方便排查。

设置页:通知

插件在 设置 → 左侧导航里注册了一个「通知」页(客户端插件的 settings.section 槽位),可以自由配置:

| 分组 | 可配置项 |
| 通知哪些事 | 总开关;任务完成 / 需要我批准 / 需要我回答 / 出错失败 四个独立开关;是否包含子代理 |
| 怎么提醒我 | 应用内横幅;系统通知;横幅停留秒数 |
| 提示音 | 提示音开关;音色(清脆 / 铃铛 / 水滴 / 脉冲 / 静音)+ 试听;音量滑块(0–100%,实时生效) |

- 设置存在浏览器 localStorage(键 dsh-task-notifier:settings:v1),改完立即生效,不需要重启客户端。
- 音色只改变音品(波形 / 包络 / 八度),四类事件仍用不同音高区分,所以换了音色也听得出是哪一类。
- cordis.patch.yml 里的 config 只作为初始默认值:只有当你从没在设置页里改过时才生效;一旦动过任何一项,就以设置页为准。

它怎么工作

宿主进程 (lib/index.js) 页面半区 A (assets/notifier-client.js)
├─ 订阅 4 个事件 ┌─► ├─ EventSource('/dsh-notifier/events') ├─ webServer 注册 4 条路由 ─── SSE ─────┘ ├─ 应用内横幅(Shadow DOM,样式隔离) └─ webserver/index-inject 注入 ──► ├─ 提示音(WebAudio 合成,无音频资源) └─ 系统通知(页面 Notification API) ▲ 页面半区 B (lib/client.js) ── 设置页「通知」────────┘ dsh.client 声明的客户端插件,注册进 settings.section;改动写 localStorage 并广播事件,半区 A 立即生效(试听也走事件,音色合成只有一份实现)

注入走两条并存的通道:

- webserver/index-inject 的内联 script 行 —— 官方桌面端(Electron)唯一生效的通道。桌面壳的 index.html 从安装包静态 dist 直出,不经过宿主 renderIndex(),tapIndex 到不了。
必须是内联行而不是 script-src 行:页面侧解释器对 script-src 是「加载失败即 reject 整个 boot」,内联行自己 createElement 并吞掉 onerror,路由不在也只是静默失败。
- webServer.tapIndex —— 浏览器形态(dsh web)走 renderIndex(),这条生效。

安装

插件以 bundle 形式装进某个 profile:该 profile 的 package.json 里 dsh.profile.bundles 会出现 dsh-task-notifier,依赖以 link:(软链)或 file:(拷贝)指向插件目录。

⚠️ 官方桌面端(Electron)读的是 desktop profile,而这个 profile 由客户端独占管理,
dsh plugin --profile desktop 会被拒绝。正确做法是在 DSH 会话里让 DSH 自己装:

让 DSH 调用内置 plugin_manager: install_bundle target = link:<插件目录绝对路径> # 软链安装:改完存盘即生效,最省事 install_bundle target = file:<插件目录绝对路径> # 拷贝安装:自包含,源码丢了插件照跑

生效方式:新装通常热生效(返回 "application":"applied");换版本、或改 package.json (例如新增 dsh.client)需要重开客户端(返回 "restart-required")。

卸载:

plugin_manager remove_bundle target = dsh-task-notifier

配置

改 cordis.patch.yml 的 config 段(每项都可省略,省略即用 lib/index.js 里的默认值):

| 键 | 默认 | 说明 |
| notifyOnDone | true | 任务完成通知 |
| notifyOnApproval | true | 需要批准时通知 |
| notifyOnQuestion | true | 需要回答时通知 |
| notifyOnError | true | 出错时通知 |
| includeSubagents | true | 子代理 / teammate 也通知;false = 只通知主会话 |
| suppressDoneAfterError | true | 同一轮已报错就不再补「完成」 |
| coalesceMs | 1200 | 同键事件在该窗口内只发一次,防重试 / 并行抖动刷屏 |
| sound | true | 提示音 |
| systemNotification | true | 系统通知(Windows 通知中心,点击切回窗口) |
| toastDurationMs | 8000 | 横幅停留时长 |
| errorToastDurationMs | 15000 | 出错类横幅停留时长 |
| volume | 0.35 | 提示音音量 0~1 |

配置在重启客户端后生效(profile patch 改动需要一次 config reload,桌面端最稳的是重开客户端)。

自检

宿主侧(不需要看页面):

插件是否活着 + 当前配置 + 已连上的页面数 + 已发通知数 + 正卡在等谁输入 Invoke-RestMethod http://127.0.0.1:19387/dsh-notifier/status

回看最近发过哪些通知(排查"到底发了没 / 发了几条 / 是不是误报") Invoke-RestMethod 'http://127.0.0.1:19387/dsh-notifier/recent?limit=20'

真的走一遍通知链路:页面会弹横幅 + 响铃 + 系统通知 Invoke-RestMethod 'http://127.0.0.1:19387/dsh-notifier/test?kind=approval' kind 可取 done | approval | question | error

进程外单元验证(不需要 DSH 在跑):

node test/smoke.mjs

排查

| 现象 | 原因 / 处理 |
| /dsh-notifier/status 返回 404 | 插件没激活。看 profile 的 patch 里 dsh-task-notifier 是否 disabled: false,然后重开客户端 |
| 路由通了但页面不弹 | 页面半区没注入。桌面端注入表在宿主启动时收集一次,改完必须重开客户端;浏览器形态直接 Ctrl+F5 |
| 有横幅没声音 | 浏览器 / Electron 要求先有用户手势才能播音频。在页面里点一下任意位置即可解锁 |
| 没有系统通知 | 页面侧 Notification.permission 不是 granted。点一下页面任意位置会触发一次授权请求,允许即可 |
| 改了 assets/notifier-client.js 不生效 | 宿主按 mtime 热读取,正常刷新页面即可;不生效再 Ctrl+F5 |
| 改了 lib/index.js 不生效 | 宿主进程的 ESM 模块缓存不会因文件改动失效 —— 必须重开客户端 |

改代码后怎么生效(开发工作流)

改哪个文件,决定你要做什么才能看到效果——这三者完全不同,别搞混:

| 你改了 | 怎么生效 | 为什么 |
| assets/notifier-client.js | 刷新页面(F5)即可 | 宿主每次请求 /dsh-notifier/client.js 都按 mtime 重读文件 |
| lib/client.js(设置页) | 刷新页面(F5);新增 / 删除 dsh.client 声明要重开客户端 | 客户端包体由 clientModules 提供,页面刷新即重新拉取 |
| lib/index.js | 必须重开客户端 | Cordis 重新 apply 时命中 Node 的 ESM 模块缓存,文件改动不会失效 |
| cordis.patch.yml(配置项) | 必须重开客户端 | profile patch 需要一次 config reload |
| package.json(dsh.client / exports) | 必须重开客户端 | 客户端入口图在宿主启动时合成 |
| 任何文件 | 改完先跑 node test/smoke.mjs | 17 个用例覆盖事件、路由、客户端交付契约,几秒出结果 |

推荐的改 bug 流程:

1) 改代码
2) 先跑进程外回归(不需要 DSH 在跑,失败会非零退出)
node test/smoke.mjs
3) 只改了页面半区 → F5;动了宿主半区或 package.json → 重开客户端
4) 自检确认活着 Invoke-RestMethod http://127.0.0.1:19387/dsh-notifier/status

保存、备份与迁移

先记住一件事:这个插件的源码只有一份。 profile 里的 ~/.dsh/profiles/desktop/node_modules/dsh-task-notifier 不是拷贝,而是一个指向源码目录的 Junction(目录联接)。源码目录一旦被移动、改名或删除,插件立刻失效(表现为启动时 entry 激活失败)。

所以源码必须放在一个你不会随手清理的固定位置:

- 开发期用 link: 安装:改完存盘就生效(按上面的表决定要不要重启),最省事。
代价是源码目录不能动。
- 想彻底冻结 / 自包含用 file: 安装:pnpm 会把包拷贝进 profile,源码丢了插件照跑。
代价是每次改完都要重新 install 一次才生效。

切换安装方式(两者都是让 DSH 调内置 plugin_manager):

换到新位置(绝对路径,路径含空格 / CJK 都要原样写) install_bundle target = link:<插件目录绝对路径>

或者改成拷贝安装,冻结当前版本 install_bundle target = file:<插件目录绝对路径>

迁移步骤(把源码搬出临时目录):先复制整个目录到新位置 → 用新路径重新 install_bundle → 确认 Invoke-RestMethod .../dsh-notifier/status 正常 → 再删旧目录。

版本管理

本仓库用 git 管理。养成这个习惯就够了:

cd <插件目录>
git add -A
git commit -m "fix: 描述这次改了什么"

改 package.json 的 version 并打 tag,便于回滚和对照:

git tag v0.1.1

想跨机器/长期保存,再推到一个私有仓库,之后就能像其他 DSH 插件一样从 GitHub 安装:

install_bundle target = github:<你的用户名>/<仓库名>

已知限制

- 宿主进程里的模块改动无法热重载:Cordis 重新 apply 时会命中 Node 的 ESM 缓存,改 lib/index.js 只能重启客户端(或改文件名后重新 install)。
- 桌面端的 index 注入表是一次性的:宿主启动时 collectIndexInjections() 经 IPC 交给渲染层,之后没有刷新路径。
- 桌面端拿不到 Electron 的 Notification:运行时是被桌面壳 spawn 出来的独立子进程,插件跑在子进程里。
从无包标识进程调 WinRT toast 会报 0x80073D54,所以系统通知只能在页面侧用 Notification API。
- 路由带一层极简信任栅栏(只接受回环 Host、拒绝 Sec-Fetch-Site: cross-site),因为事件流里含会话路径。
- 设置存在浏览器 localStorage,不写回 profile 配置:换浏览器/清缓存会回到默认值。这是刻意的取舍 ——走 Host 设置文档(configForms)需要给条目声明 schemastery schema 并依赖宿主设置服务,一旦版本不匹配会让整条 entry 激活失败;通知偏好属于纯展示层,不值得冒这个风险。

目录结构

dsh-task-notifier/
├── package.json # dsh.bundle.patch + dsh.client(exports["./client"])
├── cordis.patch.yml # 挂载声明 + 宿主侧可配置项 ├── lib/index.js # 宿主半区:事件订阅 + 路由 + 注入 ├── lib/client.js # 客户端半区:设置里的「通知」页(__ModuleLoader__ 格式) ├── assets/notifier-client.js # 页面半区:横幅 + 提示音 + 系统通知 └── test/smoke.mjs # 进程外冒烟测试(17 个用例)

许可证

MIT —— 见 LICENSE。
预览分享卡片长什么样 ↓xubin0628/dsh-task-notifier
分享 · DeepSeek Harness Hub
xubin0628/dsh-task-notifier

任务完成或需批准时用横幅、提示音和系统通知提醒你

这是你的仓库?认领条目

回到顶部