DSH Plugins Marketplace

DSH Plugins

Plugins

/

dsh-weixin-link

r

dsh-weixin-link

Manifest valid

Weixin iLink channel plugin for DeepSeek Harness (DSH): bidirectional send/receive with delivery receipts

hasBundlePatch

@ruqinhu/dsh-weixin-link

English | 中文

The Weixin (iLink) channel for DeepSeek Harness: receives messages, and delivers turn results without the model having to remember to send them.

1. The constraint

ConstraintConsequence
Every send must carry a context_tokena token can only come from an inbound message
No token can be minteda quiet night parks the 07:00 report until the owner speaks
A fallback channel would hide failureno fallback; parked text is replayed, never rerouted
Over-long payloads can return a message id and still not arrivethe 2,200-char cap is enforced in code, not trusted to the model

2. Which turns are delivered

source.kindOriginDelivered
schedulecron task✅
weixin-linkowner messaged from Weixin✅
usertyped in terminal / web UI❌ answer already on screen
runtime-context / skill-catalog / time-contextinjected context❌ not speech
compact-checkpoint / provider / fallbackcompaction, title generation❌ internal noise

Only the first user message names the origin: every turn is followed by injected context, so the last one would classify every turn as context and deliver nothing.

3. Mechanisms

ProblemDecisionRejected alternativeCost paid
Who deliversthe channel subscribes to session/event and sends on turn/endtelling the model "you must call weixin_push" — it answered in-session and delivered nothing, pushed meta-commentary, and shipped errors as reportsthe model cannot choose silence, except via [SILENT]
Duplicate sendsidentical text within 10 min counts as delivered; a manual weixin_push stands auto-delivery downan LLM "is this worth it" gate: a round trip per message, and a silent "don't send" is indistinguishable from a crashduplicates outside the window still go out
Empty turns本次无产出(timestamp)silence: "ran and failed" looks like "never ran"one message that may say nothing
Failed turns⚠️ 回合未完成(reason,timestamp):本次没有可投递的内容。, at most one per session per hoursending the partial text: a fragment reads like an answer; skipping: a crashed 07:00 report looks like a day with no schedulethe hourly floor is in memory, so a restart can add one
Receive vs sendreplay on its own timer + single-flight; bootstrap does not await itawaiting replay inside the poll loop: a 30/60/120 s backoff means 3.5 minutes deafreplay is serial — one slow send delays the rest
Livenessrewrite state/heartbeat.json every round; judge every 60 s; restart when no round has been attempted for 3 budgets (≥ 90 s)judging by last success: a loop failing every round gets restarted every tick, aborting the retry in flightcannot tell "hung" from "paused"
Replay deletiondelete only on a provably permanent failuredeleting on "anything not NEEDS_INBOUND/RATE_LIMITED": ret:-2 prepare failed is transient, and that rule ate a 12:40 reportqueue keeps entries that may never send
Batching turnsnot donecoalescing near-simultaneous turns: delays a decaying report, complicates the cap, harder to replayoccasional burst of separate messages

4. Failure handling

ClassActionWhy not the alternative
stale tokenpark, do not retryonly a new inbound can mint a token
rate limitedback off 30/60/120 s, then parkdropping after the ladder looks like "never scheduled"
otherone immediate retry, then give upmore retries turn a blip into a queue stall
no context_token at all (auto-delivery)drop, do not parkreplaying a week-old report is worse than dropping it
replayed entry failskeep it, never re-parka second file for the same text means every copy is sent

5. Measured

ItemResult
Unit tests248 across 21 files; tsc --noEmit clean
Delivery round tripinbound 10:00:04 → turn completed 10:00:24 → ok msgid=7523202391886746000 in the same second
Watchdogheartbeat advances every round, restarts: 0 across a 14-hour run
Receiptsone JSONL line per attempt, keyed by the operator's local day

5.1 An outage, as the trace recorded it. Quota exhaustion (429 AccountQuotaExceeded), two consecutive builds on the same channel:

Time (UTC)BuildBehaviour
10:40:29oldskip … turn=304 reason=not-completed
10:42:31oldskip … turn=305 reason=not-completed
10:44:34oldskip … turn=306 reason=not-completed
10:46:33newsend … turn=307 kind=failure len=44 → ok msgid=7522972414050248000
10:46+newfurther notices held back: skip … reason=failure-notice-rate-limited

Four minutes of silence became one line on the phone saying the run did not finish.

6. Open questions

QuestionCurrent state
Token refreshcannot be done by the plugin; ~12 h without an inbound message parks sends
Recipientsone poll loop, one recipient; multi-account needs a routing layer
Replay concurrencyserial; per-entry locking would be needed
Failure-notice floorin memory; persisting costs a write per failure
Media / rich cardsnone — text is the only payload whose failure is observable here
Watchdog false positivesa debugger pause or long GC looks like a stall; restart is harmless but recorded
Outbox validationnone at write time; bad entries are skipped on read and logged

7. Compatibility

ItemValue
DSH0.2.1-rc.5 (peer dependencies pinned)
RuntimeNode 22+, no native modules
Required servicestools, credentials, sessionController; agents optional
Payloadtext only, ≤ 2,200 chars

8. Install, credentials, configuration

dsh plugin add @ruqinhu/dsh-weixin-link

The token is read through the DSH credential store (ctx.credentials.resolve()), not process.env: the store already layers $DSH_HOME/.credentials.yaml → environment → project/user .env, and reading the environment directly would shadow it.

KeyDefaultMeaning
tokenEnvWEIXIN_BOT_TOKENcredential name for the bot token
accountIdEnvWEIXIN_BOT_ACCOUNT_IDcredential name for the account id
baseUrlhttps://ilinkai.weixin.qq.comiLink endpoint
dataDir~/.dsh/weixin-linktokens, outbox, receipts, trace
polltruerun the inbound long-poll loop
pollTimeoutMs40000client budget; must exceed the server's 35 s hold
defaultUserId""recipient; empty = most recent inbound sender
echoOwnMessagesfalsesurface the bot's own messages as inbound
sessionId""session inbound is routed to, resumed when cold
replayIntervalMs300000outbox retry interval, own timer
dedupeWindowMs600000identical texts inside this window count as delivered
notifyTurnFailurestrueannounce a turn that ended without completing
watchdogIntervalMs60000liveness check interval; 0 disables

9. Tools and files

ToolPurpose
weixin_pushsend now; parks automatically when it cannot deliver
weixin_statuslogin state, token age, last delivery, outbox depth, poll liveness
FileContent
receipts/YYYY-MM-DD.jsonlone line per send attempt, keyed by the +08:00 day
delivery-trace.logone line per turn decision, including skips and why
outbox/parked messages awaiting a token
state/heartbeat.jsonlast attempt/success, failures, inbound count, restarts
send session=... turn=12 kind=turn len=63
ok   session=... turn=12 msgid=7521135910923441000
skip session=... turn=13 reason=source-not-deliverable
skip session=... turn=14 reason=duplicate
watchdog-restart reason=stalled lagMs=142000 failures=0

10. Inbound routing

SituationBehaviour
session configured, cold startresume via sessionController.resolveAgent() (bare Agent, { agent }, or { error } — all three handled)
no session configuredroute to the first live root agent
no agent at alltoken cache still refreshed; that is what unblocks delivery

sessionController must be in static inject: cordis throws on an undeclared service rather than returning undefined, and a try/catch turns that into "messages arrive but nothing ever answers".

License

MIT

Comments

Loading…

Similar plugins

dsh-channel-wechat

by wangx-wx

dsh-channel-wechat

Tools & CapabilitiesManifest valid

★ 5

↓ 3.1k/wk

MIT

TypeScript

Oct 23, 2026

dsh plugin --profile web add dsh-channel-wechat

by xiaoshihou514

DeepSeek Harness: Weixin

Notifications & IntegrationsTerminal & ClientsManifest valid

★ 4

↓ 269/wk

MIT

TypeScript

Nov 5, 2026

dsh plugin --profile web add dsh-weixin

by fu827707013

DSH(DeepSeek Harness)并发请求监控与门闩插件。

Development & InfrastructureTerminal & ClientsManifest valid

★ 4

↓ 224/wk

MIT

JavaScript

Sep 17, 2026

dsh plugin --profile web add dsh-concurrency-guard

by loadingvx

Deepseek-harness-workbench-plugin

UI & ExperienceManifest valid

★ 36

↓ 211/wk

MIT

TypeScript

Oct 19, 2026

dsh plugin --profile web add dsh-workbench-plugin

by gsh150801

Bioinformatics plugin for DeepSeek Harness (dsh)

Manifest valid

★ 0

MIT

TypeScript

Sep 1, 2026

dsh plugin --profile web add dsh-bioinf-routed

by yangbobo2021

Codex integration plugin for DeepSeek Harness, providing native Codex conversations powered by the Codex App Server, with workspace, terminal, approval, and DSH tool support.

Terminal & ClientsManifest valid

★ 19

↓ 92/wk

MIT

JavaScript

Sep 19, 2026

dsh plugin --profile web add relay-dsh-plugin-codex