opencode-auto-resume 1.1.5 → 1.1.6
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 +1 -16
- package/dist/index.js +178 -158
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -265,11 +265,7 @@ Periodic: cleanup idle sessions older than 10min or >50 entries
|
|
|
265
265
|
|
|
266
266
|
## Installation
|
|
267
267
|
|
|
268
|
-
###
|
|
269
|
-
|
|
270
|
-
```bash
|
|
271
|
-
npm install opencode-auto-resume
|
|
272
|
-
```
|
|
268
|
+
### Opencode
|
|
273
269
|
|
|
274
270
|
Add to your `opencode.jsonc`:
|
|
275
271
|
|
|
@@ -294,17 +290,6 @@ With options:
|
|
|
294
290
|
}
|
|
295
291
|
```
|
|
296
292
|
|
|
297
|
-
### Via GitHub (manual clone)
|
|
298
|
-
|
|
299
|
-
OpenCode may clone the repository to `~/.config/opencode/plugins/opencode-auto-resume/` automatically.
|
|
300
|
-
|
|
301
|
-
**To update** the plugin:
|
|
302
|
-
```bash
|
|
303
|
-
cd ~/.config/opencode/plugins/opencode-auto-resume
|
|
304
|
-
git pull
|
|
305
|
-
bun run build
|
|
306
|
-
```
|
|
307
|
-
|
|
308
293
|
## Configuration
|
|
309
294
|
|
|
310
295
|
```json
|
package/dist/index.js
CHANGED
|
@@ -12593,7 +12593,21 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12593
12593
|
async function log(level, msg) {
|
|
12594
12594
|
try {
|
|
12595
12595
|
await ctx.client.app.log({ body: { service: "auto-resume", level, message: msg } });
|
|
12596
|
-
} catch {
|
|
12596
|
+
} catch (e) {
|
|
12597
|
+
console.error("[auto-resume] log() failed:", e instanceof Error ? e.message : String(e));
|
|
12598
|
+
}
|
|
12599
|
+
}
|
|
12600
|
+
async function safe(fn, ctxLabel) {
|
|
12601
|
+
try {
|
|
12602
|
+
return await fn();
|
|
12603
|
+
} catch (e) {
|
|
12604
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
12605
|
+
console.error(`[auto-resume] ${ctxLabel}: ${msg}`);
|
|
12606
|
+
try {
|
|
12607
|
+
await log("error", `${ctxLabel}: ${msg}`);
|
|
12608
|
+
} catch {}
|
|
12609
|
+
return;
|
|
12610
|
+
}
|
|
12597
12611
|
}
|
|
12598
12612
|
function ensureWatch(sid) {
|
|
12599
12613
|
let w = sessions.get(sid);
|
|
@@ -13497,186 +13511,188 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13497
13511
|
if (timer)
|
|
13498
13512
|
return;
|
|
13499
13513
|
timer = setInterval(async () => {
|
|
13500
|
-
|
|
13501
|
-
|
|
13502
|
-
|
|
13503
|
-
|
|
13504
|
-
const
|
|
13505
|
-
|
|
13506
|
-
w.status
|
|
13507
|
-
|
|
13508
|
-
|
|
13509
|
-
|
|
13510
|
-
|
|
13511
|
-
|
|
13512
|
-
|
|
13513
|
-
|
|
13514
|
-
|
|
13515
|
-
|
|
13516
|
-
|
|
13517
|
-
|
|
13518
|
-
|
|
13519
|
-
if (
|
|
13520
|
-
if (
|
|
13521
|
-
|
|
13522
|
-
|
|
13523
|
-
|
|
13524
|
-
|
|
13525
|
-
const hasActiveTool = await checkSessionHasActiveTool(sid);
|
|
13526
|
-
if (hasActiveTool) {
|
|
13527
|
-
await log("debug", `Parent ${short(sid)} has active tool call, skipping orphan-watch abort`);
|
|
13528
|
-
w.orphanWatchStartAt = now;
|
|
13529
|
-
continue;
|
|
13530
|
-
}
|
|
13531
|
-
const subStatus = await checkSubagentStatus(sid);
|
|
13532
|
-
if (subStatus.status === "crashed" && subStatus.stuckSid) {
|
|
13533
|
-
const recovered = await recoverSubagent(subStatus.stuckSid);
|
|
13534
|
-
if (recovered) {
|
|
13535
|
-
await log("info", `Sent recovery prompt to stuck subagent ${short(subStatus.stuckSid)}, waiting...`);
|
|
13536
|
-
} else {
|
|
13537
|
-
await log("info", `Subagent crashed, triggering abort+resume on ${short(sid)}`);
|
|
13538
|
-
tryAbortAndResume(sid, w);
|
|
13514
|
+
await safe(async () => {
|
|
13515
|
+
const now = Date.now();
|
|
13516
|
+
const numBusy = busyCount();
|
|
13517
|
+
const statusMap = await getSessionStatusMap();
|
|
13518
|
+
for (const [sid, w] of sessions) {
|
|
13519
|
+
const realStatus = statusMap[sid];
|
|
13520
|
+
if (realStatus && realStatus !== w.status) {
|
|
13521
|
+
w.status = realStatus;
|
|
13522
|
+
if (realStatus === "busy")
|
|
13523
|
+
w.idleSince = null;
|
|
13524
|
+
}
|
|
13525
|
+
if (w.status !== "busy")
|
|
13526
|
+
continue;
|
|
13527
|
+
if (w.userCancelled)
|
|
13528
|
+
continue;
|
|
13529
|
+
if (w.aborting)
|
|
13530
|
+
continue;
|
|
13531
|
+
if (w.orphanWatchStartAt !== null) {
|
|
13532
|
+
const orphanIdle = now - w.orphanWatchStartAt;
|
|
13533
|
+
if (orphanIdle >= subagentWaitMs + gracePeriodMs) {
|
|
13534
|
+
if (w.resumeAttempts < maxRetries) {
|
|
13535
|
+
if (hasInflightTools(w)) {
|
|
13536
|
+
await log("debug", `Parent ${short(sid)} has ${w.pendingTools} tool(s) in-flight, skipping orphan-watch abort`);
|
|
13537
|
+
w.orphanWatchStartAt = now;
|
|
13538
|
+
continue;
|
|
13539
13539
|
}
|
|
13540
|
-
|
|
13541
|
-
|
|
13542
|
-
|
|
13543
|
-
|
|
13540
|
+
const hasActiveTool = await checkSessionHasActiveTool(sid);
|
|
13541
|
+
if (hasActiveTool) {
|
|
13542
|
+
await log("debug", `Parent ${short(sid)} has active tool call, skipping orphan-watch abort`);
|
|
13543
|
+
w.orphanWatchStartAt = now;
|
|
13544
|
+
continue;
|
|
13545
|
+
}
|
|
13546
|
+
const subStatus = await checkSubagentStatus(sid);
|
|
13547
|
+
if (subStatus.status === "crashed" && subStatus.stuckSid) {
|
|
13548
|
+
const recovered = await recoverSubagent(subStatus.stuckSid);
|
|
13549
|
+
if (recovered) {
|
|
13550
|
+
await log("info", `Sent recovery prompt to stuck subagent ${short(subStatus.stuckSid)}, waiting...`);
|
|
13551
|
+
} else {
|
|
13552
|
+
await log("info", `Subagent crashed, triggering abort+resume on ${short(sid)}`);
|
|
13553
|
+
tryAbortAndResume(sid, w);
|
|
13554
|
+
}
|
|
13555
|
+
} else if (subStatus.status === "idle") {
|
|
13556
|
+
const hasBusySub = await hasBusySubagents(sid);
|
|
13557
|
+
if (hasBusySub) {
|
|
13558
|
+
await log("debug", `Subagents exist but not busy yet, waiting for startup...`);
|
|
13559
|
+
} else {
|
|
13560
|
+
await log("info", `Parent ${short(sid)} stuck with no active subagents. Triggering abort+resume.`);
|
|
13561
|
+
tryAbortAndResume(sid, w);
|
|
13562
|
+
}
|
|
13544
13563
|
} else {
|
|
13545
|
-
await log("
|
|
13546
|
-
tryAbortAndResume(sid, w);
|
|
13564
|
+
await log("debug", `Subagent still running, waiting...`);
|
|
13547
13565
|
}
|
|
13548
|
-
} else {
|
|
13549
|
-
|
|
13566
|
+
} else if (!w.gaveUp) {
|
|
13567
|
+
w.gaveUp = true;
|
|
13568
|
+
dbg(`State transition on ${short(sid)}: gaveUp=false -> true`);
|
|
13569
|
+
w.orphanWatchStartAt = null;
|
|
13570
|
+
w.aborting = false;
|
|
13571
|
+
log("warn", `${short(sid)} - orphan retries exhausted.`);
|
|
13550
13572
|
}
|
|
13551
|
-
} else if (!w.gaveUp) {
|
|
13552
|
-
w.gaveUp = true;
|
|
13553
|
-
dbg(`State transition on ${short(sid)}: gaveUp=false -> true`);
|
|
13554
|
-
w.orphanWatchStartAt = null;
|
|
13555
|
-
w.aborting = false;
|
|
13556
|
-
log("warn", `${short(sid)} - orphan retries exhausted.`);
|
|
13557
13573
|
}
|
|
13558
|
-
}
|
|
13559
|
-
continue;
|
|
13560
|
-
}
|
|
13561
|
-
if (numBusy > 1)
|
|
13562
|
-
continue;
|
|
13563
|
-
if (now - w.lastSubagentCheckAt < checkIntervalMs * 2)
|
|
13564
|
-
continue;
|
|
13565
|
-
w.lastSubagentCheckAt = now;
|
|
13566
|
-
if (w.lastActivityAt > 0 && now - w.lastActivityAt > subagentWaitMs) {
|
|
13567
|
-
if (realStatus === "busy") {
|
|
13568
|
-
await log("debug", `Session ${short(sid)} is still busy (real status), skipping abort`);
|
|
13569
|
-
w.lastSubagentCheckAt = now;
|
|
13570
|
-
continue;
|
|
13571
|
-
}
|
|
13572
|
-
if (hasInflightTools(w)) {
|
|
13573
|
-
await log("debug", `Session ${short(sid)} has ${w.pendingTools} tool(s) in-flight, skipping abort check`);
|
|
13574
|
-
w.lastSubagentCheckAt = now;
|
|
13575
13574
|
continue;
|
|
13576
13575
|
}
|
|
13577
|
-
|
|
13578
|
-
if (hasActiveTool) {
|
|
13579
|
-
await log("debug", `Session ${short(sid)} has active tool call, skipping abort check`);
|
|
13580
|
-
w.lastSubagentCheckAt = now;
|
|
13576
|
+
if (numBusy > 1)
|
|
13581
13577
|
continue;
|
|
13582
|
-
|
|
13583
|
-
const subStatus = await checkSubagentStatus(sid);
|
|
13584
|
-
if (subStatus.status === "idle" || subStatus.status === "unknown") {
|
|
13585
|
-
await log("info", `Parent ${short(sid)} stuck with no active subagents. Triggering abort+resume.`);
|
|
13586
|
-
tryAbortAndResume(sid, w);
|
|
13578
|
+
if (now - w.lastSubagentCheckAt < checkIntervalMs * 2)
|
|
13587
13579
|
continue;
|
|
13588
|
-
|
|
13589
|
-
|
|
13590
|
-
if (
|
|
13591
|
-
await log("
|
|
13592
|
-
|
|
13593
|
-
|
|
13594
|
-
|
|
13580
|
+
w.lastSubagentCheckAt = now;
|
|
13581
|
+
if (w.lastActivityAt > 0 && now - w.lastActivityAt > subagentWaitMs) {
|
|
13582
|
+
if (realStatus === "busy") {
|
|
13583
|
+
await log("debug", `Session ${short(sid)} is still busy (real status), skipping abort`);
|
|
13584
|
+
w.lastSubagentCheckAt = now;
|
|
13585
|
+
continue;
|
|
13586
|
+
}
|
|
13587
|
+
if (hasInflightTools(w)) {
|
|
13588
|
+
await log("debug", `Session ${short(sid)} has ${w.pendingTools} tool(s) in-flight, skipping abort check`);
|
|
13589
|
+
w.lastSubagentCheckAt = now;
|
|
13590
|
+
continue;
|
|
13595
13591
|
}
|
|
13596
|
-
continue;
|
|
13597
|
-
}
|
|
13598
|
-
}
|
|
13599
|
-
const idle = now - w.lastActivityAt;
|
|
13600
|
-
if (idle >= chunkTimeoutMs + gracePeriodMs) {
|
|
13601
|
-
if (hasInflightTools(w)) {
|
|
13602
|
-
await log("debug", `Session ${short(sid)} has ${w.pendingTools} tool(s) in-flight, skipping stall recovery`);
|
|
13603
|
-
w.lastSubagentCheckAt = now;
|
|
13604
|
-
} else {
|
|
13605
13592
|
const hasActiveTool = await checkSessionHasActiveTool(sid);
|
|
13606
13593
|
if (hasActiveTool) {
|
|
13607
|
-
await log("debug", `Session ${short(sid)} has active tool call, skipping
|
|
13594
|
+
await log("debug", `Session ${short(sid)} has active tool call, skipping abort check`);
|
|
13608
13595
|
w.lastSubagentCheckAt = now;
|
|
13609
|
-
|
|
13610
|
-
|
|
13611
|
-
|
|
13612
|
-
|
|
13613
|
-
|
|
13614
|
-
|
|
13596
|
+
continue;
|
|
13597
|
+
}
|
|
13598
|
+
const subStatus = await checkSubagentStatus(sid);
|
|
13599
|
+
if (subStatus.status === "idle" || subStatus.status === "unknown") {
|
|
13600
|
+
await log("info", `Parent ${short(sid)} stuck with no active subagents. Triggering abort+resume.`);
|
|
13601
|
+
tryAbortAndResume(sid, w);
|
|
13602
|
+
continue;
|
|
13603
|
+
} else if (subStatus.status === "crashed" && subStatus.stuckSid) {
|
|
13604
|
+
const recovered = await recoverSubagent(subStatus.stuckSid);
|
|
13605
|
+
if (recovered) {
|
|
13606
|
+
await log("info", `Sent recovery prompt to stuck subagent ${short(subStatus.stuckSid)}, waiting...`);
|
|
13607
|
+
} else {
|
|
13608
|
+
await log("info", `Parent ${short(sid)} subagent recovery failed. Triggering abort+resume.`);
|
|
13609
|
+
tryAbortAndResume(sid, w);
|
|
13610
|
+
}
|
|
13611
|
+
continue;
|
|
13612
|
+
}
|
|
13613
|
+
}
|
|
13614
|
+
const idle = now - w.lastActivityAt;
|
|
13615
|
+
if (idle >= chunkTimeoutMs + gracePeriodMs) {
|
|
13616
|
+
if (hasInflightTools(w)) {
|
|
13617
|
+
await log("debug", `Session ${short(sid)} has ${w.pendingTools} tool(s) in-flight, skipping stall recovery`);
|
|
13618
|
+
w.lastSubagentCheckAt = now;
|
|
13619
|
+
} else {
|
|
13620
|
+
const hasActiveTool = await checkSessionHasActiveTool(sid);
|
|
13621
|
+
if (hasActiveTool) {
|
|
13622
|
+
await log("debug", `Session ${short(sid)} has active tool call, skipping stall recovery`);
|
|
13623
|
+
w.lastSubagentCheckAt = now;
|
|
13624
|
+
} else if (w.resumeAttempts < maxRetries) {
|
|
13625
|
+
tryResume(sid, w, "Stream stall");
|
|
13626
|
+
} else if (!w.gaveUp) {
|
|
13627
|
+
w.gaveUp = true;
|
|
13628
|
+
dbg(`State transition on ${short(sid)}: gaveUp=false -> true`);
|
|
13629
|
+
log("warn", `${short(sid)} - all ${maxRetries} retries exhausted.`);
|
|
13630
|
+
}
|
|
13615
13631
|
}
|
|
13616
13632
|
}
|
|
13617
13633
|
}
|
|
13618
|
-
|
|
13619
|
-
|
|
13620
|
-
|
|
13621
|
-
|
|
13622
|
-
|
|
13623
|
-
|
|
13624
|
-
|
|
13625
|
-
|
|
13626
|
-
|
|
13634
|
+
for (const [sid, w] of sessions) {
|
|
13635
|
+
if (w.pendingRecovery && w.status === "idle" && !w.userCancelled && !w.aborting && !w.continuing && !w.gaveUp && w.recoveryAttempts === 0) {
|
|
13636
|
+
dbg(`Pending recovery check on ${short(sid)}: pendingRecovery=${w.pendingRecovery}, status=${w.status}, userCancelled=${w.userCancelled}, aborting=${w.aborting}, continuing=${w.continuing}, gaveUp=${w.gaveUp}, recoveryAttempts=${w.recoveryAttempts}, pendingRecoveryAt=${w.pendingRecoveryAt}`);
|
|
13637
|
+
const elapsed = Date.now() - w.pendingRecoveryAt;
|
|
13638
|
+
const requiredBackoff2 = backoffMs(w.recoveryAttempts, baseBackoffMs, maxBackoffMs);
|
|
13639
|
+
if (elapsed < requiredBackoff2) {
|
|
13640
|
+
dbg(`Backoff check on ${short(sid)}: elapsed=${elapsed}ms, required=${requiredBackoff2}ms, attempt=${w.recoveryAttempts}, pass=false`);
|
|
13641
|
+
dbg(`Pending recovery on ${short(sid)} waiting for backoff: ${requiredBackoff2 - elapsed}ms remaining`);
|
|
13642
|
+
continue;
|
|
13643
|
+
}
|
|
13644
|
+
dbg(`Backoff check on ${short(sid)}: elapsed=${elapsed}ms, required=${requiredBackoff2}ms, attempt=${w.recoveryAttempts}, pass=true`);
|
|
13645
|
+
await log("info", `Pending recovery triggered on ${short(sid)}: reason=${w.pendingRecoveryReason}, attempt=${w.recoveryAttempts + 1}, maxRetries=${maxRecoveryRetries}`);
|
|
13646
|
+
dbg(`Recovery timing on ${short(sid)}: detectionToAttemptMs=${Date.now() - w.pendingRecoveryAt}`);
|
|
13647
|
+
w.recoveryAttempts++;
|
|
13648
|
+
dbg(`State transition on ${short(sid)}: recoveryAttempts=${w.recoveryAttempts - 1} -> ${w.recoveryAttempts}`);
|
|
13649
|
+
try {
|
|
13650
|
+
await sendContinuePrompt(sid, continuePrompt, w);
|
|
13651
|
+
} catch (err) {
|
|
13652
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
13653
|
+
await log("warn", `${short(sid)} - pending recovery failed: ${errMsg}`);
|
|
13654
|
+
w.recoveryAttempts = 0;
|
|
13655
|
+
}
|
|
13656
|
+
}
|
|
13657
|
+
if (w.status !== "idle")
|
|
13658
|
+
continue;
|
|
13659
|
+
if (w.isSubagent)
|
|
13660
|
+
continue;
|
|
13661
|
+
if (w.userCancelled || w.completionSignaled)
|
|
13662
|
+
continue;
|
|
13663
|
+
if (w.continuing)
|
|
13664
|
+
continue;
|
|
13665
|
+
if (busyCount() !== 0)
|
|
13666
|
+
continue;
|
|
13667
|
+
const open = getOpenTodos(w.todos || []);
|
|
13668
|
+
if (open.length === 0)
|
|
13669
|
+
continue;
|
|
13670
|
+
if (w.todoNudgeAttempts >= maxRetries)
|
|
13671
|
+
continue;
|
|
13672
|
+
const elapsedSinceLastNudge = Date.now() - w.lastRetryAt;
|
|
13673
|
+
const requiredBackoff = backoffMs(w.todoNudgeAttempts, baseBackoffMs, maxBackoffMs);
|
|
13674
|
+
if (w.lastRetryAt > 0 && elapsedSinceLastNudge < requiredBackoff)
|
|
13675
|
+
continue;
|
|
13676
|
+
const isCelebration = await lastAssistantEndsWithCelebration(sid);
|
|
13677
|
+
if (isCelebration) {
|
|
13678
|
+
w.toolTextRecovered = true;
|
|
13679
|
+
w.completionSignaled = true;
|
|
13627
13680
|
continue;
|
|
13628
13681
|
}
|
|
13629
|
-
|
|
13630
|
-
|
|
13631
|
-
|
|
13632
|
-
|
|
13633
|
-
|
|
13634
|
-
try {
|
|
13635
|
-
await sendContinuePrompt(sid, continuePrompt, w);
|
|
13636
|
-
} catch (err) {
|
|
13637
|
-
const errMsg = err instanceof Error ? err.message : String(err);
|
|
13638
|
-
await log("warn", `${short(sid)} - pending recovery failed: ${errMsg}`);
|
|
13639
|
-
w.recoveryAttempts = 0;
|
|
13682
|
+
const reminder = buildOpenTodosReminder(w.todos || []);
|
|
13683
|
+
const sent = await tryResume(sid, w, "Idle with open todos (periodic)", reminder);
|
|
13684
|
+
if (sent) {
|
|
13685
|
+
w.todoNudgeAttempts++;
|
|
13686
|
+
await log("info", `${short(sid)} - idle periodic recheck: nudge ${w.todoNudgeAttempts}/${maxRetries}`);
|
|
13640
13687
|
}
|
|
13641
13688
|
}
|
|
13642
|
-
|
|
13643
|
-
|
|
13644
|
-
if (w.isSubagent)
|
|
13645
|
-
continue;
|
|
13646
|
-
if (w.userCancelled || w.completionSignaled)
|
|
13647
|
-
continue;
|
|
13648
|
-
if (w.continuing)
|
|
13649
|
-
continue;
|
|
13650
|
-
if (busyCount() !== 0)
|
|
13651
|
-
continue;
|
|
13652
|
-
const open = getOpenTodos(w.todos || []);
|
|
13653
|
-
if (open.length === 0)
|
|
13654
|
-
continue;
|
|
13655
|
-
if (w.todoNudgeAttempts >= maxRetries)
|
|
13656
|
-
continue;
|
|
13657
|
-
const elapsedSinceLastNudge = Date.now() - w.lastRetryAt;
|
|
13658
|
-
const requiredBackoff = backoffMs(w.todoNudgeAttempts, baseBackoffMs, maxBackoffMs);
|
|
13659
|
-
if (w.lastRetryAt > 0 && elapsedSinceLastNudge < requiredBackoff)
|
|
13660
|
-
continue;
|
|
13661
|
-
const isCelebration = await lastAssistantEndsWithCelebration(sid);
|
|
13662
|
-
if (isCelebration) {
|
|
13663
|
-
w.toolTextRecovered = true;
|
|
13664
|
-
w.completionSignaled = true;
|
|
13665
|
-
continue;
|
|
13666
|
-
}
|
|
13667
|
-
const reminder = buildOpenTodosReminder(w.todos || []);
|
|
13668
|
-
const sent = await tryResume(sid, w, "Idle with open todos (periodic)", reminder);
|
|
13669
|
-
if (sent) {
|
|
13670
|
-
w.todoNudgeAttempts++;
|
|
13671
|
-
await log("info", `${short(sid)} - idle periodic recheck: nudge ${w.todoNudgeAttempts}/${maxRetries}`);
|
|
13672
|
-
}
|
|
13673
|
-
}
|
|
13674
|
-
cleanupIdleSessions();
|
|
13689
|
+
cleanupIdleSessions();
|
|
13690
|
+
}, "periodic timer");
|
|
13675
13691
|
}, checkIntervalMs);
|
|
13676
13692
|
if (timer.unref)
|
|
13677
13693
|
timer.unref();
|
|
13678
13694
|
discoveryTimer = setInterval(() => {
|
|
13679
|
-
discoverSessions();
|
|
13695
|
+
safe(discoverSessions, "discoveryTimer").catch(() => {});
|
|
13680
13696
|
}, SESSION_DISCOVERY_INTERVAL_MS);
|
|
13681
13697
|
if (discoveryTimer.unref)
|
|
13682
13698
|
discoveryTimer.unref();
|
|
@@ -13997,7 +14013,11 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13997
14013
|
initialised = true;
|
|
13998
14014
|
log("info", `opencode-auto-resume ready. timeout=${chunkTimeoutMs}ms, orphan=${subagentWaitMs}ms, loop=${loopMaxContinues}x/${loopWindowMs / 1000}s`);
|
|
13999
14015
|
}
|
|
14000
|
-
handleEvent(event)
|
|
14016
|
+
handleEvent(event).catch((e) => {
|
|
14017
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
14018
|
+
console.error(`[auto-resume] handleEvent error: ${msg}`);
|
|
14019
|
+
log("error", `handleEvent error: ${msg}`).catch(() => {});
|
|
14020
|
+
});
|
|
14001
14021
|
},
|
|
14002
14022
|
config: async () => {
|
|
14003
14023
|
log("info", `opencode-auto-resume config OK`);
|
package/package.json
CHANGED