notifier

by JohnXu22786

0 通知与集成github未核验到 manifest 社区精选 收录于 08-16

dsh-chime:DeepSeek Harness桌面信号插件 — 任务完成、等待审批或出错时桌面通知和音效

dsh-chime: desktop signal plugin for DeepSeek Harness — desktop notifications and tones when a task finishes, waits for approval, or errors out

安装

dsh plugin --profile web add github:JohnXu22786/notifier

GitHub 源码安装:首次需按提示配置 allowBuilds 构建授权后重试

安装与环境配置指引、插件开发教程见 DSH 中文社区文档 ↗

安装即在你的机器上以你的权限运行第三方代码——它可读写文件、使用凭据、访问网络,DSH 的工具审批不会为插件代码加沙箱。「检测到 manifest」仅代表发现 dsh.bundle / dsh.plugin 清单,不构成兼容性或安全审查;安装前请审阅源码,不熟悉的插件先在不含密钥的环境试用。

README

目录

English

dsh-chime

在 dsh(DeepSeek Harness)上运行的桌面提醒信号插件:任务完成、等待批准、运行出错时,在 dsh 所在机器的桌面弹出系统通知,并按需播放提示音——不用一直盯着终端或网页界面。

零运行时依赖:不需要 npm 通知库,直接调用操作系统自带能力(macOS 的 osascript/afplay、Linux 的 notify-send/音频后端、Windows 的 PowerShell 原生组件)。


目录

设计理念

「只在需要人回来的时候提醒,不为每个微事件打扰」是插件的核心原则。dsh 每次生成响应、每次工具调用都会产生大量事件,如果全部弹窗,提醒就变成了噪音。因此 dsh-chime 只提炼三类信号:

信号 含义 默认提示音
done 一个回合完整跑完(生成结束) 完成音
blocked 正在等待真人批准 / 需要人介入 警示音
failed 回合或请求出错 错误音

信号在内部沿一条四段流水线流动,每一段都可以独立配置或关闭:

捕获(bridge 监听 dsh 事件)
  → 裁定(policy:总开关 → 种类开关 → 免打扰时段 → 频率限制)
  → 渲染(templates:标题/正文模板)
  → 分发(channels:桌面通知 / 提示音 / 终端响铃)

特性

  • 三类信号独立控制:完成 / 批准 / 报错可分别开关、分别定制文案与音效(事件类型过滤)。
  • 跨平台桌面通知:macOS、Windows、Linux 原生实现,无需任何第三方包。
  • 可定制提示音:系统音效或自定义音频文件,支持音量;也可整体静音。
  • 自定义文案模板:标题与正文均支持占位符(会话、项目、耗时、错误摘要等)。
  • 自定义图标:桌面通知图标可指定图片文件(Windows 需 .ico,Linux 任意格式)。
  • 免打扰时段(hush):支持跨午夜窗口(如 22:00–08:00)与按星期生效。
  • 频率限制(cadence):同类信号最小间隔 + 全局突发上限,防刷屏。
  • 审批宽限期:审批请求若被自动裁决(策略拒绝/无应答者),不会打扰;只有确实在等真人时才提醒。
  • 会话耗时统计:完成通知里带上本回合耗时。
  • 命令行自检:不启动 dsh 也能试响、探测通道可用性、查看生效配置。

快速开始

前置条件:Node.js ≥ 22.19(dsh 的运行要求),已装好 dsh CLI 并初始化过 profile。

# 在包含本目录的位置执行;link: 指向本地目录
dsh plugin --profile web add link:/绝对/路径/notifier

或者发布到 npm 后:

dsh plugin --profile web add dsh-chime

验证接入:

# 配置树中应出现 # == dsh-chime 层
dsh --profile web --dump-config

# 启动 dsh,观察日志中的 [chime] 行
dsh --profile web

试响(不需要 dsh 运行):

chime probe          # 检查各通道可用性
chime ping done      # 弹一条「任务完成」测试通知 + 提示音

注意:通知发生在 dsh 服务进程所在的机器上。若 dsh 运行在远程服务器,提醒会出现在服务器桌面,而不是你的本地桌面。

在 DSH 中安装

直接用 dsh 插件命令从 GitHub 仓库安装:

dsh plugin --profile demo add github:JohnXu22786/notifier

安装后插件会以配置层(dsh.bundle.patch → cordis.patch.yml)注册自身,下次启动 dsh 时即开始弹出桌面通知。卸载:

dsh plugin --profile demo remove notifier

接入说明(给 dsh 的加载机制)

dsh 的插件体系是 bundle(包)+ patch(配置层) 双层模型。本插件包包含三个要素:

1. bundle 声明(package.json)

{
  "name": "dsh-chime",
  "type": "module",
  "main": "dist/index.js",
  "dsh": { "bundle": { "patch": "./cordis.patch.yml" } }
}

dsh.bundle.patch 告诉 dsh:这个包贡献一个配置层。没有这个字段的包只会被当作普通依赖,不会激活成插件。

2. 配置层(cordis.patch.yml)

- insert:
    - id: chime
      name: dsh-chime

insert 把一行插件配置插入 profile 的配置树,id 是行标识(全局唯一,可被上层 patch 覆盖),name 指向包名,由 Node 模块解析加载实际代码。

3. 入口文件(dist/index.js)

按 dsh 插件入口约定导出两个成员:

export const name = 'dsh-chime';                 // 插件名
export function apply(ctx, config) { /* ... */ } // 插件主体
  • apply 在配置就绪后被调用,ctx 是 Cordis 上下文,config 是本包插件行的 config 字段。
  • 插件只使用 ctx.on() 订阅事件、ctx.effect() 注册卸载清理,不注入任何服务,因此不依赖 dsh 内部服务的版本细节。
  • 所有注册都是可逆副作用:dsh 卸载/热重载插件时会自动撤销监听,挂起的审批定时器也会经 ctx.effect 注册的清理函数被一并清除。
  • 配置被修改时会热重载插件实例(dsh 的 HMR),无需重启。

接入注意事项

  • dsh 目前处于开发者预览期,官方声明事件名与接口可能发生不兼容变更。事件映射集中在 src/bridge.ts,事件契约声明在 src/bridge.ts 的头部注释中;若未来事件改名,只需同步更新该文件。
  • 插件不依赖任何运行时第三方包,dist/ 是编译产物,已被 .gitignore 忽略且未提交到仓库;从源码目录直接安装(link:)前请先执行 npm run build。npm 在日常安装(dsh plugin add github:JohnXu22786/notifier)时会通过 prepare 脚本自动构建。

事件与信号映射

dsh 事件 信号 说明
session/event(turn/start) — 记录回合开始时刻,用于耗时统计
session/event(turn/end,reason 正常结束) done 回合完整跑完
session/event(turn/end,reason.kind = 'error') failed 回合以错误收尾(detail 取 reason.error)
session/event(turn/end,reason.kind = 'aborted') — 用户主动中止,不提醒
session/event(approval/asked) blocked(延迟判定) 审批请求挂起,宽限期(bridge.decisionGraceMs)内若收到 approval/decided(自动裁决/快速应答)则不打扰;超时未决才发信号
agent/error failed 回合/步骤出错(emit 事件,载荷可能不含 agent 字段;会话不可知时按全局窗口去重,避免与随后 turn/end 的 failed 重复提醒)
bridge.attentionFrom 中列出的事件 blocked 逃生舱:dsh 事件名演进或自定义事件时,把额外事件视为「等待人」

session/event 是持久会话事件流,turn/*、approval/* 都是其中的事件类型;agent/error 是实时事件。信号内容全部防御式提取(字段缺失时使用占位文案),任何事件畸形都不会让插件抛错。

配置

配置来源按优先级从低到高:

  1. 内置默认值(见 src/config.ts 的 DEFAULT_CONFIG)——插件总是先与内置默认值深层合并,因此任意来源只需写想改的键。

  2. 插件行 config 字段——用户在自己 profile 层的 cordis.patch.yml 里按同一行 id(chime)覆盖。注意 dsh 的 patch 层语义:后一层会整体替换前一层的 config(不做深层合并),但保留行的 name。对本插件而言,行的名字由 bundle 自带,用户覆盖行只需给出 id 与要设置的键:

    $DSH_HOME/profiles/<profile名>/cordis.patch.yml:

    - id: chime
      config:
        hush:
          armed: true
          from: '22:00'
          to: '08:00'
    

    配置被修改后会触发插件热重载(HMR),无需重启 dsh。

  3. 配置文件(机器级覆盖,可跨 profile 共享):$DSH_HOME/chime.config.json,或通过环境变量 DSH_CHIME_CONFIG 指定其他路径。支持 JSONC(注释、行尾逗号)。文件覆盖在行配置之上,同样按键深层合并:

    // $DSH_HOME/chime.config.json
    {
      "hush": { "armed": true, "from": "22:00", "to": "08:00" },   // 只改这几个键即可
      "kinds": { "blocked": { "tone": { "mode": "file", "file": "~/sounds/urgent.wav" } } }
    }
    

    配置有误时插件拒绝加载并打印具体原因(失败要响亮,不静默降级)。

完整配置项

{
  "armed": true,                    // 总开关
  "channels": {
    "desktop": true,                // 桌面通知通道
    "tone": true,                   // 提示音通道
    "bell": false,                  // 终端响铃(BEL,仅交互式终端有效)
    "toneProgram": "auto"           // Linux 音效后端:auto | canberra | paplay | aplay | ffplay
  },
  "lingerMs": 8000,                 // 通知展示时长(毫秒)
  "kinds": {
    "done": {
      "armed": true,                // 完成信号开关
      "title": "任务完成",          // 标题模板
      "message": "会话 {session} 已完成,耗时 {elapsed}",  // 正文模板
      "icon": "",                   // 自定义图标路径(Windows 需 .ico)
      "urgency": "normal",          // low | normal | critical(Linux 生效)
      "tone": {
        "mode": "system",           // none | system | file
        "name": "Glass",            // macOS 系统音效名 / Linux canberra 主题 id
        "file": "",                 // 自定义音效文件(mode=file 时生效;Windows 仅 .wav)
        "volume": 60                // 音量 0-100(macOS/Linux 部分后端生效)
      }
    },
    "blocked": { /* 等待批准:默认 title「等待批准」,urgency critical */ },
    "failed":  { /* 运行出错:默认 title「运行出错」,urgency critical */ }
  },
  "cadence": {
    "minIntervalMs": 5000,          // 同类信号最小触发间隔
    "burstLimit": 8,                // 突发上限:窗口内最多条数
    "burstWindowMs": 60000          // 突发统计窗口
  },
  "hush": {
    "armed": false,                 // 免打扰时段开关
    "from": "22:00",                // 开始 HH:MM(本地时区)
    "to": "08:00",                  // 结束 HH:MM,支持跨午夜
    "weekdays": []                  // 生效星期 [0=周日…6=周六],空=每天
  },
  "bridge": {
    "decisionGraceMs": 600,         // 审批宽限期(毫秒)
    "attentionFrom": []             // 额外视为「等待人」的 dsh 事件名
  }
}

文案占位符

标题与正文模板支持以下占位符(未提供的占位符会原样保留,便于发现拼写错误):

占位符 含义
{kind} 信号类别中文名(完成 / 等待批准 / 出错)
{session} 会话 id
{project} 项目名(dsh 提供时才有值)
{subject} 主题(如发起审批的工具名、错误摘要)
{detail} 细节(审批原因、错误消息)
{elapsed} 本回合耗时(done 信号,以及 turn/end 来源的 failed 信号)
{source} 触发信号的事件名
{time} 触发时刻 HH:MM

命令行工具

包自带 CLI(npm 全局安装后为 chime,也可 node dist/cli.js):

chime ping [done|blocked|failed]   发送一条测试信号(试响)
                                   (退出码:0=至少一通道成功,1=无启用通道或全部失败,2=被策略拦截/用法错误)
chime probe                        自检通道可用性与配置来源
chime config                       打印生效配置(JSON)
chime help                         帮助

CLI 与插件共享同一套配置加载逻辑(默认值 + 配置文件;注意 CLI 不读取 dsh 插件行的 config,因为它在 dsh 之外运行),因此 chime probe 验证的是插件实际会使用的系统通道。

平台与系统依赖

平台 桌面通知 提示音(system) 提示音(file) 图标 音量
macOS osascript(系统自带) afplay + /System/Library/Sounds/*.aiff afplay + 任意格式 不支持(系统通知无图标位) afplay -v
Windows PowerShell + NotifyIcon 气泡(系统自带) winmm PlaySound 系统音效事件 winmm PlaySound,仅 .wav .ico 文件 不支持
Linux notify-send(需安装 libnotify-bin / libnotify) canberra-gtk-play 主题音 paplay → aplay → ffplay → canberra(-f) 探测链 任意图片格式 paplay/ffplay
  • 各平台通道都有可用性自检(chime probe),不可用时会在日志中给出原因,不影响其他通道。
  • Linux 的 system 音效需要 canberra-gtk-play(GNOME 桌面通常自带),kinds.<类别>.tone.name 可指定 canberra 主题 id(如 dialog-warning、complete);file 音效按 paplay(PulseAudio)→ aplay(ALSA)→ ffplay(ffmpeg)→ canberra-gtk-play -f 兜底的顺序探测,可用 channels.toneProgram 强制指定。
  • macOS 系统音效名可选:Basso、Blow、Bottle、Frog、Funk、Glass、Hero、Morse、Ping、Pop、Purr、Sosumi、Submarine、Tink。
  • Windows 桌面通知为托盘气泡样式(Windows 10/11 会以通知中心样式展示)。无桌面会话的环境(服务账户、SSH 无桌面)中气泡可能不显示,属系统行为。

故障排查

症状 检查
完全没有提醒 chime probe 看通道是否可用;确认 armed 与 kinds.*.armed 未关;确认不在免打扰时段;看 dsh 日志中 [chime] 行是 [已发] 还是 [拦截]
只有桌面通知没有声音 kinds.<类别>.tone.mode 是否被置为 none;Linux 用 channels.toneProgram 换后端;自定义文件是否被播放器支持(Windows 仅 wav)
审批请求没提醒 策略为 never 或没有应答者时会自动裁决,宽限期内 approval/decided 到达即不打扰(这是预期行为);人工应答极慢时可调大 bridge.decisionGraceMs
报错没提醒 failed 信号来自 agent/error 与 turn/end(reason.kind='error')两条路径,均会经会话级去重合并为一条;若 dsh 版本改动了事件名或载荷结构,更新 src/bridge.ts 中的提取逻辑(或把新事件名加入 bridge.attentionFrom,会作为 blocked 处理)
启动时报 duplicate loader entry id 通常是同一插件在 profile 层与 bundle 层被重复挂载(例如旧式手动 insert 行与 dsh plugin add 的 bundle 行同时存在),删除旧的手动行即可
通知刷屏 调大 cadence.minIntervalMs 或调小 burstLimit;也可直接关闭 done 类信号
配置改完没生效 配置文件改完需触发插件热重载(dsh HMR);确认没有语法错误(有错会拒绝加载并打印原因)

开发

npm install     # 安装开发依赖(typescript、tsx、类型包)
npm test        # 运行单元测试(node:test + tsx,无测试框架依赖)
npm run build   # 编译到 dist/

代码结构:

src/
  index.ts      入口(name / apply,装配流水线)
  bridge.ts     事件桥:dsh 事件 → 信号(事件契约与映射集中在此)
  pipeline.ts   流水线:裁定 → 渲染 → 分发
  policy.ts     裁定:cadence(频率)与 hush(免打扰)
  config.ts     配置:默认值、JSONC 解析、合并、严格校验
  templates.ts  文案模板渲染与耗时格式化
  memory.ts     会话记忆(回合开始时刻,带上限)
  desktop.ts    桌面通知通道(三平台)
  tone.ts       提示音通道(三平台)
  runner.ts     子进程执行器(命令探测、超时强杀、PowerShell 编码调用)
  types.ts      类型定义
  cli.ts        命令行入口
test/           单元测试(node:test)

许可

基于 MIT License 发布。

原始 README: https://github.com/JohnXu22786/notifier/blob/main/README.zh.md ↗

同类插件

查看全部 →
通知与集成alvinunreal

dsh

将 DeepSeek Harness 的生命周期状态、错误与审批请求,桥接到本地运行的 OpenPets 桌面伙伴。

查看详情
1081github+08-21
通知与集成tencent-connect

dsh-qqbot

让 QQ Bot 接入 DeepSeek Harness(dsh)的官方插件

查看详情
55github+08-17
通知与集成omdsh-dev

dsh-open-in-vscode

从 Web GUI 一键在 VS Code 中打开工作区目录。

查看详情
39github+08-13
通知与集成omdsh-dev

dsh-notification

回合完成桌面通知,按结果分控 + 关键词过滤。

查看详情
38github+08-13
通知与集成THEWOLFWALKER

dsh-notifier

DSH 统一通知推送与远程控制:一个 `notify()` API 打通 25+ 渠道(Telegram / 钉钉 / 飞书 / 企业微信 / QQ 机器人 / WxPusher / PushPlus / Server 酱 / Bark / Discord / Slack / ntfy / webhook 等),timeSensitive / active / passive 分级路由并重试;五通道反向审批(Telegram 按钮 / 飞书卡片 / QQ / WxPusher / 微信 iLink);QQ/钉钉/飞书官方扫码登录;本地 Web 管理台;多 agent 路由;系统桌面通知——以及**手机指挥中心**:在手机上发 `!status` / `!stop` / `!retry` 遥控 agent,通知带可操作按钮(查看结果 / 重试 / 日志,点击回调 agent)。密钥脱敏、工具限流、零运行时依赖。

查看详情
27github+08-16
通知与集成wzj998

chatccc

飞书(Lark)或微信(WeChat)聊天控制 DeepSeek Harness / Claude Code / Cursor / Codex / CCC Agent

查看详情
22github+08-23