@sideboard-ai/core 0.1.186 → 0.1.188
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.js +1 -1
- package/dist/{agents-R6RQMMNE.js → agents-WH3TW5OP.js} +1 -1
- package/dist/{agents-HC6HWBDB.js → agents-XPWKGOVT.js} +2 -2
- package/dist/{chunk-3QTEXR7L.js → chunk-72FO6OLT.js} +44 -9
- package/dist/{chunk-5FTIOINZ.js → chunk-ISOCLQEX.js} +16 -7
- package/dist/{chunk-AHV36NL3.js → chunk-QU663NPO.js} +41 -1
- package/dist/{chunk-VTIVVVEC.js → chunk-TBG2Z3ZV.js} +46 -11
- package/dist/{chunk-NQTKRAUF.js → chunk-ZSFQLR7Y.js} +34 -0
- package/dist/index.cjs +92 -13
- package/dist/index.d.cts +5 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +3 -3
- package/dist/mcp/run-stdio.cjs +84 -8
- package/dist/mcp/run-stdio.js +2 -2
- package/dist/{orchestrator-RJEULR5I.js → orchestrator-7A66YINC.js} +2 -2
- package/dist/{orchestrator-RNDMJXAY.js → orchestrator-ZMXSPFSF.js} +3 -3
- package/package.json +1 -1
|
@@ -32,7 +32,7 @@ import {
|
|
|
32
32
|
resolveLoginCommand,
|
|
33
33
|
resolveQuotaFallbackAgent,
|
|
34
34
|
whichOnPath
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-ISOCLQEX.js";
|
|
36
36
|
import "./chunk-VIODP5PT.js";
|
|
37
37
|
import "./chunk-WXKXSZN4.js";
|
|
38
38
|
import "./chunk-6K64FJDD.js";
|
|
@@ -44,7 +44,7 @@ import {
|
|
|
44
44
|
parseCursorRunnerLine,
|
|
45
45
|
preferredCursorCostCents,
|
|
46
46
|
turnCostUsdFromCursorUsage
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-ZSFQLR7Y.js";
|
|
48
48
|
import {
|
|
49
49
|
ORCHESTRATOR_AGENT_KINDS,
|
|
50
50
|
assertOrchestratorCapableAgent,
|
|
@@ -33,7 +33,7 @@ import {
|
|
|
33
33
|
summarizeTurnStderr,
|
|
34
34
|
toolDescription,
|
|
35
35
|
turnFailChatText
|
|
36
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-QU663NPO.js";
|
|
37
37
|
import {
|
|
38
38
|
extractPresentedPlan,
|
|
39
39
|
readPlanFile,
|
|
@@ -402,7 +402,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
402
402
|
await continueOnReply(threadId, prompt);
|
|
403
403
|
return;
|
|
404
404
|
}
|
|
405
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
405
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-7A66YINC.js");
|
|
406
406
|
await getOrchestrator2().send(threadId, prompt);
|
|
407
407
|
} catch {
|
|
408
408
|
}
|
|
@@ -2675,6 +2675,10 @@ function mcpWaitFinishedHint(status) {
|
|
|
2675
2675
|
|
|
2676
2676
|
// src/mcp/wait-for-job.ts
|
|
2677
2677
|
var MAX_JOB_CONTINUES = 8;
|
|
2678
|
+
var MAX_JOB_DELTA_LINES = 80;
|
|
2679
|
+
var MAX_JOB_DELTA_CHARS = 4e3;
|
|
2680
|
+
var DEFERRED_DONE_MAX_CHARS = 480;
|
|
2681
|
+
var GH_WATCH_REFRESH = "Refreshing run status every 3 seconds.";
|
|
2678
2682
|
var MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
|
|
2679
2683
|
var MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
|
|
2680
2684
|
var JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
@@ -2748,8 +2752,37 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
2748
2752
|
}
|
|
2749
2753
|
function looksLikeDeferredDonePromise(text) {
|
|
2750
2754
|
const t = (text ?? "").trim();
|
|
2751
|
-
if (!t) return false;
|
|
2752
|
-
|
|
2755
|
+
if (!t || t.length > DEFERRED_DONE_MAX_CHARS) return false;
|
|
2756
|
+
const unquoted = t.replace(/`[^`]*`/g, " ").replace(/["“”][^"“”]*["“”]/g, " ").replace(/\s+/g, " ").trim();
|
|
2757
|
+
if (!unquoted) return false;
|
|
2758
|
+
return /\b(i['’]?ll|i will)\s+let you know\b/i.test(unquoted) || /\blet you know when\b/i.test(unquoted) || /\b(check back|ping me)\s+when\b/i.test(unquoted) || /\bi(?:['’]ll| will)\s+(report|update you)\s+when\b/i.test(unquoted);
|
|
2759
|
+
}
|
|
2760
|
+
function isJobContinuePrompt(text) {
|
|
2761
|
+
const t = text.trim();
|
|
2762
|
+
return t.startsWith("Detached job still running:") || t.startsWith("You ended the turn after promising to report later");
|
|
2763
|
+
}
|
|
2764
|
+
function collapseGhRunWatchLog(text) {
|
|
2765
|
+
if (!text.includes(GH_WATCH_REFRESH)) return text;
|
|
2766
|
+
const frames = text.split(/(?=Refreshing run status every 3 seconds\.)/);
|
|
2767
|
+
const watchFrames = frames.filter((f) => f.includes(GH_WATCH_REFRESH));
|
|
2768
|
+
if (watchFrames.length <= 1) return text;
|
|
2769
|
+
const prefix = frames[0]?.includes(GH_WATCH_REFRESH) ? "" : frames[0] ?? "";
|
|
2770
|
+
const last = watchFrames[watchFrames.length - 1] ?? "";
|
|
2771
|
+
const omitted = watchFrames.length - 1;
|
|
2772
|
+
const note = `(${omitted} identical gh run watch refresh${omitted === 1 ? "" : "es"} omitted)
|
|
2773
|
+
`;
|
|
2774
|
+
return [prefix.trimEnd(), note, last.trimStart()].filter(Boolean).join("\n");
|
|
2775
|
+
}
|
|
2776
|
+
function capJobLogDelta(text) {
|
|
2777
|
+
const collapsed = collapseGhRunWatchLog(text);
|
|
2778
|
+
const lines = collapsed.split("\n");
|
|
2779
|
+
let out = lines.length > MAX_JOB_DELTA_LINES ? `\u2026(${lines.length - MAX_JOB_DELTA_LINES} earlier lines omitted)
|
|
2780
|
+
${lines.slice(-MAX_JOB_DELTA_LINES).join("\n")}` : collapsed;
|
|
2781
|
+
if (out.length > MAX_JOB_DELTA_CHARS) {
|
|
2782
|
+
out = `\u2026(truncated ${out.length} chars)
|
|
2783
|
+
${out.slice(-MAX_JOB_DELTA_CHARS)}`;
|
|
2784
|
+
}
|
|
2785
|
+
return out;
|
|
2753
2786
|
}
|
|
2754
2787
|
function formatJobStillRunningContinuePrompt(jobIds) {
|
|
2755
2788
|
const ids = jobIds.join(", ");
|
|
@@ -2812,7 +2845,7 @@ function takeDelta(logFile, cursorFile) {
|
|
|
2812
2845
|
const lines = readLogLines(logFile);
|
|
2813
2846
|
const cursor = readIntFile(cursorFile) ?? 0;
|
|
2814
2847
|
const start = Math.min(Math.max(0, cursor), lines.length);
|
|
2815
|
-
return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
|
|
2848
|
+
return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
|
|
2816
2849
|
}
|
|
2817
2850
|
function snapshotJob(dir) {
|
|
2818
2851
|
const pid = readIntFile(join11(dir, "pid"));
|
|
@@ -6425,7 +6458,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6425
6458
|
${prompt}`;
|
|
6426
6459
|
}
|
|
6427
6460
|
async function defaultDeps() {
|
|
6428
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6461
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-7A66YINC.js");
|
|
6429
6462
|
const orch = getOrchestrator2();
|
|
6430
6463
|
return {
|
|
6431
6464
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -7214,11 +7247,13 @@ var Orchestrator = class {
|
|
|
7214
7247
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
7215
7248
|
thread = this.requireThread(threadId);
|
|
7216
7249
|
}
|
|
7217
|
-
const
|
|
7250
|
+
const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
|
|
7251
|
+
const sentAttachments = !autoContinue && thread.attachments.length > 0 ? [...thread.attachments] : void 0;
|
|
7218
7252
|
appendMessage(threadId, {
|
|
7219
7253
|
role: "user",
|
|
7220
7254
|
text: prompt,
|
|
7221
7255
|
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
7256
|
+
...autoContinue ? { origin: "continue" } : {},
|
|
7222
7257
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
7223
7258
|
});
|
|
7224
7259
|
thread = this.requireThread(threadId);
|
|
@@ -7227,7 +7262,7 @@ var Orchestrator = class {
|
|
|
7227
7262
|
thread.worktreePath,
|
|
7228
7263
|
gitPrompt,
|
|
7229
7264
|
{
|
|
7230
|
-
attachments: sentAttachments ?? thread.attachments
|
|
7265
|
+
attachments: autoContinue ? [] : sentAttachments ?? thread.attachments
|
|
7231
7266
|
}
|
|
7232
7267
|
);
|
|
7233
7268
|
const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
|
|
@@ -7280,7 +7315,7 @@ var Orchestrator = class {
|
|
|
7280
7315
|
slackReplyContext,
|
|
7281
7316
|
expandedPrompt
|
|
7282
7317
|
].filter(Boolean).join("\n\n");
|
|
7283
|
-
if (thread.attachments.length > 0) {
|
|
7318
|
+
if (!autoContinue && thread.attachments.length > 0) {
|
|
7284
7319
|
updateThread(threadId, { attachments: [] });
|
|
7285
7320
|
}
|
|
7286
7321
|
const adapter = getAdapter(thread.agent);
|
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
packagedMcpStdioPath,
|
|
30
30
|
parseCursorRunnerLine,
|
|
31
31
|
resolveNodeLaunch
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-ZSFQLR7Y.js";
|
|
33
33
|
import {
|
|
34
34
|
claudeChromeEnabled,
|
|
35
35
|
isAbleTimeConnected,
|
|
@@ -599,10 +599,18 @@ function asRecord(input) {
|
|
|
599
599
|
function str(v) {
|
|
600
600
|
return typeof v === "string" && v.trim() ? v : void 0;
|
|
601
601
|
}
|
|
602
|
+
var CHAT_DETAIL_MAX = 72;
|
|
603
|
+
function clipChatLine(value, max = CHAT_DETAIL_MAX) {
|
|
604
|
+
const line = value.trim().split(/\r?\n/, 1)[0] ?? "";
|
|
605
|
+
if (line.length <= max) return line;
|
|
606
|
+
return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
607
|
+
}
|
|
602
608
|
function looksLikeFilePath(value) {
|
|
603
|
-
|
|
604
|
-
if (
|
|
605
|
-
|
|
609
|
+
const trimmed = value.trim();
|
|
610
|
+
if (!trimmed || /[\s;|&<>]/.test(trimmed)) return false;
|
|
611
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("~/")) return true;
|
|
612
|
+
if (/^[A-Za-z]:[\\/]/.test(trimmed)) return true;
|
|
613
|
+
return trimmed.includes("/") || trimmed.includes("\\");
|
|
606
614
|
}
|
|
607
615
|
function stripWorktreePrefix(path, worktreePath) {
|
|
608
616
|
if (!worktreePath) return path;
|
|
@@ -616,8 +624,9 @@ function visibleToolRowDetail(detail, description, worktreePath) {
|
|
|
616
624
|
const raw = detail.trim();
|
|
617
625
|
const desc = (description ?? "").trim();
|
|
618
626
|
if (!looksLikeFilePath(raw)) {
|
|
619
|
-
|
|
620
|
-
return
|
|
627
|
+
const clipped = clipChatLine(raw);
|
|
628
|
+
if (!clipped || desc === clipped || desc === raw) return void 0;
|
|
629
|
+
return clipped;
|
|
621
630
|
}
|
|
622
631
|
const rel = stripWorktreePrefix(raw, worktreePath);
|
|
623
632
|
if (!rel) return void 0;
|
|
@@ -631,7 +640,7 @@ function visibleToolRowDetail(detail, description, worktreePath) {
|
|
|
631
640
|
function toolDetail(name, input) {
|
|
632
641
|
if (!input) return void 0;
|
|
633
642
|
const command = str(input.command) ?? str(input.cmd);
|
|
634
|
-
if (command) return command;
|
|
643
|
+
if (command) return clipChatLine(command);
|
|
635
644
|
const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
|
|
636
645
|
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
637
646
|
if (isSearch && pattern) {
|
|
@@ -229,11 +229,45 @@ function looksLikeHugeToolResultDump(text) {
|
|
|
229
229
|
if (t.length < 4e3) return false;
|
|
230
230
|
return looksLikeMinifiedJsDump(t);
|
|
231
231
|
}
|
|
232
|
+
function clipJobWaitResultJson(content) {
|
|
233
|
+
const trimmed = content.trim();
|
|
234
|
+
if (!trimmed.startsWith("{")) return void 0;
|
|
235
|
+
try {
|
|
236
|
+
const rec = JSON.parse(trimmed);
|
|
237
|
+
const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
|
|
238
|
+
if (!isJob) return void 0;
|
|
239
|
+
if (typeof rec.delta === "string" && rec.delta.length > 3500) {
|
|
240
|
+
rec.delta = `\u2026(truncated ${rec.delta.length} chars)
|
|
241
|
+
${rec.delta.slice(-3500)}`;
|
|
242
|
+
}
|
|
243
|
+
if (typeof rec.progress === "string" && rec.progress.length > 800) {
|
|
244
|
+
rec.progress = rec.progress.slice(-800);
|
|
245
|
+
}
|
|
246
|
+
if (typeof rec.hint === "string" && rec.hint.length > 240) {
|
|
247
|
+
rec.hint = rec.hint.slice(0, 240);
|
|
248
|
+
}
|
|
249
|
+
let out = JSON.stringify(rec);
|
|
250
|
+
if (out.length <= TOOL_RESULT_STORE_MAX_CHARS) return out;
|
|
251
|
+
return JSON.stringify({
|
|
252
|
+
stillRunning: rec.stillRunning,
|
|
253
|
+
ok: rec.ok,
|
|
254
|
+
failed: rec.failed,
|
|
255
|
+
status: rec.status,
|
|
256
|
+
id: rec.id,
|
|
257
|
+
phase: rec.phase,
|
|
258
|
+
delta: typeof rec.delta === "string" ? rec.delta.slice(-2500) : ""
|
|
259
|
+
});
|
|
260
|
+
} catch {
|
|
261
|
+
return void 0;
|
|
262
|
+
}
|
|
263
|
+
}
|
|
232
264
|
function clipToolResultForStore(content) {
|
|
233
265
|
if (content == null) return void 0;
|
|
234
266
|
if (looksLikeCursorSdkSourceDump(content) || looksLikeMinifiedJsDump(content)) {
|
|
235
267
|
return `${HUGE_TOOL_RESULT_SUMMARY} (${content.length} chars omitted)`;
|
|
236
268
|
}
|
|
269
|
+
const jobClipped = clipJobWaitResultJson(content);
|
|
270
|
+
if (jobClipped) return jobClipped;
|
|
237
271
|
if (content.length <= TOOL_RESULT_STORE_MAX_CHARS) return content;
|
|
238
272
|
const head = 5e3;
|
|
239
273
|
const tail = 2e3;
|
|
@@ -828,10 +862,16 @@ function asRecord(input) {
|
|
|
828
862
|
function str(v) {
|
|
829
863
|
return typeof v === "string" && v.trim() ? v : void 0;
|
|
830
864
|
}
|
|
865
|
+
var CHAT_DETAIL_MAX = 72;
|
|
866
|
+
function clipChatLine(value, max = CHAT_DETAIL_MAX) {
|
|
867
|
+
const line = value.trim().split(/\r?\n/, 1)[0] ?? "";
|
|
868
|
+
if (line.length <= max) return line;
|
|
869
|
+
return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
870
|
+
}
|
|
831
871
|
function toolDetail(name, input) {
|
|
832
872
|
if (!input) return void 0;
|
|
833
873
|
const command = str(input.command) ?? str(input.cmd);
|
|
834
|
-
if (command) return command;
|
|
874
|
+
if (command) return clipChatLine(command);
|
|
835
875
|
const pattern = str(input.pattern) ?? str(input.glob) ?? str(input.glob_pattern);
|
|
836
876
|
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
837
877
|
if (isSearch && pattern) {
|
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
stripBrightsyNdjsonNoise,
|
|
25
25
|
sumUsageList,
|
|
26
26
|
toolDescription
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-ISOCLQEX.js";
|
|
28
28
|
import {
|
|
29
29
|
SLACK_REPLY_FORMATTING,
|
|
30
30
|
addWorkspace,
|
|
@@ -124,7 +124,7 @@ import {
|
|
|
124
124
|
shouldRetryFailedAgentTurn,
|
|
125
125
|
summarizeTurnStderr,
|
|
126
126
|
turnFailChatText
|
|
127
|
-
} from "./chunk-
|
|
127
|
+
} from "./chunk-ZSFQLR7Y.js";
|
|
128
128
|
import {
|
|
129
129
|
assertOrchestratorCapableAgent,
|
|
130
130
|
childEnvWithAppSettings,
|
|
@@ -467,7 +467,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
467
467
|
await continueOnReply(threadId, prompt);
|
|
468
468
|
return;
|
|
469
469
|
}
|
|
470
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
470
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-ZMXSPFSF.js");
|
|
471
471
|
await getOrchestrator2().send(threadId, prompt);
|
|
472
472
|
} catch {
|
|
473
473
|
}
|
|
@@ -2762,6 +2762,10 @@ function mcpWaitFinishedHint(status) {
|
|
|
2762
2762
|
|
|
2763
2763
|
// src/mcp/wait-for-job.ts
|
|
2764
2764
|
var MAX_JOB_CONTINUES = 8;
|
|
2765
|
+
var MAX_JOB_DELTA_LINES = 80;
|
|
2766
|
+
var MAX_JOB_DELTA_CHARS = 4e3;
|
|
2767
|
+
var DEFERRED_DONE_MAX_CHARS = 480;
|
|
2768
|
+
var GH_WATCH_REFRESH = "Refreshing run status every 3 seconds.";
|
|
2765
2769
|
var MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
|
|
2766
2770
|
var MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
|
|
2767
2771
|
var JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
@@ -2835,8 +2839,37 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
2835
2839
|
}
|
|
2836
2840
|
function looksLikeDeferredDonePromise(text) {
|
|
2837
2841
|
const t = (text ?? "").trim();
|
|
2838
|
-
if (!t) return false;
|
|
2839
|
-
|
|
2842
|
+
if (!t || t.length > DEFERRED_DONE_MAX_CHARS) return false;
|
|
2843
|
+
const unquoted = t.replace(/`[^`]*`/g, " ").replace(/["“”][^"“”]*["“”]/g, " ").replace(/\s+/g, " ").trim();
|
|
2844
|
+
if (!unquoted) return false;
|
|
2845
|
+
return /\b(i['’]?ll|i will)\s+let you know\b/i.test(unquoted) || /\blet you know when\b/i.test(unquoted) || /\b(check back|ping me)\s+when\b/i.test(unquoted) || /\bi(?:['’]ll| will)\s+(report|update you)\s+when\b/i.test(unquoted);
|
|
2846
|
+
}
|
|
2847
|
+
function isJobContinuePrompt(text) {
|
|
2848
|
+
const t = text.trim();
|
|
2849
|
+
return t.startsWith("Detached job still running:") || t.startsWith("You ended the turn after promising to report later");
|
|
2850
|
+
}
|
|
2851
|
+
function collapseGhRunWatchLog(text) {
|
|
2852
|
+
if (!text.includes(GH_WATCH_REFRESH)) return text;
|
|
2853
|
+
const frames = text.split(/(?=Refreshing run status every 3 seconds\.)/);
|
|
2854
|
+
const watchFrames = frames.filter((f) => f.includes(GH_WATCH_REFRESH));
|
|
2855
|
+
if (watchFrames.length <= 1) return text;
|
|
2856
|
+
const prefix = frames[0]?.includes(GH_WATCH_REFRESH) ? "" : frames[0] ?? "";
|
|
2857
|
+
const last = watchFrames[watchFrames.length - 1] ?? "";
|
|
2858
|
+
const omitted = watchFrames.length - 1;
|
|
2859
|
+
const note = `(${omitted} identical gh run watch refresh${omitted === 1 ? "" : "es"} omitted)
|
|
2860
|
+
`;
|
|
2861
|
+
return [prefix.trimEnd(), note, last.trimStart()].filter(Boolean).join("\n");
|
|
2862
|
+
}
|
|
2863
|
+
function capJobLogDelta(text) {
|
|
2864
|
+
const collapsed = collapseGhRunWatchLog(text);
|
|
2865
|
+
const lines = collapsed.split("\n");
|
|
2866
|
+
let out = lines.length > MAX_JOB_DELTA_LINES ? `\u2026(${lines.length - MAX_JOB_DELTA_LINES} earlier lines omitted)
|
|
2867
|
+
${lines.slice(-MAX_JOB_DELTA_LINES).join("\n")}` : collapsed;
|
|
2868
|
+
if (out.length > MAX_JOB_DELTA_CHARS) {
|
|
2869
|
+
out = `\u2026(truncated ${out.length} chars)
|
|
2870
|
+
${out.slice(-MAX_JOB_DELTA_CHARS)}`;
|
|
2871
|
+
}
|
|
2872
|
+
return out;
|
|
2840
2873
|
}
|
|
2841
2874
|
function formatJobStillRunningContinuePrompt(jobIds) {
|
|
2842
2875
|
const ids = jobIds.join(", ");
|
|
@@ -2899,7 +2932,7 @@ function takeDelta(logFile, cursorFile) {
|
|
|
2899
2932
|
const lines = readLogLines(logFile);
|
|
2900
2933
|
const cursor = readIntFile(cursorFile) ?? 0;
|
|
2901
2934
|
const start = Math.min(Math.max(0, cursor), lines.length);
|
|
2902
|
-
return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
|
|
2935
|
+
return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
|
|
2903
2936
|
}
|
|
2904
2937
|
function snapshotJob(dir) {
|
|
2905
2938
|
const pid = readIntFile(join11(dir, "pid"));
|
|
@@ -3841,7 +3874,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3841
3874
|
return readThread(thread.id) ?? thread;
|
|
3842
3875
|
}
|
|
3843
3876
|
async function listLinearIssues(agent, repoPath) {
|
|
3844
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3877
|
+
const { getAdapter: getAdapter2 } = await import("./agents-XPWKGOVT.js");
|
|
3845
3878
|
await requireAgent(agent, { requireLinear: true });
|
|
3846
3879
|
const adapter = getAdapter2(agent);
|
|
3847
3880
|
if (!adapter.listLinearIssues) {
|
|
@@ -6772,7 +6805,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6772
6805
|
${prompt}`;
|
|
6773
6806
|
}
|
|
6774
6807
|
async function defaultDeps() {
|
|
6775
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6808
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-ZMXSPFSF.js");
|
|
6776
6809
|
const orch = getOrchestrator2();
|
|
6777
6810
|
return {
|
|
6778
6811
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -7561,11 +7594,13 @@ var Orchestrator = class {
|
|
|
7561
7594
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
7562
7595
|
thread = this.requireThread(threadId);
|
|
7563
7596
|
}
|
|
7564
|
-
const
|
|
7597
|
+
const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
|
|
7598
|
+
const sentAttachments = !autoContinue && thread.attachments.length > 0 ? [...thread.attachments] : void 0;
|
|
7565
7599
|
appendMessage(threadId, {
|
|
7566
7600
|
role: "user",
|
|
7567
7601
|
text: prompt,
|
|
7568
7602
|
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
7603
|
+
...autoContinue ? { origin: "continue" } : {},
|
|
7569
7604
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
7570
7605
|
});
|
|
7571
7606
|
thread = this.requireThread(threadId);
|
|
@@ -7574,7 +7609,7 @@ var Orchestrator = class {
|
|
|
7574
7609
|
thread.worktreePath,
|
|
7575
7610
|
gitPrompt,
|
|
7576
7611
|
{
|
|
7577
|
-
attachments: sentAttachments ?? thread.attachments
|
|
7612
|
+
attachments: autoContinue ? [] : sentAttachments ?? thread.attachments
|
|
7578
7613
|
}
|
|
7579
7614
|
);
|
|
7580
7615
|
const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
|
|
@@ -7627,7 +7662,7 @@ var Orchestrator = class {
|
|
|
7627
7662
|
slackReplyContext,
|
|
7628
7663
|
expandedPrompt
|
|
7629
7664
|
].filter(Boolean).join("\n\n");
|
|
7630
|
-
if (thread.attachments.length > 0) {
|
|
7665
|
+
if (!autoContinue && thread.attachments.length > 0) {
|
|
7631
7666
|
updateThread(threadId, { attachments: [] });
|
|
7632
7667
|
}
|
|
7633
7668
|
const adapter = getAdapter(thread.agent);
|
|
@@ -86,11 +86,45 @@ function looksLikeHugeToolResultDump(text) {
|
|
|
86
86
|
if (t.length < 4e3) return false;
|
|
87
87
|
return looksLikeMinifiedJsDump(t);
|
|
88
88
|
}
|
|
89
|
+
function clipJobWaitResultJson(content) {
|
|
90
|
+
const trimmed = content.trim();
|
|
91
|
+
if (!trimmed.startsWith("{")) return void 0;
|
|
92
|
+
try {
|
|
93
|
+
const rec = JSON.parse(trimmed);
|
|
94
|
+
const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
|
|
95
|
+
if (!isJob) return void 0;
|
|
96
|
+
if (typeof rec.delta === "string" && rec.delta.length > 3500) {
|
|
97
|
+
rec.delta = `\u2026(truncated ${rec.delta.length} chars)
|
|
98
|
+
${rec.delta.slice(-3500)}`;
|
|
99
|
+
}
|
|
100
|
+
if (typeof rec.progress === "string" && rec.progress.length > 800) {
|
|
101
|
+
rec.progress = rec.progress.slice(-800);
|
|
102
|
+
}
|
|
103
|
+
if (typeof rec.hint === "string" && rec.hint.length > 240) {
|
|
104
|
+
rec.hint = rec.hint.slice(0, 240);
|
|
105
|
+
}
|
|
106
|
+
let out = JSON.stringify(rec);
|
|
107
|
+
if (out.length <= TOOL_RESULT_STORE_MAX_CHARS) return out;
|
|
108
|
+
return JSON.stringify({
|
|
109
|
+
stillRunning: rec.stillRunning,
|
|
110
|
+
ok: rec.ok,
|
|
111
|
+
failed: rec.failed,
|
|
112
|
+
status: rec.status,
|
|
113
|
+
id: rec.id,
|
|
114
|
+
phase: rec.phase,
|
|
115
|
+
delta: typeof rec.delta === "string" ? rec.delta.slice(-2500) : ""
|
|
116
|
+
});
|
|
117
|
+
} catch {
|
|
118
|
+
return void 0;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
89
121
|
function clipToolResultForStore(content) {
|
|
90
122
|
if (content == null) return void 0;
|
|
91
123
|
if (looksLikeCursorSdkSourceDump(content) || looksLikeMinifiedJsDump(content)) {
|
|
92
124
|
return `${HUGE_TOOL_RESULT_SUMMARY} (${content.length} chars omitted)`;
|
|
93
125
|
}
|
|
126
|
+
const jobClipped = clipJobWaitResultJson(content);
|
|
127
|
+
if (jobClipped) return jobClipped;
|
|
94
128
|
if (content.length <= TOOL_RESULT_STORE_MAX_CHARS) return content;
|
|
95
129
|
const head = 5e3;
|
|
96
130
|
const tail = 2e3;
|
package/dist/index.cjs
CHANGED
|
@@ -8687,11 +8687,45 @@ function looksLikeHugeToolResultDump(text7) {
|
|
|
8687
8687
|
if (t.length < 4e3) return false;
|
|
8688
8688
|
return looksLikeMinifiedJsDump(t);
|
|
8689
8689
|
}
|
|
8690
|
+
function clipJobWaitResultJson(content) {
|
|
8691
|
+
const trimmed = content.trim();
|
|
8692
|
+
if (!trimmed.startsWith("{")) return void 0;
|
|
8693
|
+
try {
|
|
8694
|
+
const rec = JSON.parse(trimmed);
|
|
8695
|
+
const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
|
|
8696
|
+
if (!isJob) return void 0;
|
|
8697
|
+
if (typeof rec.delta === "string" && rec.delta.length > 3500) {
|
|
8698
|
+
rec.delta = `\u2026(truncated ${rec.delta.length} chars)
|
|
8699
|
+
${rec.delta.slice(-3500)}`;
|
|
8700
|
+
}
|
|
8701
|
+
if (typeof rec.progress === "string" && rec.progress.length > 800) {
|
|
8702
|
+
rec.progress = rec.progress.slice(-800);
|
|
8703
|
+
}
|
|
8704
|
+
if (typeof rec.hint === "string" && rec.hint.length > 240) {
|
|
8705
|
+
rec.hint = rec.hint.slice(0, 240);
|
|
8706
|
+
}
|
|
8707
|
+
let out = JSON.stringify(rec);
|
|
8708
|
+
if (out.length <= TOOL_RESULT_STORE_MAX_CHARS) return out;
|
|
8709
|
+
return JSON.stringify({
|
|
8710
|
+
stillRunning: rec.stillRunning,
|
|
8711
|
+
ok: rec.ok,
|
|
8712
|
+
failed: rec.failed,
|
|
8713
|
+
status: rec.status,
|
|
8714
|
+
id: rec.id,
|
|
8715
|
+
phase: rec.phase,
|
|
8716
|
+
delta: typeof rec.delta === "string" ? rec.delta.slice(-2500) : ""
|
|
8717
|
+
});
|
|
8718
|
+
} catch {
|
|
8719
|
+
return void 0;
|
|
8720
|
+
}
|
|
8721
|
+
}
|
|
8690
8722
|
function clipToolResultForStore(content) {
|
|
8691
8723
|
if (content == null) return void 0;
|
|
8692
8724
|
if (looksLikeCursorSdkSourceDump(content) || looksLikeMinifiedJsDump(content)) {
|
|
8693
8725
|
return `${HUGE_TOOL_RESULT_SUMMARY} (${content.length} chars omitted)`;
|
|
8694
8726
|
}
|
|
8727
|
+
const jobClipped = clipJobWaitResultJson(content);
|
|
8728
|
+
if (jobClipped) return jobClipped;
|
|
8695
8729
|
if (content.length <= TOOL_RESULT_STORE_MAX_CHARS) return content;
|
|
8696
8730
|
const head = 5e3;
|
|
8697
8731
|
const tail = 2e3;
|
|
@@ -9929,10 +9963,17 @@ function asRecord(input) {
|
|
|
9929
9963
|
function str2(v) {
|
|
9930
9964
|
return typeof v === "string" && v.trim() ? v : void 0;
|
|
9931
9965
|
}
|
|
9966
|
+
function clipChatLine(value, max = CHAT_DETAIL_MAX) {
|
|
9967
|
+
const line = value.trim().split(/\r?\n/, 1)[0] ?? "";
|
|
9968
|
+
if (line.length <= max) return line;
|
|
9969
|
+
return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
9970
|
+
}
|
|
9932
9971
|
function looksLikeFilePath(value) {
|
|
9933
|
-
|
|
9934
|
-
if (
|
|
9935
|
-
|
|
9972
|
+
const trimmed = value.trim();
|
|
9973
|
+
if (!trimmed || /[\s;|&<>]/.test(trimmed)) return false;
|
|
9974
|
+
if (trimmed.startsWith("/") || trimmed.startsWith("~/")) return true;
|
|
9975
|
+
if (/^[A-Za-z]:[\\/]/.test(trimmed)) return true;
|
|
9976
|
+
return trimmed.includes("/") || trimmed.includes("\\");
|
|
9936
9977
|
}
|
|
9937
9978
|
function stripWorktreePrefix(path2, worktreePath) {
|
|
9938
9979
|
if (!worktreePath) return path2;
|
|
@@ -9946,8 +9987,9 @@ function visibleToolRowDetail(detail, description, worktreePath) {
|
|
|
9946
9987
|
const raw = detail.trim();
|
|
9947
9988
|
const desc = (description ?? "").trim();
|
|
9948
9989
|
if (!looksLikeFilePath(raw)) {
|
|
9949
|
-
|
|
9950
|
-
return
|
|
9990
|
+
const clipped = clipChatLine(raw);
|
|
9991
|
+
if (!clipped || desc === clipped || desc === raw) return void 0;
|
|
9992
|
+
return clipped;
|
|
9951
9993
|
}
|
|
9952
9994
|
const rel = stripWorktreePrefix(raw, worktreePath);
|
|
9953
9995
|
if (!rel) return void 0;
|
|
@@ -9961,7 +10003,7 @@ function visibleToolRowDetail(detail, description, worktreePath) {
|
|
|
9961
10003
|
function toolDetail(name, input) {
|
|
9962
10004
|
if (!input) return void 0;
|
|
9963
10005
|
const command = str2(input.command) ?? str2(input.cmd);
|
|
9964
|
-
if (command) return command;
|
|
10006
|
+
if (command) return clipChatLine(command);
|
|
9965
10007
|
const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
|
|
9966
10008
|
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
9967
10009
|
if (isSearch && pattern) {
|
|
@@ -10481,10 +10523,12 @@ function normalizeParseResult(parsed) {
|
|
|
10481
10523
|
if (!parsed) return [];
|
|
10482
10524
|
return Array.isArray(parsed) ? parsed : [parsed];
|
|
10483
10525
|
}
|
|
10526
|
+
var CHAT_DETAIL_MAX;
|
|
10484
10527
|
var init_message_parts = __esm({
|
|
10485
10528
|
"src/agents/message-parts.ts"() {
|
|
10486
10529
|
"use strict";
|
|
10487
10530
|
init_error_detail();
|
|
10531
|
+
CHAT_DETAIL_MAX = 72;
|
|
10488
10532
|
}
|
|
10489
10533
|
});
|
|
10490
10534
|
|
|
@@ -15983,8 +16027,37 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
15983
16027
|
}
|
|
15984
16028
|
function looksLikeDeferredDonePromise(text7) {
|
|
15985
16029
|
const t = (text7 ?? "").trim();
|
|
15986
|
-
if (!t) return false;
|
|
15987
|
-
|
|
16030
|
+
if (!t || t.length > DEFERRED_DONE_MAX_CHARS) return false;
|
|
16031
|
+
const unquoted = t.replace(/`[^`]*`/g, " ").replace(/["“”][^"“”]*["“”]/g, " ").replace(/\s+/g, " ").trim();
|
|
16032
|
+
if (!unquoted) return false;
|
|
16033
|
+
return /\b(i['’]?ll|i will)\s+let you know\b/i.test(unquoted) || /\blet you know when\b/i.test(unquoted) || /\b(check back|ping me)\s+when\b/i.test(unquoted) || /\bi(?:['’]ll| will)\s+(report|update you)\s+when\b/i.test(unquoted);
|
|
16034
|
+
}
|
|
16035
|
+
function isJobContinuePrompt(text7) {
|
|
16036
|
+
const t = text7.trim();
|
|
16037
|
+
return t.startsWith("Detached job still running:") || t.startsWith("You ended the turn after promising to report later");
|
|
16038
|
+
}
|
|
16039
|
+
function collapseGhRunWatchLog(text7) {
|
|
16040
|
+
if (!text7.includes(GH_WATCH_REFRESH)) return text7;
|
|
16041
|
+
const frames = text7.split(/(?=Refreshing run status every 3 seconds\.)/);
|
|
16042
|
+
const watchFrames = frames.filter((f) => f.includes(GH_WATCH_REFRESH));
|
|
16043
|
+
if (watchFrames.length <= 1) return text7;
|
|
16044
|
+
const prefix = frames[0]?.includes(GH_WATCH_REFRESH) ? "" : frames[0] ?? "";
|
|
16045
|
+
const last = watchFrames[watchFrames.length - 1] ?? "";
|
|
16046
|
+
const omitted = watchFrames.length - 1;
|
|
16047
|
+
const note = `(${omitted} identical gh run watch refresh${omitted === 1 ? "" : "es"} omitted)
|
|
16048
|
+
`;
|
|
16049
|
+
return [prefix.trimEnd(), note, last.trimStart()].filter(Boolean).join("\n");
|
|
16050
|
+
}
|
|
16051
|
+
function capJobLogDelta(text7) {
|
|
16052
|
+
const collapsed = collapseGhRunWatchLog(text7);
|
|
16053
|
+
const lines = collapsed.split("\n");
|
|
16054
|
+
let out = lines.length > MAX_JOB_DELTA_LINES ? `\u2026(${lines.length - MAX_JOB_DELTA_LINES} earlier lines omitted)
|
|
16055
|
+
${lines.slice(-MAX_JOB_DELTA_LINES).join("\n")}` : collapsed;
|
|
16056
|
+
if (out.length > MAX_JOB_DELTA_CHARS) {
|
|
16057
|
+
out = `\u2026(truncated ${out.length} chars)
|
|
16058
|
+
${out.slice(-MAX_JOB_DELTA_CHARS)}`;
|
|
16059
|
+
}
|
|
16060
|
+
return out;
|
|
15988
16061
|
}
|
|
15989
16062
|
function formatJobStillRunningContinuePrompt(jobIds) {
|
|
15990
16063
|
const ids = jobIds.join(", ");
|
|
@@ -16047,7 +16120,7 @@ function takeDelta(logFile, cursorFile) {
|
|
|
16047
16120
|
const lines = readLogLines(logFile);
|
|
16048
16121
|
const cursor = readIntFile(cursorFile) ?? 0;
|
|
16049
16122
|
const start = Math.min(Math.max(0, cursor), lines.length);
|
|
16050
|
-
return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
|
|
16123
|
+
return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
|
|
16051
16124
|
}
|
|
16052
16125
|
function snapshotJob(dir) {
|
|
16053
16126
|
const pid = readIntFile((0, import_node_path42.join)(dir, "pid"));
|
|
@@ -16215,7 +16288,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
16215
16288
|
hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
|
|
16216
16289
|
};
|
|
16217
16290
|
}
|
|
16218
|
-
var import_node_fs42, import_node_path42, MAX_JOB_CONTINUES, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
|
|
16291
|
+
var import_node_fs42, import_node_path42, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
|
|
16219
16292
|
var init_wait_for_job = __esm({
|
|
16220
16293
|
"src/mcp/wait-for-job.ts"() {
|
|
16221
16294
|
"use strict";
|
|
@@ -16224,6 +16297,10 @@ var init_wait_for_job = __esm({
|
|
|
16224
16297
|
init_workspace_scratch();
|
|
16225
16298
|
init_wait_for_turn();
|
|
16226
16299
|
MAX_JOB_CONTINUES = 8;
|
|
16300
|
+
MAX_JOB_DELTA_LINES = 80;
|
|
16301
|
+
MAX_JOB_DELTA_CHARS = 4e3;
|
|
16302
|
+
DEFERRED_DONE_MAX_CHARS = 480;
|
|
16303
|
+
GH_WATCH_REFRESH = "Refreshing run status every 3 seconds.";
|
|
16227
16304
|
MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
|
|
16228
16305
|
MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
|
|
16229
16306
|
JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
@@ -21459,11 +21536,13 @@ var init_orchestrator = __esm({
|
|
|
21459
21536
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
21460
21537
|
thread = this.requireThread(threadId);
|
|
21461
21538
|
}
|
|
21462
|
-
const
|
|
21539
|
+
const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
|
|
21540
|
+
const sentAttachments = !autoContinue && thread.attachments.length > 0 ? [...thread.attachments] : void 0;
|
|
21463
21541
|
appendMessage(threadId, {
|
|
21464
21542
|
role: "user",
|
|
21465
21543
|
text: prompt,
|
|
21466
21544
|
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
21545
|
+
...autoContinue ? { origin: "continue" } : {},
|
|
21467
21546
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
21468
21547
|
});
|
|
21469
21548
|
thread = this.requireThread(threadId);
|
|
@@ -21472,7 +21551,7 @@ var init_orchestrator = __esm({
|
|
|
21472
21551
|
thread.worktreePath,
|
|
21473
21552
|
gitPrompt,
|
|
21474
21553
|
{
|
|
21475
|
-
attachments: sentAttachments ?? thread.attachments
|
|
21554
|
+
attachments: autoContinue ? [] : sentAttachments ?? thread.attachments
|
|
21476
21555
|
}
|
|
21477
21556
|
);
|
|
21478
21557
|
const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
|
|
@@ -21525,7 +21604,7 @@ var init_orchestrator = __esm({
|
|
|
21525
21604
|
slackReplyContext,
|
|
21526
21605
|
expandedPrompt
|
|
21527
21606
|
].filter(Boolean).join("\n\n");
|
|
21528
|
-
if (thread.attachments.length > 0) {
|
|
21607
|
+
if (!autoContinue && thread.attachments.length > 0) {
|
|
21529
21608
|
updateThread(threadId, { attachments: [] });
|
|
21530
21609
|
}
|
|
21531
21610
|
const adapter = getAdapter(thread.agent);
|
package/dist/index.d.cts
CHANGED
|
@@ -87,6 +87,11 @@ interface ThreadMessage {
|
|
|
87
87
|
* in chat history after pending thread.attachments are cleared).
|
|
88
88
|
*/
|
|
89
89
|
attachments?: ThreadAttachment[];
|
|
90
|
+
/**
|
|
91
|
+
* Host-queued keep-alive (job still running / crash recover). Shown as a
|
|
92
|
+
* system note — not a user bubble.
|
|
93
|
+
*/
|
|
94
|
+
origin?: 'continue';
|
|
90
95
|
ts: string;
|
|
91
96
|
}
|
|
92
97
|
/** Composer / turn attachment (e.g. forked chat transcript). */
|
package/dist/index.d.ts
CHANGED
|
@@ -87,6 +87,11 @@ interface ThreadMessage {
|
|
|
87
87
|
* in chat history after pending thread.attachments are cleared).
|
|
88
88
|
*/
|
|
89
89
|
attachments?: ThreadAttachment[];
|
|
90
|
+
/**
|
|
91
|
+
* Host-queued keep-alive (job still running / crash recover). Shown as a
|
|
92
|
+
* system note — not a user bubble.
|
|
93
|
+
*/
|
|
94
|
+
origin?: 'continue';
|
|
90
95
|
ts: string;
|
|
91
96
|
}
|
|
92
97
|
/** Composer / turn attachment (e.g. forked chat transcript). */
|
package/dist/index.js
CHANGED
|
@@ -238,7 +238,7 @@ import {
|
|
|
238
238
|
worktreeCleanupSettings,
|
|
239
239
|
wrapReviewSkillMarkdown,
|
|
240
240
|
writeWorktreeFile
|
|
241
|
-
} from "./chunk-
|
|
241
|
+
} from "./chunk-TBG2Z3ZV.js";
|
|
242
242
|
import {
|
|
243
243
|
LEGACY_PLAN_FILE_REL,
|
|
244
244
|
PLAN_FILE_NAME,
|
|
@@ -344,7 +344,7 @@ import {
|
|
|
344
344
|
withEventParentId,
|
|
345
345
|
withEventsParentId,
|
|
346
346
|
writeInjectedMcpConfig
|
|
347
|
-
} from "./chunk-
|
|
347
|
+
} from "./chunk-ISOCLQEX.js";
|
|
348
348
|
import {
|
|
349
349
|
CLOUD_COORDINATOR_BUSY_REPLY,
|
|
350
350
|
CLOUD_COORDINATOR_STOPPED_REPLY,
|
|
@@ -553,7 +553,7 @@ import {
|
|
|
553
553
|
trustSystemCertificates,
|
|
554
554
|
turnCostUsdFromCursorUsage,
|
|
555
555
|
withMaxOldSpaceSize
|
|
556
|
-
} from "./chunk-
|
|
556
|
+
} from "./chunk-ZSFQLR7Y.js";
|
|
557
557
|
import {
|
|
558
558
|
FOLLOW_UP_BEHAVIORS,
|
|
559
559
|
GITHUB_GIT_AUTH_MODES,
|
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -1610,11 +1610,45 @@ function looksLikeHugeToolResultDump(text7) {
|
|
|
1610
1610
|
if (t.length < 4e3) return false;
|
|
1611
1611
|
return looksLikeMinifiedJsDump(t);
|
|
1612
1612
|
}
|
|
1613
|
+
function clipJobWaitResultJson(content) {
|
|
1614
|
+
const trimmed = content.trim();
|
|
1615
|
+
if (!trimmed.startsWith("{")) return void 0;
|
|
1616
|
+
try {
|
|
1617
|
+
const rec = JSON.parse(trimmed);
|
|
1618
|
+
const isJob = typeof rec.stillRunning === "boolean" || typeof rec.stopped === "boolean" || typeof rec.delta === "string" && typeof rec.status === "string";
|
|
1619
|
+
if (!isJob) return void 0;
|
|
1620
|
+
if (typeof rec.delta === "string" && rec.delta.length > 3500) {
|
|
1621
|
+
rec.delta = `\u2026(truncated ${rec.delta.length} chars)
|
|
1622
|
+
${rec.delta.slice(-3500)}`;
|
|
1623
|
+
}
|
|
1624
|
+
if (typeof rec.progress === "string" && rec.progress.length > 800) {
|
|
1625
|
+
rec.progress = rec.progress.slice(-800);
|
|
1626
|
+
}
|
|
1627
|
+
if (typeof rec.hint === "string" && rec.hint.length > 240) {
|
|
1628
|
+
rec.hint = rec.hint.slice(0, 240);
|
|
1629
|
+
}
|
|
1630
|
+
let out = JSON.stringify(rec);
|
|
1631
|
+
if (out.length <= TOOL_RESULT_STORE_MAX_CHARS) return out;
|
|
1632
|
+
return JSON.stringify({
|
|
1633
|
+
stillRunning: rec.stillRunning,
|
|
1634
|
+
ok: rec.ok,
|
|
1635
|
+
failed: rec.failed,
|
|
1636
|
+
status: rec.status,
|
|
1637
|
+
id: rec.id,
|
|
1638
|
+
phase: rec.phase,
|
|
1639
|
+
delta: typeof rec.delta === "string" ? rec.delta.slice(-2500) : ""
|
|
1640
|
+
});
|
|
1641
|
+
} catch {
|
|
1642
|
+
return void 0;
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1613
1645
|
function clipToolResultForStore(content) {
|
|
1614
1646
|
if (content == null) return void 0;
|
|
1615
1647
|
if (looksLikeCursorSdkSourceDump(content) || looksLikeMinifiedJsDump(content)) {
|
|
1616
1648
|
return `${HUGE_TOOL_RESULT_SUMMARY} (${content.length} chars omitted)`;
|
|
1617
1649
|
}
|
|
1650
|
+
const jobClipped = clipJobWaitResultJson(content);
|
|
1651
|
+
if (jobClipped) return jobClipped;
|
|
1618
1652
|
if (content.length <= TOOL_RESULT_STORE_MAX_CHARS) return content;
|
|
1619
1653
|
const head = 5e3;
|
|
1620
1654
|
const tail = 2e3;
|
|
@@ -9021,10 +9055,15 @@ function asRecord(input) {
|
|
|
9021
9055
|
function str2(v) {
|
|
9022
9056
|
return typeof v === "string" && v.trim() ? v : void 0;
|
|
9023
9057
|
}
|
|
9058
|
+
function clipChatLine(value, max = CHAT_DETAIL_MAX) {
|
|
9059
|
+
const line = value.trim().split(/\r?\n/, 1)[0] ?? "";
|
|
9060
|
+
if (line.length <= max) return line;
|
|
9061
|
+
return `${line.slice(0, Math.max(1, max - 1))}\u2026`;
|
|
9062
|
+
}
|
|
9024
9063
|
function toolDetail(name, input) {
|
|
9025
9064
|
if (!input) return void 0;
|
|
9026
9065
|
const command = str2(input.command) ?? str2(input.cmd);
|
|
9027
|
-
if (command) return command;
|
|
9066
|
+
if (command) return clipChatLine(command);
|
|
9028
9067
|
const pattern = str2(input.pattern) ?? str2(input.glob) ?? str2(input.glob_pattern);
|
|
9029
9068
|
const isSearch = /grep|glob|search|ripgrep|findfiles|semsearch/i.test(name);
|
|
9030
9069
|
if (isSearch && pattern) {
|
|
@@ -9461,10 +9500,12 @@ function normalizeParseResult(parsed) {
|
|
|
9461
9500
|
if (!parsed) return [];
|
|
9462
9501
|
return Array.isArray(parsed) ? parsed : [parsed];
|
|
9463
9502
|
}
|
|
9503
|
+
var CHAT_DETAIL_MAX;
|
|
9464
9504
|
var init_message_parts = __esm({
|
|
9465
9505
|
"src/agents/message-parts.ts"() {
|
|
9466
9506
|
"use strict";
|
|
9467
9507
|
init_error_detail();
|
|
9508
|
+
CHAT_DETAIL_MAX = 72;
|
|
9468
9509
|
}
|
|
9469
9510
|
});
|
|
9470
9511
|
|
|
@@ -14333,8 +14374,37 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
14333
14374
|
}
|
|
14334
14375
|
function looksLikeDeferredDonePromise(text7) {
|
|
14335
14376
|
const t = (text7 ?? "").trim();
|
|
14336
|
-
if (!t) return false;
|
|
14337
|
-
|
|
14377
|
+
if (!t || t.length > DEFERRED_DONE_MAX_CHARS) return false;
|
|
14378
|
+
const unquoted = t.replace(/`[^`]*`/g, " ").replace(/["“”][^"“”]*["“”]/g, " ").replace(/\s+/g, " ").trim();
|
|
14379
|
+
if (!unquoted) return false;
|
|
14380
|
+
return /\b(i['’]?ll|i will)\s+let you know\b/i.test(unquoted) || /\blet you know when\b/i.test(unquoted) || /\b(check back|ping me)\s+when\b/i.test(unquoted) || /\bi(?:['’]ll| will)\s+(report|update you)\s+when\b/i.test(unquoted);
|
|
14381
|
+
}
|
|
14382
|
+
function isJobContinuePrompt(text7) {
|
|
14383
|
+
const t = text7.trim();
|
|
14384
|
+
return t.startsWith("Detached job still running:") || t.startsWith("You ended the turn after promising to report later");
|
|
14385
|
+
}
|
|
14386
|
+
function collapseGhRunWatchLog(text7) {
|
|
14387
|
+
if (!text7.includes(GH_WATCH_REFRESH)) return text7;
|
|
14388
|
+
const frames = text7.split(/(?=Refreshing run status every 3 seconds\.)/);
|
|
14389
|
+
const watchFrames = frames.filter((f) => f.includes(GH_WATCH_REFRESH));
|
|
14390
|
+
if (watchFrames.length <= 1) return text7;
|
|
14391
|
+
const prefix = frames[0]?.includes(GH_WATCH_REFRESH) ? "" : frames[0] ?? "";
|
|
14392
|
+
const last = watchFrames[watchFrames.length - 1] ?? "";
|
|
14393
|
+
const omitted = watchFrames.length - 1;
|
|
14394
|
+
const note = `(${omitted} identical gh run watch refresh${omitted === 1 ? "" : "es"} omitted)
|
|
14395
|
+
`;
|
|
14396
|
+
return [prefix.trimEnd(), note, last.trimStart()].filter(Boolean).join("\n");
|
|
14397
|
+
}
|
|
14398
|
+
function capJobLogDelta(text7) {
|
|
14399
|
+
const collapsed = collapseGhRunWatchLog(text7);
|
|
14400
|
+
const lines = collapsed.split("\n");
|
|
14401
|
+
let out = lines.length > MAX_JOB_DELTA_LINES ? `\u2026(${lines.length - MAX_JOB_DELTA_LINES} earlier lines omitted)
|
|
14402
|
+
${lines.slice(-MAX_JOB_DELTA_LINES).join("\n")}` : collapsed;
|
|
14403
|
+
if (out.length > MAX_JOB_DELTA_CHARS) {
|
|
14404
|
+
out = `\u2026(truncated ${out.length} chars)
|
|
14405
|
+
${out.slice(-MAX_JOB_DELTA_CHARS)}`;
|
|
14406
|
+
}
|
|
14407
|
+
return out;
|
|
14338
14408
|
}
|
|
14339
14409
|
function formatJobStillRunningContinuePrompt(jobIds) {
|
|
14340
14410
|
const ids = jobIds.join(", ");
|
|
@@ -14397,7 +14467,7 @@ function takeDelta(logFile, cursorFile) {
|
|
|
14397
14467
|
const lines = readLogLines(logFile);
|
|
14398
14468
|
const cursor = readIntFile(cursorFile) ?? 0;
|
|
14399
14469
|
const start = Math.min(Math.max(0, cursor), lines.length);
|
|
14400
|
-
return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
|
|
14470
|
+
return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
|
|
14401
14471
|
}
|
|
14402
14472
|
function snapshotJob(dir) {
|
|
14403
14473
|
const pid = readIntFile((0, import_node_path40.join)(dir, "pid"));
|
|
@@ -14565,7 +14635,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
14565
14635
|
hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
|
|
14566
14636
|
};
|
|
14567
14637
|
}
|
|
14568
|
-
var import_node_fs40, import_node_path40, MAX_JOB_CONTINUES, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
|
|
14638
|
+
var import_node_fs40, import_node_path40, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
|
|
14569
14639
|
var init_wait_for_job = __esm({
|
|
14570
14640
|
"src/mcp/wait-for-job.ts"() {
|
|
14571
14641
|
"use strict";
|
|
@@ -14574,6 +14644,10 @@ var init_wait_for_job = __esm({
|
|
|
14574
14644
|
init_workspace_scratch();
|
|
14575
14645
|
init_wait_for_turn();
|
|
14576
14646
|
MAX_JOB_CONTINUES = 8;
|
|
14647
|
+
MAX_JOB_DELTA_LINES = 80;
|
|
14648
|
+
MAX_JOB_DELTA_CHARS = 4e3;
|
|
14649
|
+
DEFERRED_DONE_MAX_CHARS = 480;
|
|
14650
|
+
GH_WATCH_REFRESH = "Refreshing run status every 3 seconds.";
|
|
14577
14651
|
MCP_WAIT_JOB_STILL_RUNNING_HINT = "Job is still running. The type=log pane already appended this delta. Call wait_for_job again. If it is hanging, producing no useful output, or doing the wrong thing, call stop_job (same id) instead of looping forever. Do not end the turn or tell the user you will let them know later.";
|
|
14578
14652
|
MCP_STOP_JOB_HINT = "Stopped. The type=log pane is status=failed with the last delta. Do not wait again unless you start a new command.";
|
|
14579
14653
|
JOB_ID_RE = /^[a-zA-Z0-9._-]{1,64}$/;
|
|
@@ -20090,11 +20164,13 @@ var init_orchestrator = __esm({
|
|
|
20090
20164
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
20091
20165
|
thread = this.requireThread(threadId);
|
|
20092
20166
|
}
|
|
20093
|
-
const
|
|
20167
|
+
const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
|
|
20168
|
+
const sentAttachments = !autoContinue && thread.attachments.length > 0 ? [...thread.attachments] : void 0;
|
|
20094
20169
|
appendMessage(threadId, {
|
|
20095
20170
|
role: "user",
|
|
20096
20171
|
text: prompt,
|
|
20097
20172
|
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
20173
|
+
...autoContinue ? { origin: "continue" } : {},
|
|
20098
20174
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
20099
20175
|
});
|
|
20100
20176
|
thread = this.requireThread(threadId);
|
|
@@ -20103,7 +20179,7 @@ var init_orchestrator = __esm({
|
|
|
20103
20179
|
thread.worktreePath,
|
|
20104
20180
|
gitPrompt,
|
|
20105
20181
|
{
|
|
20106
|
-
attachments: sentAttachments ?? thread.attachments
|
|
20182
|
+
attachments: autoContinue ? [] : sentAttachments ?? thread.attachments
|
|
20107
20183
|
}
|
|
20108
20184
|
);
|
|
20109
20185
|
const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
|
|
@@ -20156,7 +20232,7 @@ var init_orchestrator = __esm({
|
|
|
20156
20232
|
slackReplyContext,
|
|
20157
20233
|
expandedPrompt
|
|
20158
20234
|
].filter(Boolean).join("\n\n");
|
|
20159
|
-
if (thread.attachments.length > 0) {
|
|
20235
|
+
if (!autoContinue && thread.attachments.length > 0) {
|
|
20160
20236
|
updateThread(threadId, { attachments: [] });
|
|
20161
20237
|
}
|
|
20162
20238
|
const adapter = getAdapter(thread.agent);
|
package/dist/mcp/run-stdio.js
CHANGED
|
@@ -37,7 +37,7 @@ import {
|
|
|
37
37
|
syncBoardPins,
|
|
38
38
|
updateSchedule,
|
|
39
39
|
waitForDetachedJob
|
|
40
|
-
} from "../chunk-
|
|
40
|
+
} from "../chunk-72FO6OLT.js";
|
|
41
41
|
import {
|
|
42
42
|
applySystemCaEnv,
|
|
43
43
|
isCursorApiKeyConfigured,
|
|
@@ -46,7 +46,7 @@ import {
|
|
|
46
46
|
materializeSystemCaBundle,
|
|
47
47
|
sideboardMcpProfile,
|
|
48
48
|
trustSystemCertificates
|
|
49
|
-
} from "../chunk-
|
|
49
|
+
} from "../chunk-QU663NPO.js";
|
|
50
50
|
import "../chunk-HVIEYTUK.js";
|
|
51
51
|
import "../chunk-Y4MIXGPA.js";
|
|
52
52
|
import {
|
|
@@ -8,8 +8,8 @@ import {
|
|
|
8
8
|
resolveSendFollowUp,
|
|
9
9
|
startOrchestration,
|
|
10
10
|
waitForPidExit
|
|
11
|
-
} from "./chunk-
|
|
12
|
-
import "./chunk-
|
|
11
|
+
} from "./chunk-72FO6OLT.js";
|
|
12
|
+
import "./chunk-QU663NPO.js";
|
|
13
13
|
import "./chunk-HVIEYTUK.js";
|
|
14
14
|
import "./chunk-Y4MIXGPA.js";
|
|
15
15
|
import "./chunk-VKQGAWHY.js";
|
|
@@ -6,9 +6,9 @@ import {
|
|
|
6
6
|
resolveSendFollowUp,
|
|
7
7
|
startOrchestration,
|
|
8
8
|
waitForPidExit
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-TBG2Z3ZV.js";
|
|
10
10
|
import "./chunk-DJU54RYW.js";
|
|
11
|
-
import "./chunk-
|
|
11
|
+
import "./chunk-ISOCLQEX.js";
|
|
12
12
|
import "./chunk-VIODP5PT.js";
|
|
13
13
|
import "./chunk-WXKXSZN4.js";
|
|
14
14
|
import "./chunk-6K64FJDD.js";
|
|
@@ -16,7 +16,7 @@ import "./chunk-IEEAVWAP.js";
|
|
|
16
16
|
import "./chunk-AN3THU7F.js";
|
|
17
17
|
import "./chunk-N7WZ6NIN.js";
|
|
18
18
|
import "./chunk-AXQ4ZWHK.js";
|
|
19
|
-
import "./chunk-
|
|
19
|
+
import "./chunk-ZSFQLR7Y.js";
|
|
20
20
|
import "./chunk-J7LQVLFQ.js";
|
|
21
21
|
import "./chunk-4TR3HZFT.js";
|
|
22
22
|
import "./chunk-AO35MGOE.js";
|