Repository navigation
Releases: GooDAnDReaDY/dsh-plugin-notify
Releases · GooDAnDReaDY/dsh-plugin-notify
Release list
v0.4.8
English
Added
- Interactive Question and Plan Review Notifications (#5): Added
question_requestedevent kind (in default events) observing Cordis waterfalluser-questions/requestas a passive observer (return next()). Accurately discriminates plan-mode review cards (exit_plan_mode,intent.kind === 'plan-review') with summary'Plan ready for review'and generic questions (ask_user_question) with question header/text. Dispatches to all configured channels (SSE, IM webhooks, Web Push, audio chimes, toasts, desktop push) with full subagent and prefix filtering support.
简体中文
新增
- 用户提问与计划审阅通知 (#5):新增
question_requested事件类型(默认启用),作为被动观察者(return next())监听 Cordis waterfalluser-questions/request。准确识别计划模式审阅卡片(exit_plan_mode,intent.kind === 'plan-review',摘要为“Plan ready for review”)以及通用问题(ask_user_question,携带标题与问题文本)。支持全部通知通道(SSE、IM Webhooks、Web Push、提示音、横幅 Toast、系统桌面推送),并完整继承会话前缀排除与子代理过滤逻辑。
Русский
Добавлено
- Уведомления для вопросов пользователю и ревью плана (#5): добавлен тип события
question_requested(включён в события по умолчанию), прослушивающий Cordis waterfalluser-questions/requestв качестве пассивного наблюдателя (return next()). Точно распознаёт карточки ревью плана (exit_plan_mode,intent.kind === 'plan-review') со сводкой'Plan ready for review'и стандартные вопросы пользователю (ask_user_question) с текстом/заголовком вопроса. Поддерживает все каналы доставки (SSE, вебхуки, Web Push, звуковые сигналы, тосты, десктопные пуши) с фильтрацией субагентов и исключённых префиксов сессий.
v0.4.7
English
Added
- Subagent Session Filtering & Noise Suppression (#4): Added
notifySubagentsoption (boolean, defaultfalse) in configuration schema and settings card UI. Suppresses turn completion (turn/end) and approval (approval/asked) notifications from delegated subagents (such asdsh-mnemonand background subagent runs). Subagents are recognized by session metadata (origin === 'subagent',header.parentSession,header.parentId,isSubagent,agentType) and bare UUID format, while main interactive user conversations (session-<uuid>) continue to notify as expected.
简体中文
新增
- 子代理会话过滤与静音 (#4):在配置 Schema 和设置卡片中新增
notifySubagents选项(布尔值,默认false)。自动过滤并抑制来自委托子代理(例如dsh-mnemon及后台子代理任务)的回合完成(turn/end)和等待审批(approval/asked)通知。系统通过会话元数据(origin === 'subagent'、header.parentSession、header.parentId、isSubagent、agentType)以及纯 UUID 格式准确识别子代理,同时完全保留主交互会话(session-<uuid>)的正常通知。
Русский
Добавлено
- Фильтрация и подавление шума от субагентов (#4): добавлена опция
notifySubagents(boolean, по умолчаниюfalse) в схеме настроек и карточке интерфейса. Подавляет уведомления о завершении хода (turn/end) и ожидании подтверждения (approval/asked) для вспомогательных субагентов (например,dsh-mnemonи фоновых запусков задач). Субагенты определяются по метаданным сессии (origin === 'subagent',header.parentSession,header.parentId,isSubagent,agentType) и формату чистого UUID, сохраняя штатные уведомления для основных интерактивных сессий пользователя (session-<uuid>).
v0.4.6 [Security: Web Push SSRF Protection]
English
Security
- Web Push Endpoint Allowlist & SSRF Protection: Enforce strict validation of subscription endpoints against canonical Web Push gateways (Google FCM, Mozilla Autopush, Apple Web Push, Microsoft WNS) with optional
webPush.allowedHosts; reject loopback, private IPv4/IPv6, link-local, userinfo, and non-standard ports. - Push Endpoint Masking in Logs: Mask subscription endpoint tokens in server logs (
maskEndpoint) and delivery error messages to prevent token exfiltration. - Subscription Capacity Bound: Constrain total stored subscriptions (max 100) to prevent state file exhaustion DoS.
- Dead & Disallowed Endpoint Pruning: Prune any invalid or unapproved endpoints during
deliverWebPushwithout dispatching requests.
简体中文
安全性
- Web Push 端点白名单与 SSRF 防护:对推送订阅端点实施严格校验,仅允许规范的 Web Push 网关(Google FCM、Mozilla Autopush、Apple Web Push、Microsoft WNS),支持可选的
webPush.allowedHosts;严格拒绝环回、私有 IPv4/IPv6、链路本地地址、凭据以及非标准端口。 - 日志端点脱敏:在服务端日志(
maskEndpoint)和发送错误提示中对订阅端点 Token 进行脱敏,防止凭证泄露。 - 订阅容量限制:限制持久化订阅最大数量(上限 100),防止状态文件资源耗尽。
- 自动清理无效端点:在
deliverWebPush执行期间自动检测并清理未授权或失效的端点,拒绝向其派发请求。
Русский
Безопасность
- Allowlist эндпоинтов Web Push и защита от SSRF: введена строгая валидация эндпоинтов подписки с разрешением только канонических Web Push шлюзов (Google FCM, Mozilla Autopush, Apple Web Push, Microsoft WNS) и поддержкой
webPush.allowedHosts; блокируются loopback, private IPv4/IPv6, link-local адреса, userinfo и нестандартные порты. - Маскирование токенов эндпоинтов в логах: полные URL с токенами подписок маскируются в логах сервера (
maskEndpoint) и текстах ошибок отправки для защиты от утечки данных. - Ограничение емкости подписок: зафиксирован лимит количества активных подписок (максимум 100) для предотвращения исчерпания ресурсов хранилища.
- Очистка недопустимых эндпоинтов: при вызове
deliverWebPushнедопустимые или отклонённые эндпоинты удаляются без выполнения сетевых запросов.
v0.4.5 [DSH v0.2.0-rc.2]
English
Fixed
- Safe Logger Invocations: Guard logger method invocations with
safeLog(ctx, message)binding receiverthis(fn.call(logger, message)) to preventTypeError: this is not a functionin Cordis 0.2LoggerService. - Object Settings Persistence: Decompose non-leaf object configuration fields (
webhooks,dnd,webPush) into individual leaf paths (['webhooks', key]) and save atomically viascope.mutate(ops)with fallback toscope.set, passingdsh-settingsvolatile path validation. - Session Events & Title Cascade: Add
eventsOf(session)supporting append-onlysession.log,session.eventsSnapshot, andsession.snapshotEvents(); addcachedTitle(session)reading projected title cache from disk (storages/session_projcache/sessions/<id>.json), preventing fallback to raw UUIDs. - Session Navigation Priority: Target
uiWorkspace.openSession(sessionId)as the primary navigation service innavigateToSessionwith graceful fallbacks.
简体中文
修复
- 安全的日志记录调用:使用
safeLog(ctx, message)绑定this接收器(fn.call(logger, message)),防止 Cordis 0.2LoggerService抛出TypeError: this is not a function。 - 对象设置持久化:将非叶子对象配置项(
webhooks、dnd、webPush)分解为单独的叶子路径(['webhooks', key]),并通过scope.mutate(ops)原子化保存(兼容scope.set),符合dsh-settings的 volatile 模式校验。 - 会话事件与标题级联:新增
eventsOf(session)支持只追加的session.log、session.eventsSnapshot和session.snapshotEvents();新增cachedTitle(session)从磁盘读取投射的标题缓存(storages/session_projcache/sessions/<id>.json),防止标题回退为原始 UUID。 - 会话导航优先级:在
navigateToSession中优先使用uiWorkspace.openSession(sessionId)作为主导航服务,并保留向下兼容回退。
Русский
Исправления
- Безопасный вызов методов логгера: функция
safeLog(ctx, message)с явной привязкой контекстаthis(fn.call(logger, message)) устраняет падение сTypeError: this is not a functionвLoggerServiceфреймворка Cordis 0.2. - Персистентность объектных настроек: поля-объекты (
webhooks,dnd,webPush) раскладываются на листовые пути (['webhooks', key]) и сохраняются атомарно черезscope.mutate(ops)с фолбэком наscope.set, успешно проходя валидацию volatile-схемыdsh-settings. - Каскад поиска событий и заголовков сессии: функция
eventsOf(session)извлекает события из современных структур (session.log,session.eventsSnapshot,session.snapshotEvents()); функцияcachedTitle(session)читает спроецированный кэш с диска (storages/session_projcache/sessions/<id>.json), предотвращая показ UUID вместо заголовков. - Приоритет навигации к сессии:
navigateToSessionприоритетно используетuiWorkspace.openSession(sessionId)(основной навигатор DSH 0.2) с каскадными фолбэками.
v0.4.4
Fixed
- Client config form lookup (#61): Query \ctx.configForms\ strictly by canonical entry id \plugin-notify\ (\ROW_ID) rather than attempting fallback queries to scoped package name @goodandready/dsh-plugin-notify, fixing unresolvable configuration lookups in the settings panel.
v0.4.3 [DSH v0.1.7-rc.2 / v0.2.0-rc.2]
Fixed
- Host event cleanup (#59): Prune dead listener on non-existent host event \settings/updated\ in \lib/index.js\ (active settings updates remain reliably monitored via \settings/document-updated\ and \loader/volatile-update).
- Client slot registration (#59): Remove dead registration of non-existent client seat \settings.plugin.item\ in \lib/client.js\ (official plugin list page seat \plugins.item\ and row config seat \plugins.row.config\ handle settings cards).
- Web push state path containment (#59): Constrain custom \webPush.stateFile\ paths by resolving relative paths against the DSH home directory instead of returning raw unconstrained strings.
v0.4.2 [DSH v0.1.7-rc.2 / v0.2.0-rc.2]
Fixed
- Request trust enforcement on HTTP/SSE routes (#46): Route SSE and Push subscriptions through \isTrustedRequest\ / \getRequestRejection, ensuring origin and session checks with loopback fallback.
- Webhook error logging diagnostic (#49): Log human-readable channel name instead of truncated webhook URL on POST failure, preventing credential token leakage.
- Multi-instance SSE client isolation (#50): Isolate SSE client sets per plugin lifecycle context on dispose, avoiding cross-instance connection drops on reload.
- Deterministic memory bound on turnStarts map (#51): Enforce deterministic FIFO eviction bound (\maxSize = 100) on \ urnStarts\ map under session bursts.
v0.4.1 [DSH v0.1.7-rc.2 / v0.2.0-rc.2]
Fixed
- Settings registration namespace & Desktop crash protection (#55): Use canonical ENTRY_ID = \plugin-notify' instead of scoped package name in settings.register; wrap call with try/catch logging warning instead of throwing TypeError in DSH Desktop.
- Settings form slot binding (#54): Bind UI settings.plugin.item slot key to ROW_ID (\plugin-notify'), and prioritize ROW_ID in configForms candidates over legacy NS.
- Dynamic settings observation (#48): Make describe settings fallback reactive: observe loader/volatile-update, settings/document-updated, and settings/updated to dynamically refresh settings when edited in UI or external config.
- Config unboxing guarantee (#47): Guarantee getConfig() always unwraps volatile boxes via unwrapConfig(config ?? {}), preventing TypeError during session/event event unboxing.
- DSH 0.2.0-rc.1 clean activation & volatile schema (#42): Guarantee clean activation on DSH 0.2.0-rc.1 when settings.register is absent; confirm all user-facing fields in Config have .volatile() markers.
v0.4.0: Web Push PWA Background Notifications
@goodandready/dsh-plugin-notify v0.4.0
🇬🇧 English
Web Push (PWA) Background Notification Channel
- Background Delivery: Real-time push notifications delivered via W3C Push API & Service Worker (
/dsh-plugin-notify/sw.js), reaching desktop and mobile devices even when all DeepSeek Harness browser tabs are closed. - Instant Deep-Linking: Clicking or tapping the push notification immediately navigates to or opens the triggering session (
?dshNotifySession=<id>). - Smart Away Filtering:
webPush.onlyWhenAwayautomatically suppresses push notifications while a live browser client is connected to the SSE stream. - Zero-Config VAPID: Automatic key generation and persistent storage in
$DSH_HOME/plugin-notify-state.json, with optional environment overrides (DSH_NOTIFY_VAPID_PUBLIC_KEY,DSH_NOTIFY_VAPID_PRIVATE_KEY). - Interactive Card Controls: Native settings card section with device push enrollment, live status, and one-click test push.
- Full Test Coverage: Comprehensive 27 new tests covering VAPID persistence, route security, gating, and delivery (total 48 passing tests).
Special thanks to @tespio for contributing the feature (PR #2)!
🇨🇳 中文说明
Web Push (PWA) 后台推送通知通道
- 真后台推送:基于 W3C Push API 和 Service Worker (
/dsh-plugin-notify/sw.js),即使所有 DeepSeek Harness 浏览器标签页已关闭,手机或电脑也能收到推送提醒。 - 即时深度链接:点击通知可直接跳转或激活触发事件的对应会话 (
?dshNotifySession=<id>)。 - 智能免打扰过滤:
webPush.onlyWhenAway在已有浏览器客户端连接 SSE 流时自动跳过推送,避免前台操作时的重复打扰。 - 免配置 VAPID:初次启用自动生成密钥并持久化保存至
$DSH_HOME/plugin-notify-state.json,支持环境变量覆盖。 - 交互式设置卡片:插件卡片中提供一键开启本机推送、实时状态查看与测试推送功能。
- 完整测试覆盖:新增 27 项自动化测试,全套件 48 项测试全部通过。
🇷🇺 Русский
Фоновый канал Web Push (PWA)
- Фоновая доставка: Настоящие push-уведомления по стандарту W3C Push API через Service Worker (
/dsh-plugin-notify/sw.js), доставляемые даже при полностью закрытых вкладках DeepSeek Harness. - Мгновенный переход: Нажатие на уведомление сразу открывает сессию, в которой завершился ход или ожидается подтверждение (
?dshNotifySession=<id>). - Умная фильтрация активности:
webPush.onlyWhenAwayавтоматически пропускает web push, пока открыта активная вкладка с SSE-потоком. - Автогенерация VAPID: Ключи генерируются автоматически и сохраняются в
$DSH_HOME/plugin-notify-state.jsonс поддержкой env-переменныхDSH_NOTIFY_VAPID_PUBLIC_KEYиDSH_NOTIFY_VAPID_PRIVATE_KEY. - Интерактивное управление: В карточке настроек доступны кнопки включения push на устройстве, проверка статуса и тестовый пуш.
- Полное покрытие тестами: 27 новых тестов, 48 тестов в наборе — все пройдены (FAIL=0 в preflight).
v0.3.6
[0.3.6] - 2026-09-25
Fixed
- SSE Authentication Security Boundary (#21): Replaced client-controlled header checks (\Authorization.length > 5, \sec-fetch-site) with authentic DSH session verification via \connection.requestRejection(req)\ (\Host/\Origin\ fence and browser session validation), with loopback-only fallback when connection service is absent.
- SSE Clients & Turn Starts Lifecycle Leak (#40): Bound SSE clients, route registration, heartbeat timer, and \ urnStarts\ map to unified effect-owned lifecycle. On plugin dispose, active SSE connections are cleanly terminated with closing comment and ended, route is unregistered, and \ urnStarts\ map is cleared to ensure complete isolation on reload.
Gitea commit: 623bf90d00efa13d220074c960085ed3ea743442
Mirror commit: 6b46dc3