npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@ltao0829/dsh-task-notify

v0.3.0

Published

Task-completion reminder for DeepSeek Harness 0.2: in-page toast, OS notification, and sound when an agent turn or background job finishes

Downloads

457

Readme

dsh-task-notify

AI 编程代理的生命周期通知层,当前支持 DeepSeek Harness。

CI npm version npm downloads License: BSD-3-Clause

English · 简体中文

AI 编程代理越来越多地运行长时间、自主的任务:一轮任务可能持续数分钟,而用户通常已经切到别的窗口。本项目在代理任务生命周期之上补上了缺失的通知层:当代理完成、失败、后台任务结束、或开始等待人工介入(审批 / 计划评审 / 提问)时,立即通过页面 toast、操作系统级桌面通知以及可选提示音提醒你。

借鉴 Codex 的桌面通知体验,而非 Codex 集成。与 OpenAI 无关联,也不受 OpenAI 赞助。 目前本项目以 DeepSeek Harness(DSH)插件形式发布;其生命周期检测核心与宿主无关,设计目标是逐步演进为支持更多编程代理的适配器。

为什么需要它

长任务代理反转了传统注意力模型:用户提交任务后就会切走,而不是盯着终端。纯 UI 状态提示(后台标签页里的一个 spinner)恰恰在关键时刻失效——用户没有在看。dsh-task-notify 把生命周期变化转化为可打断的、系统级的信号,闭合自主代理与分心用户之间的反馈环。

演示

录屏尚未入库,因此下表只列出三个片段的文件名,而不是直接嵌入图片。录制方案(场景、工具、体积建议)与恢复图片所需的精确写法见 docs/demo-guide.md。

| 任务完成 | 需要审核 | 后台任务失败 | | --- | --- | --- | | docs/demo-turn.gif | docs/demo-review.gif | docs/demo-failure.gif |

功能

  • 对话任务完成提醒 —— 助手一轮任务(思考或工具调用)结束时提醒。
  • 后台任务完成提醒 —— 后台命令或子代理作业结束时提醒(completed / failed / killed)。
  • 需要审核提醒 —— 运行中等待审批 / 计划评审 / 回答提问时提醒。
  • 失败提醒 —— 对话任务报错或后台任务失败 / 被终止时提醒。
  • 三种通知通道 —— 浏览器系统通知 + 页面 toast + 可选双音提示音。
  • 逐项开关 —— 每类事件和每种通道均可独立开关。
  • 可自定义 —— 标题 / 正文模板、提示音样式与音量、toast 停靠角落与停留时长、免打扰时段、按会话静音。

环境要求

| 依赖项 | 说明 | | --- | --- | | DeepSeek Harness | 0.2.0-rc.2 或更新的 0.2.x —— 兼容性网关读取的是 peerDependencies,本包把所有 DSH peer 固定为 ^0.2.0-rc.2 | | Node.js | >=22.0.0(CI 覆盖 Node 22 与 24;桌面端内置运行时为 Node 24) | | pnpm | 仅在使用 dsh plugin 命令行安装时需要;桌面端使用其内置的 pnpm |

安装

# 从 npm 安装 —— 请写明版本范围,原因见下方冷却期说明
dsh plugin --profile <profile> add @ltao0829/dsh-task-notify@^0.3.0

# 或从 Git 安装,锁定发布标签
dsh plugin --profile <profile> add git+https://github.com/ltao0829/dsh-task-notify.git#v0.3.0

<profile> 是要装入的 DSH Profile:dsh web 服务器用 web,桌面端用 desktop。安装会把包写入该 Profile 并注册它的 bundle patch,由后者插入唯一一行 task-notify,同时挂载插件的宿主半部与浏览器半部。

在桌面端请从应用自身的 设置 → 插件 安装。desktop Profile 由 Electron 应用独占管理:活动 Profile 的插件变更会立即生效、无需重启,而 dsh --profile desktop … 会拒绝在第二个命令行进程里运行该 Profile。

装入 dsh web 服务器后,重启服务并刷新页面。首次在页面里点击/按键时,浏览器会请求「通知」权限,点允许即可收到系统通知。

版本必须与 DSH 系列对应。 0.2.x 与 0.3.x 需要 DeepSeek Harness 0.2;0.1.x 需要 DSH 0.1.x。两个系列不能互相通用:DSH 0.2 的兼容性网关会直接拒绝 0.1.x 系列,而 DSH 0.1.x 也无法加载更新的系列。

0.1.x 系列已停止维护。npm 上只有 0.1.0;之后的 0.1.1、0.1.2 修复只存在于 Git 历史中,从未打过标签、也从未发布。如果你仍在 DSH 0.1.x,请先把 DSH 升级到 0.2,再安装 0.3.x。

为什么要写版本范围而不是裸包名。 pnpm 11 内置了 24 小时供应链冷却期(minimumReleaseAge 默认为 24 * 60 分钟)。发布时间不足一天的版本对版本解析不可见,因此 dsh plugin add @ltao0829/dsh-task-notify 会静默解析到上一个发布版本,进而被判为不兼容而拒绝。写明版本或范围后,pnpm 会写入 minimumReleaseAgeExclude 并立即安装;等发布满一天后,裸包名也会正常解析到最新版。

卸载

dsh plugin --profile <profile> remove @ltao0829/dsh-task-notify
# 桌面端:在「设置 → 插件」中移除

这会同时移除包与它的 bundle 条目,task-notify 行随即从合成后的 Profile 中消失。浏览器侧的 localStorage 记录(dsh.taskNotify.v3)不属于 Profile:若希望重装后从默认值开始,请手动清除该键。

配置

设置页面位于 DSH 设置界面的**「插件」**区(DSH 0.2 新增的 settings.plugins.tab 插槽),页面标题为任务完成提醒。配置存于 localStorage(键 dsh.taskNotify.v3)。遗留的 v2 记录会被迁移一次——所有开关保留,旧的提示音开关映射为双音模式——随后 v2 键会被移除:

| 开关 | 默认 | 说明 | | --- | --- | --- | | 启用提醒 | 开 | 总开关 | | 对话任务完成提醒 | 开 | 助手一轮任务结束时提醒 | | 后台任务完成提醒 | 开 | 后台命令 / 子代理作业结束时提醒 | | 监听全部会话的后台任务 | 关 | 为会话列表中每个会话各开一条后台任务流,而非仅监听本页面打开后活跃过的会话 | | 需要审核时提醒 | 开 | 运行中等待审批 / 计划评审 / 提问时提醒 | | 失败时提醒 | 开 | 对话任务报错或后台任务失败 / 被终止时提醒 | | 浏览器系统通知 | 开 | 同时发送操作系统通知(需授权) |

提示音、弹窗与免打扰

| 设置 | 默认 | 说明 | | --- | --- | --- | | 提示音 | 无 | 无 / 单音 / 双音 / 自定义音频 | | 音频 URL | 空 | 提示音为自定义音频时播放;留空或加载失败时回退为双音 | | 音量 | 100% | 对所有提示音样式生效 | | 弹窗位置 | 右下 | 四个屏幕角落任选 | | 停留时长(秒) | 5 | 弹窗显示 3–15 秒后自动消失 | | 自定义标题 / 正文模板 | 空 | 占位符:{title}(任务标题)、{session}(会话 ID)、{kind}(事件类型);留空使用内置文案 | | 免打扰时段 | 关 | 该本地时间段内不触发任何提醒;支持跨零点(如 22:00 → 08:00) | | 静音的会话 | 空 | 每行一个会话 ID;这些会话不触发任何提醒 |

页面内 toast 没有开关——它是始终可用的通道,也是系统通知被拒绝、提示音被拦截时的兜底。模板输出按纯文本渲染,模板无法注入任何标记。

故障排查

| 现象 | 原因 | 处理 | | --- | --- | --- | | 有 toast,但没有系统通知 | Notification.permission 不是 granted,插件会静默跳过而非报错 | 授予通知权限。浏览器只允许在用户手势中弹窗,因此在页面里点击一次即可;或把浏览器系统通知关掉再打开,它会主动请求权限 | | 没有提示音 | Web Audio 在用户手势之前处于 suspended 状态 | 在页面里点击一次或按一下键盘,音频会在首个手势解锁 | | 完全没有任何提醒 | 总开关或对应事件开关是关的 | 检查启用提醒与各事件开关 | | 设定时段附近没有提醒 | 已开启免打扰时段,当前本地时间落在窗口内 | 关闭免打扰时段或调整时间;静音的会话列表中的会话同样保持静音 | | 已经跑完的任务没有补发提醒 | 页面加载后的首个快照只建立基线 | 属预期行为——刷新页面不会重放历史 | | 只对当前在看的会话有后台任务提醒 | 默认只为「本页面打开后被观察到运行过」的会话各开一条 job.list 流 | 打开监听全部会话的后台任务 | | 任务失败但没有提醒 | lastAgentError 只存在于被 retain 的会话 face 上 | 属预期行为——插件覆盖工作区已保持打开的会话,不会为了监听报错而额外 retain 会话 | | 安装被判为不兼容 | 0.1.x 插件装在 DSH 0.2 上,或反之 | 让两个系列对应,见安装中的配对说明 | | 用裸包名装到了旧版本 | pnpm 11 的 24 小时 minimumReleaseAge 冷却期 | 写明范围:@^0.3.0 |

架构

              coding agent(编程代理)
                   │
                   ▼
     宿主适配器(当前为 DeepSeek Harness;
                 未来可扩展 Claude Code / Codex / OpenCode)
                   │
                   ▼
     会话快照(N-1 与 N)
                   │
                   ▼
     生命周期检测器 ──►  事件:turn | job | review | failure
                   │
                   ▼
     通知分发器
       │          │          │
       ▼          ▼          ▼
    系统通知     toast      提示音

检测器(src/detect.ts)是纯函数:快照进去,生命周期事件出来。它不依赖 DSH 或 DOM,因此未来支持更多编程代理只需实现新的快照提供者,而无需重写通知核心。

DSH 0.2 的数据来源

DSH 0.2 移除了原先同时承载 jobsBySession 与逐行 pendingInteraction 的单一 sessions.list store。监听器现在把三个彼此独立的客户端数据源折叠成一份快照:

| 数据源 | 服务 | 提供内容 | | --- | --- | --- | | 会话目录 | ctx.sessions.list | id、标题、宿主基线的运行标志、引用计数 | | 客户端状态投影 | ctx.uiSession.sessionStatus | 实时的 running、待处理交互(key + kind)、未读完成标记 | | 后台任务名册 | ctx.jobs.state | 每个被监听会话的 JobView 行,由每会话一条 job.list 流驱动 |

值得注意的行为:

  • 首个快照只建立基线 —— 刷新页面不会补发历史提醒;此后才出现的会话或任务名册同样视为既存,不触发提醒。
  • 待处理交互以其不透明请求 key 追踪:被替换的新请求(审批之后又来一个提问)会再次提醒,而重连时对同一请求的重放不会重复提醒。
  • job.list 是按会话的流。默认只为「本页面打开后被观察到运行过」的会话各开一条;未在此页面运行过的会话,不可能持有本页面正在等待的后台任务。开启「监听全部会话」则改为覆盖整个会话列表,代价是每个会话一条流。
  • 对话失败检测读取 lastAgentError,而该字段只存在于被 retain 的会话 face 上。因此本插件覆盖工作区已经打开的会话,不会为了监听报错而额外 retain 会话。

通知通道

toast 直接挂载到 document.body,不依赖 React root,也不占用任何插槽,因此在没有对话座位的界面上(未选中会话、设置面板打开等)依然可用。最多同时堆叠 4 条,每条显示 5 秒。系统通知只在权限已是 granted 时发送;提示音会先 resume() 处于 suspended 状态的 AudioContext——每条通道都选择静默降级,而不是抛错。

项目结构

src/index.ts                         宿主半部 —— 惰性加载锚点
src/detect.ts                        纯生命周期检测器(三源折叠 + 快照 diff)
src/client/index.ts                  浏览器半部 —— 监听器、后台任务流与失败监听、UI 注册
src/client/notify.ts                 toast / 系统通知 / 提示音
src/client/locales.ts                zh + en 词典与命名空间声明合并
src/client/settings.ts               localStorage 设置存储
src/client/TaskNotifySettingsCard.tsx 设置页面(settings.plugins.tab)
tests/*.spec.ts                      检测器、生命周期、设置、通知、Manifest 与 apply() 测试

安全与隐私

  • 无外部服务器,无云后端。
  • 无遥测、无分析、无追踪。
  • 无需 API 密钥。
  • 通知全部在浏览器本地生成。
  • 设置仅保存在本地 localStorage。
  • 插件不会上传或外传对话内容。

与其他 DSH 插件一样,插件以你 DSH 进程的权限运行。

路线图

本节是"计划中工作"的唯一真源;CHANGELOG.md 只记录已经交付的内容。每项的范围、依赖、风险与验收标准见 docs/roadmap-plan.md。

当前阶段

  • [x] 对话任务完成通知
  • [x] 后台任务通知
  • [x] 审批 / 计划评审 / 提问通知
  • [x] 失败通知
  • [x] 系统通知 + toast + 提示音
  • [x] npm 正式发布(@ltao0829/dsh-task-notify)
  • [x] CI/CD(typecheck + test + build + pack dry-run)

近期

  • [ ] README 演示录屏
  • [x] npm 下载量徽章(shields.io,仅用 npm 公共统计 API)
  • [ ] 采用度趋势跟踪(周度下载量变化)
  • [ ] 跨平台通知后端
  • [x] 通知自定义
  • [x] 测试覆盖率度量与"只升不降"回归门禁
  • [ ] 提升监听器与通知渲染器的覆盖率

长期

  • [ ] 与代理无关的生命周期 API
  • [ ] 更多编程代理集成(Claude Code、Codex、OpenCode……)
  • [ ] 可复用的通知核心

相关项目

  • dsh-launcher —— DeepSeek Harness Web 的一键启动器。

两者共同构成一套面向 AI 编程代理工作流的小型工具集。

同一作者的另一个项目:buaa-auto-auth —— 为一台 Windows 机器每天自动完成校园网(SRun)认证。

贡献

见 CONTRIBUTING.md。

兼容性与一次性 Profile 验证

  • Node.js:>=22.0.0(CI 矩阵覆盖 Node 22 与 24)
  • DeepSeek Harness:^0.2.0-rc.2

DSH 0.2 已不再读取被废弃的 dsh.compatibility 字段。Profile 导入插件前,evaluatePluginCompatibility(@deepseek-ai/dsh-app-boot)会把插件 peerDependencies 中所有 @deepseek-ai/dsh / @deepseek-ai/dsh-* 项与唯一运行时版本逐一比对,预发布版本参与范围匹配。因此本包把所有 DSH peer 固定为 ^0.2.0-rc.2,并在 engines.dsh 中镜像同一范围;只要有任何一项漂移,tests/manifest.spec.ts 就会失败。

0.2.0 是破坏性的重新定位,而非增量发布:0.1.x 系列基于已被移除的 @deepseek-ai/dsh-client-runtime 与 settings.plugin.item 插槽构建,这两者在 DSH 0.2 中都不复存在。npm 上只发布过 0.1.0;0.1.1 与 0.1.2 仅存在于 Git 历史中。

一次性 Profile 验证命令

在不污染任何现有用户配置(~/.dsh)的隔离临时 Profile 中,验证插件安装、配置合成、Web 启动监听与卸载:

pnpm run verify:profile

脚本默认等待 DSH 首次准备 Profile 最多 90 秒。如果 CI Runner 或本机需要调整,可将 DSH_WEB_START_TIMEOUT_MS 设置为正整数毫秒值。插件安装另有默认五分钟的等待限制,可通过 DSH_PLUGIN_INSTALL_TIMEOUT_MS 调整。

验证日志证据报告:docs/verification-evidence.md。

限制与边界说明:Catalog 准入及一次性 Profile 验收证明插件生命周期契约与标准 Web Profile 启动兼容;系统级操作系统通知依然依赖用户在浏览器前端授予通知权限。一次性 Profile 验证会把打包后的 tarball 装入一个临时 DSH_HOME,证明插件被接受并成功加载;此外构建产物还会被单独校验,确认其外部依赖只包含平台模块。该脚本不驱动真实浏览器,页面内通知行为由 jsdom 测试套件覆盖。

开发

pnpm install
pnpm run typecheck
pnpm test
pnpm run coverage
pnpm run build
pnpm run verify:profile

必须先 pnpm run build 再 pnpm test:tests/bundle.spec.ts 会断言产出的 lib/client.js 只 require 冻结的平台模块。lib/ 是提交进仓库的,因此改动源码后必须把重新构建的产物一并纳入提交。

License

BSD-3-Clause