opencode-auto-resume 1.0.24 → 1.1.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/dist/index.js +45 -14
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12346,6 +12346,7 @@ var ABORT_CONTINUE_DELAY_MS = 2000;
|
|
|
12346
12346
|
var DEFAULT_LOOP_MAX_CONTINUES = 3;
|
|
12347
12347
|
var DEFAULT_LOOP_WINDOW_MS = 10 * 60000;
|
|
12348
12348
|
var TOOL_TEXT_CHECK_DELAY_MS = 3000;
|
|
12349
|
+
var MIN_ACTIVITY_GAP_MS = 1000;
|
|
12349
12350
|
var MAX_IDLE_SESSIONS = 50;
|
|
12350
12351
|
var IDLE_CLEANUP_MS = 10 * 60000;
|
|
12351
12352
|
var SESSION_DISCOVERY_INTERVAL_MS = 60000;
|
|
@@ -12679,6 +12680,28 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12679
12680
|
return;
|
|
12680
12681
|
return msg.role ?? msg.info?.role;
|
|
12681
12682
|
}
|
|
12683
|
+
async function lastAssistantEndsWithCelebration(sid) {
|
|
12684
|
+
try {
|
|
12685
|
+
const msgs = await getSessionMessages(sid);
|
|
12686
|
+
for (let i = msgs.length - 1;i >= 0; i--) {
|
|
12687
|
+
const msg = msgs[i];
|
|
12688
|
+
if (roleOf(msg) !== "assistant")
|
|
12689
|
+
continue;
|
|
12690
|
+
const parts = msg.parts;
|
|
12691
|
+
if (!parts)
|
|
12692
|
+
continue;
|
|
12693
|
+
let text = "";
|
|
12694
|
+
for (const part of parts) {
|
|
12695
|
+
if (part.type === "text") {
|
|
12696
|
+
text += part.text ?? "";
|
|
12697
|
+
}
|
|
12698
|
+
}
|
|
12699
|
+
const normalized = text.trim().replace(/[.!?]+$/, "");
|
|
12700
|
+
return normalized.endsWith("\uD83C\uDF89");
|
|
12701
|
+
}
|
|
12702
|
+
} catch {}
|
|
12703
|
+
return false;
|
|
12704
|
+
}
|
|
12682
12705
|
async function getSessionStatusMap() {
|
|
12683
12706
|
try {
|
|
12684
12707
|
const response = await ctx.client.session.status();
|
|
@@ -13037,14 +13060,14 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13037
13060
|
if (!bestCandidate) {
|
|
13038
13061
|
const todos = w.todos || [];
|
|
13039
13062
|
const hasOpenTodos = todos.some((t) => t.status === "pending" || t.status === "in_progress");
|
|
13040
|
-
if (hasOpenTodos && busyCount() ===
|
|
13063
|
+
if (hasOpenTodos && busyCount() === 0) {
|
|
13041
13064
|
await log("info", `${short(sid)} - no activity detected but todos remain open (${todos.filter((t) => t.status === "pending" || t.status === "in_progress").length} tasks). Sending continue...`);
|
|
13042
13065
|
bestCandidate = {
|
|
13043
13066
|
prompt: "continue",
|
|
13044
13067
|
source: "idle-with-open-todos",
|
|
13045
13068
|
priority: 2
|
|
13046
13069
|
};
|
|
13047
|
-
} else if (hasOpenTodos && busyCount() >
|
|
13070
|
+
} else if (hasOpenTodos && busyCount() > 0) {
|
|
13048
13071
|
await log("debug", `${short(sid)} - todos remain open but ${busyCount()} sessions busy (subagents running), skipping continue`);
|
|
13049
13072
|
}
|
|
13050
13073
|
}
|
|
@@ -13054,7 +13077,7 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13054
13077
|
w.toolTextAttempts++;
|
|
13055
13078
|
await log("info", `${bestCandidate.source} detected on ${short(sid)}! ` + `Attempt ${w.toolTextAttempts}/${maxRetries}. Sending recovery prompt...`);
|
|
13056
13079
|
const timeSinceActivity = Date.now() - w.lastActivityAt;
|
|
13057
|
-
if (timeSinceActivity <
|
|
13080
|
+
if (timeSinceActivity < MIN_ACTIVITY_GAP_MS) {
|
|
13058
13081
|
await log("info", `${short(sid)} - skipping ${bestCandidate.source}, session was active ${Math.round(timeSinceActivity / 1000)}s ago`);
|
|
13059
13082
|
return;
|
|
13060
13083
|
}
|
|
@@ -13331,9 +13354,19 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13331
13354
|
if (!w.isSubagent) {
|
|
13332
13355
|
const todos = w.todos || [];
|
|
13333
13356
|
const hasOpenTodos = todos.some((t) => t.status === "pending" || t.status === "in_progress");
|
|
13334
|
-
if (hasOpenTodos && currentBusy ===
|
|
13335
|
-
|
|
13336
|
-
|
|
13357
|
+
if (hasOpenTodos && currentBusy === 0 && !w.toolTextRecovered) {
|
|
13358
|
+
const isCelebration = await lastAssistantEndsWithCelebration(sid);
|
|
13359
|
+
if (isCelebration) {
|
|
13360
|
+
await log("info", `${short(sid)} - \uD83C\uDF89 detected in idle handler, skipping continue`);
|
|
13361
|
+
w.toolTextRecovered = true;
|
|
13362
|
+
if (w.toolTextTimer) {
|
|
13363
|
+
clearTimeout(w.toolTextTimer);
|
|
13364
|
+
w.toolTextTimer = null;
|
|
13365
|
+
}
|
|
13366
|
+
} else {
|
|
13367
|
+
await log("info", `${short(sid)} - idle with ${todos.filter((t) => t.status === "pending" || t.status === "in_progress").length} open todos. Sending continue...`);
|
|
13368
|
+
tryResume(sid, w, "Idle with open todos");
|
|
13369
|
+
}
|
|
13337
13370
|
}
|
|
13338
13371
|
}
|
|
13339
13372
|
if (!w.toolTextRecovered && w.toolTextAttempts < maxRetries) {
|
|
@@ -13419,14 +13452,12 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13419
13452
|
break;
|
|
13420
13453
|
const props = ev.properties;
|
|
13421
13454
|
const todos = props?.todos ?? [];
|
|
13422
|
-
const w =
|
|
13423
|
-
|
|
13424
|
-
|
|
13425
|
-
|
|
13426
|
-
|
|
13427
|
-
|
|
13428
|
-
}));
|
|
13429
|
-
}
|
|
13455
|
+
const w = ensureWatch(sid);
|
|
13456
|
+
w.todos = todos.map((t) => ({
|
|
13457
|
+
content: t.content ?? "",
|
|
13458
|
+
status: t.status ?? "pending",
|
|
13459
|
+
priority: t.priority ?? "medium"
|
|
13460
|
+
}));
|
|
13430
13461
|
break;
|
|
13431
13462
|
}
|
|
13432
13463
|
case "session.error": {
|
package/package.json
CHANGED