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

dsh-task-notify

v0.4.0

Published

DSH task completion system notifications (host-side node-notifier)

Readme

🔔 dsh-task-notify

DSH(DeepSeek Harness)插件:任务完成 · 系统弹窗通知

模型回答完你的请求,系统立即弹出原生通知——切到别的窗口刷剧、写代码时,再也不怕错过 DSH 的完成信号。

系统通知 · 零侵入 · 防打扰 · 可配置

npm version npm downloads License DSH Gitee


✨ 特性一览

| 特性 | 说明 | |---|---| | 🪟 原生系统通知 | host 端 node-notifier:Windows 通知中心 / macOS 通知 / Linux 原生通知 | | ✅ 准确的完成信号 | 监听 turn/end (completed),只在模型真正回答完时弹;失败/中断不误报 | | ⏳ 等待授权提醒 | 运行中需要用户批准时同样弹窗提醒回到界面;授权结果不再重复通知 | | 💬 等待回答提醒 | 模型暂停询问、需要你作答时同样弹窗提醒回到界面 | | 📝 回复预览 | 通知正文带模型回答的开头文本(长度可配置) | | 🧘 防打扰设计 | 默认仅在页面不在前台时弹;秒回的小问答不弹;任务完成默认跳过子代理(授权提醒不受限) | | 🎛️ 7 项可配置 | 设置页「任务通知」区块可视化调整,或 cordis patch 覆盖 | | 🛡️ 安全 | 全部 API 经 Host 头信任围栏;与 /api 网关同源校验 | | 📦 一键安装 | dsh plugin add 自动装依赖 + 自动挂载,零配置 |


📦 安装

前置要求

| 要求 | 说明 | |---|---| | DSH | 已安装且 dsh web 可正常运行(首次运行会自动初始化 ~/.dsh/profiles/web) | | Node.js | ≥ 20 | | pnpm | ≥ 10 |

方式一:npm 安装(推荐)

dsh plugin --profile web add dsh-task-notify

dsh plugin add 自动完成三步:① 安装依赖(node-notifier、schemastery 自动带上);② 检测 dsh.bundle 声明自动挂载;③ 无需手动改任何配置。

方式二:本地开发(link)

cd ~/.dsh/profiles/web
pnpm add "dsh-task-notify@link:<插件目录绝对路径>"

卸载

dsh plugin --profile web remove dsh-task-notify

生效

  • host 端(监听逻辑)改动 → 重启 dsh web
  • client 端(设置面板)改动 → 硬刷新浏览器(Ctrl/Cmd+Shift+R)

🔄 更新(本地 link / 开发安装)

本仓库通常以 link 安装(package.json 里 dsh-task-notify: link:<插件目录>),DSH 直接引用本地目录的 lib/。更新步骤:

# 1. 在插件目录拉取/修改源码后,重新构建
cd <插件目录绝对路径>
pnpm install     # 首次或依赖变更后
pnpm build       # 重建 host 端 tsc + client 端 tsdown → lib/

# 2. 重启 DSH 宿主,让 host 端新逻辑生效(client 端改动则硬刷新浏览器)
dsh web --port 8080

因为是 link 连接,pnpm build 产出的 lib/ 会被 DSH 立即读取,无需重装依赖或重新 pnpm add。 若更换了插件目录路径,用「方式二」重新执行一次 pnpm add "dsh-task-notify@link:<新路径>"。


🚀 快速使用

# 1. 安装
dsh plugin --profile web add dsh-task-notify

# 2. 重启
dsh web --port 8080

# 3. 使用 —— 让 DSH 跑一个任务,完成后系统弹窗:
#    标题:任务完成 · <工作目录名>
#    正文:模型回答的开头 120 字

💡 默认 onlyWhenBlurred: true——页面在前台时不弹(防打扰)。想测试效果,先把 DSH 页面切到后台/最小化再跑任务。


⚙️ 配置

设置页(推荐)

DSH 设置 → 「任务通知」区块,可视化调整全部选项。

cordis patch 覆盖

~/.dsh/profiles/web/cordis.patch.yml:

- id: task-notify
  name: 'dsh-task-notify'
  config:
    enabled: true          # 总开关
    onlyWhenBlurred: true  # 仅页面不在前台时通知
    notifyOnError: false   # 出错/中断也通知
    maxBodyChars: 120      # 正文预览长度(字符)
    minTurnMs: 0           # 最短通知时长(毫秒),过滤秒回
    sessions: top-level    # all | top-level
    showCwd: true          # 标题显示工作目录名

配置项详解

| 配置项 | 类型 | 默认值 | 说明 | |---|---|---|---| | enabled | boolean | true | 总开关 | | onlyWhenBlurred | boolean | true | 仅页面不在前台时通知(client 上报可见性) | | notifyOnError | boolean | false | 非正常结束也通知:error / aborted / max-tokens / blocked / interrupted | | maxBodyChars | number | 120 | 正文预览截断长度(0–500) | | minTurnMs | number | 0 | 回合短于此时长(毫秒)不通知,过滤快速问答 | | sessions | 'all' \| 'top-level' | 'top-level' | top-level 跳过子代理会话 | | showCwd | boolean | true | 标题附带工作目录名,区分多会话 |


🧠 工作原理

┌───────────────────────────────  DSH 运行时  ───────────────────────────────┐
│                                                                             │
│  ┌─────────────────┐   append    ┌─────────────────────────────┐           │
│  │  Agent 回合执行  │ ──────────► │  Session 事件日志(持久化)   │           │
│  │  turn/end       │             │  session/event 事件流        │           │
│  └─────────────────┘             └──────────────┬──────────────┘           │
│                                                 │ ctx.on('session/event')  │
│  ┌──────────────────────────────────────────────▼──────────────┐           │
│  │              dsh-task-notify (host 端)                        │           │
│  │  · turn/end & reason.kind === 'completed' 触发               │           │
│  │  · 过滤:enabled / sessions / onlyWhenBlurred / minTurnMs    │           │
│  │  · 提取该回合最后一条 assistant 文本作正文(截断)            │           │
│  │  · node-notifier 弹原生系统通知(失败回退 msg.exe)           │           │
│  └──────────────────────────────────────────────┬──────────────┘           │
│                                                 │                           │
│  ┌──────────────────────────────────────────────▼──────────────┐           │
│  │              dsh-task-notify (client 端)                     │           │
│  │  · 监听 visibilitychange/blur/focus → POST /task-notify/api/ │           │
│  │    visibility 上报页面可见性,供 onlyWhenBlurred 门控        │           │
│  │  · 设置页「任务通知」区块 → /task-notify/api/settings.* 读写  │           │
│  └─────────────────────────────────────────────────────────────┘           │
└─────────────────────────────────────────────────────────────────────────────┘

通知时机

| 信号 | 事件 | 说明 | |---|---|---| | 任务完成 | session/event → turn/end | reason.kind === 'completed' = 模型回答完一轮 | | 非正常结束 | error / aborted / max-tokens / blocked / interrupted | 默认不通知;notifyOnError 开启时这五种都通知(blocked、interrupted 自 DSH 0.1.5 起提供) | | 等待授权 | approval/asked | 任务运行中需要用户批准;子代理的授权同样提醒 | | 需要回答 | tool/call = ask_user_question | 暂停等待用户作答时提醒;正文带问题文本 | | 授权结果 | approval/decided | 不通知(授权决策须回主界面操作),仅用于摘除待办记录 |

兼容性

| 依赖 | 说明 | |---|---| | DSH 版本 | 面向 0.2.0-rc.1 开发与验证。peerDependencies 声明 ^0.2.0-rc.1,可直接通过 DSH 的插件兼容性检查(evaluatePluginCompatibility 只校验 @deepseek-ai/dsh* peer 与运行时版本的 semver 匹配),不豁免、不报警告。0.1.5-rc.2 及更早版本不适用 | | profile | 需要 web profile。webServer 与 webRuntime 由 web bundle 提供,装进 headless / acp / sdk profile 时该行会永久停在 PENDING(不报错,也不工作) |

0.2.0 迁移要点(v0.4.0)

| 变化 | 本插件的适配 | |---|---| | peer 版本范围 | 4 个 @deepseek-ai/dsh-* peer 从 ^0.1.5-rc.2 升到 ^0.2.0-rc.1(^0.1.5-rc.2 展开为 >=0.1.5-rc.2 <0.2.0-0,天然不匹配 0.2.0-rc.1,会触发启动跳过 + 预检禁用 + 安装拒绝三层阻断) | | settings.register() 被删除 | 改为导出 Config = PrefsSchema(Cordis Loader 模型);设置读写走 settings.describe()/update(),命名空间是 profile entry id(task-notify,必须与 cordis.patch.yml 的 id 一致) | | 表单只收录 .volatile() 字段 | 7 个配置字段全部加 .volatile()——否则 describe() 不返回本插件、update() 报 no volatile fields | | volatile 字段热更新不重挂载 fiber | 偏好改为事件发生时现读 describe()(apply 捕获的启动配置会过期),读不到时回退启动配置 | | 声明 Config 后设置页自动生成原生表单 | settings.configure({ auto: false }) 抑制原生页,沿用自定义「任务通知」区块,避免重复入口 | | schema 库 | 改用 DSH 维护的 @deepseek-ai/schemastery(npm schemastery 没有 .volatile()) |

安全设计

  • 所有 /task-notify/api/* 路由经过 Host 头信任围栏(loopback / webRuntime.trustedHosts),与 /api 网关同一套校验
  • 插件只读会话日志,不修改任何 DSH 数据
  • 通知内容截断(maxBodyChars),无敏感信息外泄

📁 项目结构

dsh-task-notify/
├── package.json           # dsh.client 声明 + 双端 exports + bundle patch
├── cordis.patch.yml       # 挂载声明(dsh plugin add 自动识别)
├── tsconfig.json          # 开发类型检查
├── tsconfig.build.json    # 构建编译(host 端 tsc → lib/)
├── tsdown.config.ts       # client bundle 打包(__ModuleLoader__ 格式)
├── README.md
├── DISTRIBUTE.md          # 发布与安装指南
└── src/
    ├── index.ts           # host 端:订阅 turn/end → node-notifier 弹窗
    ├── config.ts          # schemastery 配置 schema(7 项)
    ├── context-types.ts   # cordis Context 类型增强
    └── client/
        └── index.tsx      # client 端:设置面板 + 页面可见性上报

🛠️ 开发与构建

pnpm install      # 安装依赖
pnpm typecheck    # tsc --noEmit 类型检查
pnpm build        # tsc(host) + tsdown(client) → lib/
pnpm watch        # tsdown --watch(client 热重载)
pnpm pack         # 生成可分发 tarball

构建产物

| 产物 | 说明 | |---|---| | lib/index.js | host 端(Node,ESM) | | lib/client.js | client 端 bundle(window.__ModuleLoader__.load 格式,供浏览器加载) | | lib/*.d.ts | 类型声明 |

发布到 npm

# 改 package.json version → 0.1.x
npm publish

❓ 常见问题

硬刷新浏览器(Ctrl/Cmd+Shift+R)。client 端改动不需要重启 DSH。

按顺序排查:

  1. 页面是否在前台?默认 onlyWhenBlurred: true,页面可见时故意不弹(防打扰)——切后台再试,或到设置页关掉该项
  2. 系统通知权限?Windows「设置 → 系统 → 通知」允许来自 PowerShell/终端的通知;macOS「系统设置 → 通知」
  3. 检查设置页「任务通知」是否启用了总开关

正常现象。@deepseek-ai/* 由 DSH 运行时提供(不在 profile 的 node_modules 里),pnpm 在 profile 层检查不到所以告警,不影响运行——官方 dsh-better-sidebar 安装时同样如此。

node-notifier 在 Windows 走 PowerShell toast 脚本,首次可能被 SmartScreen 拦截,放行一次即可;插件内置回退(msg.exe),实在不行会在会话日志输出 [dsh-task-notify] 警告。

默认不弹(sessions: top-level 跳过 delegationDepth > 0 的子代理会话)。改为 all 则所有会话都通知。


📄 许可证

MIT


dsh-task-notify · 让每一次任务完成都不被错过