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:
- 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.
- Subscribe to desktop shell bridge events: By default, subscribes to
window.__dshExobridge events, including conversation completion, service events, update readiness, and others. - 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. - 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
sessionsstore and self-renders turn-completion toasts. - Tiered display: Displays different styles and left-side vertical color bars according to notification type (info/success/error/warning).
- Automatic dismissal policy: Automatically dismisses based on type: info 8s, success 6s, error and update 15s, warning 12s.
- Self-contained container: Renders using a custom
fixedcontainer, without moving DSH slot nodes, avoiding rendering deadlocks. - Internationalization: Supports
zhandenlanguages.
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; ifunknown id, it reports an error; if the session is in thependingstate, it retries every 500ms up to 4 times. - Read receipt: Triggering
notify:seenis 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
minimumReleaseAgeExcludeallowlist. - 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.