opencode-auto-resume 1.0.19 → 1.0.21
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 +89 -32
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12583,9 +12583,9 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12583
12583
|
return;
|
|
12584
12584
|
}
|
|
12585
12585
|
w.continuing = true;
|
|
12586
|
+
let agent;
|
|
12587
|
+
let model;
|
|
12586
12588
|
try {
|
|
12587
|
-
let agent2;
|
|
12588
|
-
let model2;
|
|
12589
12589
|
const msgResp = await ctx.client.session.messages({ path: { id: sid } });
|
|
12590
12590
|
const msgs = extractMessages(msgResp);
|
|
12591
12591
|
for (let i = msgs.length - 1;i >= 0; i--) {
|
|
@@ -12594,11 +12594,11 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12594
12594
|
if (role === "user") {
|
|
12595
12595
|
const rawAgent = msg.agent;
|
|
12596
12596
|
if (typeof rawAgent === "string") {
|
|
12597
|
-
|
|
12597
|
+
agent = rawAgent;
|
|
12598
12598
|
} else {
|
|
12599
12599
|
const fallbackAgent = msg.info?.agent;
|
|
12600
12600
|
if (typeof fallbackAgent === "string") {
|
|
12601
|
-
|
|
12601
|
+
agent = fallbackAgent;
|
|
12602
12602
|
}
|
|
12603
12603
|
}
|
|
12604
12604
|
let rawModel = msg.model;
|
|
@@ -12606,7 +12606,7 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12606
12606
|
rawModel = msg.info?.model;
|
|
12607
12607
|
}
|
|
12608
12608
|
if (rawModel && typeof rawModel.providerID === "string" && typeof rawModel.modelID === "string") {
|
|
12609
|
-
|
|
12609
|
+
model = {
|
|
12610
12610
|
providerID: rawModel.providerID,
|
|
12611
12611
|
modelID: rawModel.modelID
|
|
12612
12612
|
};
|
|
@@ -12618,11 +12618,11 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12618
12618
|
path: { id: sid },
|
|
12619
12619
|
body: {
|
|
12620
12620
|
parts: [{ type: "text", text }],
|
|
12621
|
-
agent
|
|
12622
|
-
model
|
|
12621
|
+
agent,
|
|
12622
|
+
model
|
|
12623
12623
|
}
|
|
12624
12624
|
});
|
|
12625
|
-
await log("debug", `${short(sid)} - prompt sent with agent: ${
|
|
12625
|
+
await log("debug", `${short(sid)} - prompt sent with agent: ${agent ?? "(default)"}, model: ${model ? `${model.providerID}/${model.modelID}` : "(default)"}`);
|
|
12626
12626
|
recordContinue(sid);
|
|
12627
12627
|
w.lastRetryAt = Date.now();
|
|
12628
12628
|
} catch (err) {
|
|
@@ -12679,6 +12679,54 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12679
12679
|
return false;
|
|
12680
12680
|
}
|
|
12681
12681
|
}
|
|
12682
|
+
async function hasBusySubagents(parentSid) {
|
|
12683
|
+
try {
|
|
12684
|
+
const response = await ctx.client.session.list();
|
|
12685
|
+
const allSessions = extractMessages(response);
|
|
12686
|
+
for (const s of allSessions) {
|
|
12687
|
+
const sId = s.id;
|
|
12688
|
+
if (!sId || sId === parentSid)
|
|
12689
|
+
continue;
|
|
12690
|
+
const status = s.status;
|
|
12691
|
+
if (status === "busy")
|
|
12692
|
+
return true;
|
|
12693
|
+
}
|
|
12694
|
+
return false;
|
|
12695
|
+
} catch (err) {
|
|
12696
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
12697
|
+
await log("debug", `hasBusySubagents failed for ${short(parentSid)}: ${errMsg}`);
|
|
12698
|
+
return false;
|
|
12699
|
+
}
|
|
12700
|
+
}
|
|
12701
|
+
async function checkSessionHasActiveTool(sid) {
|
|
12702
|
+
try {
|
|
12703
|
+
const listResponse = await ctx.client.session.list();
|
|
12704
|
+
const sessions2 = extractMessages(listResponse);
|
|
12705
|
+
const currentSession = sessions2.find((s) => s.id === sid);
|
|
12706
|
+
const status = currentSession?.status;
|
|
12707
|
+
if (status === "busy") {
|
|
12708
|
+
await log("debug", `Session ${short(sid)} is busy, likely executing a tool`);
|
|
12709
|
+
return true;
|
|
12710
|
+
}
|
|
12711
|
+
const response = await ctx.client.session.messages({ path: { id: sid } });
|
|
12712
|
+
const messages = extractMessages(response);
|
|
12713
|
+
const lastMsg = messages[messages.length - 1];
|
|
12714
|
+
if (!lastMsg)
|
|
12715
|
+
return false;
|
|
12716
|
+
const rawRole = lastMsg?.role ?? lastMsg?.info?.role;
|
|
12717
|
+
if (rawRole !== "assistant")
|
|
12718
|
+
return false;
|
|
12719
|
+
const toolCall = lastMsg.toolCall;
|
|
12720
|
+
const toolCalls = lastMsg.tool_calls;
|
|
12721
|
+
const parts = lastMsg.parts;
|
|
12722
|
+
const hasToolCall = toolCall !== undefined || (toolCalls?.length ?? 0) > 0 || (parts?.some((p) => p.type === "tool-call" || p.type === "tool_use") ?? false);
|
|
12723
|
+
return hasToolCall;
|
|
12724
|
+
} catch (err) {
|
|
12725
|
+
const errMsg = err instanceof Error ? err.message : String(err);
|
|
12726
|
+
await log("debug", `checkSessionHasActiveTool failed for ${short(sid)}: ${errMsg}`);
|
|
12727
|
+
return false;
|
|
12728
|
+
}
|
|
12729
|
+
}
|
|
12682
12730
|
async function checkSubagentStatus(parentSid) {
|
|
12683
12731
|
try {
|
|
12684
12732
|
const response = await ctx.client.session.list();
|
|
@@ -12698,10 +12746,15 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12698
12746
|
const rawRole = lastMsg?.role ?? lastMsg?.info?.role;
|
|
12699
12747
|
if (lastMsg && rawRole === "assistant" && (("error" in lastMsg) || lastMsg.info && ("error" in lastMsg.info))) {
|
|
12700
12748
|
await log("debug", `Subagent ${short(sId)} appears crashed`);
|
|
12701
|
-
return "crashed";
|
|
12749
|
+
return { status: "crashed" };
|
|
12702
12750
|
}
|
|
12703
12751
|
const msgTime = lastMsg?.time?.created ?? lastMsg?.time;
|
|
12704
|
-
|
|
12752
|
+
if (!msgTime)
|
|
12753
|
+
continue;
|
|
12754
|
+
const toolCall = lastMsg.toolCall;
|
|
12755
|
+
const toolCalls = lastMsg.tool_calls;
|
|
12756
|
+
const parts = lastMsg.parts;
|
|
12757
|
+
const hasToolCall = toolCall !== undefined || (toolCalls?.length ?? 0) > 0 || (parts?.some((p) => p.type === "tool-call") ?? false);
|
|
12705
12758
|
const isStuck = hasToolCall ? now - msgTime > SUBAGENT_STUCK_MS * 3 : now - msgTime > SUBAGENT_STUCK_MS;
|
|
12706
12759
|
if (isStuck) {
|
|
12707
12760
|
await log("debug", `Subagent ${short(sId)} stuck - no new text in >${hasToolCall ? 3 : 1}min`);
|
|
@@ -12770,10 +12823,10 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12770
12823
|
}
|
|
12771
12824
|
return false;
|
|
12772
12825
|
}
|
|
12773
|
-
function trackToolCall(w,
|
|
12826
|
+
function trackToolCall(w, toolName) {
|
|
12774
12827
|
const now = Date.now();
|
|
12775
12828
|
w.recentToolCalls = w.recentToolCalls.filter((call) => now - call.at < 120000);
|
|
12776
|
-
w.recentToolCalls.push({ toolName
|
|
12829
|
+
w.recentToolCalls.push({ toolName, at: now });
|
|
12777
12830
|
const recentTools = w.recentToolCalls.slice(-15).map((call) => call.toolName);
|
|
12778
12831
|
if (recentTools.length < 6)
|
|
12779
12832
|
return false;
|
|
@@ -12816,18 +12869,18 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12816
12869
|
continue;
|
|
12817
12870
|
const toolCall = msg.toolCall;
|
|
12818
12871
|
if (toolCall && typeof toolCall === "object" && "name" in toolCall) {
|
|
12819
|
-
const
|
|
12820
|
-
if (
|
|
12821
|
-
trackToolCall(w,
|
|
12872
|
+
const toolName = toolCall.name;
|
|
12873
|
+
if (toolName) {
|
|
12874
|
+
trackToolCall(w, toolName);
|
|
12822
12875
|
}
|
|
12823
12876
|
}
|
|
12824
12877
|
const toolCalls = msg.tool_calls;
|
|
12825
12878
|
if (toolCalls) {
|
|
12826
12879
|
for (const tc of toolCalls) {
|
|
12827
12880
|
if (typeof tc === "object" && "name" in tc) {
|
|
12828
|
-
const
|
|
12829
|
-
if (
|
|
12830
|
-
trackToolCall(w,
|
|
12881
|
+
const toolName = tc.name;
|
|
12882
|
+
if (toolName) {
|
|
12883
|
+
trackToolCall(w, toolName);
|
|
12831
12884
|
}
|
|
12832
12885
|
}
|
|
12833
12886
|
}
|
|
@@ -12847,14 +12900,15 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12847
12900
|
isReasoning = true;
|
|
12848
12901
|
} else if (partType === "tool_use") {
|
|
12849
12902
|
isToolUse = true;
|
|
12850
|
-
const
|
|
12851
|
-
text = `tool_use: ${
|
|
12903
|
+
const toolName = part.name ?? "unknown";
|
|
12904
|
+
text = `tool_use: ${toolName}`;
|
|
12852
12905
|
} else {
|
|
12853
12906
|
continue;
|
|
12854
12907
|
}
|
|
12855
12908
|
allAssistantText += text + `
|
|
12856
12909
|
`;
|
|
12857
12910
|
if (isToolUse) {
|
|
12911
|
+
const toolName = part.name ?? "unknown";
|
|
12858
12912
|
const isLoop = trackToolCall(w, toolName);
|
|
12859
12913
|
if (isLoop && w.toolLoopAttempts < 2) {
|
|
12860
12914
|
w.toolLoopAttempts++;
|
|
@@ -12880,8 +12934,8 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
12880
12934
|
if (containsToolCallAsText(text)) {
|
|
12881
12935
|
const toolMatch = text.match(/<function=([a-zA-Z_]+)/) || text.match(/<invoke\s+name=([a-zA-Z_]+)/) || text.match(/"name":\s*"([a-zA-Z_]+)/);
|
|
12882
12936
|
if (toolMatch) {
|
|
12883
|
-
const
|
|
12884
|
-
const isLoop = trackToolCall(w,
|
|
12937
|
+
const toolName = toolMatch[1] || "unknown";
|
|
12938
|
+
const isLoop = trackToolCall(w, toolName);
|
|
12885
12939
|
if (isLoop && w.toolLoopAttempts < 2) {
|
|
12886
12940
|
w.toolLoopAttempts++;
|
|
12887
12941
|
const loopCandidate = {
|
|
@@ -13117,8 +13171,13 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13117
13171
|
tryAbortAndResume(sid, w);
|
|
13118
13172
|
}
|
|
13119
13173
|
} else if (subStatus.status === "idle") {
|
|
13120
|
-
|
|
13121
|
-
|
|
13174
|
+
const hasBusySub = await hasBusySubagents(sid);
|
|
13175
|
+
if (hasBusySub) {
|
|
13176
|
+
await log("debug", `Subagents exist but not busy yet, waiting for startup...`);
|
|
13177
|
+
} else {
|
|
13178
|
+
await log("info", `Parent ${short(sid)} stuck with no active subagents. Triggering abort+resume.`);
|
|
13179
|
+
tryAbortAndResume(sid, w);
|
|
13180
|
+
}
|
|
13122
13181
|
} else {
|
|
13123
13182
|
await log("debug", `Subagent still running, waiting...`);
|
|
13124
13183
|
}
|
|
@@ -13137,6 +13196,12 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13137
13196
|
continue;
|
|
13138
13197
|
w.lastSubagentCheckAt = now;
|
|
13139
13198
|
if (w.lastActivityAt > 0 && now - w.lastActivityAt > subagentWaitMs) {
|
|
13199
|
+
const hasActiveTool = await checkSessionHasActiveTool(sid);
|
|
13200
|
+
if (hasActiveTool) {
|
|
13201
|
+
await log("debug", `Parent ${short(sid)} has active tool call, skipping abort check`);
|
|
13202
|
+
w.lastSubagentCheckAt = now;
|
|
13203
|
+
continue;
|
|
13204
|
+
}
|
|
13140
13205
|
const subStatus = await checkSubagentStatus(sid);
|
|
13141
13206
|
if (subStatus.status === "idle" || subStatus.status === "unknown") {
|
|
13142
13207
|
await log("info", `Parent ${short(sid)} stuck with no active subagents. Triggering abort+resume.`);
|
|
@@ -13365,14 +13430,6 @@ var AutoResumePlugin = async (ctx, options) => {
|
|
|
13365
13430
|
},
|
|
13366
13431
|
config: async () => {
|
|
13367
13432
|
log("info", `opencode-auto-resume config OK`);
|
|
13368
|
-
if (ctx.ui && typeof ctx.ui.toast === "function") {
|
|
13369
|
-
ctx.ui.toast({
|
|
13370
|
-
title: "Auto-Resume Plugin",
|
|
13371
|
-
message: `Loaded with ${chunkTimeoutMs}ms timeout, ${loopMaxContinues} loop attempts`,
|
|
13372
|
-
variant: "success",
|
|
13373
|
-
duration: 5000
|
|
13374
|
-
});
|
|
13375
|
-
}
|
|
13376
13433
|
},
|
|
13377
13434
|
tool: {
|
|
13378
13435
|
task_complete: taskCompleteTool
|
package/package.json
CHANGED