opencode-auto-resume 1.2.0 → 1.2.1

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
@@ -453,7 +453,7 @@ On v2 a clean load writes nothing at startup: warnings and recovery lines go to
453
453
  | Tool-text not detected | Check server logs — requires SDK message fetching (v1). On v2 the history comes from the client message surface or loopback HTTP — check the server process output instead |
454
454
  | Long-running tool killed | Should not happen — active-tool guard prevents it. Report a bug. |
455
455
  | No plugin activity in the log | The entry is not in a location opencode scans, or not listed in `plugins`; fix the config and restart opencode. |
456
- | Log says `ctx.app.version is missing` (or `ctx.serverUrl is missing` on v1) | The build was loaded on the wrong server generation. Update the npm package (the universal entry auto-selects the branch) or match the build file to the server. |
456
+ | Log says `ctx.app.version is missing` (or `ctx.serverUrl is missing` on v1) | The build was loaded on the wrong server generation. The plugin disables itself with this diagnostic instead of crashing. Update the npm package (the universal entry auto-selects the branch by context shape) or match the build file to the server. |
457
457
  | Never recovers a parent waiting on a subagent | Intentional: parent sessions blocked on a running subagent are left alone. |
458
458
  | Never recovers while a permission dialog is open | Intentional: recovery is held until the permission is answered. |
459
459
  | Recovers but you don't see a notice (v2) | Your model/provider may reject `session.synthetic()`; the plugin falls back to `session.prompt()` (no TUI banner). |
package/dist/index.js CHANGED
@@ -12389,6 +12389,12 @@ var TASK_COMPLETE_REPEAT_ERROR = "task_complete already acknowledged twice with
12389
12389
  var CTX_WRAPUP_TRIGGER = "ctx-wrapup";
12390
12390
  var UNKNOWN_TOOL_THRESHOLD = 2;
12391
12391
  var TOOL_IDS_CACHE_MS = 5 * 60000;
12392
+ var OWN_PROMPT_SHAPES = [
12393
+ /^continue\s*\u2014\s*stalled\s*\(/,
12394
+ /^continue\s*\nOnly continue work already in progress\./,
12395
+ /^continue\s*\nIf work was already in progress,/,
12396
+ /^You tried to use the tool "/
12397
+ ];
12392
12398
  var TOOL_TEXT_PATTERNS = [
12393
12399
  /<function\s*=/i,
12394
12400
  /<function>/i,
@@ -12677,6 +12683,10 @@ Please continue working on ${thisWord} ${taskWord}.`;
12677
12683
  var AutoResumePlugin = async (ctx, options) => {
12678
12684
  if (!ctx.serverUrl) {
12679
12685
  console.warn("[auto-resume] this looks like the opencode v1 build running on the wrong server: ctx.serverUrl is missing. The v1 bundle requires opencode v1 \u2014 update the plugin package (the npm build auto-selects per server) or load the build matching your server; see the README on npm (opencode-auto-resume).");
12686
+ return {
12687
+ event: async () => {},
12688
+ config: async () => {}
12689
+ };
12680
12690
  }
12681
12691
  const chunkTimeoutMs = options?.chunkTimeoutMs ?? DEFAULT_CHUNK_TIMEOUT_MS;
12682
12692
  const checkIntervalMs = options?.checkIntervalMs ?? DEFAULT_CHECK_INTERVAL_MS;
@@ -13201,7 +13211,11 @@ var AutoResumePlugin = async (ctx, options) => {
13201
13211
  if (available.length === 0)
13202
13212
  return false;
13203
13213
  const messages = await getSessionMessages(sid);
13214
+ const lastUserAt = lastUserMessageTimeOf(messages);
13204
13215
  for (const msg of messages) {
13216
+ if (lastUserAt !== undefined && messageTimeOf(msg) !== undefined && messageTimeOf(msg) <= lastUserAt) {
13217
+ continue;
13218
+ }
13205
13219
  const parts = msg.parts;
13206
13220
  if (!parts)
13207
13221
  continue;
@@ -13245,6 +13259,39 @@ var AutoResumePlugin = async (ctx, options) => {
13245
13259
  return;
13246
13260
  return msg.role ?? msg.info?.role;
13247
13261
  }
13262
+ function messageTimeOf(msg) {
13263
+ if (!msg)
13264
+ return;
13265
+ const direct = msg.time;
13266
+ const viaInfo = msg.info?.time;
13267
+ const raw = typeof direct === "number" ? direct : direct?.created ?? (typeof viaInfo === "number" ? viaInfo : viaInfo?.created);
13268
+ return typeof raw === "number" && raw > 0 ? raw : undefined;
13269
+ }
13270
+ function lastUserMessageTimeOf(messages) {
13271
+ for (let i = messages.length - 1;i >= 0; i--) {
13272
+ const msg = messages[i];
13273
+ if (roleOf(msg) !== "user")
13274
+ continue;
13275
+ const t = messageTimeOf(msg);
13276
+ if (t !== undefined)
13277
+ return t;
13278
+ }
13279
+ return;
13280
+ }
13281
+ function looksLikeOwnPrompt(props) {
13282
+ if (!props)
13283
+ return false;
13284
+ const parts = props.parts ?? props.info?.parts;
13285
+ let text;
13286
+ if (Array.isArray(parts)) {
13287
+ text = parts.filter((p) => p?.type === "text").map((p) => p.text).join(`
13288
+ `);
13289
+ }
13290
+ text = text ?? props.text ?? props.info?.text;
13291
+ if (!text)
13292
+ return false;
13293
+ return OWN_PROMPT_SHAPES.some((re) => re.test(text));
13294
+ }
13248
13295
  async function lastAssistantEndsWithCelebration(sid) {
13249
13296
  try {
13250
13297
  const msgs = await getSessionMessages(sid);
@@ -14600,13 +14647,15 @@ var AutoResumePlugin = async (ctx, options) => {
14600
14647
  const info = props?.info;
14601
14648
  const role = info?.role ?? props?.role;
14602
14649
  if (role === "user") {
14650
+ if (looksLikeOwnPrompt(props)) {
14651
+ break;
14652
+ }
14603
14653
  const w = sessions.get(sid);
14604
14654
  if (w) {
14605
14655
  w.doneClaimNoTodosAttempts = 0;
14606
14656
  w.lastUserMessageAt = Date.now();
14607
14657
  w.unknownToolErrors.clear();
14608
14658
  w.unknownToolSuggestionSent = false;
14609
- w.checkedToolPartIDs.clear();
14610
14659
  }
14611
14660
  break;
14612
14661
  }
@@ -15479,15 +15528,16 @@ function messageTextOf(m) {
15479
15528
  return mm.info.content;
15480
15529
  return;
15481
15530
  }
15482
- var OWN_PROMPT_SHAPES = [
15531
+ var OWN_PROMPT_SHAPES2 = [
15483
15532
  /^continue\s*\u2014\s*stalled\s*\(/,
15484
15533
  /^continue\s*\nOnly continue work already in progress\./,
15485
- /^continue\s*\nIf work was already in progress,/
15534
+ /^continue\s*\nIf work was already in progress,/,
15535
+ /^You tried to use the tool "/
15486
15536
  ];
15487
15537
  function looksLikeOwnPrompt(text) {
15488
15538
  if (typeof text !== "string" || text.length === 0)
15489
15539
  return false;
15490
- return OWN_PROMPT_SHAPES.some((re) => re.test(text));
15540
+ return OWN_PROMPT_SHAPES2.some((re) => re.test(text));
15491
15541
  }
15492
15542
  function isTaskToolCall(ev) {
15493
15543
  const tool = ev.data?.tool ?? ev.data?.toolName;
@@ -15636,6 +15686,7 @@ var v2_default = define({
15636
15686
  }
15637
15687
  if (typeof ctx.app?.version !== "string") {
15638
15688
  log("warn", "this looks like the opencode v1 build running on the wrong server: ctx.app.version is missing. The v2 bundle requires opencode v2 \u2014 update the plugin package (the npm build auto-selects per server) or load the build matching your server; see the README on npm (opencode-auto-resume).");
15689
+ return () => {};
15639
15690
  }
15640
15691
  const gatedInUse = Object.keys(opts).filter((key) => FEATURE_GATED_OPTIONS.includes(key));
15641
15692
  const dbg = (...args) => {
@@ -17223,7 +17274,10 @@ ${suffix}`).slice(0, 2000);
17223
17274
  const available = await getAvailableToolIds();
17224
17275
  if (available.length === 0)
17225
17276
  return false;
17277
+ const lastUserAt = lastUserMessageAt(messages);
17226
17278
  for (const msg of messages) {
17279
+ if (lastUserAt !== undefined && msgAt(msg) <= lastUserAt)
17280
+ continue;
17227
17281
  const content = msg?.content;
17228
17282
  if (!Array.isArray(content))
17229
17283
  continue;
@@ -18868,10 +18922,22 @@ ${reminder}`;
18868
18922
  });
18869
18923
 
18870
18924
  // src/dispatch.ts
18925
+ var noopDispose = () => {};
18871
18926
  var dispatcher = {
18872
18927
  id: "auto-resume.v2",
18873
18928
  server: AutoResumePlugin,
18874
- setup: v2_default.setup
18929
+ setup: async (ctx) => {
18930
+ if (ctx?.app?.version)
18931
+ return v2_default.setup(ctx);
18932
+ if (typeof ctx?.event?.subscribe === "function") {
18933
+ return v2_default.setup(ctx);
18934
+ }
18935
+ if (ctx?.serverUrl || ctx?.client?.session) {
18936
+ return AutoResumePlugin(ctx, ctx.options);
18937
+ }
18938
+ console.warn("[auto-resume] unrecognised host context \u2014 no ctx.app.version (opencode v2), no ctx.event.subscribe (v2 loader), no ctx.serverUrl/client (opencode v1). Plugin disabled; see the README on npm (opencode-auto-resume).");
18939
+ return noopDispose;
18940
+ }
18875
18941
  };
18876
18942
  var dispatch_default = dispatcher;
18877
18943
  export {
package/dist/v2/index.js CHANGED
@@ -620,7 +620,8 @@ function messageTextOf(m) {
620
620
  var OWN_PROMPT_SHAPES = [
621
621
  /^continue\s*\u2014\s*stalled\s*\(/,
622
622
  /^continue\s*\nOnly continue work already in progress\./,
623
- /^continue\s*\nIf work was already in progress,/
623
+ /^continue\s*\nIf work was already in progress,/,
624
+ /^You tried to use the tool "/
624
625
  ];
625
626
  function looksLikeOwnPrompt(text) {
626
627
  if (typeof text !== "string" || text.length === 0)
@@ -774,6 +775,7 @@ var v2_default = define({
774
775
  }
775
776
  if (typeof ctx.app?.version !== "string") {
776
777
  log("warn", "this looks like the opencode v1 build running on the wrong server: ctx.app.version is missing. The v2 bundle requires opencode v2 \u2014 update the plugin package (the npm build auto-selects per server) or load the build matching your server; see the README on npm (opencode-auto-resume).");
778
+ return () => {};
777
779
  }
778
780
  const gatedInUse = Object.keys(opts).filter((key) => FEATURE_GATED_OPTIONS.includes(key));
779
781
  const dbg = (...args) => {
@@ -2361,7 +2363,10 @@ ${suffix}`).slice(0, 2000);
2361
2363
  const available = await getAvailableToolIds();
2362
2364
  if (available.length === 0)
2363
2365
  return false;
2366
+ const lastUserAt = lastUserMessageAt(messages);
2364
2367
  for (const msg of messages) {
2368
+ if (lastUserAt !== undefined && msgAt(msg) <= lastUserAt)
2369
+ continue;
2365
2370
  const content = msg?.content;
2366
2371
  if (!Array.isArray(content))
2367
2372
  continue;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "opencode-auto-resume",
3
- "version": "1.2.0",
3
+ "version": "1.2.1",
4
4
  "description": "OpenCode plugin that automatically resumes stalled LLM sessions when thinking/streaming freezes mid-generation.",
5
5
  "keywords": [
6
6
  "opencode",