@sideboard-ai/core 0.1.307 → 0.1.309
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/agents/cursor-runner.cjs +36 -1
- package/dist/agents/cursor-runner.js +17 -5
- package/dist/{agents-IWNQOQOU.js → agents-DG2UPJ6N.js} +4 -4
- package/dist/{agents-PGU5WVSO.js → agents-LK6JGQRF.js} +2 -2
- package/dist/{chunk-HO5R3ZRH.js → chunk-5XNT6BCG.js} +40 -2
- package/dist/{chunk-F36QRDM4.js → chunk-7Q327QF2.js} +1 -1
- package/dist/{chunk-5SFA27CF.js → chunk-AILQRQ26.js} +14 -3
- package/dist/{chunk-G2L3CR3A.js → chunk-FMSLOWKR.js} +3 -3
- package/dist/{chunk-5XQ43YZU.js → chunk-I5TESHDN.js} +9 -2
- package/dist/{chunk-R5RQLKMP.js → chunk-M6PAT6HG.js} +47 -13
- package/dist/{chunk-YJBUYGPN.js → chunk-NCHOTN3C.js} +1 -1
- package/dist/{chunk-IEOOYBYT.js → chunk-OU5V56OI.js} +24 -10
- package/dist/{chunk-MMVMQ34G.js → chunk-UA3YKQ3D.js} +1 -1
- package/dist/{chunk-OVNIP265.js → chunk-VBVSJUM2.js} +51 -6
- package/dist/{chunk-EZYZGDWU.js → chunk-VXI7FFGO.js} +1 -1
- package/dist/{conductor-ZFRXTVGP.js → conductor-AMZ5SKG2.js} +2 -2
- package/dist/{conductor-YBXURAUL.js → conductor-OFXA5BST.js} +3 -3
- package/dist/index.cjs +131 -27
- package/dist/index.d.cts +53 -3
- package/dist/index.d.ts +53 -3
- package/dist/index.js +46 -25
- package/dist/mcp/run-stdio.cjs +42 -10
- package/dist/mcp/run-stdio.js +4 -4
- package/dist/{orchestrator-MB2Q6KIR.js → orchestrator-4OIMDLIR.js} +4 -4
- package/dist/{orchestrator-XRTUGSKX.js → orchestrator-T76JRIIN.js} +6 -6
- package/package.json +1 -1
|
@@ -638,6 +638,33 @@ var CURSOR_STREAM_CUTOFF = /nghttp2|premature close|\[unavailable\]\s+error\b|ht
|
|
|
638
638
|
function looksLikeCursorStreamCutOff(text) {
|
|
639
639
|
return CURSOR_STREAM_CUTOFF.test(text.trim());
|
|
640
640
|
}
|
|
641
|
+
function cursorModelDisplayName(model) {
|
|
642
|
+
const raw = (model ?? "").trim();
|
|
643
|
+
if (!raw || /^(auto|default)$/i.test(raw)) return "";
|
|
644
|
+
if (/^grok-/i.test(raw)) return raw.replace(/^grok-/i, "Grok ");
|
|
645
|
+
return raw;
|
|
646
|
+
}
|
|
647
|
+
function formatCursorStreamIdleAfterToolsError(model) {
|
|
648
|
+
const label = cursorModelDisplayName(model);
|
|
649
|
+
return label ? `Cursor stopped responding after a tool call (${label})` : "Cursor stopped responding after a tool call";
|
|
650
|
+
}
|
|
651
|
+
function createCursorStreamToolProgress() {
|
|
652
|
+
return { completedTool: false, assistantAfterTool: false };
|
|
653
|
+
}
|
|
654
|
+
function noteCursorAgentEvent(state, event) {
|
|
655
|
+
if (event.type === "tool_result" && event.partial !== true) {
|
|
656
|
+
state.completedTool = true;
|
|
657
|
+
state.assistantAfterTool = false;
|
|
658
|
+
return;
|
|
659
|
+
}
|
|
660
|
+
if (event.type === "stdout" && !event.parentId) {
|
|
661
|
+
const text = typeof event.data === "string" ? event.data.trim() : "";
|
|
662
|
+
if (state.completedTool && text) state.assistantAfterTool = true;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
function isCursorIdleAfterCompletedTool(state) {
|
|
666
|
+
return state.completedTool && !state.assistantAfterTool;
|
|
667
|
+
}
|
|
641
668
|
|
|
642
669
|
// src/agents/error-detail.ts
|
|
643
670
|
function formatUnknownDetail(err) {
|
|
@@ -2081,25 +2108,29 @@ async function main() {
|
|
|
2081
2108
|
} catch {
|
|
2082
2109
|
}
|
|
2083
2110
|
let lastUsageRunId;
|
|
2111
|
+
const toolProgress = createCursorStreamToolProgress();
|
|
2084
2112
|
const run2 = await sendPrompt(agent, prompt, {
|
|
2085
2113
|
onDelta: ({ update }) => {
|
|
2086
2114
|
bump();
|
|
2087
2115
|
for (const event of cursorDeltaToEvents(update)) {
|
|
2116
|
+
noteCursorAgentEvent(toolProgress, event);
|
|
2088
2117
|
stream.push(event);
|
|
2089
2118
|
}
|
|
2090
2119
|
}
|
|
2091
2120
|
});
|
|
2092
2121
|
liveRun = run2;
|
|
2093
2122
|
let streamIdle = false;
|
|
2123
|
+
let streamIdleAfterTools = false;
|
|
2094
2124
|
try {
|
|
2095
2125
|
for await (const msg of iterateUntilIdle(
|
|
2096
2126
|
run2.stream(),
|
|
2097
2127
|
CURSOR_STREAM_IDLE_MS,
|
|
2098
2128
|
() => {
|
|
2099
2129
|
streamIdle = true;
|
|
2130
|
+
streamIdleAfterTools = isCursorIdleAfterCompletedTool(toolProgress);
|
|
2100
2131
|
emit({
|
|
2101
2132
|
type: "stderr",
|
|
2102
|
-
data: "Cursor stream idle \u2014 finishing the turn (SDK stream did not close)"
|
|
2133
|
+
data: streamIdleAfterTools ? `Cursor run failed: ${formatCursorStreamIdleAfterToolsError(req.model)}` : "Cursor stream idle \u2014 finishing the turn (SDK stream did not close)"
|
|
2103
2134
|
});
|
|
2104
2135
|
void cancelLiveRun();
|
|
2105
2136
|
},
|
|
@@ -2111,6 +2142,7 @@ async function main() {
|
|
|
2111
2142
|
lastUsageRunId = sdkMsg.run_id.trim();
|
|
2112
2143
|
}
|
|
2113
2144
|
for (const event of cursorSdkMessageToEvents(msg)) {
|
|
2145
|
+
noteCursorAgentEvent(toolProgress, event);
|
|
2114
2146
|
stream.push(event);
|
|
2115
2147
|
}
|
|
2116
2148
|
}
|
|
@@ -2121,6 +2153,9 @@ async function main() {
|
|
|
2121
2153
|
setTimeout(() => resolve2({ status: "cancelled" }), 5e3);
|
|
2122
2154
|
})
|
|
2123
2155
|
]) : await run2.wait();
|
|
2156
|
+
if (streamIdleAfterTools) {
|
|
2157
|
+
return 2;
|
|
2158
|
+
}
|
|
2124
2159
|
if (result.status === "error") {
|
|
2125
2160
|
const detail = formatUnknownDetail(result.error);
|
|
2126
2161
|
if (isAgentBusyError(detail)) {
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
guardCursorCustomTool,
|
|
6
6
|
shouldReturnRunErrorToAgent,
|
|
7
7
|
sideboardCursorRpcTools
|
|
8
|
-
} from "../chunk-
|
|
8
|
+
} from "../chunk-NCHOTN3C.js";
|
|
9
9
|
import {
|
|
10
10
|
createAgentStreamCoalescer
|
|
11
11
|
} from "../chunk-AXQ4ZWHK.js";
|
|
@@ -20,12 +20,16 @@ import {
|
|
|
20
20
|
fetchCursorTurnCostUsd,
|
|
21
21
|
importCursorSdk,
|
|
22
22
|
resolveCursorSdkRoot
|
|
23
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-UA3YKQ3D.js";
|
|
24
24
|
import {
|
|
25
25
|
TOOL_RESULT_STORE_MAX_CHARS,
|
|
26
|
+
createCursorStreamToolProgress,
|
|
27
|
+
formatCursorStreamIdleAfterToolsError,
|
|
26
28
|
formatUnknownDetail,
|
|
27
|
-
|
|
28
|
-
|
|
29
|
+
isCursorIdleAfterCompletedTool,
|
|
30
|
+
looksLikeCursorStreamCutOff,
|
|
31
|
+
noteCursorAgentEvent
|
|
32
|
+
} from "../chunk-5XNT6BCG.js";
|
|
29
33
|
import "../chunk-6K64FJDD.js";
|
|
30
34
|
import {
|
|
31
35
|
cursorSdkStoreDir
|
|
@@ -829,25 +833,29 @@ async function main() {
|
|
|
829
833
|
} catch {
|
|
830
834
|
}
|
|
831
835
|
let lastUsageRunId;
|
|
836
|
+
const toolProgress = createCursorStreamToolProgress();
|
|
832
837
|
const run = await sendPrompt(agent, prompt, {
|
|
833
838
|
onDelta: ({ update }) => {
|
|
834
839
|
bump();
|
|
835
840
|
for (const event of cursorDeltaToEvents(update)) {
|
|
841
|
+
noteCursorAgentEvent(toolProgress, event);
|
|
836
842
|
stream.push(event);
|
|
837
843
|
}
|
|
838
844
|
}
|
|
839
845
|
});
|
|
840
846
|
liveRun = run;
|
|
841
847
|
let streamIdle = false;
|
|
848
|
+
let streamIdleAfterTools = false;
|
|
842
849
|
try {
|
|
843
850
|
for await (const msg of iterateUntilIdle(
|
|
844
851
|
run.stream(),
|
|
845
852
|
CURSOR_STREAM_IDLE_MS,
|
|
846
853
|
() => {
|
|
847
854
|
streamIdle = true;
|
|
855
|
+
streamIdleAfterTools = isCursorIdleAfterCompletedTool(toolProgress);
|
|
848
856
|
emit({
|
|
849
857
|
type: "stderr",
|
|
850
|
-
data: "Cursor stream idle \u2014 finishing the turn (SDK stream did not close)"
|
|
858
|
+
data: streamIdleAfterTools ? `Cursor run failed: ${formatCursorStreamIdleAfterToolsError(req.model)}` : "Cursor stream idle \u2014 finishing the turn (SDK stream did not close)"
|
|
851
859
|
});
|
|
852
860
|
void cancelLiveRun();
|
|
853
861
|
},
|
|
@@ -859,6 +867,7 @@ async function main() {
|
|
|
859
867
|
lastUsageRunId = sdkMsg.run_id.trim();
|
|
860
868
|
}
|
|
861
869
|
for (const event of cursorSdkMessageToEvents(msg)) {
|
|
870
|
+
noteCursorAgentEvent(toolProgress, event);
|
|
862
871
|
stream.push(event);
|
|
863
872
|
}
|
|
864
873
|
}
|
|
@@ -869,6 +878,9 @@ async function main() {
|
|
|
869
878
|
setTimeout(() => resolve2({ status: "cancelled" }), 5e3);
|
|
870
879
|
})
|
|
871
880
|
]) : await run.wait();
|
|
881
|
+
if (streamIdleAfterTools) {
|
|
882
|
+
return 2;
|
|
883
|
+
}
|
|
872
884
|
if (result.status === "error") {
|
|
873
885
|
const detail = formatUnknownDetail(result.error);
|
|
874
886
|
if (isAgentBusyError(detail)) {
|
|
@@ -37,9 +37,9 @@ import {
|
|
|
37
37
|
planModeTurnInstruction,
|
|
38
38
|
resolveCursorModelId,
|
|
39
39
|
resolveQuotaFallbackAgent
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-FMSLOWKR.js";
|
|
41
41
|
import "./chunk-VEVFHO6K.js";
|
|
42
|
-
import "./chunk-
|
|
42
|
+
import "./chunk-7Q327QF2.js";
|
|
43
43
|
import {
|
|
44
44
|
getAgentSetupInfo,
|
|
45
45
|
installAgent,
|
|
@@ -67,8 +67,8 @@ import {
|
|
|
67
67
|
preferredCursorCostCents,
|
|
68
68
|
resolveCursorSdkRoot,
|
|
69
69
|
turnCostUsdFromCursorUsage
|
|
70
|
-
} from "./chunk-
|
|
71
|
-
import "./chunk-
|
|
70
|
+
} from "./chunk-UA3YKQ3D.js";
|
|
71
|
+
import "./chunk-5XNT6BCG.js";
|
|
72
72
|
import "./chunk-6K64FJDD.js";
|
|
73
73
|
import "./chunk-LG6RJBIY.js";
|
|
74
74
|
import {
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
resolveCursorSdkRoot,
|
|
47
47
|
resolveQuotaFallbackAgent,
|
|
48
48
|
turnCostUsdFromCursorUsage
|
|
49
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-VXI7FFGO.js";
|
|
50
50
|
import {
|
|
51
51
|
getAgentSetupInfo,
|
|
52
52
|
installAgent,
|
|
@@ -62,7 +62,7 @@ import {
|
|
|
62
62
|
import "./chunk-42JGPPVS.js";
|
|
63
63
|
import "./chunk-PXMLMBMI.js";
|
|
64
64
|
import "./chunk-2GPQZZLY.js";
|
|
65
|
-
import "./chunk-
|
|
65
|
+
import "./chunk-I5TESHDN.js";
|
|
66
66
|
import "./chunk-X3FSWWW2.js";
|
|
67
67
|
import "./chunk-DLGGLV2M.js";
|
|
68
68
|
import "./chunk-N2WW62LF.js";
|
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
// src/agents/cursor-stream-cutoff.ts
|
|
2
2
|
var CURSOR_STREAM_CUTOFF = /nghttp2|premature close|\[unavailable\]\s+error\b|http\/2 stream closed|\bcancel \(0x8\)|error code cancel\b/i;
|
|
3
|
+
var CURSOR_STREAM_IDLE_AFTER_TOOLS = /stopped responding after a tool call/i;
|
|
3
4
|
var CURSOR_STREAM_CUTOFF_CONTINUE_LIMIT = 3;
|
|
4
5
|
function looksLikeCursorStreamCutOff(text) {
|
|
5
6
|
return CURSOR_STREAM_CUTOFF.test(text.trim());
|
|
6
7
|
}
|
|
8
|
+
function looksLikeCursorStreamIdleAfterTools(text) {
|
|
9
|
+
return CURSOR_STREAM_IDLE_AFTER_TOOLS.test(text.trim());
|
|
10
|
+
}
|
|
11
|
+
function looksLikeCursorStreamFailure(text) {
|
|
12
|
+
return looksLikeCursorStreamCutOff(text) || looksLikeCursorStreamIdleAfterTools(text);
|
|
13
|
+
}
|
|
7
14
|
function cursorStreamCutOffContinueLimit(detail) {
|
|
8
15
|
if (looksLikeCursorStreamCutOff(detail) || /connection stalled/i.test(detail)) {
|
|
9
16
|
return CURSOR_STREAM_CUTOFF_CONTINUE_LIMIT;
|
|
@@ -15,6 +22,33 @@ function nextCrashContinueCount(detail, used) {
|
|
|
15
22
|
if (used >= limit) return null;
|
|
16
23
|
return used + 1;
|
|
17
24
|
}
|
|
25
|
+
function cursorModelDisplayName(model) {
|
|
26
|
+
const raw = (model ?? "").trim();
|
|
27
|
+
if (!raw || /^(auto|default)$/i.test(raw)) return "";
|
|
28
|
+
if (/^grok-/i.test(raw)) return raw.replace(/^grok-/i, "Grok ");
|
|
29
|
+
return raw;
|
|
30
|
+
}
|
|
31
|
+
function formatCursorStreamIdleAfterToolsError(model) {
|
|
32
|
+
const label = cursorModelDisplayName(model);
|
|
33
|
+
return label ? `Cursor stopped responding after a tool call (${label})` : "Cursor stopped responding after a tool call";
|
|
34
|
+
}
|
|
35
|
+
function createCursorStreamToolProgress() {
|
|
36
|
+
return { completedTool: false, assistantAfterTool: false };
|
|
37
|
+
}
|
|
38
|
+
function noteCursorAgentEvent(state, event) {
|
|
39
|
+
if (event.type === "tool_result" && event.partial !== true) {
|
|
40
|
+
state.completedTool = true;
|
|
41
|
+
state.assistantAfterTool = false;
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
if (event.type === "stdout" && !event.parentId) {
|
|
45
|
+
const text = typeof event.data === "string" ? event.data.trim() : "";
|
|
46
|
+
if (state.completedTool && text) state.assistantAfterTool = true;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function isCursorIdleAfterCompletedTool(state) {
|
|
50
|
+
return state.completedTool && !state.assistantAfterTool;
|
|
51
|
+
}
|
|
18
52
|
|
|
19
53
|
// src/agents/error-detail.ts
|
|
20
54
|
function formatUnknownDetail(err) {
|
|
@@ -223,7 +257,7 @@ function looksLikeRetryableRunnerCrash(text) {
|
|
|
223
257
|
if (looksLikeInvalidAgentSession(text)) return false;
|
|
224
258
|
if (looksLikeV8Oom(text)) return false;
|
|
225
259
|
if (looksLikeHugeToolResultDump(text)) return true;
|
|
226
|
-
if (
|
|
260
|
+
if (looksLikeCursorStreamFailure(text)) return true;
|
|
227
261
|
if (looksLikeBrightsyEmptyCompletion(text)) return true;
|
|
228
262
|
const lower = text.trim().toLowerCase();
|
|
229
263
|
if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
|
|
@@ -300,7 +334,7 @@ function humanizeAgentFailDetail(detail) {
|
|
|
300
334
|
if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
|
|
301
335
|
return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
302
336
|
}
|
|
303
|
-
if (/connection stalled/.test(lower) ||
|
|
337
|
+
if (/connection stalled/.test(lower) || looksLikeCursorStreamFailure(raw)) {
|
|
304
338
|
return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
305
339
|
}
|
|
306
340
|
if (looksLikeBrightsyEmptyCompletion(raw)) {
|
|
@@ -387,6 +421,10 @@ function formatTurnExitError(exitCode, stderrSummary) {
|
|
|
387
421
|
export {
|
|
388
422
|
looksLikeCursorStreamCutOff,
|
|
389
423
|
nextCrashContinueCount,
|
|
424
|
+
formatCursorStreamIdleAfterToolsError,
|
|
425
|
+
createCursorStreamToolProgress,
|
|
426
|
+
noteCursorAgentEvent,
|
|
427
|
+
isCursorIdleAfterCompletedTool,
|
|
390
428
|
formatUnknownDetail,
|
|
391
429
|
extractJsonErrorMessage,
|
|
392
430
|
pushTurnStderr,
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
compactSummaryPart,
|
|
6
6
|
isInternalAgentStatusText,
|
|
7
7
|
lastAssistantMessageText
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-I5TESHDN.js";
|
|
9
9
|
import {
|
|
10
10
|
isCloudCoordinatorThread,
|
|
11
11
|
isGlobalThread,
|
|
@@ -1235,12 +1235,23 @@ function isAskUserToolName(name) {
|
|
|
1235
1235
|
const base = name.replace(/^mcp__sideboard__/i, "");
|
|
1236
1236
|
return ASK_USER_TOOL_RE.test(name) || /^ask_user$/i.test(base);
|
|
1237
1237
|
}
|
|
1238
|
+
function questionsFromToolPart(part) {
|
|
1239
|
+
const fromInput = parsePlanQuestionsInput(part.input);
|
|
1240
|
+
if (fromInput.length) return fromInput;
|
|
1241
|
+
const raw = part.result?.trim();
|
|
1242
|
+
if (!raw || !raw.startsWith("{")) return [];
|
|
1243
|
+
try {
|
|
1244
|
+
return parsePlanQuestionsInput(JSON.parse(raw));
|
|
1245
|
+
} catch {
|
|
1246
|
+
return [];
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1238
1249
|
function extractPendingPlanQuestions(parts) {
|
|
1239
1250
|
if (!parts?.length) return null;
|
|
1240
1251
|
for (let i = parts.length - 1; i >= 0; i--) {
|
|
1241
1252
|
const p = parts[i];
|
|
1242
1253
|
if (p.type !== "tool" || !isAskUserToolName(p.name)) continue;
|
|
1243
|
-
const questions =
|
|
1254
|
+
const questions = questionsFromToolPart(p);
|
|
1244
1255
|
if (!questions.length) continue;
|
|
1245
1256
|
return {
|
|
1246
1257
|
id: p.id || `ask-${i}`,
|
|
@@ -1676,7 +1687,7 @@ var PORT_RANGE_SIZE = 10;
|
|
|
1676
1687
|
var RECLAIM_RETRY_DELAY_MS = 40;
|
|
1677
1688
|
var RECLAIM_TRIES = 8;
|
|
1678
1689
|
async function killReclaimable(ports, worktreePath, signal) {
|
|
1679
|
-
const { killListenersOnPorts: killListenersOnPorts2, killStaleWorktreeListeners: killStaleWorktreeListeners2 } = await import("./conductor-
|
|
1690
|
+
const { killListenersOnPorts: killListenersOnPorts2, killStaleWorktreeListeners: killStaleWorktreeListeners2 } = await import("./conductor-AMZ5SKG2.js");
|
|
1680
1691
|
if (worktreePath) killStaleWorktreeListeners2(ports, worktreePath, signal);
|
|
1681
1692
|
else killListenersOnPorts2(ports);
|
|
1682
1693
|
}
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
looksLikeSkillBody,
|
|
10
10
|
skillCommandFromBody,
|
|
11
11
|
withEventParentId
|
|
12
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-7Q327QF2.js";
|
|
13
13
|
import {
|
|
14
14
|
isOrchestratorThread
|
|
15
15
|
} from "./chunk-5QX2NYXL.js";
|
|
@@ -45,13 +45,13 @@ import {
|
|
|
45
45
|
packagedMcpStdioPath,
|
|
46
46
|
parseCursorRunnerLine,
|
|
47
47
|
resolveNodeLaunch
|
|
48
|
-
} from "./chunk-
|
|
48
|
+
} from "./chunk-UA3YKQ3D.js";
|
|
49
49
|
import {
|
|
50
50
|
extractJsonErrorMessage,
|
|
51
51
|
formatUnknownDetail,
|
|
52
52
|
looksLikeAgentFailureMessage,
|
|
53
53
|
looksLikeBrightsyEmptyCompletion
|
|
54
|
-
} from "./chunk-
|
|
54
|
+
} from "./chunk-5XNT6BCG.js";
|
|
55
55
|
import {
|
|
56
56
|
run
|
|
57
57
|
} from "./chunk-QVN2WOKJ.js";
|
|
@@ -3,10 +3,17 @@
|
|
|
3
3
|
|
|
4
4
|
// src/agents/cursor-stream-cutoff.ts
|
|
5
5
|
var CURSOR_STREAM_CUTOFF = /nghttp2|premature close|\[unavailable\]\s+error\b|http\/2 stream closed|\bcancel \(0x8\)|error code cancel\b/i;
|
|
6
|
+
var CURSOR_STREAM_IDLE_AFTER_TOOLS = /stopped responding after a tool call/i;
|
|
6
7
|
var CURSOR_STREAM_CUTOFF_CONTINUE_LIMIT = 3;
|
|
7
8
|
function looksLikeCursorStreamCutOff(text) {
|
|
8
9
|
return CURSOR_STREAM_CUTOFF.test(text.trim());
|
|
9
10
|
}
|
|
11
|
+
function looksLikeCursorStreamIdleAfterTools(text) {
|
|
12
|
+
return CURSOR_STREAM_IDLE_AFTER_TOOLS.test(text.trim());
|
|
13
|
+
}
|
|
14
|
+
function looksLikeCursorStreamFailure(text) {
|
|
15
|
+
return looksLikeCursorStreamCutOff(text) || looksLikeCursorStreamIdleAfterTools(text);
|
|
16
|
+
}
|
|
10
17
|
function cursorStreamCutOffContinueLimit(detail) {
|
|
11
18
|
if (looksLikeCursorStreamCutOff(detail) || /connection stalled/i.test(detail)) {
|
|
12
19
|
return CURSOR_STREAM_CUTOFF_CONTINUE_LIMIT;
|
|
@@ -226,7 +233,7 @@ function looksLikeRetryableRunnerCrash(text) {
|
|
|
226
233
|
if (looksLikeInvalidAgentSession(text)) return false;
|
|
227
234
|
if (looksLikeV8Oom(text)) return false;
|
|
228
235
|
if (looksLikeHugeToolResultDump(text)) return true;
|
|
229
|
-
if (
|
|
236
|
+
if (looksLikeCursorStreamFailure(text)) return true;
|
|
230
237
|
if (looksLikeBrightsyEmptyCompletion(text)) return true;
|
|
231
238
|
const lower = text.trim().toLowerCase();
|
|
232
239
|
if (/cannot find (?:package|module)|err_module_not_found/.test(lower)) return false;
|
|
@@ -303,7 +310,7 @@ function humanizeAgentFailDetail(detail) {
|
|
|
303
310
|
if (/corrupt local agent checkpoint|missing root blob|truncated crash dump/.test(lower)) {
|
|
304
311
|
return `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
305
312
|
}
|
|
306
|
-
if (/connection stalled/.test(lower) ||
|
|
313
|
+
if (/connection stalled/.test(lower) || looksLikeCursorStreamFailure(raw)) {
|
|
307
314
|
return /retry the turn/i.test(raw) ? raw : `${raw} \u2014 retry the turn (Sideboard will start a fresh Cursor session).`;
|
|
308
315
|
}
|
|
309
316
|
if (looksLikeBrightsyEmptyCompletion(raw)) {
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
parseSessionQuotaResetAt,
|
|
15
15
|
planModeTurnInstruction,
|
|
16
16
|
resolveQuotaFallbackAgent
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-FMSLOWKR.js";
|
|
18
18
|
import {
|
|
19
19
|
REVIEW_TAB_TITLE,
|
|
20
20
|
applyWorktreePkgCacheEnv,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
worktreeDevProcessKey,
|
|
56
56
|
worktreeRunProcessKey,
|
|
57
57
|
worktreeSetupProcessKey
|
|
58
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-VBVSJUM2.js";
|
|
59
59
|
import {
|
|
60
60
|
applyAgentEvent,
|
|
61
61
|
clipAgentEventForPaint,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
partsToAssistantText,
|
|
71
71
|
stripBrightsyNdjsonNoise,
|
|
72
72
|
toolDescription
|
|
73
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-7Q327QF2.js";
|
|
74
74
|
import {
|
|
75
75
|
titleFromPrompt
|
|
76
76
|
} from "./chunk-7H655NEW.js";
|
|
@@ -181,7 +181,7 @@ import {
|
|
|
181
181
|
import {
|
|
182
182
|
applyAgentRunnerHeapEnv,
|
|
183
183
|
packagedMcpDir
|
|
184
|
-
} from "./chunk-
|
|
184
|
+
} from "./chunk-UA3YKQ3D.js";
|
|
185
185
|
import {
|
|
186
186
|
fallbackTurnFailDetail,
|
|
187
187
|
formatAgentErrorContinuePrompt,
|
|
@@ -196,7 +196,7 @@ import {
|
|
|
196
196
|
shouldRetryFailedAgentTurn,
|
|
197
197
|
summarizeTurnStderr,
|
|
198
198
|
turnFailChatText
|
|
199
|
-
} from "./chunk-
|
|
199
|
+
} from "./chunk-5XNT6BCG.js";
|
|
200
200
|
import {
|
|
201
201
|
clearStaleIndexLocks,
|
|
202
202
|
enrichPathWithNpmGlobalBin,
|
|
@@ -1654,6 +1654,23 @@ function worktreeAgentBlock(group) {
|
|
|
1654
1654
|
}
|
|
1655
1655
|
return best;
|
|
1656
1656
|
}
|
|
1657
|
+
function sidebarRowAgentBlock(group, opts) {
|
|
1658
|
+
if (opts.active) {
|
|
1659
|
+
const open = group.find((thread) => thread.id === opts.selectedId);
|
|
1660
|
+
if (open) return visibleAgentBlock(open);
|
|
1661
|
+
}
|
|
1662
|
+
return worktreeAgentBlock(group);
|
|
1663
|
+
}
|
|
1664
|
+
function sidebarParentSelectId(group, primaryId, opts) {
|
|
1665
|
+
if (opts.active) return primaryId;
|
|
1666
|
+
return sidebarQuestionThreadId(group, primaryId);
|
|
1667
|
+
}
|
|
1668
|
+
function sidebarQuestionThreadId(group, primaryId) {
|
|
1669
|
+
const block = worktreeAgentBlock(group);
|
|
1670
|
+
if (!block) return primaryId;
|
|
1671
|
+
const owner = group.find((thread) => visibleAgentBlock(thread) === block);
|
|
1672
|
+
return owner?.id ?? primaryId;
|
|
1673
|
+
}
|
|
1657
1674
|
function threadCardBlockFields(group) {
|
|
1658
1675
|
const block = worktreeAgentBlock(group);
|
|
1659
1676
|
return block ? { blockedReason: block.reason, blockedSource: block.source } : null;
|
|
@@ -1800,7 +1817,7 @@ function decisionBlockFromParts(parts, planMode, at = (/* @__PURE__ */ new Date(
|
|
|
1800
1817
|
const reason = pending ? formatAskUserNotifyMessage(pending.questions) : "Waiting for an answer in that chat.";
|
|
1801
1818
|
return {
|
|
1802
1819
|
...makeAgentBlock("ask_user", reason, at),
|
|
1803
|
-
...pending ? { questionSignature: pending.signature } : {}
|
|
1820
|
+
...pending ? { questionSignature: pending.signature, questions: pending.questions } : {}
|
|
1804
1821
|
};
|
|
1805
1822
|
}
|
|
1806
1823
|
if (!planMode || last?.type !== "tool") return null;
|
|
@@ -1815,14 +1832,24 @@ function decisionBlockFromParts(parts, planMode, at = (/* @__PURE__ */ new Date(
|
|
|
1815
1832
|
at
|
|
1816
1833
|
);
|
|
1817
1834
|
}
|
|
1835
|
+
function withStampedQuestions(decision, existing) {
|
|
1836
|
+
if (decision.source !== "ask_user" || decision.questions?.length) return decision;
|
|
1837
|
+
if (existing?.source !== "ask_user" || !existing.questions?.length) return decision;
|
|
1838
|
+
return {
|
|
1839
|
+
...decision,
|
|
1840
|
+
questions: existing.questions,
|
|
1841
|
+
questionSignature: decision.questionSignature ?? existing.questionSignature
|
|
1842
|
+
};
|
|
1843
|
+
}
|
|
1818
1844
|
function agentBlockAfterTurn(input) {
|
|
1819
1845
|
if (input.failed) return null;
|
|
1820
1846
|
const decision = decisionBlockFromParts(input.parts, input.planMode);
|
|
1821
1847
|
if (decision) {
|
|
1822
|
-
|
|
1848
|
+
const next = withStampedQuestions(decision, input.existing);
|
|
1849
|
+
if (isDismissedAskUserBlock(next, input.dismissedQuestionSignature)) {
|
|
1823
1850
|
return input.existing?.source === "reported" ? input.existing : null;
|
|
1824
1851
|
}
|
|
1825
|
-
return
|
|
1852
|
+
return next;
|
|
1826
1853
|
}
|
|
1827
1854
|
if (input.existing && input.existing.source !== "reported" && lastTopLevelTool(input.parts)) {
|
|
1828
1855
|
return null;
|
|
@@ -1865,7 +1892,7 @@ function settleAgentBlock(threadId, parts, failed) {
|
|
|
1865
1892
|
});
|
|
1866
1893
|
const prev = thread.agentBlock ?? null;
|
|
1867
1894
|
if (prev === next) return;
|
|
1868
|
-
if (prev && next && prev.source === next.source && prev.reason === next.reason && prev.at === next.at && prev.questionSignature === next.questionSignature) {
|
|
1895
|
+
if (prev && next && prev.source === next.source && prev.reason === next.reason && prev.at === next.at && prev.questionSignature === next.questionSignature && planQuestionsSignature(prev.questions ?? []) === planQuestionsSignature(next.questions ?? [])) {
|
|
1869
1896
|
return;
|
|
1870
1897
|
}
|
|
1871
1898
|
updateThread(threadId, { agentBlock: next });
|
|
@@ -1888,7 +1915,11 @@ function stampAskUserBlock(resolveCaller, questions) {
|
|
|
1888
1915
|
try {
|
|
1889
1916
|
writeAgentBlock(
|
|
1890
1917
|
resolveCaller().id,
|
|
1891
|
-
parsed.length ? {
|
|
1918
|
+
parsed.length ? {
|
|
1919
|
+
...block,
|
|
1920
|
+
questionSignature: planQuestionsSignature(parsed),
|
|
1921
|
+
questions: parsed
|
|
1922
|
+
} : block
|
|
1892
1923
|
);
|
|
1893
1924
|
} catch {
|
|
1894
1925
|
}
|
|
@@ -2996,7 +3027,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2996
3027
|
return readThread(thread.id) ?? thread;
|
|
2997
3028
|
}
|
|
2998
3029
|
async function listLinearIssues(agent, repoPath) {
|
|
2999
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3030
|
+
const { getAdapter: getAdapter2 } = await import("./agents-DG2UPJ6N.js");
|
|
3000
3031
|
await requireAgent(agent, { requireLinear: true });
|
|
3001
3032
|
const adapter = getAdapter2(agent);
|
|
3002
3033
|
if (!adapter.listLinearIssues) {
|
|
@@ -5838,7 +5869,7 @@ function formatWorktreeReminder() {
|
|
|
5838
5869
|
return "Sideboard workspace: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push. Schedules: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
|
|
5839
5870
|
}
|
|
5840
5871
|
function formatClaudeSubagentReminder() {
|
|
5841
|
-
return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself.';
|
|
5872
|
+
return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself. That note is another worker in this chat, or a worker Claude still has marked running. Do not mention it to the user.';
|
|
5842
5873
|
}
|
|
5843
5874
|
function claudeSubagentTurnReminder(thread) {
|
|
5844
5875
|
if (thread.agent !== "claude" || thread.planMode || isOrchestratorThread(thread)) {
|
|
@@ -6710,7 +6741,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6710
6741
|
${prompt}`;
|
|
6711
6742
|
}
|
|
6712
6743
|
async function defaultDeps() {
|
|
6713
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6744
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-T76JRIIN.js");
|
|
6714
6745
|
const orch = getOrchestrator2();
|
|
6715
6746
|
return {
|
|
6716
6747
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -9621,6 +9652,9 @@ export {
|
|
|
9621
9652
|
worktreeBoardStatus,
|
|
9622
9653
|
visibleAgentBlock,
|
|
9623
9654
|
worktreeAgentBlock,
|
|
9655
|
+
sidebarRowAgentBlock,
|
|
9656
|
+
sidebarParentSelectId,
|
|
9657
|
+
sidebarQuestionThreadId,
|
|
9624
9658
|
reviewLabelForRepo,
|
|
9625
9659
|
classifyWorktreeListBadges,
|
|
9626
9660
|
isHomeBoardThread,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
parseSessionQuotaResetAt,
|
|
28
28
|
planModeTurnInstruction,
|
|
29
29
|
resolveQuotaFallbackAgent
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-VXI7FFGO.js";
|
|
31
31
|
import {
|
|
32
32
|
REVIEW_TAB_TITLE,
|
|
33
33
|
applyWorktreePkgCacheEnv,
|
|
@@ -68,7 +68,7 @@ import {
|
|
|
68
68
|
worktreeDevProcessKey,
|
|
69
69
|
worktreeRunProcessKey,
|
|
70
70
|
worktreeSetupProcessKey
|
|
71
|
-
} from "./chunk-
|
|
71
|
+
} from "./chunk-AILQRQ26.js";
|
|
72
72
|
import {
|
|
73
73
|
applyAgentEvent,
|
|
74
74
|
clipAgentEventForPaint,
|
|
@@ -95,7 +95,7 @@ import {
|
|
|
95
95
|
summarizeTurnStderr,
|
|
96
96
|
toolDescription,
|
|
97
97
|
turnFailChatText
|
|
98
|
-
} from "./chunk-
|
|
98
|
+
} from "./chunk-I5TESHDN.js";
|
|
99
99
|
import {
|
|
100
100
|
SLACK_REPLY_FORMATTING,
|
|
101
101
|
addWorkspace,
|
|
@@ -1703,7 +1703,7 @@ function decisionBlockFromParts(parts, planMode, at = (/* @__PURE__ */ new Date(
|
|
|
1703
1703
|
const reason = pending ? formatAskUserNotifyMessage(pending.questions) : "Waiting for an answer in that chat.";
|
|
1704
1704
|
return {
|
|
1705
1705
|
...makeAgentBlock("ask_user", reason, at),
|
|
1706
|
-
...pending ? { questionSignature: pending.signature } : {}
|
|
1706
|
+
...pending ? { questionSignature: pending.signature, questions: pending.questions } : {}
|
|
1707
1707
|
};
|
|
1708
1708
|
}
|
|
1709
1709
|
if (!planMode || last?.type !== "tool") return null;
|
|
@@ -1718,14 +1718,24 @@ function decisionBlockFromParts(parts, planMode, at = (/* @__PURE__ */ new Date(
|
|
|
1718
1718
|
at
|
|
1719
1719
|
);
|
|
1720
1720
|
}
|
|
1721
|
+
function withStampedQuestions(decision, existing) {
|
|
1722
|
+
if (decision.source !== "ask_user" || decision.questions?.length) return decision;
|
|
1723
|
+
if (existing?.source !== "ask_user" || !existing.questions?.length) return decision;
|
|
1724
|
+
return {
|
|
1725
|
+
...decision,
|
|
1726
|
+
questions: existing.questions,
|
|
1727
|
+
questionSignature: decision.questionSignature ?? existing.questionSignature
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1721
1730
|
function agentBlockAfterTurn(input) {
|
|
1722
1731
|
if (input.failed) return null;
|
|
1723
1732
|
const decision = decisionBlockFromParts(input.parts, input.planMode);
|
|
1724
1733
|
if (decision) {
|
|
1725
|
-
|
|
1734
|
+
const next = withStampedQuestions(decision, input.existing);
|
|
1735
|
+
if (isDismissedAskUserBlock(next, input.dismissedQuestionSignature)) {
|
|
1726
1736
|
return input.existing?.source === "reported" ? input.existing : null;
|
|
1727
1737
|
}
|
|
1728
|
-
return
|
|
1738
|
+
return next;
|
|
1729
1739
|
}
|
|
1730
1740
|
if (input.existing && input.existing.source !== "reported" && lastTopLevelTool(input.parts)) {
|
|
1731
1741
|
return null;
|
|
@@ -1768,7 +1778,7 @@ function settleAgentBlock(threadId, parts, failed) {
|
|
|
1768
1778
|
});
|
|
1769
1779
|
const prev = thread.agentBlock ?? null;
|
|
1770
1780
|
if (prev === next) return;
|
|
1771
|
-
if (prev && next && prev.source === next.source && prev.reason === next.reason && prev.at === next.at && prev.questionSignature === next.questionSignature) {
|
|
1781
|
+
if (prev && next && prev.source === next.source && prev.reason === next.reason && prev.at === next.at && prev.questionSignature === next.questionSignature && planQuestionsSignature(prev.questions ?? []) === planQuestionsSignature(next.questions ?? [])) {
|
|
1772
1782
|
return;
|
|
1773
1783
|
}
|
|
1774
1784
|
updateThread(threadId, { agentBlock: next });
|
|
@@ -1791,7 +1801,11 @@ function stampAskUserBlock(resolveCaller, questions) {
|
|
|
1791
1801
|
try {
|
|
1792
1802
|
writeAgentBlock(
|
|
1793
1803
|
resolveCaller().id,
|
|
1794
|
-
parsed.length ? {
|
|
1804
|
+
parsed.length ? {
|
|
1805
|
+
...block,
|
|
1806
|
+
questionSignature: planQuestionsSignature(parsed),
|
|
1807
|
+
questions: parsed
|
|
1808
|
+
} : block
|
|
1795
1809
|
);
|
|
1796
1810
|
} catch {
|
|
1797
1811
|
}
|
|
@@ -5534,7 +5548,7 @@ function formatWorktreeReminder() {
|
|
|
5534
5548
|
return "Sideboard workspace: stay in this cwd for all file and git work. Push and open PRs against origin, never upstream. Do not edit the main repo checkout. If a goal is given (Greptile 5/5, CI green), watch-fix-push until it lands \u2014 do not watch after every push. Schedules: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
|
|
5535
5549
|
}
|
|
5536
5550
|
function formatClaudeSubagentReminder() {
|
|
5537
|
-
return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself.';
|
|
5551
|
+
return 'Claude subagents: if Task/Agent workers will edit files, write a short plan in this chat and continue in the same turn. Do not ask the user whether to isolate, and do not set worktree.bgIsolation to none. One writer may edit this workspace. Every other writer is an Agent with isolation "worktree" and a disjoint file list (read-only explore agents may overlap). While those agents run, leave their files alone. Merge each returned branch into this workspace, then remove the temporary worktree. You stay in this cwd. If Claude says another write-capable agent is in this directory, or that writes to the shared checkout are blocked, re-spawn that agent with isolation "worktree" or make the edit yourself. That note is another worker in this chat, or a worker Claude still has marked running. Do not mention it to the user.';
|
|
5538
5552
|
}
|
|
5539
5553
|
function claudeSubagentTurnReminder(thread) {
|
|
5540
5554
|
if (thread.agent !== "claude" || thread.planMode || isOrchestratorThread(thread)) {
|
|
@@ -6375,7 +6389,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6375
6389
|
${prompt}`;
|
|
6376
6390
|
}
|
|
6377
6391
|
async function defaultDeps() {
|
|
6378
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6392
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-4OIMDLIR.js");
|
|
6379
6393
|
const orch = getOrchestrator2();
|
|
6380
6394
|
return {
|
|
6381
6395
|
findThread: (id) => findThreadByRef(id),
|