dsh-plugin-notify
Verified@goodandready/dsh-plugin-notify · v0.3.1 · MIT · Web UI
DSH plugin: audio chimes, cross-session toasts, desktop push, and IM webhooks for turn completion, errors, and approvals.
Install
dsh plugin add @goodandready/dsh-plugin-notify Confirm the layer applied with dsh --profile default --dump-config — see the install guide.
Source
Tags
Readme
📦 @goodandready/dsh-plugin-notify
回合完成、出错、等待审批时发送远程 IM Webhook 通知
🇬🇧 English • 🇨🇳 中文说明 • 🇷🇺 Русский
|
⭐ 如果您喜欢这个插件,请在 GitHub 上为它点亮 Star — 这能让我知道插件对您有用,并鼓励我继续开发和维护它。
🐛 如果您发现 Bug 或希望增加功能,请使用任意语言在 GitHub 上提交 Issue — 我会评估您的建议,并在后续版本中实现有价值的改进。 |
概述 / 问题
DeepSeek Harness 已经知道回合何时完成、失败或等待审批。没有本插件时,这些事件只留在会话里。如果你同时打开多个并行会话或切换到了其他应用,不得不频繁切回窗口手动查看状态。
本插件通过四个层级全面覆盖通知场景:
- 音频提示音 (Web Audio):使用浏览器内置 Web Audio API 合成双音五声音阶提示音,在任务完成、出错或等待审批时轻柔提示,无需外部音频文件。
- 跨会话屏幕横幅 (In-App Toasts):在界面上方显示浮动通知卡片,带有交互式**“跳转至会话”**按钮,可一键切换到触发事件的目标会话。
- 桌面 / 系统级通知 (OS Push):通过 HTML5
Notification API触发 Windows、macOS、Linux 及 DSH 桌面端系统原生通知,点击自动聚焦窗口并跳转会话。 - 远程 IM Webhook:向飞书、企业微信、钉钉、Slack、Discord 或自定义 HTTP 接口投递 JSON 负载。Webhook URL 作为机密安全保存在 DSH 凭据中。
架构
graph TD
A[DSH session/event] --> B[plugin-notify host]
B -->|credential name| C[Credentials service]
C -->|webhook URL| B
B -->|POST JSON| D[Feishu / WeCom / DingTalk / Slack / Discord / custom]
B -.->|macOS only| E[osascript notification]
B -->|SSE stream: /dsh-plugin-notify/events| F[Client Listener lib/client.js]
F -->|Web Audio API| G[音频提示音]
F -->|DOM overlay| H[跨会话屏幕横幅]
F -->|Notification API| I[系统桌面通知]
J[设置卡片] -->|参数配置| B
功能说明
宿主(lib/index.js)
- 订阅
session/event。 turn/end且reason.kind === 'completed'→task_done。- 其他
turn/end原因 →error。 approval/asked→approval_requested。- 通过 Cordis
webServer服务向已连接的前端客户端提供实时 SSE 事件流(GET /dsh-plugin-notify/events)。 - 解析
webhooks.*:遗留http(s)://URL(弃用警告)→ Credentialsresolve→process.env[name]。 - 使用
AbortSignal.timeout(timeoutMs)(默认 5000 ms)。POST 失败只记录,不重试,不阻塞 agent 循环。 - 可选免打扰窗口(
HH:MM,支持跨夜)。事件仍会观察;Webhook、提示音和本机弹窗会跳过。 excludeSessionPrefixes会跳过 id 匹配前缀的会话。
客户端(lib/client.js)
- 原生设置卡片:
settings.plugin.item。 - Web Audio API 双音提示音合成器,支持
task_done、error与approval_requested,附带“测试声音”按钮。 - 跨会话浮动 Toast 管理器,支持跳转会话及“测试通知”按钮。
- HTML5 原生桌面通知集成与权限申请。
- 实时 SSE 订阅器,支持指数退避自动重连及可选的
notifyBackgroundOnly过滤。 - 快照状态
loading/unavailable/ready。 - 保存会写入全部字段并列出失败项。
- 语言包只有
en和zh。俄语界面由dsh-russian-lang在运行时提供。 - 样式标签带
data-dsh-plugin="dsh-plugin-notify"。
安装
本包为私有包(GitHub Packages)。在具备仓库访问权限后:
dsh plugin --profile web add @goodandready/dsh-plugin-notify
重启 web 配置以便加载客户端。然后打开 设置 → 插件 → Notify。
配置
把每个 Webhook URL 放到 设置 → 凭据。在插件卡片里只填写凭据名称。
- id: plugin-notify
name: '@goodandready/dsh-plugin-notify'
config:
enableSound: false
enableToasts: false
enableDesktopNotifications: false
notifyBackgroundOnly: false
webhooks:
feishu: NOTIFY_FEISHU_WEBHOOK
wecom: NOTIFY_WECOM_WEBHOOK
dingtalk: NOTIFY_DINGTALK_WEBHOOK
slack: NOTIFY_SLACK_WEBHOOK
discord: NOTIFY_DISCORD_WEBHOOK
custom: NOTIFY_CUSTOM_WEBHOOK
events: [task_done, error, approval_requested]
local: true
timeoutMs: 5000
dnd:
start: ''
end: ''
includeSession: true
includeDuration: true
excludeSessionPrefixes: []
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
enableSound |
boolean | false |
回合完成、出错或等待审批时播放 Web Audio 合成提示音(默认关闭,需显式开启)。 |
enableToasts |
boolean | false |
跨会话弹出屏幕横幅通知,附带一键跳转按钮(默认关闭,需显式开启)。 |
enableDesktopNotifications |
boolean | false |
系统原生桌面推送(Windows、macOS、Linux、DSH 桌面版,需显式开启并授权)。 |
notifyBackgroundOnly |
boolean | false |
仅当事件发生在非活跃/后台会话时才触发通知。 |
webhooks.* |
string | 空 | 值为 Webhook URL 的凭据名称。空则关闭该通道。 |
events |
string[] | task_done, error, approval_requested |
事件白名单。空则恢复默认三项。 |
local |
boolean | true |
macOS osascript 弹窗;其他平台忽略。 |
timeoutMs |
number | 5000 |
单次请求中止超时。 |
dnd.start / dnd.end |
string | 空 | HH:MM 窗口。相等或非法则关闭免打扰。 |
includeSession |
boolean | true |
在正文追加 Session: …。 |
includeDuration |
boolean | true |
在已知回合开始时间时追加 Duration: …。 |
excludeSessionPrefixes |
string[] | [] |
当 session.id 以任一前缀开头时跳过通知。 |
webhooks.* 中残留的原始 http(s):// 仍会发送,但会给出弃用警告。请迁移到凭据。
消息格式
| 通道 | JSON 正文 |
|---|---|
| 飞书 | { msg_type: 'text', content: { text } } |
| 企业微信 | { msgtype: 'text', text: { content: text } } |
| 钉钉 | { msgtype: 'text', text: { content: text } } |
| Slack | { text } |
| Discord | { content: text } |
| custom | { text, kind, title, sessionId, durationMs, time } |
测试
npm install --no-audit --no-fund --no-package-lock
npm test
pretest 会对 lib/index.js 和 lib/client.js 执行 node --check。随后 node --test test/*.test.mjs。
套件使用 stub fetch 或本地 HTTP 监听器,不会调用真实 IM 服务。真实投递需要你自己的 Webhook。
预期输出:
✔ public package identity matches host, client and patch sites
✔ client locale registration coexists with Russian language pack
✔ client apply does not register ru and can reload after effect dispose
✔ legacy raw webhook URL still posts (compat)
✔ credential ref resolves webhook URL via credentials service
✔ resolveWebhookValue prefers credentials then env
✔ missing credential name does not post
✔ each IM channel posts the expected body shape
✔ recipient HTTP failure does not throw out of the session loop
✔ AbortSignal.timeout is attached to webhook POST
✔ excluded session prefixes suppress notifications
✔ Config schema validates sound, toast, and desktop notification fields with opt-in defaults
✔ SSE route registers on webServer, rejects untrusted requests, and handles trusted stream
✔ client does not register settings.section slot (issue #16 fix)
✔ deliveries and warnings are routed through ctx.logger without console calls (issue #22 fix)
ℹ tests 15
ℹ pass 15
ℹ fail 0
许可证
MIT © GooDAnDReaDY
变更历史
完整更新日志详见 CHANGELOG.md。