dsh-web
zhu1090093659/dsh-webDeepSeek Harness(DSH)Web 插件聚合生态包 · 一切皆插件,创意工坊分发(dsh-market.com)
English | 中文
A DeepSeek Harness Cordis plugin: every non-subagent session that stops pushes a message to the configured messaging platforms (QQ / Telegram / Feishu / WeChat), so nobody has to watch the screen.
| Situation | Trigger | Text |
|---|---|---|
| Task completed | turn/end(completed) + agent/status(idle) | ✅ Task completed |
| Task interrupted | turn/end(aborted) | ⏸ Task interrupted |
| Task blocked | turn/end(blocked) | 🚫 Task blocked |
| Task failed | turn/end(error) | ❌ Task failed (with the error) |
| Token limit | turn/end(max-tokens) | ↯ Reached token limit |
| Approval needed | approval/request | ⚠️ Approval needed |
| Answer needed | user-questions/request | ❓ Your answer is needed |
Each push carries the session name (title / directory plus the session id tail), a preview of the last reply, and an “open the Web UI” link.
This plugin is the push layer: it does not decide approvals, it does not accept replies as decisions, and it never injects inbound messages into an agent session. Decisions stay in the Web UI; the push only calls you back. Other plugins can call ctx.messagePush.notify({...}) to reuse the same channels and de-duplication.
From GitHub (pinning a tag is steadier):
dsh plugin --profile web add github:DNAlec/dsh-message-push
From a local checkout (development):
git clone https://github.com/DNAlec/dsh-message-push.git
dsh plugin --profile web add "$PWD/dsh-message-push"
pnpm is required. Restart dsh web afterwards — profile composition resolves at startup, and the “Message push” settings page appears only then.
Optional dependencies (QQ QR provisioning / the Feishu SDK) are declared in the package and installed by pnpm; a missing one only degrades that channel.
From npm (after a tagged release):
dsh plugin --profile web add @dnalec/dsh-message-push
Uninstall with dsh plugin --profile web remove @dnalec/dsh-message-push. Configuration and credentials under ~/.dsh/message-push/ are not deleted.
Settings → Message push.
@larksuiteoapi/node-sdk).是 / yes / ok in a DM and that chat becomes the target.
This is a private bot design: whoever confirms first owns the push target. Never expose the bot to strangers. QQ groups must @ the bot, and the speaker’s
userIdmust be set.
webUrl, preview length, coalesce window, per-reason toggles, and “push subagent sessions too” (off by default).header.origin === 'subagent' or delegationDepth > 0 are skipped.turn/end and agent/status(idle) arrive in no guaranteed order. The first one holds the notification until turn/end supplies the reason (at most reasonUnknownDelayMs, default 8s; on timeout it pushes “Session stopped”).idle folds into the same message (“N more pending in this window”) instead of adding a “task completed” notice.repeatWindowSecs (default 60s) merge, re-notifying only when the count changes.PUSH_SKIP / PUSH_FAIL to the audit log and warns at most once per 60s.The plugin publishes its service with ctx.provide('messagePush', …) on the host plane:
const push = ctx.get('messagePush')
if (push) {
push.notify({ kind: 'needs-approval', sessionId, title: 'Fix push plugin', body: 'Approve deleting 3 files' })
}
| Method | Purpose |
|---|---|
broadcast(text, opts?) | Send to every enabled, bound, connected channel → { sent, ok, failed, skipped } |
send(channelId, chatId, text, opts?) | Send to one channel/target |
notify(event) | Push through the watcher pipeline (de-duplication + coalescing) |
onInbound(fn) | Observe inbound text (read-only); return true to claim and stop host handling |
channels() | Currently pushable channel ids |
state | Last push time / result / error |
A corrupt config file makes the plugin run on in-memory defaults and never overwrite the disk; the settings page offers an explicit overwrite.
Everything lives in $DSH_HOME/message-push/ (default ~/.dsh/message-push/, mode 0600). Never commit it.
| File | Contents |
|---|---|
config.json | Channel switches, push targets, notification rules |
secrets.json | QQ AppID/Secret, Telegram token, Feishu AppID/Secret |
wechat.json | WeChat iLink login state |
audit.log | PUSH / PUSH_FAIL / PUSH_SKIP / BIND / INBOX / CONFIG / WARN |
No audit line means this plugin did not push anything.
npm test # node --test tests/*.test.mjs
npm run check # node --check on every source file
Plain JS, zero @deepseek-ai/* imports: it uses only the cordis injection name timer plus the runtime's fetch / WebSocket. Read AGENTS.md before changing code.