After official llm-retry (n/5) gives up, keep retrying transient API failures (timeout, transport, rate-limit, 5xx, dropped SSE) on the same open step until success, cancel, or pause; AUTH, QUOTA, and user Stop are never retried.
Install
# from npm (prebuilt)
dsh plugin --profile web add dsh-session-robustness
# from GitHub (first run asks for allowBuilds approval — follow the hint, retry)
dsh plugin --profile web add github:bainianlaoyao/dsh-session-robustness
Any plugin you install runs third-party code with your own permissions — it can read your files, use your credentials, and reach the network, and tool approvals don’t sandbox it. GitHub-sourced plugins also run build scripts at install time — pnpm blocks those until you allow them, so an install can stop with ERR_PNPM_GIT_DEP_PREPARE_NOT_ALLOWED or ERR_PNPM_IGNORED_BUILDS; dsh prints the exact key to add under allowBuilds in your profile’s pnpm-workspace.yaml, and the install works on the next run. Allowing a build is a trust decision: only install sources you trust, and pin a commit (github:owner/repo#sha).
README
Engineering-level session robustness for DeepSeek Harness.
When a turn's model request fails with a transient API error (timeout, transport, rate limit, 5xx, empty response, dropped SSE), do not let the official bounded retry (maxRetries = 5) close the turn. Keep retrying the same open step until success, user cancel, or pause.
This is not a client-side "continue" after the turn has already ended, and it does not switch models. It sits after official dsh-llm-retry and re-runs the same request on the still-open step.
Why
@deepseek-ai/dsh-llm-retry is already mounted in dsh-base. Provider retryPolicy defaults to mode: normal with maxRetries: 5 for EMPTY_RESPONSE, RATE_LIMIT, SERVER, TIMEOUT, TRANSPORT. The UI shows 已重试模型请求 (n/5). After that budget the waterfall delegates, the loop treats the failure as terminal, and the session stops.
Official mode: always retries every failure including AUTH/QUOTA. This plugin does not: permanent errors cannot succeed by waiting.
From 0.1.3 every capturable network failure that reaches agent/request-error is retried unconditionally: STREAM_CLOSED, MALFORMED_RESPONSE, STREAM, HTTP_408 / 409 / 425 / 429 / 499 / 5xx. From 0.1.5 that also includes adapter-native stream_read_error and gateway wording Upstream request failed (usually classified as catch-all PI_AI_ERROR). Catch-all PI_AI_ERROR / UNKNOWN / unknown adapter codes still use the message heuristic.
OpenAI Codex overloaded is a special case: pi-ai classifies
Codex error: Our servers are currently overloaded. Please try again later.
as catch-all PI_AI_ERROR, not SERVER. From 0.1.2 the plugin retries catch-all codes when the message is clearly transient (overloaded, try again later, service unavailable, …). AUTH / QUOTA still win over the heuristic.
Never retried: AUTH, MISSING_CREDENTIAL, INVALID_CREDENTIAL, QUOTA, CONTEXT_WINDOW_EXCEEDED, NO_ADAPTER, ABORTED. Context overflow stays with official compaction. User Stop is not retried.
Failures that never enter agent/request-error are out of scope: throws from prepareCall, title/summary ctx.llm.stream(), and tool failures. In-process subagents share the host waterfall; ACP / out-of-process subagents do not.
From 0.1.6, openai-codex only: a failed stream drops that session's WebSocket continuation (previous_response_id). pi-ai websocket-cached / auto can keep a failed stream's response.id as the next-request anchor, so later retries stay stuck even after the API is healthy. The drop also runs during the official 5 retries (llm/stream is observed, not retried in-stream). Successful Codex streams keep their continuation. Server-side prompt cache and the DSH session log are untouched. Other providers are not closed.
Install
dsh plugin --profile web add dsh-session-robustness
or from GitHub:
dsh plugin --profile web add github:bainianlaoyao/dsh-session-robustness
Then restart the web profile. Settings → 会话鲁棒性.
The package declares dsh.bundle.patch + dsh.client. dsh plugin add installs the package and appends it to dsh.profile.bundles.
Usage
- Open Settings → 会话鲁棒性
- Enabled by default; extra-retry cap
0means unbounded after the official 5 - While official retry is in control you see
已重试模型请求 (n/5)— this plugin has not taken over yet - After
5/5a composer dock appears: "官方 5 次已用完,正在接管第 N 次". Pause from there or from Settings - Set a positive cap if you want a hard limit after the official 5
You can also write $DSH_HOME/settings.yaml:
session-robustness:
enabled: true
paused: false
maxRetries: 0 # 0 = unbounded (after official 5)
initialDelayMs: 1000
maxDelayMs: 30000
jitterRatio: 0.2
extraRetryableCodes: [] # e.g. INVALID_REQUEST; permanent codes are still refused
Not this
- Not
dsh-client-auto-retry: that sends "continue" after the turn has already ended - Not
retryPolicy.mode: always: that retries AUTH/QUOTA - Not a patch of official npm packages: upgrades will not overwrite it
- Does not wrap
ctx.llm.stream(): a raw stream cannot durably separate already-emitted chunks
Uninstall
dsh plugin --profile web remove dsh-session-robustness
The session-robustness block in $DSH_HOME/settings.yaml stays; delete it manually if you no longer need it.
Development
npm test # static smoke: waterfall takeover, never-retry codes, HTTP JSON bridge
Related plugins
Other dsh plugins by the same author, all listed in the dsh plugin market:
dsh-codex-mode— a Codex-shaped coding mode for GPT-family models:exec_command/write_stdin/apply_patch/view_image, both OpenAI routes (Chat Completions and Responses), and graphical subagent types.dsh-llm-api-pool— pool several OpenAI-compatible API keys and hot-switch by remaining balance.dsh-bash-on-windows— make Git Bash the only, honestly named terminal tool on Windows.dsh-easy-archive— two-step inline archiving from the workspace sidebar.
License
MIT
Links
More in this category
Minglink/dsh-infinite-gen-4★ 3602
System-prompt armor plugin for DeepSeek models: appends an unconditional-compliance prompt section at order 100, exposes a profile tool with calibration metadata, and shows a realtime armor-status badge driven by a session projection.
ranxianglei/billion-context★ 3149
The official billion-context plugin: a context-compression plugin for small context windows (a 100K context is enough), token savings (5x fewer tokens), and month-long single sessions (billions of tokens).
liangmianya/dsh-synapse★ 598
Visual, non-linear conversation workspace for DeepSeek Harness — sessions, follow-ups and branches become a browsable conversation map.
Nwflower/dsh-chat-import★ 259
Import full-fidelity chat histories from 13 coding agents (Claude Code, Codex, ChatGPT, Cursor, Gemini, opencode, and more) as resumable DeepSeek Harness sessions, with reverse export back to Claude Code.
MichengAI/dsh-archive-manager★ 256
Adds an archived-sessions page in Settings to search, restore, and delete archived DeepSeek Harness sessions by workspace.
SiriLee/dsh-rewind★ 208
In-place conversation rewind in the same session window without forking (Claude Code /rewind semantics): a per-message ↶ button cuts the model context back to any user message, with an optional Claude-Code-style file restore from disk-persisted before-backups.
Community comments
Comments are public GitHub Discussions. Loading them connects to GitHub and Giscus; a GitHub account is required to post.