Preface

The notification mechanism of DeepSeek Harness (DSH) is handled by the desktop shell. If the desktop shell is unresponsive or in a development environment, notifications may not be visible in the page. The dsh-notify plugin provides a web-side notification display layer: it subscribes to the desktop shell’s __dshExo bridge events to render a global toast stack and supports programmatic activation of sessions on click.

Installation

Install the plugin using the following command:

dsh plugin --profile web add github:qgx1992/dsh-notify

After installation, the web process must be restarted for the change to take effect:

dsh web 重启

Refreshing the page will load /plugins/dsh-notify/client.js.

Core Features

The plugin provides the following capabilities:

  1. Top-right global toast stack: Displays a notification list in the top-right corner of the page. A maximum of 5 notifications are shown on screen; additional notifications evict the oldest one.
  2. Subscribe to desktop shell bridge events: By default, subscribes to window.__dshExo bridge events, including conversation completion, service events, update readiness, and others.
  3. Programmatic session activation: When a toast is clicked, it invokes the official runtime API ctx.sessions.open(id) to activate the session, replacing DOM hack operations.
  4. Fallback mode without shell: If the desktop shell is not detected (for example, the web page is opened directly in a browser), the plugin automatically falls back to subscribing to the sessions store and self-renders turn-completion toasts.
  5. Tiered display: Displays different styles and left-side vertical color bars according to notification type (info/success/error/warning).
  6. Automatic dismissal policy: Automatically dismisses based on type: info 8s, success 6s, error and update 15s, warning 12s.
  7. Self-contained container: Renders using a custom fixed container, without moving DSH slot nodes, avoiding rendering deadlocks.
  8. Internationalization: Supports zh and en languages.

Architecture and Workflow

The plugin runs in two mutually exclusive data source modes:

Shell Bridge Mode (Default)

The desktop shell delivers notification events to the page through the __dshExo bridge. After the plugin detects that the bridge exists, it performs a handshake, subscribes to the onEvent callback, and renders the toast stack. After clicking a toast, it calls ctx.sessions.open(id) to activate the session.

Fallback Mode Without Shell

When the page runs directly in the browser and window.__dshExo is absent, the plugin subscribes to ctx.sessions.list, detects session state changes (such as from running to idle), and self-renders completion toasts.

Bridge Contract

The plugin only consumes the minimal allowlisted API of window.__dshExo and does not depend on arbitrary IPC:

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 }
}

Event types include: session-done (conversation completed), service-ready (service ready), service-error (service exception), service-restarting (service restarting), update-ready (update ready).

Behavioral Details

  • Click activation: Clicking a toast calls ctx.sessions.open(id). The plugin validates whether the session ID is in the list; if unknown id, it reports an error; if the session is in the pending state, it retries every 500ms up to 4 times.
  • Read receipt: Triggering notify:seen is sent back to the shell side as soon as the event is rendered.
  • Style and theme: Toast styles use DSH theme variables and automatically adapt to light/dark modes.
  • Exception handling: All exceptions are silently degraded through try/catch and are not thrown to the shell or the page.

Notes

  • Local distribution: This plugin is not published to npm by default and is not uploaded to GitHub. It can only be installed via dsh plugin --profile web add link:<local path>.
  • Supply chain policy: New releases within 24 hours may trigger pnpm supply chain policy errors. The version must be added to the minimumReleaseAgeExclude allowlist.
  • Local development: During local development, if the project path contains spaces or Chinese characters, use a space-free Junction pointing to the real directory; otherwise, the link: command may fail.
  • Source code modification: During development, after modifying lib/client.js, run a syntax check; then refresh the page to take effect.