Skip to content

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 通知

npm version license DSH Plugin Node version

GoodAndReady Showcase

🇬🇧 English🇨🇳 中文说明🇷🇺 Русский

如果您喜欢这个插件,请在 GitHub 上为它点亮 Star — 这能让我知道插件对您有用,并鼓励我继续开发和维护它。

🐛 如果您发现 Bug 或希望增加功能,请使用任意语言在 GitHub 上提交 Issue — 我会评估您的建议,并在后续版本中实现有价值的改进。

概述 / 问题

DeepSeek Harness 已经知道回合何时完成、失败或等待审批。没有本插件时,这些事件只留在会话里。如果你同时打开多个并行会话或切换到了其他应用,不得不频繁切回窗口手动查看状态。

本插件通过四个层级全面覆盖通知场景:

  1. 音频提示音 (Web Audio):使用浏览器内置 Web Audio API 合成双音五声音阶提示音,在任务完成、出错或等待审批时轻柔提示,无需外部音频文件。
  2. 跨会话屏幕横幅 (In-App Toasts):在界面上方显示浮动通知卡片,带有交互式**“跳转至会话”**按钮,可一键切换到触发事件的目标会话。
  3. 桌面 / 系统级通知 (OS Push):通过 HTML5 Notification API 触发 Windows、macOS、Linux 及 DSH 桌面端系统原生通知,点击自动聚焦窗口并跳转会话。
  4. 远程 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/endreason.kind === 'completed'task_done
  • 其他 turn/end 原因 → error
  • approval/askedapproval_requested
  • 通过 Cordis webServer 服务向已连接的前端客户端提供实时 SSE 事件流(GET /dsh-plugin-notify/events)。
  • 解析 webhooks.*:遗留 http(s):// URL(弃用警告)→ Credentials resolveprocess.env[name]
  • 使用 AbortSignal.timeout(timeoutMs)(默认 5000 ms)。POST 失败只记录,不重试,不阻塞 agent 循环。
  • 可选免打扰窗口(HH:MM,支持跨夜)。事件仍会观察;Webhook、提示音和本机弹窗会跳过。
  • excludeSessionPrefixes 会跳过 id 匹配前缀的会话。

客户端(lib/client.js

  • 原生设置卡片:settings.plugin.item
  • Web Audio API 双音提示音合成器,支持 task_doneerrorapproval_requested,附带“测试声音”按钮。
  • 跨会话浮动 Toast 管理器,支持跳转会话及“测试通知”按钮。
  • HTML5 原生桌面通知集成与权限申请。
  • 实时 SSE 订阅器,支持指数退避自动重连及可选的 notifyBackgroundOnly 过滤。
  • 快照状态 loading / unavailable / ready
  • 保存会写入全部字段并列出失败项。
  • 语言包只有 enzh。俄语界面由 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.jslib/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