dsh-event-relay
Manifest validdsh-event-relay
A DeepSeek Harness (DSH) plugin: install it into a profile alongside your own plugins.
Push from host to browser. The host can start a conversation; every other channel (fetch, RPC) requires the browser to ask first. If your plugin's UI should react the moment something happens host-side (a setting changed, a build finished, a notification arrived), this is that channel.
One shared SSE route (/relay/events) holds every subscriber's response open
and streams JSON messages {"topic","payload"} as things happen. One
connection per browser tab, no matter how many plugins subscribe.
Architecture
flowchart LR
subgraph HOST["🖥️ Host, dsh-event-relay (host half)"]
P["publish(topic, payload)"]
N["notifyClients<br/>filter per client"]
W[("/relay/events<br/>held-open responses")]
end
subgraph WIRE["⇄ SSE"]
direction LR
M["data: {topic, payload}<br/>...one message per event..."]
end
subgraph BROWSER["🌐 Browser tab, dsh-event-relay (client half)"]
C["eventRelay service<br/>subscribe(topic, listener)"]
S["notifyListeners<br/>fan-out per topic"]
L1["plugin A listener"]
L2["plugin B listener"]
L3["plugin C listener"]
end
P --> N --> W
W --> M
M --> C
C --> S
S --> L1
S --> L2
S --> L3
Plugin value proposition
| alternative | falls short |
|---|---|
| polling | latency + waste (N fetches to learn "nothing changed") |
| refetch on focus/navigation | free and correct, but updates only when the user acts |
| your own EventSource/WebSocket per plugin | the browser caps ~6 connections/domain (HTTP/1.1); a few plugins permanently occupy them and every other request queues. This shared stream is one connection for the whole tab |
host RPC (/api) | request→response: the frontend can ask, but the host cannot interrupt |
One direction, on purpose. Browser→host is transaction-shaped (command → reply): use plain HTTP (a route your host half registers) with status codes, validation, and error handling the stream doesn't have. Host→browser is notification-shaped: unpredictable moments, all tabs at once. Different jobs, different roads.
How to install
Requires a DeepSeek Harness checkout and a profile (here web):
# from the harness checkout
pnpm dsh plugin --profile web add /path/to/dsh-event-relay
# verify the profile still composes
pnpm dsh --profile web --dump-config
Then (re)start the harness; the host half loads at boot. Browser plugins
consume the client service with ctx.get('eventRelay'), nothing to wire up
beyond installing this package.
Producers (host plugins)
const relay = ctx.get('eventRelay') // optional, degrade if absent
relay.publish('my-topic', payload) // direct
ctx.on('my/event', (data) => relay.publish('my/event', data)) // mirror a Cordis event (do this in your plugin)
Consumers (browser bundles)
const relay = ctx.get('eventRelay') // provided by this package's client half
const unsubscribe = relay.subscribe('kanban', (topic, payload) => { ... })
// or raw: new EventSource('/relay/events?topics=kanban,notifications')
payload in the callback is whatever the publisher passed. Apply it directly
or ignore it and refetch your own truth, both are first-class styles.
Topic filtering: a subscription matches its exact topic and any child topic
('kanban' matches 'kanban/change'). The browser's connection URL carries
the union of the tab's topics, so the server only sends what this tab listens
for. When the last listener of the tab unsubscribes, the connection closes.
On every (re)open of the stream, subscribers of the synthetic topic __relay
receive '__relay/open'. Consumers that apply state from messages use it to
resynchronize: anything missed while the stream was down is recovered by one
refetch.
Design
Transport, not a bus: Cordis events remain the host-side event system; this only carries messages across the plane boundary.
Payload is optional, not doorbell-only. Some plugins use the relay purely as a
change signal, a topic-only message that tells them to refetch their own
truth. Others consume the payload directly: the notifications demo pushes the
notification itself, a kanban board pushes change messages. publish(topic, payload): send whatever is useful. Doorbells are one usage style, not the
contract.
Liveness, not correctness: the relay may be absent, and a consumer should
fall back to pull-on-focus (or pull on __relay/open) rather than depend on
the stream for state.
Route roots are composition-level contracts (/api, /plugins,
/workspace-history, /notifications, /granular-settings are taken).
Debugging
The wire can be listened to from a terminal. Very useful to verify publishes end-to-end without a browser:
curl -N 'http://127.0.0.1:3080/relay/events'
Add ?topics=<prefixes> to mirror a client's filter; -N makes curl stream
instead of buffering.
Dependencies
None
Plugins dependent on this
- dsh-granular-settings publishes doorbell-only change notifications for its scoped settings platform
Comments
Loading…
From the same category
by xmanrui
通过扫码或机器人凭据把IM机器人接入DeepSeek Harness(支持飞书、微信、钉钉、企业微信、QQ、Slack、Telegram、Discord和WhatsApp)。 Connect IM bots to DeepSeek Harness via QR code or credentials (9 channels).
★ 1.6k
↓ 17.2k/wk
MIT
JavaScript
Oct 2, 2026
dsh plugin --profile web add @xmanrui/dsh-imby inclusionAI
Distributed agent coordination platform where agents live, connect, coordinate, execute, and evolve together.
★ 625
Apache-2.0
Python
Oct 1, 2026
by omdsh-dev
Desktop notifications for DeepSeek Harness turn completions, with per-outcome controls and include/exclude keyword rules.
★ 85
MIT
JavaScript
Sep 1, 2026
dsh plugin --profile web add dsh-notificationby whyihaveyou
The living DeepSeek Harness plugin directory — refreshed hourly, compat-tested daily, with an in-app plugin store and scaffolder. DSH 插件活目录:每小时刷新,每日兼容实测,内置插件商店与脚手架。
★ 56
MIT
HTML
Oct 2, 2026
dsh plugin --profile web add @dsh-suite/allby omdsh-dev
Lark/Feishu IM bot channel for DeepSeek Harness | 飞书 DeepSeek Harness (DSH)插件
★ 55
BSD-3-Clause
TypeScript
Aug 19, 2026
dsh plugin --profile web add dsh-lark-channelby THEWOLFWALKER
Unified notification and remote-control plugin for DeepSeek Harness (DSH): one zero-dependency notify() API across 27 channels, with phone-friendly approvals/questions, six inbound control channels, a
★ 55
MIT
JavaScript
Oct 2, 2026
dsh plugin --profile web add dsh-notifier