@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
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
parseSessionQuotaResetAt,
|
|
15
15
|
planModeTurnInstruction,
|
|
16
16
|
resolveQuotaFallbackAgent
|
|
17
|
-
} from "./chunk-
|
|
17
|
+
} from "./chunk-LLIEU2ZB.js";
|
|
18
18
|
import {
|
|
19
19
|
applyWorktreePkgCacheEnv,
|
|
20
20
|
askBlockStillWaiting,
|
|
@@ -52,7 +52,7 @@ import {
|
|
|
52
52
|
worktreeDevProcessKey,
|
|
53
53
|
worktreeRunProcessKey,
|
|
54
54
|
worktreeSetupProcessKey
|
|
55
|
-
} from "./chunk-
|
|
55
|
+
} from "./chunk-DJZRDTZY.js";
|
|
56
56
|
import {
|
|
57
57
|
applyAgentEvent,
|
|
58
58
|
clipAgentEventForPaint,
|
|
@@ -67,14 +67,14 @@ import {
|
|
|
67
67
|
partsToAssistantText,
|
|
68
68
|
stripBrightsyNdjsonNoise,
|
|
69
69
|
toolDescription
|
|
70
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-QIC2JXHW.js";
|
|
71
71
|
import {
|
|
72
72
|
titleFromPrompt
|
|
73
73
|
} from "./chunk-7H655NEW.js";
|
|
74
74
|
import {
|
|
75
75
|
formatOptionalServicesDirectiveForTurn,
|
|
76
76
|
formatOptionalServicesReminderForTurn
|
|
77
|
-
} from "./chunk-
|
|
77
|
+
} from "./chunk-EQ5JY3MJ.js";
|
|
78
78
|
import {
|
|
79
79
|
SLACK_REPLY_FORMATTING,
|
|
80
80
|
addWorkspace,
|
|
@@ -99,7 +99,7 @@ import {
|
|
|
99
99
|
stageAbsolutePathsAsAttachments,
|
|
100
100
|
stageBuffersAsAttachments,
|
|
101
101
|
syncWorkspacesFromThreads
|
|
102
|
-
} from "./chunk-
|
|
102
|
+
} from "./chunk-RHJPP26T.js";
|
|
103
103
|
import {
|
|
104
104
|
addPrStackLayer,
|
|
105
105
|
allocateTeamSlug,
|
|
@@ -143,7 +143,7 @@ import {
|
|
|
143
143
|
resolveRepoRoot,
|
|
144
144
|
switchWorktreeBranch,
|
|
145
145
|
withRepoGitLock
|
|
146
|
-
} from "./chunk-
|
|
146
|
+
} from "./chunk-EDXTP2VR.js";
|
|
147
147
|
import {
|
|
148
148
|
REVIEW_TAB_TITLE,
|
|
149
149
|
agentNicknameFromWorktreePath,
|
|
@@ -171,7 +171,7 @@ import {
|
|
|
171
171
|
worktreeNameFromPath,
|
|
172
172
|
worktreeSlugForTicket,
|
|
173
173
|
writeThread
|
|
174
|
-
} from "./chunk-
|
|
174
|
+
} from "./chunk-4GZC6DDH.js";
|
|
175
175
|
import {
|
|
176
176
|
mcpServerIdForPermission,
|
|
177
177
|
mcpServerPermissionUpdate
|
|
@@ -239,7 +239,10 @@ import {
|
|
|
239
239
|
usageOnLimit,
|
|
240
240
|
withTurnScopedCost,
|
|
241
241
|
writeViewerContext
|
|
242
|
-
} from "./chunk-
|
|
242
|
+
} from "./chunk-FZKAAAEB.js";
|
|
243
|
+
import {
|
|
244
|
+
normalizeThinkingEffort
|
|
245
|
+
} from "./chunk-77WWLBCI.js";
|
|
243
246
|
import {
|
|
244
247
|
examplePrefixedBranch,
|
|
245
248
|
sanitizeGitBranchPrefix
|
|
@@ -461,9 +464,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
461
464
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
462
465
|
);
|
|
463
466
|
}
|
|
464
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
467
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-SCLQUNUI.js");
|
|
465
468
|
if (isGlobalThread2(thread)) {
|
|
466
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
469
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-NUC2ZXMJ.js");
|
|
467
470
|
ensureGlobalCoordinatorCwd2(
|
|
468
471
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
469
472
|
);
|
|
@@ -2074,6 +2077,71 @@ function claimSteerRequest(threadId) {
|
|
|
2074
2077
|
});
|
|
2075
2078
|
}
|
|
2076
2079
|
|
|
2080
|
+
// src/orchestrator/ephemeral-automation.ts
|
|
2081
|
+
function ephemeralRunReadyToArchive(thread) {
|
|
2082
|
+
if (!thread.ephemeralAutomationId?.trim()) return false;
|
|
2083
|
+
if (thread.status !== "idle" && thread.status !== "error") return false;
|
|
2084
|
+
if (thread.queue.length > 0) return false;
|
|
2085
|
+
if (thread.agentBlock?.reason?.trim()) return false;
|
|
2086
|
+
if (thread.quotaResumeAt) return false;
|
|
2087
|
+
return true;
|
|
2088
|
+
}
|
|
2089
|
+
function markEphemeralAutomation(threadId, opts) {
|
|
2090
|
+
const id = opts.ephemeralAutomationId?.trim();
|
|
2091
|
+
const current = readThread(threadId);
|
|
2092
|
+
if (!current) throw new Error(`Thread not found: ${threadId}`);
|
|
2093
|
+
if (!id) return current;
|
|
2094
|
+
const title = opts.ephemeralTitle?.trim();
|
|
2095
|
+
return updateThread(threadId, {
|
|
2096
|
+
ephemeralAutomationId: id,
|
|
2097
|
+
...title ? { title, userSetTitle: true } : {}
|
|
2098
|
+
});
|
|
2099
|
+
}
|
|
2100
|
+
async function archiveEphemeralAutomationIfReady(threadId, archive) {
|
|
2101
|
+
const keep = await withThreadLock(threadId, async () => {
|
|
2102
|
+
const thread = readThread(threadId);
|
|
2103
|
+
if (!thread || !ephemeralRunReadyToArchive(thread)) return null;
|
|
2104
|
+
const automationId = thread.ephemeralAutomationId?.trim();
|
|
2105
|
+
if (!automationId) return null;
|
|
2106
|
+
await archive(thread.id);
|
|
2107
|
+
return {
|
|
2108
|
+
automationId,
|
|
2109
|
+
keepId: archivedContinuationId(automationId, threadId) ?? threadId
|
|
2110
|
+
};
|
|
2111
|
+
});
|
|
2112
|
+
if (keep) forgetOlderEphemeralRuns(keep.automationId, keep.keepId);
|
|
2113
|
+
}
|
|
2114
|
+
function archivedContinuationId(automationId, sourceId) {
|
|
2115
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
2116
|
+
if (thread.id === sourceId || thread.status !== "archived") continue;
|
|
2117
|
+
if (thread.ephemeralAutomationId !== automationId) continue;
|
|
2118
|
+
if (thread.quotaContinuedFromId !== sourceId) continue;
|
|
2119
|
+
return thread.id;
|
|
2120
|
+
}
|
|
2121
|
+
return null;
|
|
2122
|
+
}
|
|
2123
|
+
function clearEphemeralAutomation(threadId) {
|
|
2124
|
+
const thread = readThread(threadId);
|
|
2125
|
+
if (!thread?.ephemeralAutomationId?.trim()) return;
|
|
2126
|
+
updateThread(threadId, { ephemeralAutomationId: void 0 });
|
|
2127
|
+
}
|
|
2128
|
+
function forgetOlderEphemeralRuns(automationId, keepId) {
|
|
2129
|
+
const id = automationId.trim();
|
|
2130
|
+
if (!id || !keepId) return [];
|
|
2131
|
+
const removed = [];
|
|
2132
|
+
for (const thread of listThreads({ includeArchived: true })) {
|
|
2133
|
+
if (thread.id === keepId) continue;
|
|
2134
|
+
if (thread.status !== "archived") continue;
|
|
2135
|
+
if (thread.ephemeralAutomationId !== id) continue;
|
|
2136
|
+
try {
|
|
2137
|
+
deleteThreadRecord(thread.id);
|
|
2138
|
+
removed.push(thread.id);
|
|
2139
|
+
} catch {
|
|
2140
|
+
}
|
|
2141
|
+
}
|
|
2142
|
+
return removed;
|
|
2143
|
+
}
|
|
2144
|
+
|
|
2077
2145
|
// src/threads/agent-purpose-title.ts
|
|
2078
2146
|
function agentPurposeStamp(input) {
|
|
2079
2147
|
if (input.autoContinue) return null;
|
|
@@ -2930,7 +2998,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2930
2998
|
});
|
|
2931
2999
|
await requireAgent(resolved.agent);
|
|
2932
3000
|
if (input.cowboy) {
|
|
2933
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
3001
|
+
const { cowboyModeEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
2934
3002
|
if (!cowboyModeEnabled()) {
|
|
2935
3003
|
throw new Error(
|
|
2936
3004
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -2989,7 +3057,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2989
3057
|
let sourceIsFork = false;
|
|
2990
3058
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
2991
3059
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
2992
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
3060
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-ICW6Q2AB.js");
|
|
2993
3061
|
const task = await ensureAbleTimeTask({
|
|
2994
3062
|
title: title?.trim() || "Untitled work",
|
|
2995
3063
|
description: input.prompt?.trim() || void 0
|
|
@@ -3100,7 +3168,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3100
3168
|
return readThread(thread.id) ?? thread;
|
|
3101
3169
|
}
|
|
3102
3170
|
async function listLinearIssues(agent, repoPath) {
|
|
3103
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3171
|
+
const { getAdapter: getAdapter2 } = await import("./agents-F2E2HACB.js");
|
|
3104
3172
|
await requireAgent(agent, { requireLinear: true });
|
|
3105
3173
|
const adapter = getAdapter2(agent);
|
|
3106
3174
|
if (!adapter.listLinearIssues) {
|
|
@@ -3760,17 +3828,23 @@ async function isolateQuotaFailover(run) {
|
|
|
3760
3828
|
}
|
|
3761
3829
|
}
|
|
3762
3830
|
function createQuotaFailoverChat(from, fallbackAgent, limitText, opts) {
|
|
3831
|
+
const ephemeralAutomationId = from.ephemeralAutomationId?.trim();
|
|
3832
|
+
const ephemeralTitle = ephemeralAutomationId ? from.title.trim() : "";
|
|
3763
3833
|
const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
|
|
3764
3834
|
const tab = createChatTab({
|
|
3765
3835
|
fromThreadId: from.id,
|
|
3766
3836
|
agent: fallbackAgent,
|
|
3767
3837
|
model: null,
|
|
3768
3838
|
attachments: [handoff],
|
|
3839
|
+
...ephemeralTitle ? { title: ephemeralTitle } : {},
|
|
3769
3840
|
...opts && "accountId" in opts ? { accountId: opts.accountId } : {}
|
|
3770
3841
|
});
|
|
3771
3842
|
const patch = {
|
|
3772
3843
|
quotaContinuedFromId: from.id,
|
|
3773
|
-
sourceRef: from.sourceRef
|
|
3844
|
+
sourceRef: from.sourceRef,
|
|
3845
|
+
// The original drain archives as idle. This sibling has to carry the one-off
|
|
3846
|
+
// so it archives when the continued turn finishes and History keeps it.
|
|
3847
|
+
...ephemeralAutomationId ? { ephemeralAutomationId } : {}
|
|
3774
3848
|
};
|
|
3775
3849
|
if (isOrchestratorThread(from)) {
|
|
3776
3850
|
patch.parentThreadId = from.id;
|
|
@@ -3877,7 +3951,7 @@ async function adoptThread(input) {
|
|
|
3877
3951
|
messages: input.messages ?? []
|
|
3878
3952
|
});
|
|
3879
3953
|
writeThread(thread);
|
|
3880
|
-
const { addWorkspace: addWorkspace2 } = await import("./workspaces-
|
|
3954
|
+
const { addWorkspace: addWorkspace2 } = await import("./workspaces-KWMBOTQD.js");
|
|
3881
3955
|
await addWorkspace2(repoPath);
|
|
3882
3956
|
const { ensureWorktreeSideboardIgnored } = await import("./worktree-exclude-RXZPTCNH.js");
|
|
3883
3957
|
await ensureWorktreeSideboardIgnored(input.worktreePath);
|
|
@@ -5710,6 +5784,36 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
5710
5784
|
};
|
|
5711
5785
|
}
|
|
5712
5786
|
|
|
5787
|
+
// src/composer/agent-has-replied.ts
|
|
5788
|
+
function joinSteerPrompt(base, addition) {
|
|
5789
|
+
const next = addition.trim();
|
|
5790
|
+
if (!next) return base;
|
|
5791
|
+
const head = base.replace(/\s+$/, "");
|
|
5792
|
+
if (!head) return next;
|
|
5793
|
+
return `${head}
|
|
5794
|
+
${next}`;
|
|
5795
|
+
}
|
|
5796
|
+
function trailingUnansweredUserText(messages) {
|
|
5797
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5798
|
+
const message = messages[i];
|
|
5799
|
+
if (!message || message.origin === "continue" || message.role === "summary") continue;
|
|
5800
|
+
if (message.role === "agent") {
|
|
5801
|
+
const text3 = (message.text ?? "").trim();
|
|
5802
|
+
if (text3 || (message.parts?.length ?? 0) > 0) return null;
|
|
5803
|
+
continue;
|
|
5804
|
+
}
|
|
5805
|
+
if (message.role === "user") return message.text;
|
|
5806
|
+
}
|
|
5807
|
+
return null;
|
|
5808
|
+
}
|
|
5809
|
+
function livePartsShowAgentReply(parts) {
|
|
5810
|
+
for (const part of parts) {
|
|
5811
|
+
if (part.type === "tool") return true;
|
|
5812
|
+
if ((part.type === "text" || part.type === "thinking") && part.text.trim()) return true;
|
|
5813
|
+
}
|
|
5814
|
+
return false;
|
|
5815
|
+
}
|
|
5816
|
+
|
|
5713
5817
|
// src/composer/consume-attachments.ts
|
|
5714
5818
|
function consumeComposerAttachments(thread) {
|
|
5715
5819
|
return {
|
|
@@ -5762,6 +5866,128 @@ function shiftQueuedItem(queue, queueAttachments) {
|
|
|
5762
5866
|
};
|
|
5763
5867
|
}
|
|
5764
5868
|
|
|
5869
|
+
// src/orchestrator/enqueue-thread-send.ts
|
|
5870
|
+
function resolveSendFollowUp(thread, requested) {
|
|
5871
|
+
if (requested === "steer" || requested === "queue") return requested;
|
|
5872
|
+
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
5873
|
+
}
|
|
5874
|
+
function rewriteTrailingUserPrompt(threadId, from, to) {
|
|
5875
|
+
if (from === to) return;
|
|
5876
|
+
const thread = readThread(threadId);
|
|
5877
|
+
if (!thread) return;
|
|
5878
|
+
const messages = thread.messages.slice();
|
|
5879
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
5880
|
+
const message = messages[i];
|
|
5881
|
+
if (!message || message.origin === "continue" || message.role === "summary") continue;
|
|
5882
|
+
if (message.role === "user" && message.text === from) {
|
|
5883
|
+
messages[i] = { ...message, text: to };
|
|
5884
|
+
updateThread(threadId, { messages });
|
|
5885
|
+
}
|
|
5886
|
+
return;
|
|
5887
|
+
}
|
|
5888
|
+
}
|
|
5889
|
+
function reuseJoinedUserBubble(reused, threadId, last, promptText) {
|
|
5890
|
+
return reused.delete(threadId) && last?.role === "user" && last.origin !== "continue" && last.text === promptText;
|
|
5891
|
+
}
|
|
5892
|
+
function promptForJoinedSteer(input) {
|
|
5893
|
+
if (input.latestPrompt === input.promptText) return input.agentPrompt;
|
|
5894
|
+
rewriteTrailingUserPrompt(input.threadId, input.promptText, input.latestPrompt);
|
|
5895
|
+
const { agentPrompt: expandedLatest } = expandComposerPrompt(
|
|
5896
|
+
input.worktreePath,
|
|
5897
|
+
expandCanonicalGitRequest(input.latestPrompt),
|
|
5898
|
+
{ attachments: input.attachments }
|
|
5899
|
+
);
|
|
5900
|
+
return input.expandedPrompt && input.agentPrompt.endsWith(input.expandedPrompt) ? input.agentPrompt.slice(0, -input.expandedPrompt.length) + expandedLatest : `${input.agentPrompt}
|
|
5901
|
+
|
|
5902
|
+
${expandedLatest}`;
|
|
5903
|
+
}
|
|
5904
|
+
function clearSendBookkeeping(host, threadId) {
|
|
5905
|
+
host.crashContinued.delete(threadId);
|
|
5906
|
+
host.jobContinueCount.delete(threadId);
|
|
5907
|
+
host.jobContinueNudged.delete(threadId);
|
|
5908
|
+
host.haltDrain.delete(threadId);
|
|
5909
|
+
}
|
|
5910
|
+
async function enqueueThreadSend(host, threadRef, prompt, opts) {
|
|
5911
|
+
const thread = host.requireThread(threadRef);
|
|
5912
|
+
if (thread.status === "archived") {
|
|
5913
|
+
throw new Error(`Thread is archived: ${thread.id}`);
|
|
5914
|
+
}
|
|
5915
|
+
let shouldSteer = false;
|
|
5916
|
+
const sent = await withThreadLock(thread.id, async () => {
|
|
5917
|
+
const current = host.requireThread(thread.id);
|
|
5918
|
+
if (current.status === "archived") {
|
|
5919
|
+
throw new Error(`Thread is archived: ${thread.id}`);
|
|
5920
|
+
}
|
|
5921
|
+
const followUp = resolveSendFollowUp(current, opts?.followUp);
|
|
5922
|
+
const explicit = opts?.attachments;
|
|
5923
|
+
const consumed = explicit !== void 0 ? { attachments: current.attachments, consumed: explicit } : consumeComposerAttachments(current);
|
|
5924
|
+
const inFlightEarly = host.activeTurns.has(thread.id) || host.startingTurns.has(thread.id) || current.status === "running";
|
|
5925
|
+
const agentHasRepliedEarly = livePartsShowAgentReply(readTurnLiveParts(current.id));
|
|
5926
|
+
const draft = host.openSteerPrompt.get(current.id);
|
|
5927
|
+
const queuedHead = !inFlightEarly && current.status === "queued" && current.queue.length > 0 ? current.queue[0] : null;
|
|
5928
|
+
const unanswered = followUp === "steer" && !agentHasRepliedEarly ? draft?.text ?? (inFlightEarly ? trailingUnansweredUserText(current.messages) : queuedHead) : null;
|
|
5929
|
+
if (unanswered != null && (draft ? !draft.spawned : queuedHead != null)) {
|
|
5930
|
+
clearSendBookkeeping(host, thread.id);
|
|
5931
|
+
const combined = joinSteerPrompt(unanswered, prompt);
|
|
5932
|
+
if (draft && !draft.spawned) {
|
|
5933
|
+
draft.text = combined;
|
|
5934
|
+
rewriteTrailingUserPrompt(current.id, unanswered, combined);
|
|
5935
|
+
} else {
|
|
5936
|
+
const queue = current.queue.slice();
|
|
5937
|
+
queue[0] = combined;
|
|
5938
|
+
const queueAttachments = alignQueueAttachments(queue.length, current.queueAttachments);
|
|
5939
|
+
if (consumed.consumed.length > 0) {
|
|
5940
|
+
queueAttachments[0] = [...queueAttachments[0] ?? [], ...consumed.consumed];
|
|
5941
|
+
}
|
|
5942
|
+
const patch2 = { queue, queueAttachments };
|
|
5943
|
+
if (explicit === void 0 && consumed.consumed.length > 0) {
|
|
5944
|
+
patch2.attachments = consumed.attachments;
|
|
5945
|
+
}
|
|
5946
|
+
updateThread(current.id, patch2);
|
|
5947
|
+
host.emit({ type: "queue_changed", threadId: current.id, queue });
|
|
5948
|
+
}
|
|
5949
|
+
if (thisProcessShouldDrainAgentQueues() && !inFlightEarly) {
|
|
5950
|
+
host.armDrain(current.id);
|
|
5951
|
+
}
|
|
5952
|
+
return host.requireThread(current.id);
|
|
5953
|
+
}
|
|
5954
|
+
const promptToQueue = unanswered != null ? joinSteerPrompt(unanswered, prompt) : prompt;
|
|
5955
|
+
if (unanswered != null) {
|
|
5956
|
+
if (draft) draft.text = promptToQueue;
|
|
5957
|
+
rewriteTrailingUserPrompt(current.id, unanswered, promptToQueue);
|
|
5958
|
+
host.reusedUserPrompt.add(current.id);
|
|
5959
|
+
}
|
|
5960
|
+
const queued = appendQueuedItem(
|
|
5961
|
+
current.queue,
|
|
5962
|
+
current.queueAttachments,
|
|
5963
|
+
promptToQueue,
|
|
5964
|
+
consumed.consumed
|
|
5965
|
+
);
|
|
5966
|
+
clearSendBookkeeping(host, thread.id);
|
|
5967
|
+
const inFlight = host.activeTurns.has(thread.id) || host.startingTurns.has(thread.id) || current.status === "running";
|
|
5968
|
+
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
5969
|
+
const patch = queued;
|
|
5970
|
+
if (explicit === void 0 && consumed.consumed.length > 0) {
|
|
5971
|
+
patch.attachments = consumed.attachments;
|
|
5972
|
+
}
|
|
5973
|
+
if (!inFlight) patch.status = "queued";
|
|
5974
|
+
const pid = current.agentPid;
|
|
5975
|
+
if (typeof pid === "number" && pid > 0 && !host.pidAlive(pid)) {
|
|
5976
|
+
patch.agentPid = null;
|
|
5977
|
+
}
|
|
5978
|
+
updateThread(thread.id, patch);
|
|
5979
|
+
host.emit({ type: "queue_changed", threadId: thread.id, queue: queued.queue });
|
|
5980
|
+
if (!inFlight) {
|
|
5981
|
+
host.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
5982
|
+
}
|
|
5983
|
+
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
5984
|
+
host.armDrain(thread.id);
|
|
5985
|
+
}
|
|
5986
|
+
return host.requireThread(thread.id);
|
|
5987
|
+
});
|
|
5988
|
+
return { thread: sent, shouldSteer };
|
|
5989
|
+
}
|
|
5990
|
+
|
|
5765
5991
|
// src/agents/instructions.ts
|
|
5766
5992
|
import { existsSync as existsSync12 } from "fs";
|
|
5767
5993
|
import { join as join12 } from "path";
|
|
@@ -5920,7 +6146,7 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
5920
6146
|
lines.push(formatDevAccessHint(opts?.activeRuns));
|
|
5921
6147
|
lines.push("");
|
|
5922
6148
|
lines.push(
|
|
5923
|
-
"
|
|
6149
|
+
"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."
|
|
5924
6150
|
);
|
|
5925
6151
|
lines.push(
|
|
5926
6152
|
"`set_workspace_tags` labels this checkout (omit ref; replace, add, or remove). Not another checkout."
|
|
@@ -5940,7 +6166,7 @@ function connectedOrchestratorTurnReminder(thread, find) {
|
|
|
5940
6166
|
return formatConnectedOrchestratorReminder(connectedOrchestrator(thread, find));
|
|
5941
6167
|
}
|
|
5942
6168
|
function formatWorktreeReminder() {
|
|
5943
|
-
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.
|
|
6169
|
+
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).";
|
|
5944
6170
|
}
|
|
5945
6171
|
function formatClaudeSubagentReminder() {
|
|
5946
6172
|
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.';
|
|
@@ -6580,7 +6806,7 @@ function parseDurationMs(every) {
|
|
|
6580
6806
|
}
|
|
6581
6807
|
function defaultScheduleName(prompt) {
|
|
6582
6808
|
const line = prompt.trim().split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
6583
|
-
if (!line) return "Untitled
|
|
6809
|
+
if (!line) return "Untitled automation";
|
|
6584
6810
|
return line.length > 60 ? `${line.slice(0, 57).trimEnd()}\u2026` : line;
|
|
6585
6811
|
}
|
|
6586
6812
|
function resolveScheduleThreadId(raw, env = process.env) {
|
|
@@ -6651,6 +6877,45 @@ function normalizeWhen(raw) {
|
|
|
6651
6877
|
}
|
|
6652
6878
|
throw new Error("Schedule `when` must be once, every, or cron");
|
|
6653
6879
|
}
|
|
6880
|
+
var ATTACHMENT_KINDS = /* @__PURE__ */ new Set([
|
|
6881
|
+
"transcript",
|
|
6882
|
+
"file",
|
|
6883
|
+
"issue",
|
|
6884
|
+
"workspace",
|
|
6885
|
+
"diff-comment",
|
|
6886
|
+
"code-ref"
|
|
6887
|
+
]);
|
|
6888
|
+
function normalizeOptionalBool(raw) {
|
|
6889
|
+
if (raw === true || raw === false) return raw;
|
|
6890
|
+
return null;
|
|
6891
|
+
}
|
|
6892
|
+
function normalizeAutonomy(raw) {
|
|
6893
|
+
return raw === "default" || raw === "full" ? raw : null;
|
|
6894
|
+
}
|
|
6895
|
+
function normalizeAttachments(raw) {
|
|
6896
|
+
if (!Array.isArray(raw)) return [];
|
|
6897
|
+
const out = [];
|
|
6898
|
+
for (const item of raw) {
|
|
6899
|
+
if (!item || typeof item !== "object") continue;
|
|
6900
|
+
const row = item;
|
|
6901
|
+
if (typeof row.id !== "string" || !row.id.trim()) continue;
|
|
6902
|
+
if (typeof row.name !== "string" || !row.name) continue;
|
|
6903
|
+
if (typeof row.content !== "string") continue;
|
|
6904
|
+
if (!ATTACHMENT_KINDS.has(row.kind)) continue;
|
|
6905
|
+
const next = {
|
|
6906
|
+
id: row.id,
|
|
6907
|
+
name: row.name,
|
|
6908
|
+
kind: row.kind,
|
|
6909
|
+
content: row.content
|
|
6910
|
+
};
|
|
6911
|
+
if (typeof row.path === "string" && row.path) next.path = row.path;
|
|
6912
|
+
if (typeof row.previewDataUrl === "string" && row.previewDataUrl) {
|
|
6913
|
+
next.previewDataUrl = row.previewDataUrl;
|
|
6914
|
+
}
|
|
6915
|
+
out.push(next);
|
|
6916
|
+
}
|
|
6917
|
+
return out;
|
|
6918
|
+
}
|
|
6654
6919
|
function normalizeTask(raw) {
|
|
6655
6920
|
const when = normalizeWhen(raw.when);
|
|
6656
6921
|
const agent = raw.agent && isOrchestratorCapableAgent(raw.agent) ? raw.agent : null;
|
|
@@ -6663,6 +6928,11 @@ function normalizeTask(raw) {
|
|
|
6663
6928
|
threadId: raw.threadId?.trim() || null,
|
|
6664
6929
|
agent,
|
|
6665
6930
|
model: raw.model?.trim() || null,
|
|
6931
|
+
effort: normalizeThinkingEffort(raw.effort),
|
|
6932
|
+
fast: normalizeOptionalBool(raw.fast),
|
|
6933
|
+
planMode: normalizeOptionalBool(raw.planMode),
|
|
6934
|
+
autonomy: normalizeAutonomy(raw.autonomy),
|
|
6935
|
+
attachments: normalizeAttachments(raw.attachments),
|
|
6666
6936
|
nextRunAt: raw.nextRunAt,
|
|
6667
6937
|
lastRunAt: raw.lastRunAt ?? null,
|
|
6668
6938
|
lastThreadId: raw.lastThreadId ?? null,
|
|
@@ -6709,6 +6979,11 @@ function buildTask(input, now) {
|
|
|
6709
6979
|
threadId: input.threadId?.trim() || null,
|
|
6710
6980
|
agent,
|
|
6711
6981
|
model: input.model?.trim() || null,
|
|
6982
|
+
effort: input.effort != null ? normalizeThinkingEffort(input.effort) : null,
|
|
6983
|
+
fast: normalizeOptionalBool(input.fast),
|
|
6984
|
+
planMode: normalizeOptionalBool(input.planMode),
|
|
6985
|
+
autonomy: normalizeAutonomy(input.autonomy),
|
|
6986
|
+
attachments: normalizeAttachments(input.attachments),
|
|
6712
6987
|
nextRunAt,
|
|
6713
6988
|
lastRunAt: null,
|
|
6714
6989
|
lastThreadId: null,
|
|
@@ -6753,7 +7028,7 @@ function createSchedule(input) {
|
|
|
6753
7028
|
function updateSchedule(id, patch) {
|
|
6754
7029
|
const rows = readAll();
|
|
6755
7030
|
const idx = rows.findIndex((row) => row.id === id || id.length >= 8 && row.id.startsWith(id));
|
|
6756
|
-
if (idx < 0) throw new Error(`
|
|
7031
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
6757
7032
|
const prev = rows[idx];
|
|
6758
7033
|
const when = patch.when ? normalizeWhen(patch.when) : prev.when;
|
|
6759
7034
|
const prompt = patch.prompt !== void 0 ? patch.prompt.trim() : prev.prompt;
|
|
@@ -6768,6 +7043,11 @@ function updateSchedule(id, patch) {
|
|
|
6768
7043
|
threadId: patch.threadId !== void 0 ? patch.threadId?.trim() || null : prev.threadId,
|
|
6769
7044
|
agent: patch.agent !== void 0 ? patch.agent ? coerceOrchestratorAgent(patch.agent) : null : prev.agent,
|
|
6770
7045
|
model: patch.model !== void 0 ? patch.model?.trim() || null : prev.model,
|
|
7046
|
+
effort: patch.effort !== void 0 ? normalizeThinkingEffort(patch.effort) : prev.effort,
|
|
7047
|
+
fast: patch.fast !== void 0 ? normalizeOptionalBool(patch.fast) : prev.fast,
|
|
7048
|
+
planMode: patch.planMode !== void 0 ? normalizeOptionalBool(patch.planMode) : prev.planMode,
|
|
7049
|
+
autonomy: patch.autonomy !== void 0 ? normalizeAutonomy(patch.autonomy) : prev.autonomy,
|
|
7050
|
+
attachments: patch.attachments !== void 0 ? normalizeAttachments(patch.attachments) : prev.attachments,
|
|
6771
7051
|
nextRunAt: whenChanged ? computeNextRunAt(when).toISOString() : prev.nextRunAt,
|
|
6772
7052
|
lastError: whenChanged ? null : prev.lastError,
|
|
6773
7053
|
updatedAt: nowIso()
|
|
@@ -6782,13 +7062,13 @@ function deleteSchedule(id) {
|
|
|
6782
7062
|
const next = rows.filter(
|
|
6783
7063
|
(row) => row.id !== id && !(id.length >= 8 && row.id.startsWith(id))
|
|
6784
7064
|
);
|
|
6785
|
-
if (next.length === rows.length) throw new Error(`
|
|
7065
|
+
if (next.length === rows.length) throw new Error(`Automation not found: ${id}`);
|
|
6786
7066
|
writeAll(next);
|
|
6787
7067
|
}
|
|
6788
7068
|
function recordScheduleRun(id, result) {
|
|
6789
7069
|
const rows = readAll();
|
|
6790
7070
|
const idx = rows.findIndex((row) => row.id === id);
|
|
6791
|
-
if (idx < 0) throw new Error(`
|
|
7071
|
+
if (idx < 0) throw new Error(`Automation not found: ${id}`);
|
|
6792
7072
|
const prev = rows[idx];
|
|
6793
7073
|
const firedAt = result.firedAt ?? /* @__PURE__ */ new Date();
|
|
6794
7074
|
const next = {
|
|
@@ -6815,21 +7095,56 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6815
7095
|
${prompt}`;
|
|
6816
7096
|
}
|
|
6817
7097
|
async function defaultDeps() {
|
|
6818
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
7098
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-NPFWU3XU.js");
|
|
6819
7099
|
const orch = getOrchestrator2();
|
|
6820
7100
|
return {
|
|
6821
7101
|
findThread: (id) => findThreadByRef(id),
|
|
6822
|
-
send: (id, prompt) =>
|
|
7102
|
+
send: async (id, prompt, opts) => {
|
|
7103
|
+
if (opts?.options && Object.keys(opts.options).length > 0) {
|
|
7104
|
+
try {
|
|
7105
|
+
orch.setThreadOptions(id, opts.options);
|
|
7106
|
+
} catch {
|
|
7107
|
+
const rest = scheduleOptionsAfterRefusedAgentSwitch(opts.options);
|
|
7108
|
+
if (Object.keys(rest).length > 0) {
|
|
7109
|
+
try {
|
|
7110
|
+
orch.setThreadOptions(id, rest);
|
|
7111
|
+
} catch {
|
|
7112
|
+
}
|
|
7113
|
+
}
|
|
7114
|
+
}
|
|
7115
|
+
}
|
|
7116
|
+
const thread = findThreadByRef(id);
|
|
7117
|
+
const attachments = thread ? persistPendingFileAttachments(thread.worktreePath, opts?.attachments ?? []) : opts?.attachments ?? [];
|
|
7118
|
+
return orch.send(id, prompt, { attachments });
|
|
7119
|
+
},
|
|
6823
7120
|
startOrchestration: (opts) => startOrchestration2(opts)
|
|
6824
7121
|
};
|
|
6825
7122
|
}
|
|
7123
|
+
function scheduleOptionsAfterRefusedAgentSwitch(options) {
|
|
7124
|
+
const { agent: _agent, model: _model, ...rest } = options;
|
|
7125
|
+
return rest;
|
|
7126
|
+
}
|
|
7127
|
+
function scheduleSendOptions(schedule) {
|
|
7128
|
+
const patch = {};
|
|
7129
|
+
if (schedule.agent) {
|
|
7130
|
+
patch.agent = schedule.agent;
|
|
7131
|
+
patch.model = schedule.model;
|
|
7132
|
+
} else if (schedule.model) {
|
|
7133
|
+
patch.model = schedule.model;
|
|
7134
|
+
}
|
|
7135
|
+
if (schedule.effort) patch.effort = schedule.effort;
|
|
7136
|
+
if (schedule.fast != null) patch.fast = schedule.fast;
|
|
7137
|
+
if (schedule.planMode != null) patch.planMode = schedule.planMode;
|
|
7138
|
+
if (schedule.autonomy) patch.autonomy = schedule.autonomy;
|
|
7139
|
+
return Object.keys(patch).length > 0 ? patch : void 0;
|
|
7140
|
+
}
|
|
6826
7141
|
function pickAgent(schedule) {
|
|
6827
7142
|
if (schedule.agent) return schedule.agent;
|
|
6828
7143
|
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
6829
7144
|
}
|
|
6830
7145
|
async function fireSchedule(id) {
|
|
6831
7146
|
const schedule = getSchedule(id);
|
|
6832
|
-
if (!schedule) throw new Error(`
|
|
7147
|
+
if (!schedule) throw new Error(`Automation not found: ${id}`);
|
|
6833
7148
|
if (firing.has(schedule.id)) return schedule;
|
|
6834
7149
|
firing.add(schedule.id);
|
|
6835
7150
|
try {
|
|
@@ -6837,18 +7152,28 @@ async function fireSchedule(id) {
|
|
|
6837
7152
|
const prompt = formatScheduledPrompt(schedule.name, schedule.prompt);
|
|
6838
7153
|
const target = schedule.threadId ? deps.findThread(schedule.threadId) : null;
|
|
6839
7154
|
if (target && target.status !== "archived") {
|
|
6840
|
-
const sent = await deps.send(target.id, prompt
|
|
7155
|
+
const sent = await deps.send(target.id, prompt, {
|
|
7156
|
+
attachments: schedule.attachments,
|
|
7157
|
+
options: scheduleSendOptions(schedule)
|
|
7158
|
+
});
|
|
6841
7159
|
return recordScheduleRun(schedule.id, {
|
|
6842
7160
|
lastThreadId: sent.id,
|
|
6843
7161
|
lastError: null
|
|
6844
7162
|
});
|
|
6845
7163
|
}
|
|
7164
|
+
const pinReplacement = Boolean(schedule.threadId) && schedule.when.kind !== "once";
|
|
6846
7165
|
const created = await deps.startOrchestration({
|
|
6847
7166
|
goal: prompt,
|
|
6848
7167
|
agent: pickAgent(schedule),
|
|
6849
|
-
model: schedule.model
|
|
7168
|
+
model: schedule.model,
|
|
7169
|
+
...schedule.effort ? { effort: schedule.effort } : {},
|
|
7170
|
+
...schedule.fast != null ? { fast: schedule.fast } : {},
|
|
7171
|
+
...schedule.planMode != null ? { planMode: schedule.planMode } : {},
|
|
7172
|
+
...schedule.autonomy ? { autonomy: schedule.autonomy } : {},
|
|
7173
|
+
attachments: schedule.attachments,
|
|
7174
|
+
...pinReplacement ? {} : { ephemeralAutomationId: schedule.id, ephemeralTitle: schedule.name }
|
|
6850
7175
|
});
|
|
6851
|
-
if (
|
|
7176
|
+
if (pinReplacement) {
|
|
6852
7177
|
updateSchedule(schedule.id, { threadId: created.id });
|
|
6853
7178
|
}
|
|
6854
7179
|
return recordScheduleRun(schedule.id, {
|
|
@@ -6931,10 +7256,6 @@ async function waitForPidExit(pid, timeoutMs) {
|
|
|
6931
7256
|
}
|
|
6932
7257
|
return true;
|
|
6933
7258
|
}
|
|
6934
|
-
function resolveSendFollowUp(thread, requested) {
|
|
6935
|
-
if (requested === "steer" || requested === "queue") return requested;
|
|
6936
|
-
return isOrchestratorThread(thread) ? followUpBehavior() : "queue";
|
|
6937
|
-
}
|
|
6938
7259
|
function resolveOrchChildFollowUp(requested) {
|
|
6939
7260
|
if (requested === "steer" || requested === "queue") return requested;
|
|
6940
7261
|
return followUpBehavior();
|
|
@@ -6963,6 +7284,13 @@ var Orchestrator = class {
|
|
|
6963
7284
|
draining = /* @__PURE__ */ new Set();
|
|
6964
7285
|
/** Threads past setStatus(running) but not yet in activeTurns (spawn in flight). */
|
|
6965
7286
|
startingTurns = /* @__PURE__ */ new Set();
|
|
7287
|
+
/**
|
|
7288
|
+
* Prompt for the turn that has not been answered yet. Steer follow-ups before
|
|
7289
|
+
* any agent output are joined onto this text instead of starting a second bubble.
|
|
7290
|
+
*/
|
|
7291
|
+
openSteerPrompt = /* @__PURE__ */ new Map();
|
|
7292
|
+
/** Next runTurn should keep the user bubble already rewritten to this prompt. */
|
|
7293
|
+
reusedUserPrompt = /* @__PURE__ */ new Set();
|
|
6966
7294
|
/** Last sync thread-file read for false-stop heal (throttled per thread). */
|
|
6967
7295
|
lastReconcileHealAt = /* @__PURE__ */ new Map();
|
|
6968
7296
|
/** Per-repo timestamp of the last `reconcile(repo, { light: true })`. */
|
|
@@ -7133,7 +7461,7 @@ var Orchestrator = class {
|
|
|
7133
7461
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
7134
7462
|
});
|
|
7135
7463
|
}
|
|
7136
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
7464
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
7137
7465
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
7138
7466
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
7139
7467
|
}
|
|
@@ -7527,7 +7855,7 @@ var Orchestrator = class {
|
|
|
7527
7855
|
}
|
|
7528
7856
|
await setup;
|
|
7529
7857
|
if (skipSetup) return;
|
|
7530
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
7858
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
7531
7859
|
if (autoRunAfterSetupEnabled()) {
|
|
7532
7860
|
try {
|
|
7533
7861
|
await this.startDev(threadId);
|
|
@@ -7573,54 +7901,29 @@ var Orchestrator = class {
|
|
|
7573
7901
|
return thread;
|
|
7574
7902
|
}
|
|
7575
7903
|
async send(threadRef, prompt, opts) {
|
|
7576
|
-
const
|
|
7577
|
-
|
|
7578
|
-
|
|
7579
|
-
|
|
7580
|
-
|
|
7581
|
-
|
|
7582
|
-
|
|
7583
|
-
|
|
7584
|
-
|
|
7585
|
-
|
|
7586
|
-
|
|
7587
|
-
|
|
7588
|
-
|
|
7589
|
-
|
|
7590
|
-
|
|
7591
|
-
|
|
7592
|
-
|
|
7593
|
-
|
|
7594
|
-
|
|
7595
|
-
|
|
7596
|
-
this.
|
|
7597
|
-
this.jobContinueNudged.delete(thread.id);
|
|
7598
|
-
this.haltDrain.delete(thread.id);
|
|
7599
|
-
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id) || current.status === "running";
|
|
7600
|
-
shouldSteer = followUp === "steer" && (inFlight || current.queue.length > 0);
|
|
7601
|
-
const patch = queued;
|
|
7602
|
-
if (explicit === void 0 && consumed.consumed.length > 0) {
|
|
7603
|
-
patch.attachments = consumed.attachments;
|
|
7604
|
-
}
|
|
7605
|
-
if (!inFlight) patch.status = "queued";
|
|
7606
|
-
const pid = current.agentPid;
|
|
7607
|
-
if (typeof pid === "number" && pid > 0 && !isPidAlive(pid)) {
|
|
7608
|
-
patch.agentPid = null;
|
|
7609
|
-
}
|
|
7610
|
-
updateThread(thread.id, patch);
|
|
7611
|
-
this.emit({ type: "queue_changed", threadId: thread.id, queue: queued.queue });
|
|
7612
|
-
if (!inFlight) {
|
|
7613
|
-
this.emit({ type: "status_changed", threadId: thread.id, status: "queued" });
|
|
7614
|
-
}
|
|
7615
|
-
if (thisProcessShouldDrainAgentQueues() && !shouldSteer) {
|
|
7616
|
-
this.armDrain(thread.id);
|
|
7617
|
-
}
|
|
7618
|
-
return this.requireThread(thread.id);
|
|
7619
|
-
});
|
|
7620
|
-
if (shouldSteer && sent.queue.length > 0) {
|
|
7621
|
-
return this.sendQueuedMessageNow(sent.id, sent.queue.length - 1);
|
|
7904
|
+
const sent = await enqueueThreadSend(
|
|
7905
|
+
{
|
|
7906
|
+
activeTurns: this.activeTurns,
|
|
7907
|
+
startingTurns: this.startingTurns,
|
|
7908
|
+
openSteerPrompt: this.openSteerPrompt,
|
|
7909
|
+
reusedUserPrompt: this.reusedUserPrompt,
|
|
7910
|
+
crashContinued: this.crashContinued,
|
|
7911
|
+
jobContinueCount: this.jobContinueCount,
|
|
7912
|
+
jobContinueNudged: this.jobContinueNudged,
|
|
7913
|
+
haltDrain: this.haltDrain,
|
|
7914
|
+
emit: (event) => this.emit(event),
|
|
7915
|
+
armDrain: (id) => this.armDrain(id),
|
|
7916
|
+
requireThread: (ref) => this.requireThread(ref),
|
|
7917
|
+
pidAlive: (pid) => isPidAlive(pid)
|
|
7918
|
+
},
|
|
7919
|
+
threadRef,
|
|
7920
|
+
prompt,
|
|
7921
|
+
opts
|
|
7922
|
+
);
|
|
7923
|
+
if (sent.shouldSteer && sent.thread.queue.length > 0) {
|
|
7924
|
+
return this.sendQueuedMessageNow(sent.thread.id, sent.thread.queue.length - 1);
|
|
7622
7925
|
}
|
|
7623
|
-
return sent;
|
|
7926
|
+
return sent.thread;
|
|
7624
7927
|
}
|
|
7625
7928
|
async fanOut(threadRefs, prompt, opts) {
|
|
7626
7929
|
const results = [];
|
|
@@ -7761,6 +8064,7 @@ var Orchestrator = class {
|
|
|
7761
8064
|
} finally {
|
|
7762
8065
|
this.draining.delete(threadId);
|
|
7763
8066
|
}
|
|
8067
|
+
await archiveEphemeralAutomationIfReady(threadId, (id) => this.archive(id));
|
|
7764
8068
|
}
|
|
7765
8069
|
async runTurn(threadId, prompt) {
|
|
7766
8070
|
const existing = readThread(threadId);
|
|
@@ -7777,6 +8081,10 @@ var Orchestrator = class {
|
|
|
7777
8081
|
this.emit({ type: "status_changed", threadId, status: "running" });
|
|
7778
8082
|
this.emit({ type: "turn_started", threadId, prompt });
|
|
7779
8083
|
try {
|
|
8084
|
+
this.openSteerPrompt.set(threadId, {
|
|
8085
|
+
text: typeof prompt === "string" ? prompt : "",
|
|
8086
|
+
spawned: false
|
|
8087
|
+
});
|
|
7780
8088
|
try {
|
|
7781
8089
|
const baseline = await captureTurnBaseline(thread.worktreePath);
|
|
7782
8090
|
if (baseline) this.turnBaselines.set(threadId, baseline);
|
|
@@ -7802,18 +8110,21 @@ var Orchestrator = class {
|
|
|
7802
8110
|
this.emit({ type: "error", threadId, message: `context compact failed: ${message}` });
|
|
7803
8111
|
thread = this.requireThread(threadId);
|
|
7804
8112
|
}
|
|
7805
|
-
const promptText = typeof prompt === "string" ? prompt : "";
|
|
8113
|
+
const promptText = this.openSteerPrompt.get(threadId)?.text ?? (typeof prompt === "string" ? prompt : "");
|
|
7806
8114
|
const autoContinue = isJobContinuePrompt(promptText) || promptText.startsWith("The previous agent process ended before it finished.");
|
|
7807
8115
|
const parked = takePendingTurnAttachments(thread);
|
|
7808
8116
|
const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
|
|
7809
8117
|
if (!autoContinue) clearAgentBlock(threadId);
|
|
7810
|
-
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
8118
|
+
const lastShown = this.requireThread(threadId).messages.at(-1);
|
|
8119
|
+
if (!reuseJoinedUserBubble(this.reusedUserPrompt, threadId, lastShown, promptText)) {
|
|
8120
|
+
appendMessage(threadId, {
|
|
8121
|
+
role: "user",
|
|
8122
|
+
text: promptText,
|
|
8123
|
+
...sentAttachments ? { attachments: sentAttachments } : {},
|
|
8124
|
+
...autoContinue ? { origin: "continue" } : {},
|
|
8125
|
+
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
8126
|
+
});
|
|
8127
|
+
}
|
|
7817
8128
|
if (!autoContinue) {
|
|
7818
8129
|
const live = this.requireThread(threadId);
|
|
7819
8130
|
const stamp = agentPurposeStamp({
|
|
@@ -7921,7 +8232,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
7921
8232
|
}
|
|
7922
8233
|
const isBrightsy = fresh.agent === "brightsy";
|
|
7923
8234
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
7924
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-
|
|
8235
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode, gitBranchPrefixSetting } = await import("./app-settings-P3H4SEIK.js");
|
|
7925
8236
|
const gitAuthMode = getGithubGitAuthMode();
|
|
7926
8237
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
7927
8238
|
githubSlug: await withTimeout(
|
|
@@ -8012,11 +8323,22 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
8012
8323
|
].filter(Boolean).join("\n\n---\n\n");
|
|
8013
8324
|
const stderrTail = [];
|
|
8014
8325
|
traceTurn("runTurn.beforeSpawn", { threadId, agent: fresh.agent });
|
|
8326
|
+
const steerDraft = this.openSteerPrompt.get(threadId);
|
|
8327
|
+
if (steerDraft) steerDraft.spawned = true;
|
|
8328
|
+
const promptForAgent = promptForJoinedSteer({
|
|
8329
|
+
threadId,
|
|
8330
|
+
promptText,
|
|
8331
|
+
latestPrompt: steerDraft?.text ?? promptText,
|
|
8332
|
+
agentPrompt,
|
|
8333
|
+
expandedPrompt,
|
|
8334
|
+
worktreePath: fresh.worktreePath,
|
|
8335
|
+
attachments: autoContinue ? [] : sentAttachments ?? []
|
|
8336
|
+
});
|
|
8015
8337
|
const handle = await spawnAgentTurn(
|
|
8016
8338
|
fresh,
|
|
8017
8339
|
{
|
|
8018
8340
|
cachedPrefix,
|
|
8019
|
-
prompt:
|
|
8341
|
+
prompt: promptForAgent,
|
|
8020
8342
|
systemPrompt: turnReminders,
|
|
8021
8343
|
isolateCodexPlugins: fresh.isolateCodexPlugins === true
|
|
8022
8344
|
},
|
|
@@ -8144,7 +8466,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
8144
8466
|
retryThread,
|
|
8145
8467
|
{
|
|
8146
8468
|
cachedPrefix: retryPrefix,
|
|
8147
|
-
prompt:
|
|
8469
|
+
prompt: promptForAgent,
|
|
8148
8470
|
systemPrompt: turnReminders,
|
|
8149
8471
|
isolateCodexPlugins: isolateCodexPluginRetry || retryThread.isolateCodexPlugins === true
|
|
8150
8472
|
},
|
|
@@ -8304,6 +8626,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
8304
8626
|
} finally {
|
|
8305
8627
|
this.startingTurns.delete(threadId);
|
|
8306
8628
|
this.activeTurns.delete(threadId);
|
|
8629
|
+
this.openSteerPrompt.delete(threadId);
|
|
8307
8630
|
this.processes.delete(`${threadId}:agent`);
|
|
8308
8631
|
this.stoppedTurns.delete(threadId);
|
|
8309
8632
|
this.runningCount = Math.max(0, this.runningCount - 1);
|
|
@@ -9237,7 +9560,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9237
9560
|
if (Object.keys(patch).length === 0) continue;
|
|
9238
9561
|
updateThread(t.id, patch);
|
|
9239
9562
|
}
|
|
9240
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
9563
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
9241
9564
|
const latest = this.requireThread(thread.id);
|
|
9242
9565
|
if (!shouldAutoArchiveOnPrMerge({
|
|
9243
9566
|
previousPrState: prevState || null,
|
|
@@ -9561,7 +9884,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9561
9884
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
9562
9885
|
} catch {
|
|
9563
9886
|
}
|
|
9564
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
9887
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-P3H4SEIK.js");
|
|
9565
9888
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
9566
9889
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
9567
9890
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -9575,6 +9898,7 @@ ${formatEnvReminder(projectNameForRepoPath(thread.repoPath || thread.worktreePat
|
|
|
9575
9898
|
if (thread.status !== "archived") {
|
|
9576
9899
|
throw new Error("Thread is not archived");
|
|
9577
9900
|
}
|
|
9901
|
+
clearEphemeralAutomation(thread.id);
|
|
9578
9902
|
if (isGlobalThread(thread)) {
|
|
9579
9903
|
const { globalAgentCwd } = await import("./paths-PHWEVXD5.js");
|
|
9580
9904
|
updateThread(thread.id, { worktreePath: globalAgentCwd() });
|
|
@@ -9674,10 +9998,11 @@ async function startOrchestration(opts) {
|
|
|
9674
9998
|
planMode: opts.planMode,
|
|
9675
9999
|
attachments: opts.attachments
|
|
9676
10000
|
});
|
|
10001
|
+
const ready2 = markEphemeralAutomation(thread2.id, opts);
|
|
9677
10002
|
if (goal) {
|
|
9678
|
-
return orch.send(
|
|
10003
|
+
return orch.send(ready2.id, goal);
|
|
9679
10004
|
}
|
|
9680
|
-
return
|
|
10005
|
+
return ready2;
|
|
9681
10006
|
}
|
|
9682
10007
|
const { titleFromPrompt: titleFromPrompt2 } = await import("./title-Z7WAJN57.js");
|
|
9683
10008
|
const title = titleFromPrompt2(goal) || "Orchestration";
|
|
@@ -9697,7 +10022,7 @@ async function startOrchestration(opts) {
|
|
|
9697
10022
|
sourceRef: "default",
|
|
9698
10023
|
...createOpts
|
|
9699
10024
|
}).catch(async () => {
|
|
9700
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
10025
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-7EATHVYQ.js");
|
|
9701
10026
|
const repo = await resolveRepoRoot2(repoPath);
|
|
9702
10027
|
const def = await resolveDefaultBranch2(repo);
|
|
9703
10028
|
return orch.createThread({
|
|
@@ -9707,15 +10032,16 @@ async function startOrchestration(opts) {
|
|
|
9707
10032
|
repoPath: repo
|
|
9708
10033
|
});
|
|
9709
10034
|
});
|
|
9710
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
10035
|
+
const { updateThread: upd } = await import("./thread-store-QHYN2ZMQ.js");
|
|
9711
10036
|
const updated = upd(thread.id, {
|
|
9712
10037
|
sourceType: "orchestration",
|
|
9713
10038
|
sourceRef: goal
|
|
9714
10039
|
});
|
|
10040
|
+
const ready = markEphemeralAutomation(updated.id, opts);
|
|
9715
10041
|
if (goal) {
|
|
9716
|
-
return orch.send(
|
|
10042
|
+
return orch.send(ready.id, goal);
|
|
9717
10043
|
}
|
|
9718
|
-
return
|
|
10044
|
+
return ready;
|
|
9719
10045
|
}
|
|
9720
10046
|
|
|
9721
10047
|
export {
|
|
@@ -9867,6 +10193,9 @@ export {
|
|
|
9867
10193
|
discoverSkills,
|
|
9868
10194
|
readSkillBody,
|
|
9869
10195
|
expandComposerPrompt,
|
|
10196
|
+
joinSteerPrompt,
|
|
10197
|
+
trailingUnansweredUserText,
|
|
10198
|
+
livePartsShowAgentReply,
|
|
9870
10199
|
consumeComposerAttachments,
|
|
9871
10200
|
takePendingTurnAttachments,
|
|
9872
10201
|
alignQueueAttachments,
|
|
@@ -9875,6 +10204,7 @@ export {
|
|
|
9875
10204
|
removeQueuedItem,
|
|
9876
10205
|
moveQueuedItemToFront,
|
|
9877
10206
|
shiftQueuedItem,
|
|
10207
|
+
resolveSendFollowUp,
|
|
9878
10208
|
packagedDetachedJobPath,
|
|
9879
10209
|
resolveDetachedJobScript,
|
|
9880
10210
|
formatDetachedJobInvoke,
|
|
@@ -9914,7 +10244,6 @@ export {
|
|
|
9914
10244
|
RUN_SCRIPT_DESKTOP_ADOPT_MS,
|
|
9915
10245
|
isPidAlive,
|
|
9916
10246
|
waitForPidExit,
|
|
9917
|
-
resolveSendFollowUp,
|
|
9918
10247
|
resolveOrchChildFollowUp,
|
|
9919
10248
|
LIGHT_RECONCILE_THROTTLE_MS,
|
|
9920
10249
|
Orchestrator,
|