
Security News
Rust 1.100 Will Add Dependency Cooldowns to Cargo
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.
dsh-task-notify
Advanced tools
DSH(DeepSeek Harness)插件:任务完成 · 系统弹窗通知
模型回答完你的请求,系统立即弹出原生通知——切到别的窗口刷剧、写代码时,再也不怕错过 DSH 的完成信号。
系统通知 · 零侵入 · 防打扰 · 可配置
| 特性 | 说明 |
|---|---|
| 🪟 原生系统通知 | 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 |
dsh plugin --profile web add dsh-task-notify
dsh plugin add自动完成三步:① 安装依赖(node-notifier、schemastery自动带上);② 检测dsh.bundle声明自动挂载;③ 无需手动改任何配置。
cd ~/.dsh/profiles/web
pnpm add "dsh-task-notify@link:<插件目录绝对路径>"
dsh plugin --profile web remove dsh-task-notify
dsh web本仓库通常以 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 设置 → 「任务通知」区块,可视化调整全部选项。
~/.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.1-alpha.1+ 开发与验证(当前实测 0.2.1-alpha.2)。peerDependencies 声明 ^0.2.1-alpha.1,可直接通过 DSH 的插件兼容性检查(evaluatePluginCompatibility 只校验 @deepseek-ai/dsh* peer 与运行时版本的 semver 匹配,且以 includePrerelease 判定),不豁免、不报警告。0.2.0-rc.x 及更早版本不适用 |
| profile | 需要 web profile。webServer 与 webStartup 由 web bundle 提供,装进 headless / acp / sdk profile 时该行会永久停在 PENDING(不报错,也不工作) |
| 变化 | 本插件的适配 |
|---|---|
Web profile 删除 webRuntime 服务 | Cordis fiber 注入一个永不挂载的服务会永久停在 PENDING:apply() 不执行 → 通知全不发、/task-notify/api/* 路由不注册(设置区块读写全废),且不报错。现已改为注入 webStartup(web-startup 行发布),信任围栏读 ctx.webStartup.trustedHosts,字段名与语义不变 |
| peer 版本范围 | 4 个 @deepseek-ai/dsh-* peer 与 7 个同款 devDependency 从 ^0.2.0-rc.1 升到 ^0.2.1-alpha.1——否则 0.2.0-rc.x 会通过兼容性检查却静默失效(这正是 v0.4.0 在 0.2.1 上的实际故障) |
| 同步验证 | dsh --profile web --dump-config 可见 web-startup 行与 task-notify 行;重启后 curl -X POST -d '{}' http://127.0.0.1:8080/task-notify/api/settings.get 应返回 {"ok":true,...}(PENDING 时是 405) |
| 变化 | 本插件的适配 |
|---|---|
| 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 / webStartup.trustedHosts),与 /api 网关同一套校验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 | 类型声明 |
# 改 package.json version → 0.1.x
npm publish
硬刷新浏览器(Ctrl/Cmd+Shift+R)。client 端改动不需要重启 DSH。
按顺序排查:
onlyWhenBlurred: true,页面可见时故意不弹(防打扰)——切后台再试,或到设置页关掉该项正常现象。@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 则所有会话都通知。
dsh-task-notify · 让每一次任务完成都不被错过
FAQs
DSH task completion system notifications (host-side node-notifier)
We found that dsh-task-notify demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 1 open source maintainer collaborating on the project.

Security News
Rust 1.100 will add opt-in dependency cooldowns to Cargo, giving security scanners and maintainers time to catch malicious crate releases.

Security News
Cloudflare is acquiring Deno’s team, which will provide another year of bug fixes and security updates before ending support for the runtime.

Security News
Anthropic’s free OSS Scanner uses Mythos and other Claude models to find open source vulnerabilities and send maintainers reports with proposed fixes.