Skip to content

Releases: shengyvself/dsh-autoresume

v0.1.5

Choose a tag to compare

@shengyvself shengyvself released this 21 Sep 08:30

dsh-autoresume v0.1.5 — 缺陷 A/B 修复

两个分类 bug 修复(用户明示「绝对的 bug」):

缺陷 B:用户手动停止触发自动继续

根因:turn/end kind='aborted' 是驱动主动收尾(cancel 的 finally 写出 turn/end、边界闭合),与「环境杀死进程」(turn/end 缺失、open turn)本质不同。旧分类器见 openStep / 无结果 tool/call 一律判 interrupted 并注入「继续」,等于推翻用户指令。全量取证:133 个 aborted/user 事件全数无悬挂边界——旧代码靠「边界恰好闭合」这一巧合才未误注入,保证脆弱。

修复:① 悬挂边界只在轮次仍打开(openTurn)时计入可继续判据;闭合轮次一律按 turn/end 原因判定。② 新增显式 aborted 分支判 settled(动因 user/disposed),位置在 reasons 判定之后——上一个 aborted 后若又起新轮次并被环境杀死,仍判 interrupted 继续。

顺带消除:闭合轮次 + 悬挂 tool/call 旧判 interrupted 并注入;新按 turn/end 分流(网络 error → network-stopped 不变,completed → 不注入)。

缺陷 A:工具调用被中断于「记录为开始」之前自动继续完全不生效

根因:宿主补写 ToolNotStartedError 的 tool/result("interrupted before the Harness recorded it as started. Retry it if it is still needed."),上一条 assistant/message 是未执行的工具请求,轮次并未结束。旧代码见 lastType === 'assistant/message' 一律判 completed,不设例外。

修复:新增 messageHasToolCall(message)——lastType === 'assistant/message' 且不含 tool-call 块时才判 completed;含 tool-call 块落到 open turn 判定接手续跑。

验证

  • node --check src + lib:通过
  • build src → lib:64715 bytes 一致
  • tests/manual-stop.test.mjs:12/12 PASS
  • 全量:26/26 PASS(14 既有 + 12 新增)
  • 负向对照:回退 3 处改动 → 4 PASS / 8 FAIL(8 项正是缺陷 A/B 回归用例)
  • 全量回放:147 会话 / 110,439 事件,新旧分类并跑,状态分布完全一致(completed=100, settled=43, interrupted=2, pending-input=2)——零行为回归

安装

npm install https://github.com/shengyvself/dsh-autoresume/releases/download/v0.1.5/dsh-autoresume-0.1.5.tgz

兼容性

  • DSH >= 0.1.5-rc.2
  • @deepseek-ai/cordis >= 4.0.1
  • 配置无变更(未新增配置项)

Asset

dsh-autoresume-0.1.5.tgz · 40686 bytes · SHA256 770c75ebd72e16c951215728920f5f5443b696fe1ab3a5db3f16d621f6208dca

v0.1.4 — align to npm + visual assets

Choose a tag to compare

@shengyvself shengyvself released this 20 Sep 15:47

What changed

  • package.json version 0.0.21 → 0.1.4 (align to npm sequence 0.1.0-0.1.3)
  • Dark-mode adaptive banner via <picture> + prefers-color-scheme: dark
  • GitHub social-preview OG card (1200×630) for social sharing
  • Decision flow workflow diagram (triggers → classify → guards → inject → result)
  • README.md + README.zh.md updated to use banner + workflow.svg

Visual assets

Asset File Purpose
Banner (light) assets/banner.svg Hero area, light theme
Banner (dark) assets/banner-dark.svg Hero area, dark theme
Social preview assets/social-preview.svg GitHub OG card
Workflow assets/workflow.svg Decision flow diagram

npm publish: npm publish

v0.0.21 — 0.1.5 adaptation fixes

Choose a tag to compare

@shengyvself shengyvself released this 13 Sep 08:41

v0.0.21 — 2026-09-13

0.1.5 adaptation fixes: inspect removal + AgentSetup callback + queue guard

What's Fixed

  • 0.1.5 SessionPersistence.inspect() removal: DSH 0.1.5 removed the inspect() method. New inspectSession() uses open('read') + handle.read() to read session events without breaking the persistence contract.
  • 0.1.5 AgentSetup callback signature: The callback now receives (agentCtx, agent) instead of just (agentCtx). Fixed 3 setup closures to use the two-arg form.
  • Queue guard (skipWhenInputPending): Prevents injecting auto-resume messages when user messages are queued in the inbox. Uses persistent spliced-inbox analysis + live agent.inbox check.

DSH 0.1.5-rc.2 Adaptation

  • Session format v3: session.v3.jsonl.zstd (was session.jsonl.zstd)
  • Enumerates by generation, taking the highest available format

Tests

  • tests/inspect-open.test.mjs: 4/4 PASS (static guards + end-to-end)
  • tests/pending-input.test.mjs: 27/27 PASS (generation selection, inbox folding, queue guard, regression)
  • node --check all green, build src==lib verified

Install

[WARN] Tarball download average speed 43 KiB/s (size 46 KiB) is below 50 KiB/s: https://codeload.github.com/shengyvself/dsh-autoresume/tar.gz/9943ef170feefcec44738b398ba01c0d2410a596 (GET)
✓ Lockfile passes supply-chain policies (verified 1h ago)
[WARN] Tarball download average speed 41 KiB/s (size 46 KiB) is below 50 KiB/s: https://codeload.github.com/shengyvself/dsh-autoresume/tar.gz/9943ef170feefcec44738b398ba01c0d2410a596 (GET)
Packages: +178
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 178, reused 176, downloaded 1, added 178, done
[WARN] Issues with peer dependencies found. Run "pnpm peers check" to list them.

dependencies:

  • dsh-autoresume github:shengyvself/dsh-autoresume

Done in 7.7s using pnpm v12.3.4

v0.0.19 — README cross-platform fixes (docs only)

Choose a tag to compare

@shengyvself shengyvself released this 09 Sep 15:11

Highlights

  • README cross-platform fixes (docs only, no source change). User report: "the plugin intro has problems — not everyone is on Linux."

What was wrong

The plugin's source is already cross-platform — process.env.HOME ?? os.homedir() + node:path give identical behavior on Windows / Linux / macOS. But the README had three Unix/Linux assumptions that confused non-Linux users:

  1. ~/.dsh/sessions — the ~ shorthand is Unix-only (Windows uses %USERPROFILE%)
  2. Unix / path separators (Windows uses \)
  3. Install / restart commands that only work on Linux:
    • mkdir -p node_modules/@deepseek-ai
    • ln -sfn /usr/lib/node_modules/@deepseek-ai/dsh/node_modules/@deepseek-ai/dsh-agent node_modules/@deepseek-ai/dsh-agent
    • sudo systemctl restart dsh-web

What changed

  • Cross-platform callout at the top of README: <home> = user home directory (Linux/macOS: ~, Windows: %USERPROFILE%), auto-resolved by Node's os.homedir().
  • All ~/.dsh/sessions → <home>/.dsh/sessions; the behavior section now notes that node:path handles separators per-platform automatically.
  • Install section split into two code blocks:
    • bash (Linux/macOS): mkdir -p + ln -sfn unchanged
    • powershell (Windows): New-Item -ItemType Directory -Force + mklink /D, with the DSH global install dir discovered via npm root -g instead of hardcoding /usr/lib/
  • Restart section now lists all three platforms in parallel:
    • sudo systemctl restart dsh-web (Linux systemd)
    • brew services restart dsh-web (macOS Homebrew)
    • Restart-Service dsh-web (Windows admin PowerShell)

Diff

  • README.md — +39 / -5 (install & restart sections rewritten, cross-platform callout added)
  • CHANGELOG.md — +5 (new 0.0.19 entry)
  • package.json — 0.0.18 → 0.0.19
  • src/service.js / lib/service.js — unchanged (docs-only patch)

Validation

  • node --check on all 5 JS files — pass
  • Privacy scan regex (/home/ubuntu | world-Shengyv | narrative | ox-alpha | 考研 | 111.231 | shengyv.cn | 4ecb3d7d | ShengyvServer.pem) — 0 hits
  • tar tzf dsh-autoresume-0.0.19.tgz | grep -cE '\.bak|\.broken' — 0 (no backup files leaked into the tarball)

Install

npm install shengyvself/dsh-autoresume@0.0.19

Or from the release asset: dsh-autoresume-0.0.19.tgz (18.6 KB, SHA256 81e0782cf28997dff16fbeb1b9f29443c282d4341acf524faf5df4789b7608e1).

Notes for contributors

If you find further platform-specific wording in this repo, please open an issue — this is the second such report in two months, so it's worth treating as a general lint check on any new README/CHANGELOG edit.

v0.0.18 — maxResumeAttempts=2 (double-resume on SenseNova quota exhaustion) + new 429 forms + v0.0.17 backport

Choose a tag to compare

@shengyvself shengyvself released this 09 Sep 15:00

Highlights

  • Continuous 2-time auto-resume for SenseNova (maxResumeAttempts, default 2, failStreak counter): SenseNova's daily quota window is long and often produces two consecutive 429s (rpm exhausted / inference exceeds tpm/rpm limit). Previously the loop-guard converted to settled after a single no-output retry. Now network-class failures allow one more injection before settling (inject → fail → inject → fail → stop). Balance failures (isBalanceFailure) remain single-shot — the v0.0.15 infinite-loop guard is unchanged.
  • New 429 forms recognized: type=quota_exceeded_error (code="8", message rpm exhausted), type=rate_limit_error (code="429001", message inference exceeds tpm/rpm limit), and messages containing tpm exhausted / rpm exhausted / 429001.
  • v0.0.17 backport: insufficient_quota moved from BALANCE_LLM_CODES to RETRYABLE_LLM_CODES (SenseNova uses this code for tpm/rpm rate limiting, not persistent balance shortage); RATE_LIMIT_MESSAGE_PATTERN added for message-level arbitration against QUOTA-wrapped 429 envelopes (the persisted form: outer code=QUOTA + inner 429: {"message":"inference exceeds tpm/rpm limit",...}).

Two fixes explained

1. Continuous 2-time resume (v0.0.18, 2026-09-08)

SenseNova's daily quota produces long rate-limit windows. The old loop-guard fired on lastOursSeq > -1 && lastTurnEnd > lastOursSeq && !assistantAfterOurs — i.e. one injection with no progress → settled. With maxResumeAttempts=2 the new predicate is:

const continuedThenFell =
  lastOursSeq > -1 && lastTurnEnd > lastOursSeq &&
  (balanceFailed || failStreak >= maxResumeAttempts);

failStreak increments on each no-output retry; resets to 0 when any assistant or tool output appears after the injection (re-arming). Balance failures bypass failStreak — they settle after a single failed retry, preserving the §五十四 402-loop guard.

2. New 429 forms + QUOTA wrapper arbitration (v0.0.17, 2026-09-02)

Three paths previously failed to detect the SenseNova tpm/rpm limit:

  • insufficient_quota was in BALANCE_LLM_CODES (but blocked by isNetworkFailure's gate first, and the balance/limit semantics conflict) → moved to RETRYABLE_LLM_CODES
  • rate_limit_error was not in RETRYABLE_LLM_TYPES → added
  • message inference exceeds tpm/rpm limit did not match NETWORK_FAILURE_PATTERN → added

The persisted form is a QUOTA-wrapped 429: outer code=QUOTA (ambiguous — could be balance or limit), with the real 429 body nested inside the message. isBalanceFailure now checks RATE_LIMIT_MESSAGE_PATTERN first — if the message contains any of 429|too many requests|rate[-_ ]?limit|rate_limit_error|tpm\/rpm|insufficient_quota, the error is reclassified as non-balance (injectable). Balance semantics are still enforced via BALANCE_LLM_CODES (QUOTA / insufficient_balance / payment_required) and the 402 pattern, so the §五十四 infinite-loop guard is preserved.

Validation

  1. node --check on src/service.js, lib/service.js, src/client.js, lib/client.js, scripts/build.mjs — all pass
  2. build — src and lib identical (md5 492a3f16..., no rebuild needed)
  3. Scenario matrix (per CHANGELOG 0.0.18): 18/18 PASS
    • A (new forms, 5 cases): rpm exhausted in all shapes / message only / type only / 429001 / bare insufficient_quota → network-stopped
    • B (double-resume, 4 cases): inject→fail 1×→still network-stopped (2nd allowed); inject→fail 2×→settled; inject→tool/text output→fail→network-stopped (re-armed)
    • C (balance loop-guard, 3 cases): QUOTA first fail→inject; inject→fail again (with or without output)→settled
    • D (regression, 6 cases): UNKNOWN_MODEL/CTX/429/service_unavailable/completed/QUOTA-wrapped 429
  4. DSH restart verification per CHANGELOG (PID change, Result=success, 3× HTTP 200)

Diff

  • package.json — version 0.0.16 → 0.0.18
  • CHANGELOG.md — +2 entries (0.0.18, 0.0.17)
  • README.md — 2 new feature highlights + config table maxResumeAttempts row
  • cordis.patch.yml — new default maxResumeAttempts: 2
  • src/service.js / lib/service.js — 68 lines added / 40 removed (identical)
    • RETRYABLE_LLM_CODES += insufficient_quota
    • RETRYABLE_LLM_TYPES += quota_exceeded_error, rate_limit_error
    • BALANCE_LLM_CODES -= insufficient_quota
    • new RATE_LIMIT_MESSAGE_PATTERN (rate-limit message arbitration)
    • NETWORK_FAILURE_PATTERN += rpm exhausted, tpm exhausted, rate_limit
    • analyzeSessionEvents(...) signature: added maxResumeAttempts = 2 parameter
    • new failStreak counter + positiveInt(config.maxResumeAttempts, 2) default

Install

npm install shengyvself/dsh-autoresume@0.0.18

Or from the release asset: dsh-autoresume-0.0.18.tgz (17.9 KB, SHA256 7f7ffbef03621cf30d50b23a291cf4b442fd32990126eef90752622b68f5aee3).

v0.0.10

Choose a tag to compare

@shengyvself shengyvself released this 02 Sep 08:27

v0.0.10

Highlights

  • Permanent automatic watch (bootGraceMs default → Infinity): the plugin now watches indefinitely by default, covering sessions stuck longer than the previous 30-minute grace window (e.g. a session stopped by a network error 14h+ ago is resumed against on this process's boot).
  • Deeper error-envelope unwrapping + 429 / service_unavailable recognition: multi-level {error:{...}} and failure-payload envelopes are peeled correctly; 429 and "service unavailable" style responses are treated as retryable network failures and trigger auto-continue.
  • Adds the model-selection-on-self-resume fix for the {{model}} assembly error path (subagent first-turn).
  • Sample config no longer hardcodes bootGraceMs (server default is the Infinity permanent watch; opt-out via an explicit value).
  • Note: v0.0.10.x release describes the trigger-scenario UX; this tag is the code state.

Install

npm install dsh-autoresume@0.0.10

v0.0.9

Choose a tag to compare

@shengyvself shengyvself released this 02 Sep 08:27

v0.0.9

Authoritative server build.

Highlights

  • Global interrupted-session scan: on boot, scans all sessions whose last event-stream state is an open/interrupted turn and resumes them.
  • Network-failure auto-continue: sessions stopped by network/transient failures (EMPTY_RESPONSE / RATE_LIMIT / SERVER / TIMEOUT / TRANSPORT, or a message matching network patterns) get a 继续(自动) injected once. Config/model errors (e.g. UNKNOWN_MODEL, MISSING_CREDENTIAL) stay untouched.
  • liveWatch (default true) + dead-loop guard: keeps polling after boot (mtime-changed sessions only) and re-injects on mid-session transient failure; the guard settles (stops injecting) if a post-inject message produces no progress and fails again with the same network error — prevents infinite empty-return loops.
  • Marketplace hygiene: @deepseek-ai/dsh-agent moved to peer-only per marketplace guideline.
  • Version numbering fixed: this lineage is v0.0.9 (legacy v0.1.x from initial releases == v0.0.3 of this lineage).

Install

npm install dsh-autoresume@0.0.9

v0.0.16 — ctx.agents inactive-context guard + 402/balance loop fix (v0.0.15 backport)

Choose a tag to compare

@shengyvself shengyvself released this 01 Sep 13:31

Highlights

Two independent fixes shipped together as one maintenance release:

v0.0.16: ctx.agents inactive-context guard (boot crash fix)

DSH 0.1.2-alpha.3 plugin tree load fails when ctx.agents.get() runs before the plugin context becomes active / service injection settles — cordis inactive context throws a fatal load failure (journal: 13 restart loop observed). Fix: defensive helper getAgent(sessionId) wraps try/catch, logs warn, returns undefined; checkOnce()/injectIfIdle() use it. Settles gracefully, next 5s poll retries. Mirrors the prompt-polish ctx 服务访问 try/catch 降级 pattern.

v0.0.15 (backport): 402 / balance failure infinite-loop guard

Two root causes for the observed 真没余额后自动继续无限循环 (401860fc reproduced 9 times):

  1. assistant/chunk usage / finish (LLM billing/shutdown metadata) was miscounted as "progress after inject" — loop-guard never fired. Fix: only real output blocks (text-delta / reasoning-delta / tool-call-delta / block-start / block-end) count (new PROGRESS_CHUNK_TYPES).
  2. Balance failures (402 / QUOTA / insufficient_balance / payment_required) are persistent, not transient. Fix: new BALANCE_LLM_CODES / BALANCE_FAILURE_PATTERN / isBalanceFailure() — inject once, then settled on subsequent balance failure. First 402 still injects (covers "post-topup recovery").

Plus:

  • NETWORK_FAILURE_PATTERN gains \b400\b (tokenrhythm fallback 400 status code (no body)) + Chinese transient features (模型服务暂时不可用 / 请稍后重试 / 当前繁忙 / etc.).
  • New PERMANENT_LLM_CODES excludes UNKNOWN_MODEL / MISSING_CREDENTIAL / NO_ADAPTER / INVALID_MODEL_INFO / CONTEXT_WINDOW_EXCEEDED / MODEL_NOT_FOUND — keeps v0.0.12 regression baseline (e.g. CONTEXT_WINDOW_EXCEEDED settles even when its message contains 400 status code (no body)).

Validation

  • DSH web restart verified: journal clean (no cannot get required service "agents", no inactive context, no status=1), [dsh-autoresume] logs normal, stable across 60s.
  • Restart executed by server-ops per protocol (this release commit does not self-restart).
  • Replay 401860fc event stream: first 402 → network-stopped (inject once); second 402 → settled (loop cut). Real recovery succeeded — turn 13 produced normal output.
  • Regression matrix 19/19 PASS (transient 429/5xx/upstream-with-output still injectable; first 402 still injects; completed/aborted/interrupted/UNKNOWN_MODEL/empty unaffected).
  • 400 + Chinese transient matrix 16/16 PASS.

Diff

5 files, +212 / −21. node --check clean, build src → lib md5 3c1733df... matches.

Install

npm install dsh-autoresume@0.0.16

Then rebuild your profile (dsh plugin --profile web add <path>) — the inactive-context guard is automatic; no config changes required.


版本历史

GitHub 可见 Releases:v0.0.9 / v0.0.10 / v0.0.11 / v0.0.12 / v0.0.13 / v0.0.14 / v0.0.16(各带 tgz 资产)。

早期版本 v0.0.2 ~ v0.0.8 为 legacy 编号期:CHANGELOG.md 有逐版本文字记载,但 git 历史无独立 commit(源码不可追溯),故无 tag/Release(不补造);v0.0.10.1(docs-only)与 v0.0.15(并入本版 backport)无独立 Release。完整变更见 CHANGELOG.md,下载见 Releases 页。

v0.0.14 — double-inject guard + assistant/chunk + inject# audit

Choose a tag to compare

@shengyvself shengyvself released this 01 Sep 03:02

dsh-autoresume v0.0.14 — 2026-09-01

修复「双注入」bug(核心)

dsh-web 崩溃循环(如会话日志文件损坏导致的连续重启失败)后,一个会话被注入两条「继续(自动)」——先后两个进程各注入一次,造成重复执行。

根因

死循环守卫原本只覆盖「网络错误」路径;当注入「继续」后模型尚未产生任何内容(流式推理块或工具调用都还没有)进程就被再次杀死,新进程重扫时会话尾部呈 interrupted 形态,与「用户手动重启打断」无法区分 → 误判为可恢复 → 再次注入。

修复

  • 新增 interrupted 分支循环守卫:若「我们上次注入后零产出即再次被打断」,判定为环境噪音(进程死亡/重启循环)→ 转 settled 不再注入,把决定权交还用户;
  • assistant/chunk(流式推理块)计入「注入后进展」——模型已开始产出内容再被打断,仍视为真实中断并正常续跑,不误伤;
  • 注入日志带 inject#<唯一 id>,跨进程审计可精确定位「同一进程第几次注入」与「不同进程各注入一次」。

判定健壮性

  • 守卫逻辑基于持久化会话事件流判定(不依赖进程内存态),跨进程/跨重启一致生效;
  • 真实中断(注入后已有产出或工具调用)不受影响,照常自动继续。

顺带修复

  • agentOptions 自动注入到 ctx.agents.resume(),修复 sidechat.start 子代理首轮装配报 prompt variable "{{model}}" has no value 的隐性 race。

验证

  • 13/13 场景矩阵 PASS(双注入守卫两路 + assistant/chunk 计入 + agentOptions 透传;回归 loop-guard / UNKNOWN_MODEL / network-stopped / 真实中断四路全绿)。
  • 与 ARCHITECTURE.json 架构版本 0.0.58 联动。

安装

npm install dsh-autoresume@0.0.14

完整 changelog

详见仓库 CHANGELOG.md。

v0.0.13

Choose a tag to compare

@shengyvself shengyvself released this 02 Sep 08:27

v0.0.13

Highlights

  • "Provider returned error" recognized as transient upstream failure: the NETWORK_FAILURE_PATTERN now matches provider returned error — the standard wording OpenRouter returns for an upstream provider outage (e.g. minimax). pi-ai adapter buckets it PI_AI_ERROR; it is a transient upstream fault that can recover on the same provider shortly after, and sessions stopped by it now get a 继续(自动) injection.
  • Verified against a real session that spent 78s with no output, ending in PI_AI_ERROR: Provider returned error (previously settled, no injection); a manual same-provider 继续 moments later succeeded — confirming it is transient and should be auto-injected.
  • Scenario matrix 14/14 PASS (real failed session → network-stopped → injected + self-resumed; loop-guard / UNKNOWN_MODEL / completed / TRANSPORT / 504 nested envelope / open-turn regressions all green).

Install

npm install dsh-autoresume@0.0.13