DSH Plugins Marketplace

DSH Plugins

Plugins

/

Tools & Capabilities

/

dsh-notify

q

dsh-notify

Manifest valid

DSH Notification Display Layer Plugin: A global toast stack that subscribes to the desktop shell's `__dshExo` bridge events; clicks programmatically activate sessions through the official sessions runtime. When no shell is present, it degrades to subscribing to the sessions store and renders itself. The pluggable web side of the notification display layer.

UI (client)hasBundlePatch

dsh-notify

DSH 通知显示层插件(可插拔通知显示层的 web 侧) 全局右上角 toast 栈,订阅桌面壳 __dshExo 桥事件(对话完成 / 服务事件 / 更新就绪),点击经官方 dsh-client-runtime 的 sessions store 程序化激活会话(替代壳侧 __reactFiber$ DOM hack);无壳时自动降级订阅 sessions store 自绘轮次完成 toast。

面向 DSH-Exoskeleton 设计文档 docs/NOTIFICATION-PLUGIN-DESIGN.md §6 实现。壳核分离不破坏:检测逻辑(zstd watcher / 服务健康 / 更新)留在主进程,本插件只负责显示与交互。


1. 解决什么问题

用户问题本插件对应的解法
通知不弹 / 漏报桌面壳把事件经 webview 预加载桥(__dshExo)投递给页面内插件 → auto 决策「webview 在线优先」,dev/portable 无 System Toast 时通知仍然在页面内可见
点击跳错会话 / 跳不过去插件在页面内直接用官方 @deepseek-ai/dsh-client-runtime/client 的 sessions store 程序化选中/打开会话(会话 ID 精确),不再从壳外猜 DOM、不依赖 __reactFiber$
每轮对话都通知,太吵显示层策略化:聚合窗口、每轮/聚合粒度由壳侧 hub 决定后下发(本插件只渲染);无壳降级时同会话连发原位刷新而非堆积,避免覆盖层通知风暴

2. 架构(两种数据源,运行时互斥)

┌─ 壳桥模式(默认,覆盖式首选)────────────────────────────────────┐
│  DSH-Exoskeleton 主进程 notification-hub(壳侧,P1)              │
│   └─ webviewProvider(P2:WebContentsView 预加载桥 __dshExo)      │
│        │ onEvent(ev)                              send()           │
│        ▼                                                ▲          │
│  ┌─ dsh web 页面 ─────────────────────────────────────────────┐   │
│  │  dsh-notify 插件(本包)                                   │   │
│  │   · 检测到 window.__dshExo → ready() 握手 → 订阅 onEvent    │   │
│  │   · 渲染 toast 栈(按 kind 分级)                          │   │
│  │   · 点击 → ctx.sessions.open(id) 程序化激活                 │   │
│  │          → __dshExo.send('notify:click', …)                │   │
│  └────────────────────────────────────────────────────────────┘   │
└──────────────────────────────────────────────────────────────────┘

┌─ 无壳降级(浏览器直开 dsh web,无 __dshExo)───────────────────┐
│  dsh-notify 插件                                                │
│   · 订阅 ctx.sessions.list,检测 completed 0→1 边缘(= 侧边栏    │
│     绿色 "done":运行中→完成且未选中)                            │
│   · 自绘「对话完成」toast;点击 → ctx.sessions.open(id)          │
│   · 页面内闭环,无 OS 通知                                        │
└────────────────────────────────────────────────────────────────┘
  • 事件是"事实",显示是"策略":本插件只渲染壳/列表喂给它的完成事件,聚合/渠道等策略由壳侧 hub 决策。
  • 桥与降级互斥(有桥绝不再开 sessions 降级),天然无双通道重复。

3. 桥契约(window.__dshExo)

壳侧 P2 已落地(src/preload/dsh-view.ts + window-manager.attachDshView 挂 preload + notification-hub webview 通道),本契约即当前实现,供壳侧后续维护对齐。

插件只消费最小白名单 API,不依赖任何任意 IPC:

// 壳侧 → 页面(预加载桥 window.__dshExo,经 contextBridge 暴露)
interface DshExoBridge {
  /** 订阅壳推送的通知事件,返回取消函数 */
  onEvent(cb: (ev: NotificationEvent) => void): () => void
  /** 页面 → 壳:点击 / 已读回执 */
  send(channel: 'notify:click' | 'notify:seen', payload: { id: string; sessionId?: string }): void
  /** 页面 → 壳:握手(插件就绪后才投递,防事件丢失) */
  ready(): void
  /** 壳版本探针(仅用于日志) */
  appInfo(): { version: string }
}

// 通知事件(与设计 §3.1 一致)
type NotificationEventKind =
  | 'session-done' | 'service-ready' | 'service-error' | 'service-restarting' | 'update-ready'

interface NotificationEvent {
  id: string
  kind: NotificationEventKind
  title: string
  body: string
  ts: number
  session?: { sessionDir: string; workspace: string; uuid: string; file: string; turn?: number; project?: string; sessionTitle?: string; firstUserText?: string }
  service?: { port?: number; error?: string; restartCount?: number }
  update?: { version?: string }
  actions?: { onClick?: () => void }   // 原生 provider 专用;webview 通道序列化后无回调
}

桥侧交互时序(壳实现参考):

壳 webviewProvider 建桥(preload:sandbox+contextIsolation 暴露 __dshExo)
  → 等页面 __dshExo.ready() 握手
  → 握手后「webview 在线」,auto 决策投向 webview provider
  → view.webContents.send('dsh-notify:event', ev) → preload 转发给 onEvent 订阅者
  → 收到 notify:click → windowManager.show()(会话激活由插件侧 ctx.sessions.open 完成)
  → 收到 notify:seen → hub 记录已读回执(R-26)
未握手不投递(防漏报);握手丢失 → native 兜底。

4. 安装

从包源(npm / GitHub,推荐 —— 任意机器可装)

# npm 源(发布后)
dsh plugin --profile web add dsh-notify
# GitHub 源
dsh plugin --profile web add github:qgx1992/dsh-notify

桌面壳内也可用「插件」面板安装:目录会按 dsh-plugin topic / npm keywords 自动发现,一键安装。

已知坑(AGENT.md §7.1):新发布 <24h 时 pnpm 供应链策略可能报 ERR_PNPM_MINIMUM_RELEASE_AGE_VIOLATION,把该版本加进 profile 的 minimumReleaseAgeExclude 白名单即可。

本地开发装法(改源码调试用)

# 因项目路径含空格+中文,link: 直连会在 dsh→pnpm 转发链里被拆坏;
# 用无空格 junction 指向真实目录(改动实时生效,路径移动后需重建 junction)
New-Item -ItemType Junction -Path "$env:USERPROFILE\dsh-notify-link" `
  -Target "D:/A-my project/研究agent桌面端/DSH-Exoskeleton/plugins/dsh-notify"
dsh plugin --profile web add link:C:/Users/QIU/dsh-notify-link

装完后:dsh web 重启生效(客户端 bundle 在启动时组合,仅刷页面不生效), 页面刷新即加载 /plugins/dsh-notify/client.js。


5. 行为细节

  • toast 栈:右上角,全局。按 kind 分级:对话完成=信息、服务就绪=成功、服务异常=错误、服务重启=警告、更新就绪=信息(左侧竖色条 + DSW 主题变量,自动适配亮/暗色)。
  • 自动关闭:信息 8s / 成功 6s / 错误与更新 15s / 警告 12s;× 手动关闭;同屏上限 5 条(超出淘汰最旧)。
  • 对话完成 toast:项目「X」· 标题(壳下发 body 原样渲染;无壳降级由插件按 cwd 项目名 + displayTitle 组装)。点击 → ctx.sessions.open(sessionId) 程序化激活 + notify:click 回传。
  • 激活可靠性与防御:open() 前先校验会话 id 是否在列表(unknown id 会 fail loud,避免炸进插件);列表瞬态(phase=pending)下每 500ms 重试至多 4 次;再点可按需复用 byId 精确 id。
  • 已读回执:事件渲染即 notify:seen(壳侧 hub 用以上报投递成功/去重)。
  • i18n:独立 locale NS dsh-notify(zh/en)。data 前缀:data-dsh-notify-*。
  • DOM 纪律:toast 栈是插件自建的 fixed 覆盖容器,绝不搬动 DSH slot 渲染出的节点(搬节点 ↔ 框架重渲染互相触发会导致渲染进程 100% CPU 卡死,见 AGENT.md 已知坑);卸载插件(fiber dispose)整体拆除样式 + 根容器 + 全部 toast。
  • 静默降级:所有异常 try/catch,不向壳/页面抛。

6. 设计验证结论(对应设计文档 §11「待验证清单」)

#待验证项结论(本插件取证)
1dsh-client-runtime 的 sessions store 是否暴露程序化选中/打开会话的 API✅ 存在。ISessions.open(id: SessionId): void("Select a session as current"),实现 SessionRuntime.open;ctx.sessions 可见(inject "sessions" 后)。§6.3 首选路径可行
2页面是否容忍注入 __dshExo 全局插件侧只消费,不注入;__dshExo 命名冲突检测由壳侧 preload 负责(R-27,页面无同名全局时才注入)
4WebContentsView + sandbox + preload + contextBridge 兼容性壳侧 P2 阶段验证;本插件按标准 contextBridge 契约实现,无特殊前提
—覆盖式 toast 渲染安全性✅ 与生态先例(dsh-pet)同型:自建 position: fixed 容器 + <style>,不搬 slot 节点

无壳降级的"轮次完成"信号:SessionSummary.completed(侧边栏绿色 done 标记, SessionManager 在 running→idle 且未选中时 arming)。勘察结果见 @deepseek-ai/dsh-client-runtime/lib/types/client/contract/sessions.d.ts 与 sessions/service.d.ts。


7. 与 DSH-Exoskeleton 壳侧协作(P0–P2 已落地,P3/P4 约定)

壳侧已完成(本次同步交付,npm run typecheck / npm test(113 项)通过):

  • P0 ✅:AUMID 对齐(index.ts setAppUserModelId('io.dsh.exoskeleton'),与 electron-builder.yml appId 一致)。
  • P1 ✅:src/main/notification-hub.ts(dispatch / 聚合策略 / Provider 路由 / 投递回执日志 R-26),原 notify.ts 降为 native 内部实现。
  • P2 ✅:src/preload/dsh-view.ts 预加载桥(window.__dshExo 白名单,R-27)+ window-manager.attachDshView 挂 preload + hub webview 通道(在线判定 = view attach && 收到 ready() 握手)+ 三处事件源(session-watcher / index 服务事件 / updater)改走 hub。

约定:webview 通道下,壳收到 notify:click 只需 windowManager.show(),会话激活由插件 ctx.sessions.open() 完成 —— 这是替换 activateSessionInWebUi DOM hack 的关键收益;壳侧 activateSessionInWebUi 保留为 native 通道 / 页面异常时的兜底(actions.onClick 携带)。

P3 / P4(未做,按需后续):把 dsh-notify 加入 RECOMMENDED_PLUGINS 默认预置/推荐;管理面板「设置」页渠道自检 + 通知渠道/粒度/聚合窗口 UI(现状:notifyChannel 默认 auto 已生效,粒度默认 per-turn 保持现状零回归,聚合窗口默认 20000ms,均可在 config.json 手动调整)。


8. 目录结构

plugins/dsh-notify/
├── package.json          # dsh.client.platform=web;dsh.client.inject 留空(不静态注入源码上下文)
├── cordis.patch.yml      # bundle 挂载声明(insert 进 DSH 配置树)
├── lib/
│   ├── index.js          # 宿主(node 侧)入口:纯浏览器插件,无宿主行为
│   └── client.js         # 浏览器 bundle:toast 栈 + 桥订阅 + 程序化激活 + 无壳降级 + i18n
├── README.md             # 本文档
└── LICENSE               # MIT

9. 开发 / 发布

  • 改 lib/client.js 后:node --check lib/client.js 语法校验 → node test/smoke.cjs 冒烟测试(在无浏览器环境用最小 DOM shim 真实执行 apply(),覆盖:bundle 导出形状 / 无壳降级 completed 边缘弹 toast / 程序化激活 / 更新就绪 notify:install / 同事件去重 / 卸载拆除)→ 本地 link: 重装 → 重启 dsh web 实测。
  • 当前默认本地分发:不推 GitHub、不 npm publish。版本语义化(改代码后 bump),README/description 维护好即可。
  • 平台标记:dsh.client.platform = "web";exports['./client'] 供模块系统组合 /plugins/dsh-notify/client.js。

Versions

Latest versionPublishedSize
0.1.1——
0.1.2——
0.1.3——
0.1.4——
0.1.5——
0.1.6——
0.1.7——

Comments

Loading…

From the same category

reactive-resume

DeepSeek Harness plugin for Reactive Resume: bridges your resumes and job applications into a Harness session over MCP.

Tools & CapabilitiesManifest valid

★ 41.7k

↓ 270/wk

MIT

Aug 24, 2026

dsh plugin --profile web add dsh-plugin-reactive-resume

by Tencent

Let AI agents use your real, logged-in browser without interrupting your work. CLI + extension for browser automation across any shell-capable AI agent.

Tools & CapabilitiesManifest valid

★ 8.1k

↓ 7k/wk

MIT

TypeScript

Sep 30, 2026

dsh plugin --profile terminal add @wxg-prc-cpg/browser-skill-dsh-plugin

by yjh051108

dsh-routing-suite — injector + router-standard kit: install the runtime injector first, then the task-aware reasoning-mode router preset (measured P1-P23).

Tools & CapabilitiesManifest valid

★ 7k

MIT

JavaScript

Sep 18, 2026

dsh plugin --profile web add @dsh-external/dsh-super-injector

by Q00

Agent OS: the agent gets smarter on its own. We just hold the line: Interview-gated, staged evaluation, budgeted evolution loop. MCP server, 14 runtimes: Claude Code, Codex CLI, Gemini CLI, OpenCode,

Tools & CapabilitiesManifest valid

★ 6.2k

MIT

Python

Oct 4, 2026

Index only — not installable

by dsh-market

The plugin market inside DeepSeek Harness — browse, search, one-click install · DSH 可视化插件市场

Tools & CapabilitiesManifest valid

★ 5.5k

↓ 164.4k/wk

MIT

TypeScript

Oct 3, 2026

dsh plugin --profile web add dshmarket

by superdesigndev

OpenRouter for agent tools. Join community here: https://discord.gg/6mQYYfFMAn

Tools & CapabilitiesManifest valid

★ 4.1k

NOASSERTION

Python

Oct 4, 2026

dsh plugin --profile web add treg-dsh