@sideboard-ai/core 0.1.318 → 0.1.320
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/{abletime-TKAFNXCM.js → abletime-CRRLEYTE.js} +6 -4
- package/dist/{abletime-KWOBUL46.js → abletime-ICW6Q2AB.js} +6 -4
- package/dist/{abletime-oauth-S4AXA4WR.js → abletime-oauth-P3KPPJE4.js} +3 -3
- package/dist/{abletime-oauth-IUIAGLFJ.js → abletime-oauth-Q76XBSPG.js} +3 -3
- package/dist/{abletime-rest-RWN4EPY3.js → abletime-rest-DNFAYYLP.js} +3 -3
- package/dist/{abletime-rest-ORBELZQO.js → abletime-rest-DQ3PNKXP.js} +3 -3
- package/dist/{agents-KABJUDPI.js → agents-CJZYJOWP.js} +7 -7
- package/dist/{agents-2AR7I6B6.js → agents-F2E2HACB.js} +7 -7
- package/dist/{app-settings-CZVFMOI5.js → app-settings-KMPVI2B7.js} +1 -1
- package/dist/{app-settings-V6YPYY57.js → app-settings-P3H4SEIK.js} +1 -1
- package/dist/{chunk-YEIHCSZS.js → chunk-4GZC6DDH.js} +2 -0
- package/dist/{chunk-XOZNEAWF.js → chunk-56M6VEXI.js} +3 -3
- package/dist/{chunk-7SCVGGF6.js → chunk-5OQONGHO.js} +5 -5
- package/dist/{chunk-A6C67DY5.js → chunk-5S3YP5KH.js} +4 -4
- package/dist/{chunk-I5CLCWUK.js → chunk-72PUPPV2.js} +9 -5
- package/dist/{chunk-BXTISNKW.js → chunk-B7UL36WH.js} +428 -99
- package/dist/{chunk-W5QZWAUB.js → chunk-BTIXTH4N.js} +9 -5
- package/dist/{chunk-AESO2KJS.js → chunk-CB5Z5C3J.js} +2 -2
- package/dist/{chunk-2HOZMSKQ.js → chunk-DFUXW2IT.js} +2 -2
- package/dist/{chunk-ST2UQBJT.js → chunk-DJZRDTZY.js} +6 -6
- package/dist/{chunk-TUJFCJJU.js → chunk-EDXTP2VR.js} +2 -2
- package/dist/{chunk-I5TESHDN.js → chunk-EQ52JR3Q.js} +5 -5
- package/dist/{chunk-FDXHNROD.js → chunk-EQ5JY3MJ.js} +2 -2
- package/dist/{chunk-E52SQENB.js → chunk-FZKAAAEB.js} +3 -1
- package/dist/{chunk-VZAJVX36.js → chunk-HHPTGIKS.js} +2 -2
- package/dist/{chunk-23ZUL2EX.js → chunk-IDPFLXRY.js} +429 -100
- package/dist/{chunk-GCHSJCCX.js → chunk-IFU4W4C4.js} +3 -1
- package/dist/{chunk-IAPO7ZFG.js → chunk-LLIEU2ZB.js} +5 -5
- package/dist/{chunk-MBYGWNLQ.js → chunk-OAFBHCSM.js} +1 -1
- package/dist/{chunk-NRSC4N5X.js → chunk-P74GXA5V.js} +6 -6
- package/dist/{chunk-A46CIARU.js → chunk-PNLGWAYE.js} +2 -2
- package/dist/{chunk-53OCOGND.js → chunk-QGY3UNNL.js} +2 -2
- package/dist/{chunk-7Q327QF2.js → chunk-QIC2JXHW.js} +5 -5
- package/dist/{chunk-YALFZKSC.js → chunk-RHJPP26T.js} +11 -11
- package/dist/{chunk-AZ4GEEGL.js → chunk-UK2KESBN.js} +2 -2
- package/dist/{chunk-7ADEYEMH.js → chunk-V76MQ7MH.js} +5 -5
- package/dist/{chunk-HOLB6ZFZ.js → chunk-XMHMVEIY.js} +2 -0
- package/dist/{chunk-GH7UMULC.js → chunk-ZYZBCLJR.js} +6 -6
- package/dist/{conductor-MG2RAQNT.js → conductor-FPFY6Z5S.js} +6 -6
- package/dist/{conductor-NIUBJLTS.js → conductor-JA5W3L7C.js} +6 -6
- package/dist/{coordinator-prompt-3CT3D5UM.js → coordinator-prompt-M75TAN43.js} +4 -4
- package/dist/{coordinator-prompt-X74F3JIC.js → coordinator-prompt-NUC2ZXMJ.js} +4 -4
- package/dist/{global-workspace-BUWMRNW5.js → global-workspace-5A4H34AF.js} +4 -4
- package/dist/{global-workspace-FTNJEML3.js → global-workspace-SCLQUNUI.js} +4 -4
- package/dist/index.cjs +861 -475
- package/dist/index.d.cts +56 -13
- package/dist/index.d.ts +56 -13
- package/dist/index.js +54 -31
- package/dist/mcp/run-stdio.cjs +459 -95
- package/dist/mcp/run-stdio.js +23 -23
- package/dist/{optional-cli-EMSZBYDE.js → optional-cli-2V3SLME5.js} +3 -3
- package/dist/{optional-cli-6GGESWGE.js → optional-cli-MRNQKVIR.js} +4 -4
- package/dist/{orchestrator-N54V3B76.js → orchestrator-7BDZ5GWD.js} +10 -10
- package/dist/{orchestrator-2SXK4U65.js → orchestrator-NPFWU3XU.js} +10 -10
- package/dist/{thread-store-PLNIWFZ4.js → thread-store-JWHVXLDX.js} +1 -1
- package/dist/{thread-store-7BBA63KV.js → thread-store-QHYN2ZMQ.js} +1 -1
- package/dist/{workspaces-2V5UYPYC.js → workspaces-5QA3YM4L.js} +4 -4
- package/dist/{workspaces-MGKEAYNM.js → workspaces-KWMBOTQD.js} +4 -4
- package/dist/{worktree-THAXW5U7.js → worktree-7EATHVYQ.js} +3 -3
- package/dist/{worktree-XJKLDYOL.js → worktree-O6BANO2I.js} +3 -3
- package/package.json +1 -1
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
import {
|
|
7
7
|
formatOptionalServicesDirectiveForTurn,
|
|
8
8
|
formatOptionalServicesReminderForTurn
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-OAFBHCSM.js";
|
|
10
10
|
import {
|
|
11
11
|
extractPresentedPlan,
|
|
12
12
|
isPresentPlanToolName,
|
|
@@ -27,7 +27,7 @@ import {
|
|
|
27
27
|
parseSessionQuotaResetAt,
|
|
28
28
|
planModeTurnInstruction,
|
|
29
29
|
resolveQuotaFallbackAgent
|
|
30
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-ZYZBCLJR.js";
|
|
31
31
|
import {
|
|
32
32
|
applyWorktreePkgCacheEnv,
|
|
33
33
|
askBlockStillWaiting,
|
|
@@ -65,7 +65,7 @@ import {
|
|
|
65
65
|
worktreeDevProcessKey,
|
|
66
66
|
worktreeRunProcessKey,
|
|
67
67
|
worktreeSetupProcessKey
|
|
68
|
-
} from "./chunk-
|
|
68
|
+
} from "./chunk-P74GXA5V.js";
|
|
69
69
|
import {
|
|
70
70
|
applyAgentEvent,
|
|
71
71
|
clipAgentEventForPaint,
|
|
@@ -92,7 +92,7 @@ import {
|
|
|
92
92
|
summarizeTurnStderr,
|
|
93
93
|
toolDescription,
|
|
94
94
|
turnFailChatText
|
|
95
|
-
} from "./chunk-
|
|
95
|
+
} from "./chunk-EQ52JR3Q.js";
|
|
96
96
|
import {
|
|
97
97
|
SLACK_REPLY_FORMATTING,
|
|
98
98
|
addWorkspace,
|
|
@@ -117,7 +117,7 @@ import {
|
|
|
117
117
|
stageAbsolutePathsAsAttachments,
|
|
118
118
|
stageBuffersAsAttachments,
|
|
119
119
|
syncWorkspacesFromThreads
|
|
120
|
-
} from "./chunk-
|
|
120
|
+
} from "./chunk-5S3YP5KH.js";
|
|
121
121
|
import {
|
|
122
122
|
addPrStackLayer,
|
|
123
123
|
allocateTeamSlug,
|
|
@@ -159,7 +159,7 @@ import {
|
|
|
159
159
|
resolveRepoRoot,
|
|
160
160
|
switchWorktreeBranch,
|
|
161
161
|
withRepoGitLock
|
|
162
|
-
} from "./chunk-
|
|
162
|
+
} from "./chunk-PNLGWAYE.js";
|
|
163
163
|
import {
|
|
164
164
|
clearStaleIndexLocks,
|
|
165
165
|
enrichPathWithNpmGlobalBin,
|
|
@@ -201,7 +201,7 @@ import {
|
|
|
201
201
|
usageOnLimit,
|
|
202
202
|
withTurnScopedCost,
|
|
203
203
|
writeViewerContext
|
|
204
|
-
} from "./chunk-
|
|
204
|
+
} from "./chunk-IFU4W4C4.js";
|
|
205
205
|
import {
|
|
206
206
|
writePrivateFile
|
|
207
207
|
} from "./chunk-NSTQ6QKD.js";
|
|
@@ -242,7 +242,10 @@ import {
|
|
|
242
242
|
worktreeNameFromPath,
|
|
243
243
|
worktreeSlugForTicket,
|
|
244
244
|
writeThread
|
|
245
|
-
} from "./chunk-
|
|
245
|
+
} from "./chunk-XMHMVEIY.js";
|
|
246
|
+
import {
|
|
247
|
+
normalizeThinkingEffort
|
|
248
|
+
} from "./chunk-KGZBYWZ3.js";
|
|
246
249
|
import {
|
|
247
250
|
annotateDevAccessRuns,
|
|
248
251
|
appDataDir,
|
|
@@ -507,9 +510,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
507
510
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
508
511
|
);
|
|
509
512
|
}
|
|
510
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
513
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-5A4H34AF.js");
|
|
511
514
|
if (isGlobalThread2(thread)) {
|
|
512
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
515
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-M75TAN43.js");
|
|
513
516
|
ensureGlobalCoordinatorCwd2(
|
|
514
517
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
515
518
|
);
|
|
@@ -1955,6 +1958,71 @@ function claimSteerRequest(threadId) {
|
|
|
1955
1958
|
});
|
|
1956
1959
|
}
|
|
1957
1960
|
|
|
1961
|
+
// src/orchestrator/ephemeral-automation.ts
|
|
1962
|
+
function ephemeralRunReadyToArchive(thread) {
|
|
1963
|
+
if (!thread.ephemeralAutomationId?.trim()) return false;
|
|
1964
|
+
if (thread.status !== "idle" && thread.status !== "error") return false;
|
|
1965
|
+
if (thread.queue.length > 0) return false;
|
|
1966
|
+
if (thread.agentBlock?.reason?.trim()) return false;
|
|
1967
|
+
if (thread.quotaResumeAt) return false;
|
|
1968
|
+
return true;
|
|
1969
|
+
}
|
|
1970
|
+
function markEphemeralAutomation(threadId, opts) {
|
|
1971
|
+
const id = opts.ephemeralAutomationId?.trim();
|
|
1972
|
+
const current = readThread(threadId);
|
|
1973
|
+
if (!current) throw new Error(`Thread not found: ${threadId}`);
|
|
1974
|
+
if (!id) return current;
|
|
1975
|
+
const title = opts.ephemeralTitle?.trim();
|
|
1976
|
+
return updateThread(threadId, {
|
|
1977
|
+
ephemeralAutomationId: id,
|
|
1978
|
+
...title ? { title, userSetTitle: true } : {}
|
|
1979
|
+
});
|
|
1980
|
+
}
|
|
1981
|
+
async function archiveEphemeralAutomationIfReady(threadId, archive) {
|
|
1982
|
+
const keep = await withThreadLock(threadId, async () => {
|
|
1983
|
+
const thread = readThread(threadId);
|
|
1984
|
+
if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
|
|
1985
|
+
const automationId = thread.ephemeralAutomationId?.trim();
|
|
1986
|
+
if (!automationId) return null;
|
|
1987
|
+
await archive(thread.id);
|
|
1988
|
+
return {
|
|
1989
|
+
automationId,
|
|
1990
|
+
keepId: archivedContinuationId(automationId, threadId) ?? threadId
|
|
1991
|
+
};
|
|
1992
|
+
});
|
|
1993
|
+
if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
|
|
1994
|
+
}
|
|
1995
|
+
function archivedContinuationId(automationId, sourceId) {
|
|
1996
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
1997
|
+
if (thread.id === sourceId || thread.status !== "archived") continue;
|
|
1998
|
+
if (thread.ephemeralAutomationId !== automationId) continue;
|
|
1999
|
+
if (thread.quotaContinuedFromId !== sourceId) continue;
|
|
2000
|
+
return thread.id;
|
|
2001
|
+
}
|
|
2002
|
+
return null;
|
|
2003
|
+
}
|
|
2004
|
+
function clearEphemeralAutomation(threadId) {
|
|
2005
|
+
const thread = readThread(threadId);
|
|
2006
|
+
if (!thread?.ephemeralAutomationId?.trim()) return;
|
|
2007
|
+
updateThread(threadId, { ephemeralAutomationId: void 0 });
|
|
2008
|
+
}
|
|
2009
|
+
function forgetOlderEphemeralRuns(automationId, keepId) {
|
|
2010
|
+
const id = automationId.trim();
|
|
2011
|
+
if (!id || !keepId) return [];
|
|
2012
|
+
const removed = [];
|
|
2013
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
2014
|
+
if (thread.id === keepId) continue;
|
|
2015
|
+
if (thread.status !== "archived") continue;
|
|
2016
|
+
if (thread.ephemeralAutomationId !== id) continue;
|
|
2017
|
+
try {
|
|
2018
|
+
deleteThreadRecord(thread.id);
|
|
2019
|
+
removed.push(thread.id);
|
|
2020
|
+
} catch {
|
|
2021
|
+
}
|
|
2022
|
+
}
|
|
2023
|
+
return removed;
|
|
2024
|
+
}
|
|
2025
|
+
|
|
1958
2026
|
// src/threads/agent-purpose-title.ts
|
|
1959
2027
|
function agentPurposeStamp(input) {
|
|
1960
2028
|
if (input.autoContinue) return null;
|
|
@@ -2632,7 +2700,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2632
2700
|
});
|
|
2633
2701
|
await requireAgent(resolved.agent);
|
|
2634
2702
|
if (input.cowboy) {
|
|
2635
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
2703
|
+
const { cowboyModeEnabled } = await import("./app-settings-KMPVI2B7.js");
|
|
2636
2704
|
if (!cowboyModeEnabled()) {
|
|
2637
2705
|
throw new Error(
|
|
2638
2706
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -2691,7 +2759,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2691
2759
|
let sourceIsFork = false;
|
|
2692
2760
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
2693
2761
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
2694
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
2762
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-CRRLEYTE.js");
|
|
2695
2763
|
const task = await ensureAbleTimeTask({
|
|
2696
2764
|
title: title?.trim() || "Untitled work",
|
|
2697
2765
|
description: input.prompt?.trim() || void 0
|
|
@@ -3210,6 +3278,9 @@ function writeTurnLive(threadId, progress) {
|
|
|
3210
3278
|
}
|
|
3211
3279
|
}
|
|
3212
3280
|
}
|
|
3281
|
+
function readTurnLiveParts(threadId) {
|
|
3282
|
+
return buffers.get(threadId)?.parts.slice() ?? [];
|
|
3283
|
+
}
|
|
3213
3284
|
function readTurnLive(threadId) {
|
|
3214
3285
|
const path = threadLivePath(threadId);
|
|
3215
3286
|
if (!existsSync6(path)) return null;
|
|
@@ -3447,17 +3518,23 @@ async function isolateQuotaFailover(run) {
|
|
|
3447
3518
|
}
|
|
3448
3519
|
}
|
|
3449
3520
|
function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
|
|
3521
|
+
const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
|
|
3522
|
+
const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
|
|
3450
3523
|
const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
|
|
3451
3524
|
const tab = createChatTab({
|
|
3452
3525
|
fromThreadId: from.id,
|
|
3453
3526
|
agent: fallbackAgent,
|
|
3454
3527
|
model: null,
|
|
3455
3528
|
attachments: [handoff],
|
|
3529
|
+
...ephemeralTitle ? { title: ephemeralTitle } : {},
|
|
3456
3530
|
...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
|
|
3457
3531
|
});
|
|
3458
3532
|
const patch = {
|
|
3459
3533
|
quotaContinuedFromId: from.id,
|
|
3460
|
-
sourceRef: from.sourceRef
|
|
3534
|
+
sourceRef: from.sourceRef,
|
|
3535
|
+
// The original drain archives as idle. This sibling has to carry the one-off
|
|
3536
|
+
// so it archives when the continued turn finishes and History keeps it.
|
|
3537
|
+
...ephemeralAutomationId ? { ephemeralAutomationId } : {}
|
|
3461
3538
|
};
|
|
3462
3539
|
if (isOrchestratorThread(from)) {
|
|
3463
3540
|
patch.parentThreadId = from.id;
|
|
@@ -3564,7 +3641,7 @@ async function adoptThread(input) {
|
|
|
3564
3641
|
messages: input.messages ?? []
|
|
3565
3642
|
});
|
|
3566
3643
|
writeThread(thread);
|
|
3567
|
-
const { addWorkspace: addWorkspace2 } = await import("./workspaces-
|
|
3644
|
+
const { addWorkspace: addWorkspace2 } = await import("./workspaces-5QA3YM4L.js");
|
|
3568
3645
|
await addWorkspace2(repoPath);
|
|
3569
3646
|
const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-5N2KTYIT.js");
|
|
3570
3647
|
await ensureWorktreeSideboardIgnored(input.worktreePath);
|
|
@@ -5384,6 +5461,36 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
5384
5461
|
};
|
|
5385
5462
|
}
|
|
5386
5463
|
|
|
5464
|
+
// src/composer/agent-has-replied.ts
|
|
5465
|
+
function joinSteerPrompt(base, addition) {
|
|
5466
|
+
const next = addition.trim();
|
|
5467
|
+
if (!next) return base;
|
|
5468
|
+
const head = base.replace(/\s+$/, "");
|
|
5469
|
+
if (!head) return next;
|
|
5470
|
+
return `${head}
|
|
5471
|
+
${next}`;
|
|
5472
|
+
}
|
|
5473
|
+
function trailingUnansweredUserText(messages) {
|
|
5474
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5475
|
+
const message = messages[i];
|
|
5476
|
+
if (!message || message.origin === "continue" || message.role === "summary") continue;
|
|
5477
|
+
if (message.role === "agent") {
|
|
5478
|
+
const text3 = (message.text ?? "").trim();
|
|
5479
|
+
if (text3 || (message.parts?.length ?? 0) > 0) return null;
|
|
5480
|
+
continue;
|
|
5481
|
+
}
|
|
5482
|
+
if (message.role === "user") return message.text;
|
|
5483
|
+
}
|
|
5484
|
+
return null;
|
|
5485
|
+
}
|
|
5486
|
+
function livePartsShowAgentReply(parts) {
|
|
5487
|
+
for (const part of parts) {
|
|
5488
|
+
if (part.type === "tool") return true;
|
|
5489
|
+
if ((part.type === "text" || part.type === "thinking") && part.text.trim()) return true;
|
|
5490
|
+
}
|
|
5491
|
+
return false;
|
|
5492
|
+
}
|
|
5493
|
+
|
|
5387
5494
|
// src/composer/consume-attachments.ts
|
|
5388
5495
|
function consumeComposerAttachments(thread) {
|
|
5389
5496
|
return {
|
|
@@ -5436,6 +5543,128 @@ function shiftQueuedItem(queue, queueAttachments) {
|
|
|
5436
5543
|
};
|
|
5437
5544
|
}
|
|
5438
5545
|
|
|
5546
|
+
// src/orchestrator/enqueue-thread-send.ts
|
|
5547
|
+
function resolveSendFollowUp(thread, requested) {
|
|
5548
|
+
if (requested === "steer" || requested === "queue") return requested;
|
|
5549
|
+
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
5550
|
+
}
|
|
5551
|
+
function rewriteTrailingUserPrompt(threadId, from, to) {
|
|
5552
|
+
if (from === to) return;
|
|
5553
|
+
const thread = readThread(threadId);
|
|
5554
|
+
if (!thread) return;
|
|
5555
|
+
const messages = thread.messages.slice();
|
|
5556
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5557
|
+
const message = messages[i];
|
|
5558
|
+
if (!message || message.origin === "continue" || message.role === "summary") continue;
|
|
5559
|
+
if (message.role === "user" && message.text === from) {
|
|
5560
|
+
messages[i] = { ...message, text: to };
|
|
5561
|
+
updateThread(threadId, { messages });
|
|
5562
|
+
}
|
|
5563
|
+
return;
|
|
5564
|
+
}
|
|
5565
|
+
}
|
|
5566
|
+
function reuseJoinedUserBubble(reused, threadId, last, promptText) {
|
|
5567
|
+
return reused.delete(threadId) && last?.role === "user" && last.origin !== "continue" && last.text === promptText;
|
|
5568
|
+
}
|
|
5569
|
+
function promptForJoinedSteer(input) {
|
|
5570
|
+
if (input.latestPrompt === input.promptText) return input.agentPrompt;
|
|
5571
|
+
rewriteTrailingUserPrompt(input.threadId, input.promptText, input.latestPrompt);
|
|
5572
|
+
const { agentPrompt: expandedLatest } = expandComposerPrompt(
|
|
5573
|
+
input.worktreePath,
|
|
5574
|
+
expandCanonicalGitRequest(input.latestPrompt),
|
|
5575
|
+
{ attachments: input.attachments }
|
|
5576
|
+
);
|
|
5577
|
+
return input.expandedPrompt && input.agentPrompt.endsWith(input.expandedPrompt) ? input.agentPrompt.slice(0, -input.expandedPrompt.length) + expandedLatest : `${input.agentPrompt}
|
|
5578
|
+
|
|
5579
|
+
${expandedLatest}`;
|
|
5580
|
+
}
|
|
5581
|
+
function clearSendBookkeeping(host, threadId) {
|
|
5582
|
+
host.crashContinued.delete(threadId);
|
|
5583
|
+
host.jobContinueCount.delete(threadId);
|
|
5584
|
+
host.jobContinueNudged.delete(threadId);
|
|
5585
|
+
host.haltDrain.delete(threadId);
|
|
5586
|
+
}
|
|
5587
|
+
async function enqueueThreadSend(host, threadRef, prompt, opts) {
|
|
5588
|
+
const thread = host.requireThread(threadRef);
|
|
5589
|
+
if (thread.status === "archived") {
|
|
5590
|
+
throw new Error(`Thread is archived: ${thread.id}`);
|
|
5591
|
+
}
|
|
5592
|
+
let shouldSteer = false;
|
|
5593
|
+
const sent = await withThreadLock(thread.id, async () => {
|
|
5594
|
+
const current = host.requireThread(thread.id);
|
|
5595
|
+
if (current.status === "archived") {
|
|
5596
|
+
throw new Error(`Thread is archived: ${thread.id}`);
|
|
5597
|
+
}
|
|
5598
|
+
const followUp = resolveSendFollowUp(current, opts?.followUp);
|
|
5599
|
+
const explicit = opts?.attachments;
|
|
5600
|
+
const consumed = explicit !== void 0 ? { attachments: current.attachments, consumed: explicit } : consumeComposerAttachments(current);
|
|
5601
|
+
const inFlightEarly = host.activeTurns.has(thread.id) || host.startingTurns.has(thread.id) || current.status === "running";
|
|
5602
|
+
const agentHasRepliedEarly = livePartsShowAgentReply(readTurnLiveParts(current.id));
|
|
5603
|
+
const draft = host.openSteerPrompt.get(current.id);
|
|
5604
|
+
const queuedHead = !inFlightEarly && current.status === "queued" && current.queue.length > 0 ? current.queue[0] : null;
|
|
5605
|
+
const unanswered = followUp === "steer" && !agentHasRepliedEarly ? draft?.text ?? (inFlightEarly ? trailingUnansweredUserText(current.messages) : queuedHead) : null;
|
|
5606
|
+
if (unanswered != null && (draft ? !draft.spawned : queuedHead != null)) {
|
|
5607
|
+
clearSendBookkeeping(host, thread.id);
|
|
5608
|
+
const combined = joinSteerPrompt(unanswered, prompt);
|
|
5609
|
+
if (draft && !draft.spawned) {
|
|
5610
|
+
draft.text = combined;
|
|
5611
|
+
rewriteTrailingUserPrompt(current.id, unanswered, combined);
|
|
5612
|
+
} else {
|
|
5613
|
+
const queue = current.queue.slice();
|
|
5614
|
+
queue[0] = combined;
|
|
5615
|
+
const queueAttachments = alignQueueAttachments(queue.length, current.queueAttachments);
|
|
5616
|
+
if (consumed.consumed.length > 0) {
|
|
5617
|
+
queueAttachments[0] = [...queueAttachments[0] ?? [], ...consumed.consumed];
|
|
5618
|
+
}
|
|
5619
|
+
const patch2 = { queue, queueAttachments };
|
|
5620
|
+
if (explicit === void 0 && consumed.consumed.length > 0) {
|
|
5621
|
+
patch2.attachments = consumed.attachments;
|
|
5622
|
+
}
|
|
5623
|
+
updateThread(current.id, patch2);
|
|
5624
|
+
host.emit({ type: "queue_changed", threadId: current.id, queue });
|
|
5625
|
+
}
|
|
5626
|
+
if (thisProcessShouldDrainAgentQueues() && !inFlightEarly) {
|
|
5627
|
+
host.armDrain(current.id);
|
|
5628
|
+
}
|
|
5629
|
+
return host.requireThread(current.id);
|
|
5630
|
+
}
|
|
5631
|
+
const promptToQueue = unanswered != null ? joinSteerPrompt(unanswered, prompt) : prompt;
|
|
5632
|
+
if (unanswered != null) {
|
|
5633
|
+
if (draft) draft.text = promptToQueue;
|
|
5634
|
+
rewriteTrailingUserPrompt(current.id, unanswered, promptToQueue);
|
|
5635
|
+
host.reusedUserPrompt.add(current.id);
|
|
5636
|
+
}
|
|
5637
|
+
const queued = appendQueuedItem(
|
|
5638
|
+
current.queue,
|
|
5639
|
+
current.queueAttachments,
|
|
5640
|
+
promptToQueue,
|
|
5641
|
+
consumed.consumed
|
|
5642
|
+
);
|
|
5643
|
+
clearSendBookkeeping(host, thread.id);
|
|
5644
|
+
const inFlight = host.activeTurns.has(thread.id) || host.startingTurns.has(thread.id) || current.status === "running";
|
|
5645
|
+
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
5646
|
+
const patch = queued;
|
|
5647
|
+
if (explicit === void 0 && consumed.consumed.length > 0) {
|
|
5648
|
+
patch.attachments = consumed.attachments;
|
|
5649
|
+
}
|
|
5650
|
+
if (!inFlight) patch.status = "queued";
|
|
5651
|
+
const pid = current.agentPid;
|
|
5652
|
+
if (typeof pid === "number" && pid > 0 && !host.pidAlive(pid)) {
|
|
5653
|
+
patch.agentPid = null;
|
|
5654
|
+
}
|
|
5655
|
+
updateThread(thread.id, patch);
|
|
5656
|
+
host.emit({ type: "queue_changed", threadId: thread.id, queue: queued.queue });
|
|
5657
|
+
if (!inFlight) {
|
|
5658
|
+
host.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
5659
|
+
}
|
|
5660
|
+
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
5661
|
+
host.armDrain(thread.id);
|
|
5662
|
+
}
|
|
5663
|
+
return host.requireThread(thread.id);
|
|
5664
|
+
});
|
|
5665
|
+
return { thread: sent, shouldSteer };
|
|
5666
|
+
}
|
|
5667
|
+
|
|
5439
5668
|
// src/agents/instructions.ts
|
|
5440
5669
|
import { existsSync as existsSync12 } from "fs";
|
|
5441
5670
|
import { join as join12 } from "path";
|
|
@@ -5594,7 +5823,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
5594
5823
|
lines.push(formatDevAccessHint(opts?.activeRuns));
|
|
5595
5824
|
lines.push("");
|
|
5596
5825
|
lines.push(
|
|
5597
|
-
"
|
|
5826
|
+
"Automations (sidebar, after Board): `create_schedule` / `list_schedules` (`at` / `every` / `cron`). `chatId=self` continues this chat; omit chatId for a new Global chat. Fires only while Sideboard.app is running. A future job turns on Settings \u2192 Advanced \u2192 Caffeinate while automations are enabled."
|
|
5598
5827
|
);
|
|
5599
5828
|
lines.push(
|
|
5600
5829
|
"`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
|
|
@@ -5614,7 +5843,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
|
|
|
5614
5843
|
return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
|
|
5615
5844
|
}
|
|
5616
5845
|
function formatWorktreeReminder() {
|
|
5617
|
-
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.
|
|
5846
|
+
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. Automations: create_schedule (at / every / cron; chatId=self for this chat). set_workspace_tags updates labels on this workspace (omit ref).";
|
|
5618
5847
|
}
|
|
5619
5848
|
function formatClaudeSubagentReminder() {
|
|
5620
5849
|
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.';
|
|
@@ -6232,7 +6461,7 @@ function parseDurationMs(every) {
|
|
|
6232
6461
|
}
|
|
6233
6462
|
function defaultScheduleName(prompt) {
|
|
6234
6463
|
const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
6235
|
-
if (!line) return "Untitled
|
|
6464
|
+
if (!line) return "Untitled automation";
|
|
6236
6465
|
return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
|
|
6237
6466
|
}
|
|
6238
6467
|
function resolveScheduleThreadId(raw, env = process.env) {
|
|
@@ -6297,6 +6526,45 @@ function normalizeWhen(raw) {
|
|
|
6297
6526
|
}
|
|
6298
6527
|
throw new Error("Schedule `when` must be once, every, or cron");
|
|
6299
6528
|
}
|
|
6529
|
+
var ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
|
|
6530
|
+
"transcript",
|
|
6531
|
+
"file",
|
|
6532
|
+
"issue",
|
|
6533
|
+
"workspace",
|
|
6534
|
+
"diff-comment",
|
|
6535
|
+
"code-ref"
|
|
6536
|
+
]);
|
|
6537
|
+
function normalizeOptionalBool(raw) {
|
|
6538
|
+
if (raw === true || raw === false) return raw;
|
|
6539
|
+
return null;
|
|
6540
|
+
}
|
|
6541
|
+
function normalizeAutonomy(raw) {
|
|
6542
|
+
return raw === "default" || raw === "full" ? raw : null;
|
|
6543
|
+
}
|
|
6544
|
+
function normalizeAttachments(raw) {
|
|
6545
|
+
if (!Array.isArray(raw)) return [];
|
|
6546
|
+
const out = [];
|
|
6547
|
+
for (const item of raw) {
|
|
6548
|
+
if (!item || typeof item !== "object") continue;
|
|
6549
|
+
const row = item;
|
|
6550
|
+
if (typeof row.id !== "string" || !row.id.trim()) continue;
|
|
6551
|
+
if (typeof row.name !== "string" || !row.name) continue;
|
|
6552
|
+
if (typeof row.content !== "string") continue;
|
|
6553
|
+
if (!ATTACHMENT_KINDS.has(row.kind)) continue;
|
|
6554
|
+
const next = {
|
|
6555
|
+
id: row.id,
|
|
6556
|
+
name: row.name,
|
|
6557
|
+
kind: row.kind,
|
|
6558
|
+
content: row.content
|
|
6559
|
+
};
|
|
6560
|
+
if (typeof row.path === "string" && row.path) next.path = row.path;
|
|
6561
|
+
if (typeof row.previewDataUrl === "string" && row.previewDataUrl) {
|
|
6562
|
+
next.previewDataUrl = row.previewDataUrl;
|
|
6563
|
+
}
|
|
6564
|
+
out.push(next);
|
|
6565
|
+
}
|
|
6566
|
+
return out;
|
|
6567
|
+
}
|
|
6300
6568
|
function normalizeTask(raw) {
|
|
6301
6569
|
const when = normalizeWhen(raw.when);
|
|
6302
6570
|
const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
|
|
@@ -6309,6 +6577,11 @@ function normalizeTask(raw) {
|
|
|
6309
6577
|
threadId: raw.threadId?.trim() || null,
|
|
6310
6578
|
agent,
|
|
6311
6579
|
model: raw.model?.trim() || null,
|
|
6580
|
+
effort: normalizeThinkingEffort(raw.effort),
|
|
6581
|
+
fast: normalizeOptionalBool(raw.fast),
|
|
6582
|
+
planMode: normalizeOptionalBool(raw.planMode),
|
|
6583
|
+
autonomy: normalizeAutonomy(raw.autonomy),
|
|
6584
|
+
attachments: normalizeAttachments(raw.attachments),
|
|
6312
6585
|
nextRunAt: raw.nextRunAt,
|
|
6313
6586
|
lastRunAt: raw.lastRunAt ?? null,
|
|
6314
6587
|
lastThreadId: raw.lastThreadId ?? null,
|
|
@@ -6355,6 +6628,11 @@ function buildTask(input, now) {
|
|
|
6355
6628
|
threadId: input.threadId?.trim() || null,
|
|
6356
6629
|
agent,
|
|
6357
6630
|
model: input.model?.trim() || null,
|
|
6631
|
+
effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
|
|
6632
|
+
fast: normalizeOptionalBool(input.fast),
|
|
6633
|
+
planMode: normalizeOptionalBool(input.planMode),
|
|
6634
|
+
autonomy: normalizeAutonomy(input.autonomy),
|
|
6635
|
+
attachments: normalizeAttachments(input.attachments),
|
|
6358
6636
|
nextRunAt,
|
|
6359
6637
|
lastRunAt: null,
|
|
6360
6638
|
lastThreadId: null,
|
|
@@ -6396,7 +6674,7 @@ function createSchedule(input) {
|
|
|
6396
6674
|
function updateSchedule(id, patch) {
|
|
6397
6675
|
const rows = readAll();
|
|
6398
6676
|
const idx = rows.findIndex((row) => row.id === id || id.length >= 8 && row.id.startsWith(id));
|
|
6399
|
-
if (idx < 0) throw new Error(`
|
|
6677
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
6400
6678
|
const prev = rows[idx];
|
|
6401
6679
|
const when = patch.when ? normalizeWhen(patch.when) : prev.when;
|
|
6402
6680
|
const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
|
|
@@ -6411,6 +6689,11 @@ function updateSchedule(id, patch) {
|
|
|
6411
6689
|
threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
|
|
6412
6690
|
agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
|
|
6413
6691
|
model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
|
|
6692
|
+
effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
|
|
6693
|
+
fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
|
|
6694
|
+
planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
|
|
6695
|
+
autonomy: patch.autonomy !== void 0 ? normalizeAutonomy(patch.autonomy) : prev.autonomy,
|
|
6696
|
+
attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
|
|
6414
6697
|
nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
|
|
6415
6698
|
lastError: whenChanged ? null : prev.lastError,
|
|
6416
6699
|
updatedAt: nowIso()
|
|
@@ -6425,13 +6708,13 @@ function deleteSchedule(id) {
|
|
|
6425
6708
|
const next = rows.filter(
|
|
6426
6709
|
(row) => row.id !== id && !(id.length >= 8 && row.id.startsWith(id))
|
|
6427
6710
|
);
|
|
6428
|
-
if (next.length === rows.length) throw new Error(`
|
|
6711
|
+
if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
|
|
6429
6712
|
writeAll(next);
|
|
6430
6713
|
}
|
|
6431
6714
|
function recordScheduleRun(id, result) {
|
|
6432
6715
|
const rows = readAll();
|
|
6433
6716
|
const idx = rows.findIndex((row) => row.id === id);
|
|
6434
|
-
if (idx < 0) throw new Error(`
|
|
6717
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
6435
6718
|
const prev = rows[idx];
|
|
6436
6719
|
const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
|
|
6437
6720
|
const next = {
|
|
@@ -6458,21 +6741,56 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6458
6741
|
${prompt}`;
|
|
6459
6742
|
}
|
|
6460
6743
|
async function defaultDeps() {
|
|
6461
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6744
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-7BDZ5GWD.js");
|
|
6462
6745
|
const orch = getOrchestrator2();
|
|
6463
6746
|
return {
|
|
6464
6747
|
findThread: (id) => findThreadByRef(id),
|
|
6465
|
-
send: (id, prompt) =>
|
|
6748
|
+
send: async (id, prompt, opts) => {
|
|
6749
|
+
if (opts?.options && Object.keys(opts.options).length > 0) {
|
|
6750
|
+
try {
|
|
6751
|
+
orch.setThreadOptions(id, opts.options);
|
|
6752
|
+
} catch {
|
|
6753
|
+
const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
|
|
6754
|
+
if (Object.keys(rest).length > 0) {
|
|
6755
|
+
try {
|
|
6756
|
+
orch.setThreadOptions(id, rest);
|
|
6757
|
+
} catch {
|
|
6758
|
+
}
|
|
6759
|
+
}
|
|
6760
|
+
}
|
|
6761
|
+
}
|
|
6762
|
+
const thread = findThreadByRef(id);
|
|
6763
|
+
const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
|
|
6764
|
+
return orch.send(id, prompt, { attachments });
|
|
6765
|
+
},
|
|
6466
6766
|
startOrchestration: (opts) => startOrchestration2(opts)
|
|
6467
6767
|
};
|
|
6468
6768
|
}
|
|
6769
|
+
function scheduleOptionsAfterRefusedAgentSwitch(options) {
|
|
6770
|
+
const { agent: _agent, model: _model, ...rest } = options;
|
|
6771
|
+
return rest;
|
|
6772
|
+
}
|
|
6773
|
+
function scheduleSendOptions(schedule) {
|
|
6774
|
+
const patch = {};
|
|
6775
|
+
if (schedule.agent) {
|
|
6776
|
+
patch.agent = schedule.agent;
|
|
6777
|
+
patch.model = schedule.model;
|
|
6778
|
+
} else if (schedule.model) {
|
|
6779
|
+
patch.model = schedule.model;
|
|
6780
|
+
}
|
|
6781
|
+
if (schedule.effort) patch.effort = schedule.effort;
|
|
6782
|
+
if (schedule.fast != null) patch.fast = schedule.fast;
|
|
6783
|
+
if (schedule.planMode != null) patch.planMode = schedule.planMode;
|
|
6784
|
+
if (schedule.autonomy) patch.autonomy = schedule.autonomy;
|
|
6785
|
+
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
6786
|
+
}
|
|
6469
6787
|
function pickAgent(schedule) {
|
|
6470
6788
|
if (schedule.agent) return schedule.agent;
|
|
6471
6789
|
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
6472
6790
|
}
|
|
6473
6791
|
async function fireSchedule(id) {
|
|
6474
6792
|
const schedule = getSchedule(id);
|
|
6475
|
-
if (!schedule) throw new Error(`
|
|
6793
|
+
if (!schedule) throw new Error(`Automation not found: ${id}`);
|
|
6476
6794
|
if (firing.has(schedule.id)) return schedule;
|
|
6477
6795
|
firing.add(schedule.id);
|
|
6478
6796
|
try {
|
|
@@ -6480,18 +6798,28 @@ async function fireSchedule(id) {
|
|
|
6480
6798
|
const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
|
|
6481
6799
|
const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
|
|
6482
6800
|
if (target && target.status !== "archived") {
|
|
6483
|
-
const sent = await deps.send(target.id, prompt
|
|
6801
|
+
const sent = await deps.send(target.id, prompt, {
|
|
6802
|
+
attachments: schedule.attachments,
|
|
6803
|
+
options: scheduleSendOptions(schedule)
|
|
6804
|
+
});
|
|
6484
6805
|
return recordScheduleRun(schedule.id, {
|
|
6485
6806
|
lastThreadId: sent.id,
|
|
6486
6807
|
lastError: null
|
|
6487
6808
|
});
|
|
6488
6809
|
}
|
|
6810
|
+
const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
|
|
6489
6811
|
const created = await deps.startOrchestration({
|
|
6490
6812
|
goal: prompt,
|
|
6491
6813
|
agent: pickAgent(schedule),
|
|
6492
|
-
model: schedule.model
|
|
6814
|
+
model: schedule.model,
|
|
6815
|
+
...schedule.effort ? { effort: schedule.effort } : {},
|
|
6816
|
+
...schedule.fast != null ? { fast: schedule.fast } : {},
|
|
6817
|
+
...schedule.planMode != null ? { planMode: schedule.planMode } : {},
|
|
6818
|
+
...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
|
|
6819
|
+
attachments: schedule.attachments,
|
|
6820
|
+
...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
|
|
6493
6821
|
});
|
|
6494
|
-
if (
|
|
6822
|
+
if (pinReplacement) {
|
|
6495
6823
|
updateSchedule(schedule.id, { threadId: created.id });
|
|
6496
6824
|
}
|
|
6497
6825
|
return recordScheduleRun(schedule.id, {
|
|
@@ -6574,10 +6902,6 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
6574
6902
|
}
|
|
6575
6903
|
return true;
|
|
6576
6904
|
}
|
|
6577
|
-
function resolveSendFollowUp(thread, requested) {
|
|
6578
|
-
if (requested === "steer" || requested === "queue") return requested;
|
|
6579
|
-
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
6580
|
-
}
|
|
6581
6905
|
function resolveOrchChildFollowUp(requested) {
|
|
6582
6906
|
if (requested === "steer" || requested === "queue") return requested;
|
|
6583
6907
|
return followUpBehavior();
|
|
@@ -6606,6 +6930,13 @@ var Orchestrator = class {
|
|
|
6606
6930
|
draining = /* @__PURE__ */ new Set();
|
|
6607
6931
|
/** Threads past setStatus(running) but not yet in activeTurns (spawn in flight). */
|
|
6608
6932
|
startingTurns = /* @__PURE__ */ new Set();
|
|
6933
|
+
/**
|
|
6934
|
+
* Prompt for the turn that has not been answered yet. Steer follow-ups before
|
|
6935
|
+
* any agent output are joined onto this text instead of starting a second bubble.
|
|
6936
|
+
*/
|
|
6937
|
+
openSteerPrompt = /* @__PURE__ */ new Map();
|
|
6938
|
+
/** Next runTurn should keep the user bubble already rewritten to this prompt. */
|
|
6939
|
+
reusedUserPrompt = /* @__PURE__ */ new Set();
|
|
6609
6940
|
/** Last sync thread-file read for false-stop heal (throttled per thread). */
|
|
6610
6941
|
lastReconcileHealAt = /* @__PURE__ */ new Map();
|
|
6611
6942
|
/** Per-repo timestamp of the last `reconcile(repo, { light: true })`. */
|
|
@@ -6776,7 +7107,7 @@ var Orchestrator = class {
|
|
|
6776
7107
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
6777
7108
|
});
|
|
6778
7109
|
}
|
|
6779
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
7110
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-KMPVI2B7.js");
|
|
6780
7111
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
6781
7112
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
6782
7113
|
}
|
|
@@ -7170,7 +7501,7 @@ var Orchestrator = class {
|
|
|
7170
7501
|
}
|
|
7171
7502
|
await setup;
|
|
7172
7503
|
if (skipSetup) return;
|
|
7173
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
7504
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-KMPVI2B7.js");
|
|
7174
7505
|
if (autoRunAfterSetupEnabled()) {
|
|
7175
7506
|
try {
|
|
7176
7507
|
await this.startDev(threadId);
|
|
@@ -7216,54 +7547,29 @@ var Orchestrator = class {
|
|
|
7216
7547
|
return thread;
|
|
7217
7548
|
}
|
|
7218
7549
|
async send(threadRef, prompt, opts) {
|
|
7219
|
-
const
|
|
7220
|
-
|
|
7221
|
-
|
|
7222
|
-
|
|
7223
|
-
|
|
7224
|
-
|
|
7225
|
-
|
|
7226
|
-
|
|
7227
|
-
|
|
7228
|
-
|
|
7229
|
-
|
|
7230
|
-
|
|
7231
|
-
|
|
7232
|
-
|
|
7233
|
-
|
|
7234
|
-
|
|
7235
|
-
|
|
7236
|
-
|
|
7237
|
-
|
|
7238
|
-
|
|
7239
|
-
this.
|
|
7240
|
-
this.jobContinueNudged.delete(thread.id);
|
|
7241
|
-
this.haltDrain.delete(thread.id);
|
|
7242
|
-
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
7243
|
-
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
7244
|
-
const patch = queued;
|
|
7245
|
-
if (explicit === void 0 && consumed.consumed.length > 0) {
|
|
7246
|
-
patch.attachments = consumed.attachments;
|
|
7247
|
-
}
|
|
7248
|
-
if (!inFlight) patch.status = "queued";
|
|
7249
|
-
const pid = current.agentPid;
|
|
7250
|
-
if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
|
|
7251
|
-
patch.agentPid = null;
|
|
7252
|
-
}
|
|
7253
|
-
updateThread(thread.id, patch);
|
|
7254
|
-
this.emit({ type: "queue_changed", threadId: thread.id, queue: queued.queue });
|
|
7255
|
-
if (!inFlight) {
|
|
7256
|
-
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
7257
|
-
}
|
|
7258
|
-
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
7259
|
-
this.armDrain(thread.id);
|
|
7260
|
-
}
|
|
7261
|
-
return this.requireThread(thread.id);
|
|
7262
|
-
});
|
|
7263
|
-
if (shouldSteer && sent.queue.length > 0) {
|
|
7264
|
-
return this.sendQueuedMessageNow(sent.id, sent.queue.length - 1);
|
|
7550
|
+
const sent = await enqueueThreadSend(
|
|
7551
|
+
{
|
|
7552
|
+
activeTurns: this.activeTurns,
|
|
7553
|
+
startingTurns: this.startingTurns,
|
|
7554
|
+
openSteerPrompt: this.openSteerPrompt,
|
|
7555
|
+
reusedUserPrompt: this.reusedUserPrompt,
|
|
7556
|
+
crashContinued: this.crashContinued,
|
|
7557
|
+
jobContinueCount: this.jobContinueCount,
|
|
7558
|
+
jobContinueNudged: this.jobContinueNudged,
|
|
7559
|
+
haltDrain: this.haltDrain,
|
|
7560
|
+
emit: (event) => this.emit(event),
|
|
7561
|
+
armDrain: (id) => this.armDrain(id),
|
|
7562
|
+
requireThread: (ref) => this.requireThread(ref),
|
|
7563
|
+
pidAlive: (pid) => isPidAlive(pid)
|
|
7564
|
+
},
|
|
7565
|
+
threadRef,
|
|
7566
|
+
prompt,
|
|
7567
|
+
opts
|
|
7568
|
+
);
|
|
7569
|
+
if (sent.shouldSteer && sent.thread.queue.length > 0) {
|
|
7570
|
+
return this.sendQueuedMessageNow(sent.thread.id, sent.thread.queue.length - 1);
|
|
7265
7571
|
}
|
|
7266
|
-
return sent;
|
|
7572
|
+
return sent.thread;
|
|
7267
7573
|
}
|
|
7268
7574
|
async fanOut(threadRefs, prompt, opts) {
|
|
7269
7575
|
const results = [];
|
|
@@ -7404,6 +7710,7 @@ var Orchestrator = class {
|
|
|
7404
7710
|
} finally {
|
|
7405
7711
|
this.draining.delete(threadId);
|
|
7406
7712
|
}
|
|
7713
|
+
await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
|
|
7407
7714
|
}
|
|
7408
7715
|
async runTurn(threadId, prompt) {
|
|
7409
7716
|
const existing = readThread(threadId);
|
|
@@ -7420,6 +7727,10 @@ var Orchestrator = class {
|
|
|
7420
7727
|
this.emit({ type: "status_changed", threadId, status: "running" });
|
|
7421
7728
|
this.emit({ type: "turn_started", threadId, prompt });
|
|
7422
7729
|
try {
|
|
7730
|
+
this.openSteerPrompt.set(threadId, {
|
|
7731
|
+
text: typeof prompt === "string" ? prompt : "",
|
|
7732
|
+
spawned: false
|
|
7733
|
+
});
|
|
7423
7734
|
try {
|
|
7424
7735
|
const baseline = await captureTurnBaseline(thread.worktreePath);
|
|
7425
7736
|
if (baseline) this.turnBaselines.set(threadId, baseline);
|
|
@@ -7445,18 +7756,21 @@ var Orchestrator = class {
|
|
|
7445
7756
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
7446
7757
|
thread = this.requireThread(threadId);
|
|
7447
7758
|
}
|
|
7448
|
-
const promptText = typeof prompt === "string" ? prompt : "";
|
|
7759
|
+
const promptText = this.openSteerPrompt.get(threadId)?.text ?? (typeof prompt === "string" ? prompt : "");
|
|
7449
7760
|
const autoContinue = isJobContinuePrompt(promptText) || promptText.startsWith("The previous agent process ended before it finished.");
|
|
7450
7761
|
const parked = takePendingTurnAttachments(thread);
|
|
7451
7762
|
const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
|
|
7452
7763
|
if (!autoContinue) clearAgentBlock(threadId);
|
|
7453
|
-
|
|
7454
|
-
|
|
7455
|
-
|
|
7456
|
-
|
|
7457
|
-
|
|
7458
|
-
|
|
7459
|
-
|
|
7764
|
+
const lastShown = this.requireThread(threadId).messages.at(-1);
|
|
7765
|
+
if (!reuseJoinedUserBubble(this.reusedUserPrompt, threadId, lastShown, promptText)) {
|
|
7766
|
+
appendMessage(threadId, {
|
|
7767
|
+
role: "user",
|
|
7768
|
+
text: promptText,
|
|
7769
|
+
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
7770
|
+
...autoContinue ? { origin: "continue" } : {},
|
|
7771
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
7772
|
+
});
|
|
7773
|
+
}
|
|
7460
7774
|
if (!autoContinue) {
|
|
7461
7775
|
const live = this.requireThread(threadId);
|
|
7462
7776
|
const stamp = agentPurposeStamp({
|
|
@@ -7564,7 +7878,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
7564
7878
|
}
|
|
7565
7879
|
const isBrightsy = fresh.agent === "brightsy";
|
|
7566
7880
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
7567
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-
|
|
7881
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-KMPVI2B7.js");
|
|
7568
7882
|
const gitAuthMode = getGithubGitAuthMode();
|
|
7569
7883
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
7570
7884
|
githubSlug: await withTimeout(
|
|
@@ -7655,11 +7969,22 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
7655
7969
|
].filter(Boolean).join("\n\n---\n\n");
|
|
7656
7970
|
const stderrTail = [];
|
|
7657
7971
|
traceTurn("runTurn.beforeSpawn", { threadId, agent: fresh.agent });
|
|
7972
|
+
const steerDraft = this.openSteerPrompt.get(threadId);
|
|
7973
|
+
if (steerDraft) steerDraft.spawned = true;
|
|
7974
|
+
const promptForAgent = promptForJoinedSteer({
|
|
7975
|
+
threadId,
|
|
7976
|
+
promptText,
|
|
7977
|
+
latestPrompt: steerDraft?.text ?? promptText,
|
|
7978
|
+
agentPrompt,
|
|
7979
|
+
expandedPrompt,
|
|
7980
|
+
worktreePath: fresh.worktreePath,
|
|
7981
|
+
attachments: autoContinue ? [] : sentAttachments ?? []
|
|
7982
|
+
});
|
|
7658
7983
|
const handle = await spawnAgentTurn(
|
|
7659
7984
|
fresh,
|
|
7660
7985
|
{
|
|
7661
7986
|
cachedPrefix,
|
|
7662
|
-
prompt:
|
|
7987
|
+
prompt: promptForAgent,
|
|
7663
7988
|
systemPrompt: turnReminders,
|
|
7664
7989
|
isolateCodexPlugins: fresh.isolateCodexPlugins === true
|
|
7665
7990
|
},
|
|
@@ -7787,7 +8112,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
7787
8112
|
retryThread,
|
|
7788
8113
|
{
|
|
7789
8114
|
cachedPrefix: retryPrefix,
|
|
7790
|
-
prompt:
|
|
8115
|
+
prompt: promptForAgent,
|
|
7791
8116
|
systemPrompt: turnReminders,
|
|
7792
8117
|
isolateCodexPlugins: isolateCodexPluginRetry || retryThread.isolateCodexPlugins === true
|
|
7793
8118
|
},
|
|
@@ -7947,6 +8272,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
7947
8272
|
} finally {
|
|
7948
8273
|
this.startingTurns.delete(threadId);
|
|
7949
8274
|
this.activeTurns.delete(threadId);
|
|
8275
|
+
this.openSteerPrompt.delete(threadId);
|
|
7950
8276
|
this.processes.delete(`${threadId}:agent`);
|
|
7951
8277
|
this.stoppedTurns.delete(threadId);
|
|
7952
8278
|
this.runningCount = Math.max(0, this.runningCount - 1);
|
|
@@ -8880,7 +9206,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
8880
9206
|
if (Object.keys(patch).length === 0) continue;
|
|
8881
9207
|
updateThread(t.id, patch);
|
|
8882
9208
|
}
|
|
8883
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
9209
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-KMPVI2B7.js");
|
|
8884
9210
|
const latest = this.requireThread(thread.id);
|
|
8885
9211
|
if (!shouldAutoArchiveOnPrMerge({
|
|
8886
9212
|
previousPrState: prevState || null,
|
|
@@ -9204,7 +9530,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9204
9530
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
9205
9531
|
} catch {
|
|
9206
9532
|
}
|
|
9207
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
9533
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-KMPVI2B7.js");
|
|
9208
9534
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
9209
9535
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
9210
9536
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -9218,6 +9544,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9218
9544
|
if (thread.status !== "archived") {
|
|
9219
9545
|
throw new Error("Thread is not archived");
|
|
9220
9546
|
}
|
|
9547
|
+
clearEphemeralAutomation(thread.id);
|
|
9221
9548
|
if (isGlobalThread(thread)) {
|
|
9222
9549
|
const { globalAgentCwd } = await import("./paths-HAAJNTTE.js");
|
|
9223
9550
|
updateThread(thread.id, { worktreePath: globalAgentCwd() });
|
|
@@ -9317,10 +9644,11 @@ async function startOrchestration(opts) {
|
|
|
9317
9644
|
planMode: opts.planMode,
|
|
9318
9645
|
attachments: opts.attachments
|
|
9319
9646
|
});
|
|
9647
|
+
const ready2 = markEphemeralAutomation(thread2.id, opts);
|
|
9320
9648
|
if (goal) {
|
|
9321
|
-
return orch.send(
|
|
9649
|
+
return orch.send(ready2.id, goal);
|
|
9322
9650
|
}
|
|
9323
|
-
return
|
|
9651
|
+
return ready2;
|
|
9324
9652
|
}
|
|
9325
9653
|
const { titleFromPrompt: titleFromPrompt2 } = await import("./title-ERD6D3C3.js");
|
|
9326
9654
|
const title = titleFromPrompt2(goal) || "Orchestration";
|
|
@@ -9340,7 +9668,7 @@ async function startOrchestration(opts) {
|
|
|
9340
9668
|
sourceRef: "default",
|
|
9341
9669
|
...createOpts
|
|
9342
9670
|
}).catch(async () => {
|
|
9343
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
9671
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-O6BANO2I.js");
|
|
9344
9672
|
const repo = await resolveRepoRoot2(repoPath);
|
|
9345
9673
|
const def = await resolveDefaultBranch2(repo);
|
|
9346
9674
|
return orch.createThread({
|
|
@@ -9350,15 +9678,16 @@ async function startOrchestration(opts) {
|
|
|
9350
9678
|
repoPath: repo
|
|
9351
9679
|
});
|
|
9352
9680
|
});
|
|
9353
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
9681
|
+
const { updateThread: upd } = await import("./thread-store-JWHVXLDX.js");
|
|
9354
9682
|
const updated = upd(thread.id, {
|
|
9355
9683
|
sourceType: "orchestration",
|
|
9356
9684
|
sourceRef: goal
|
|
9357
9685
|
});
|
|
9686
|
+
const ready = markEphemeralAutomation(updated.id, opts);
|
|
9358
9687
|
if (goal) {
|
|
9359
|
-
return orch.send(
|
|
9688
|
+
return orch.send(ready.id, goal);
|
|
9360
9689
|
}
|
|
9361
|
-
return
|
|
9690
|
+
return ready;
|
|
9362
9691
|
}
|
|
9363
9692
|
|
|
9364
9693
|
export {
|
|
@@ -9396,6 +9725,7 @@ export {
|
|
|
9396
9725
|
listFleetArchive,
|
|
9397
9726
|
formatFleetArchive,
|
|
9398
9727
|
readTurnLive,
|
|
9728
|
+
resolveSendFollowUp,
|
|
9399
9729
|
localhostPreviewUrl,
|
|
9400
9730
|
parseIssueSince,
|
|
9401
9731
|
formatGitHubSearchUpdatedSince,
|
|
@@ -9419,7 +9749,6 @@ export {
|
|
|
9419
9749
|
RUN_SCRIPT_DESKTOP_ADOPT_MS,
|
|
9420
9750
|
isPidAlive,
|
|
9421
9751
|
waitForPidExit,
|
|
9422
|
-
resolveSendFollowUp,
|
|
9423
9752
|
resolveOrchChildFollowUp,
|
|
9424
9753
|
LIGHT_RECONCILE_THROTTLE_MS,
|
|
9425
9754
|
Orchestrator,
|