dsh-auto-reconnect
English | 中文
Auto-reconnect for the DeepSeek Harness (DSH) web client. The official connection controller has backoff reconnect built in, but it sleeps through two real-world scenarios — this plugin wakes it. Client-only, zero build, no official package touched.
Install / Uninstall
dsh plugin --profile web add github:tqcq/dsh-auto-reconnect
Then restart dsh-web — adding or removing plugins always needs a restart; a browser refresh alone is not enough.
Upgrade (re-running add won't move the resolved commit; update re-resolves):
dsh plugin --profile web update dsh-auto-reconnect
Uninstall:
dsh plugin --profile web remove dsh-auto-reconnect
Runtime tweak, no reinstall needed (then reload the page):
localStorage["dsh-auto-reconnect"] = JSON.stringify({ minIntervalMs: 3000, retryDelayMs: 3000, maxAutoRetries: 20, log: true });
Two blind spots in the official controller (source-audited)
Audited against the actually-served @deepseek-ai/dsh-client-connection 0.1.2-rc.1:
- Terminal
disconnectedsleeps forever. Once the official 500ms→10s backoff tops out, the controller enters a terminal state and only wakes on the browseronlineevent or a manual tap. Phone sleep/wake keepsnavigator.onLine === truethe whole time, soonlinenever fires — every wake-up needs a manual tap. - Zombie
connected. The official client has no visibilitychange / focus listener and no heartbeat. A silently dropped TCP leaves the WebSocket in OPEN while the state still reportsconnected.
What this plugin does
Listens to visibilitychange(→visible), focus, pointerdown, keydown, pageshow(persisted), and subscribes to the connection state store:
- Event wakes: call
connection.reconnect()only when state ≠connected(resets backoff, retries immediately) — never interrupts a healthy connection. - bfcache restore (
persisted): sockets are dead by definition, reconnect unconditionally. - Transition into terminal
disconnected: delayed auto-retry (default 3s), budgeted to 20 consecutive attempts, reset onconnected. Covers "page already visible and focused, no browser event will ever fire again" (2026-09-11 field report: a hard refresh after a host restart landed in terminal state, still needed a manual tap).
Every trigger logs with a [dsh-auto-reconnect] prefix (DevTools console forensics), throttled to 3s by default.
Compatibility
- Field-verified on host
@deepseek-ai/dsh0.1.5-rc.2 (boot activation assertions all green). - Client contract audited against
dsh-client-connection0.1.2-rc.1 source. - Shape mismatch on
ctx.connection→ warn and stay idle, never breaks the page: graceful degradation on API drift.
Limitations
The general form of zombie connected (background tab NAT-dropped, no OS sleep) cannot be detected client-side: the RPC unary channel is separate HTTP, so a successful probe does not prove the WebSocket is alive. The real fix is a host-side heartbeat + dead-connection sweep (prior art: the deprecated enterhalf/dsh-web-network-optimizer) — a separate plugin if ever needed.
Tests
node tests/client_test.js # 14 groups, vm-sandboxed DOM/connection stubs, no browser
Forking notes
- The in-repo
cordis.patch.ymlmust stay[]: a comment-only YAML file parses to null and kills profile boot. - Client-code-only changes need just a browser hard refresh, no dsh-web restart.
License: MIT (see LICENSE).
No comments yet. Be the first to write one.