opencode-auto-resume 1.1.12 → 1.1.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -152,7 +152,7 @@ _Motivated by:_
152
152
 
153
153
  ### Silent dead-stream recovery
154
154
 
155
- The model stream can die after emitting only reasoning — no text part, no tool call — finalizing with `finish: "unknown"`. OpenCode treats the message as completed and the session goes idle, so no error or stall path triggers. On idle, if the last assistant message has a non-standard finish reason, zero text parts, and at least `silentDeadStreamMinTokens` output tokens, the plugin sends a recovery prompt.
155
+ The model stream can die after emitting only reasoning — no text part, no tool call — finalizing with `finish: "unknown"`. OpenCode treats the message as completed and the session goes idle, so no error or stall path triggers. On idle, if the **newest** assistant message has a finish reason, zero text parts, and at least `silentDeadStreamMinTokens` output tokens, the plugin sends a recovery prompt. Only the newest assistant message is evaluated — a delivered text answer means normal completion, and older tool-call steps are never misread as dead streams. Recovery is also skipped if the session has gone busy/retry again before the prompt is sent (race guard).
156
156
 
157
157
  ---
158
158
 
@@ -180,7 +180,7 @@ _Motivated by:_
180
180
 
181
181
  ### ESC cancel respected
182
182
 
183
- User presses ESC to cancel a request. The plugin detects `MessageAbortedError` and marks all busy sessions as cancelled, never resuming them. The grace period (`gracePeriodMs`) also lets late ESC/status events arrive before any action.
183
+ User presses ESC to cancel a request. The plugin detects `MessageAbortedError` and marks sessions as cancelled — regardless of their tracked status, so a late status flip to idle before the error cannot miss the latch — and never resumes them. Aborts initiated by the plugin itself (`pluginAbortInFlight`) are excluded, so recovery aborts are not mistaken for ESC. The grace period (`gracePeriodMs`) also lets late ESC/status events arrive before any action.
184
184
 
185
185
  The back-off lifts as soon as the user sends a new prompt in that session (`chat.message` hook): a fresh user message starts a new round of work, so auto-resume re-arms. The plugin's own recovery prompts do not re-arm it. The same applies to the `task_complete` latch.
186
186
 
package/dist/index.js CHANGED
@@ -12523,7 +12523,7 @@ function getLastSilentDeadStream(messages) {
12523
12523
  return t.type === "text" && typeof t.text === "string" && t.text.length > 0;
12524
12524
  });
12525
12525
  if (hasText)
12526
- continue;
12526
+ return null;
12527
12527
  const tokens = msg.tokens;
12528
12528
  const tInfo = info?.tokens;
12529
12529
  const output = (tokens?.output ?? 0) + (tInfo?.output ?? 0);
@@ -13929,11 +13929,22 @@ var AutoResumePlugin = async (ctx, options) => {
13929
13929
  try {
13930
13930
  const dead = getLastSilentDeadStream(await getSessionMessages(sid));
13931
13931
  if (dead && dead.outputTokens >= silentDeadStreamMinTokens) {
13932
- w.pendingRecovery = true;
13933
- w.pendingRecoveryReason = `silent-${dead.finish}`;
13934
- w.pendingRecoveryAt = Date.now();
13935
- await log("info", `${short(sid)} - silent dead stream: finish=${dead.finish}, ${dead.outputTokens} output tokens, no text parts; resuming`);
13936
- await tryResume(sid, w, `Silent dead stream (${dead.finish})`, continuePrompt);
13932
+ let busyAgain = false;
13933
+ try {
13934
+ const liveStatus = (await getSessionStatusMap())[sid];
13935
+ busyAgain = liveStatus === "busy" || liveStatus === "retry";
13936
+ } catch (e) {
13937
+ dbg(`session.idle sid=${short(sid)}: silent-dead-stream status check failed: ${e instanceof Error ? e.message : String(e)}`);
13938
+ }
13939
+ if (busyAgain) {
13940
+ dbg(`session.idle sid=${short(sid)}: silent-dead-stream recovery skipped, session is busy/retry again`);
13941
+ } else {
13942
+ w.pendingRecovery = true;
13943
+ w.pendingRecoveryReason = `silent-${dead.finish}`;
13944
+ w.pendingRecoveryAt = Date.now();
13945
+ await log("info", `${short(sid)} - silent dead stream: finish=${dead.finish}, ${dead.outputTokens} output tokens, no text parts; resuming`);
13946
+ await tryResume(sid, w, `Silent dead stream (${dead.finish})`, continuePrompt);
13947
+ }
13937
13948
  }
13938
13949
  } catch (e) {
13939
13950
  const errMsg = e instanceof Error ? e.message : String(e);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-auto-resume",
3
- "version": "1.1.12",
3
+ "version": "1.1.13",
4
4
  "description": "OpenCode plugin that automatically resumes stalled LLM sessions when thinking/streaming freezes mid-generation.",
5
5
  "keywords": [
6
6
  "opencode",