@sideboard-ai/core 0.1.168 → 0.1.170
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-BMS53RIZ.js → abletime-ESVTHTFH.js} +2 -2
- package/dist/{abletime-AGF54TNA.js → abletime-IC2V7CNB.js} +2 -2
- package/dist/{agents-TSO4MB3X.js → agents-GOBVOXFG.js} +9 -9
- package/dist/{agents-KWJXZAHB.js → agents-ZCIMZHXZ.js} +9 -9
- package/dist/{app-settings-BRLZQA7N.js → app-settings-LF3TS7XS.js} +5 -1
- package/dist/{app-settings-JJQDWPEK.js → app-settings-VMOTQORT.js} +5 -1
- package/dist/{chunk-74TWOSQP.js → chunk-3C4B52TS.js} +78 -42
- package/dist/{chunk-CVZ4KXVP.js → chunk-7IUO67CW.js} +122 -2
- package/dist/{chunk-HSGSQA42.js → chunk-DHPZW2EA.js} +8 -34
- package/dist/{chunk-KJFFQAMA.js → chunk-DKLGWRWC.js} +1 -1
- package/dist/{chunk-NYMFNUT5.js → chunk-GQHVICNT.js} +194 -147
- package/dist/{chunk-ILXKJ4ZD.js → chunk-NB7TEKCF.js} +1 -1
- package/dist/{chunk-RS756MKF.js → chunk-P2VCMIZU.js} +8 -34
- package/dist/{chunk-UIR4VDYA.js → chunk-SAZIRJR4.js} +30 -10
- package/dist/{chunk-UVLPL2FJ.js → chunk-TEI72FYD.js} +198 -216
- package/dist/{chunk-3A54S244.js → chunk-UDEWGTP6.js} +29 -10
- package/dist/{chunk-TW5A2HFY.js → chunk-Y7DJA3UW.js} +78 -42
- package/dist/{chunk-LTXS26K5.js → chunk-YMF5WCIA.js} +122 -2
- package/dist/{coordinator-prompt-75N74HAO.js → coordinator-prompt-JTDCEU74.js} +3 -3
- package/dist/{coordinator-prompt-Y372QRFE.js → coordinator-prompt-RRUU2OYO.js} +3 -3
- package/dist/{global-workspace-JNNFVSP7.js → global-workspace-4SI3CRRT.js} +3 -3
- package/dist/{global-workspace-TPE4LKVM.js → global-workspace-ZF6EJAM3.js} +3 -3
- package/dist/index.cjs +421 -278
- package/dist/index.d.cts +135 -37
- package/dist/index.d.ts +135 -37
- package/dist/index.js +33 -19
- package/dist/mcp/run-stdio.cjs +401 -207
- package/dist/mcp/run-stdio.js +8 -8
- package/dist/{orchestrator-XG3QCMOS.js → orchestrator-LE6L6MJC.js} +5 -5
- package/dist/{orchestrator-IIME6KXQ.js → orchestrator-UZSFTDKA.js} +5 -5
- package/dist/{workspaces-2IGQNFPL.js → workspaces-A7C3WA54.js} +3 -3
- package/dist/{workspaces-BWZSDSGG.js → workspaces-NOC2MWQV.js} +3 -3
- package/dist/{worktree-7X7XNSYL.js → worktree-GXO2VDQF.js} +12 -4
- package/dist/{worktree-5BFEK6PF.js → worktree-PODE23PD.js} +12 -4
- package/package.json +1 -1
|
@@ -24,13 +24,11 @@ import {
|
|
|
24
24
|
stripBrightsyNdjsonNoise,
|
|
25
25
|
sumUsageList,
|
|
26
26
|
toolDescription
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-SAZIRJR4.js";
|
|
28
28
|
import {
|
|
29
29
|
SLACK_REPLY_FORMATTING,
|
|
30
30
|
addWorkspace,
|
|
31
|
-
assertOrchestratorCapableAgent,
|
|
32
31
|
attachmentsFromWorktreePaths,
|
|
33
|
-
coerceOrchestratorAgent,
|
|
34
32
|
coordinatorSystemPrompt,
|
|
35
33
|
coordinatorTurnReminder,
|
|
36
34
|
createGlobalChat,
|
|
@@ -41,7 +39,6 @@ import {
|
|
|
41
39
|
isCloudCoordinatorThread,
|
|
42
40
|
isGlobalRepoPath,
|
|
43
41
|
isGlobalThread,
|
|
44
|
-
isOrchestratorCapableAgent,
|
|
45
42
|
isOrchestratorThread,
|
|
46
43
|
isSlackCoordinatorThread,
|
|
47
44
|
orchestratorSessionPoisonedByBuiltins,
|
|
@@ -50,7 +47,7 @@ import {
|
|
|
50
47
|
stageAbsolutePathsAsAttachments,
|
|
51
48
|
stageBuffersAsAttachments,
|
|
52
49
|
syncWorkspacesFromThreads
|
|
53
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-DHPZW2EA.js";
|
|
54
51
|
import {
|
|
55
52
|
addPrStackLayer,
|
|
56
53
|
allocateTeamName,
|
|
@@ -95,10 +92,12 @@ import {
|
|
|
95
92
|
resolveRepoRoot,
|
|
96
93
|
takenSlugsFromThread,
|
|
97
94
|
threadDisplayLabel,
|
|
95
|
+
ticketSlugForBranch,
|
|
98
96
|
withRepoGitLock,
|
|
99
97
|
worktreeDisplayLabelForGroup,
|
|
100
|
-
worktreeNameFromPath
|
|
101
|
-
|
|
98
|
+
worktreeNameFromPath,
|
|
99
|
+
worktreeSlugForTicket
|
|
100
|
+
} from "./chunk-3C4B52TS.js";
|
|
102
101
|
import {
|
|
103
102
|
ATTACHMENTS_DIR,
|
|
104
103
|
DETACHED_JOBS_DIR,
|
|
@@ -127,12 +126,15 @@ import {
|
|
|
127
126
|
turnFailChatText
|
|
128
127
|
} from "./chunk-XXIH6XYR.js";
|
|
129
128
|
import {
|
|
129
|
+
assertOrchestratorCapableAgent,
|
|
130
130
|
childEnvWithAppSettings,
|
|
131
|
+
coerceOrchestratorAgent,
|
|
131
132
|
formatViewerContextDirective,
|
|
132
133
|
formatViewerContextReminder,
|
|
133
134
|
getIssueSource,
|
|
134
135
|
isAbleTimeConnected,
|
|
135
136
|
isLinearConnected,
|
|
137
|
+
isOrchestratorCapableAgent,
|
|
136
138
|
isSecureFileEncrypted,
|
|
137
139
|
loadAppSettings,
|
|
138
140
|
orchestrationQuotaFallbackAgent,
|
|
@@ -140,13 +142,13 @@ import {
|
|
|
140
142
|
readSecureJson,
|
|
141
143
|
resolveEffectiveIssueSource,
|
|
142
144
|
resolveNewThreadOptions,
|
|
143
|
-
|
|
145
|
+
resolveOrchestratorDefaults,
|
|
144
146
|
resolveVaultKey,
|
|
145
147
|
resolveViewerProfileForRepo,
|
|
146
148
|
saveAppSettings,
|
|
147
149
|
updateAdvancedSettings,
|
|
148
150
|
writeSecureJson
|
|
149
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-7IUO67CW.js";
|
|
150
152
|
import {
|
|
151
153
|
stripNestedElectronEnv
|
|
152
154
|
} from "./chunk-4TR3HZFT.js";
|
|
@@ -464,7 +466,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
464
466
|
await continueOnReply(threadId, prompt);
|
|
465
467
|
return;
|
|
466
468
|
}
|
|
467
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
469
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-UZSFTDKA.js");
|
|
468
470
|
await getOrchestrator2().send(threadId, prompt);
|
|
469
471
|
} catch {
|
|
470
472
|
}
|
|
@@ -746,9 +748,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
746
748
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
747
749
|
);
|
|
748
750
|
}
|
|
749
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
751
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-ZF6EJAM3.js");
|
|
750
752
|
if (isGlobalThread2(thread)) {
|
|
751
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
753
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-JTDCEU74.js");
|
|
752
754
|
ensureGlobalCoordinatorCwd2(
|
|
753
755
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
754
756
|
);
|
|
@@ -959,6 +961,51 @@ function agentGitPrompt(action, opts) {
|
|
|
959
961
|
return "Merge PR.";
|
|
960
962
|
}
|
|
961
963
|
}
|
|
964
|
+
var RESOLVE_CONFLICTS_RE = /^Merge the remote branch(?: \(([^)]+)\))? into your branch and resolve conflicts\. Then, commit and push your changes\.$/;
|
|
965
|
+
function gitActionExpansion(action, base) {
|
|
966
|
+
switch (action) {
|
|
967
|
+
case "commit-push":
|
|
968
|
+
return "Commit any uncommitted work with a purpose-stating message, then push to origin (`git push -u origin HEAD`; this updates an existing PR when one is linked). Do not start a checks loop unless a goal was given.";
|
|
969
|
+
case "create-draft":
|
|
970
|
+
return "Commit, push, then create a draft PR with `gh pr create --draft -R <origin-owner/name>` (title/body from the change purpose). Update the existing PR instead if one is linked.";
|
|
971
|
+
case "create-web":
|
|
972
|
+
return "Commit, push, then `gh pr create --web -R <origin-owner/name>`.";
|
|
973
|
+
case "resolve-conflicts":
|
|
974
|
+
return `Fetch the PR base${base ? ` (\`${base}\`)` : ""}, merge it into this branch, resolve conflicts carefully, then commit and push until the PR is mergeable.`;
|
|
975
|
+
case "merge":
|
|
976
|
+
return "This phrase is the explicit ask to merge this thread's open pull request on GitHub. If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.";
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
function expandCanonicalGitRequest(prompt) {
|
|
980
|
+
const trimmed = prompt.trim();
|
|
981
|
+
let action = null;
|
|
982
|
+
let base = null;
|
|
983
|
+
for (const candidate of AGENT_GIT_ACTIONS) {
|
|
984
|
+
if (candidate === "resolve-conflicts") continue;
|
|
985
|
+
if (agentGitPrompt(candidate) === trimmed) {
|
|
986
|
+
action = candidate;
|
|
987
|
+
break;
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
if (!action) {
|
|
991
|
+
const m = RESOLVE_CONFLICTS_RE.exec(trimmed);
|
|
992
|
+
if (m) {
|
|
993
|
+
action = "resolve-conflicts";
|
|
994
|
+
base = m[1] ?? null;
|
|
995
|
+
}
|
|
996
|
+
}
|
|
997
|
+
let expansion = action ? gitActionExpansion(action, base) : null;
|
|
998
|
+
if (!expansion && trimmed === "Address review comments.") {
|
|
999
|
+
expansion = "Read the PR review feedback (`gh pr view --comments`, `gh api` review comments), make the requested changes, commit, and push.";
|
|
1000
|
+
} else if (!expansion && FIX_CI_RE.test(trimmed)) {
|
|
1001
|
+
expansion = "Investigate that failing check (`gh pr checks`, `gh run view --log-failed`), fix it, commit, and push. Loop only if a goal to keep going until it passes was given.";
|
|
1002
|
+
}
|
|
1003
|
+
if (!expansion) return prompt;
|
|
1004
|
+
return `${trimmed}
|
|
1005
|
+
|
|
1006
|
+
(Sideboard git request \u2014 do not ask for clarification: ${expansion})`;
|
|
1007
|
+
}
|
|
1008
|
+
var FIX_CI_RE = /^Fix CI: .+\.$/;
|
|
962
1009
|
|
|
963
1010
|
// src/git/pr-merge-archive.ts
|
|
964
1011
|
function normalizePrState(state) {
|
|
@@ -1220,47 +1267,84 @@ function formatToolPart(t, detail) {
|
|
|
1220
1267
|
}
|
|
1221
1268
|
function formatMessagesAsTranscript(messages, opts) {
|
|
1222
1269
|
const tools = opts?.tools ?? "full";
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1270
|
+
const thinking = opts?.thinking ?? true;
|
|
1271
|
+
return messages.map((m) => formatMessageBlock(m, { tools, thinking })).join("\n\n");
|
|
1272
|
+
}
|
|
1273
|
+
function formatMessageBlock(m, opts) {
|
|
1274
|
+
if (m.role === "summary") return `## Prior summary
|
|
1275
|
+
${m.text}`;
|
|
1276
|
+
if (m.role === "user") return `### User
|
|
1277
|
+
${m.text}`;
|
|
1278
|
+
const bits = [];
|
|
1279
|
+
if (m.text?.trim()) {
|
|
1280
|
+
bits.push(`### Agent
|
|
1232
1281
|
${m.text}`);
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
${m.text}`);
|
|
1239
|
-
} else {
|
|
1240
|
-
bits.push("### Agent");
|
|
1241
|
-
}
|
|
1242
|
-
const thinking = (m.parts ?? []).filter((p) => p.type === "thinking");
|
|
1243
|
-
for (const th of thinking) {
|
|
1282
|
+
} else {
|
|
1283
|
+
bits.push("### Agent");
|
|
1284
|
+
}
|
|
1285
|
+
if (opts.thinking) {
|
|
1286
|
+
for (const th of m.parts ?? []) {
|
|
1244
1287
|
if (th.type !== "thinking" || !th.text.trim()) continue;
|
|
1245
1288
|
bits.push("Thinking:");
|
|
1246
1289
|
bits.push(th.text);
|
|
1247
1290
|
}
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
)
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1291
|
+
}
|
|
1292
|
+
const toolParts = (m.parts ?? []).filter(
|
|
1293
|
+
(p) => p.type === "tool"
|
|
1294
|
+
);
|
|
1295
|
+
if (opts.tools !== "none" && toolParts.length > 0) {
|
|
1296
|
+
if (opts.tools === "summary") bits.push("Tools:");
|
|
1297
|
+
for (const t of toolParts) {
|
|
1298
|
+
bits.push(formatToolPart(t, opts.tools));
|
|
1256
1299
|
}
|
|
1257
|
-
blocks.push(bits.join("\n"));
|
|
1258
1300
|
}
|
|
1259
|
-
return
|
|
1301
|
+
return bits.join("\n");
|
|
1260
1302
|
}
|
|
1303
|
+
var SEED_MAX_CHARS = 6e4;
|
|
1304
|
+
var SEED_FULL_TOOL_MESSAGES = 6;
|
|
1261
1305
|
function buildSessionSeed(messages, opts) {
|
|
1262
1306
|
if (messages.length === 0) return null;
|
|
1263
|
-
const
|
|
1307
|
+
const tools = opts?.tools ?? "full";
|
|
1308
|
+
const fullCount = opts?.fullToolMessages ?? SEED_FULL_TOOL_MESSAGES;
|
|
1309
|
+
const maxChars = opts?.maxChars ?? SEED_MAX_CHARS;
|
|
1310
|
+
const olderTools = tools === "none" ? "none" : "summary";
|
|
1311
|
+
const fullFrom = Math.max(0, messages.length - fullCount);
|
|
1312
|
+
const blocks = messages.map(
|
|
1313
|
+
(m, i) => formatMessageBlock(m, {
|
|
1314
|
+
tools: i >= fullFrom ? tools : olderTools,
|
|
1315
|
+
thinking: false
|
|
1316
|
+
})
|
|
1317
|
+
);
|
|
1318
|
+
const keep = new Array(blocks.length).fill(false);
|
|
1319
|
+
let used = 0;
|
|
1320
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
1321
|
+
if (messages[i].role === "summary") {
|
|
1322
|
+
keep[i] = true;
|
|
1323
|
+
used += blocks[i].length + 2;
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
1327
|
+
if (keep[i]) continue;
|
|
1328
|
+
const next = used + blocks[i].length + 2;
|
|
1329
|
+
if (next > maxChars && used > 0) break;
|
|
1330
|
+
keep[i] = true;
|
|
1331
|
+
used = next;
|
|
1332
|
+
}
|
|
1333
|
+
const dropped = keep.filter((k) => !k).length;
|
|
1334
|
+
const kept = [];
|
|
1335
|
+
let markerPlaced = false;
|
|
1336
|
+
for (let i = 0; i < blocks.length; i++) {
|
|
1337
|
+
if (!keep[i]) continue;
|
|
1338
|
+
if (dropped > 0 && !markerPlaced && messages[i].role !== "summary") {
|
|
1339
|
+
kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
|
|
1340
|
+
markerPlaced = true;
|
|
1341
|
+
}
|
|
1342
|
+
kept.push(blocks[i]);
|
|
1343
|
+
}
|
|
1344
|
+
if (dropped > 0 && !markerPlaced) {
|
|
1345
|
+
kept.push(`_(${dropped} older message${dropped === 1 ? "" : "s"} omitted for length)_`);
|
|
1346
|
+
}
|
|
1347
|
+
const body = kept.join("\n\n");
|
|
1264
1348
|
if (!body.trim()) return null;
|
|
1265
1349
|
return [
|
|
1266
1350
|
"Sideboard conversation context (restored after compaction or a new session):",
|
|
@@ -1319,7 +1403,7 @@ function messagesSinceLastBrightsyContextSummary(messages) {
|
|
|
1319
1403
|
function buildBrightsySessionSeed(messages) {
|
|
1320
1404
|
const match = findLastBrightsyContextSummary(messages);
|
|
1321
1405
|
const tail = match ? messages.slice(match.index + 1) : messages;
|
|
1322
|
-
const body = formatMessagesAsTranscript(tail, { tools: "none" });
|
|
1406
|
+
const body = formatMessagesAsTranscript(tail, { tools: "none", thinking: false });
|
|
1323
1407
|
if (!match && !body.trim()) return null;
|
|
1324
1408
|
const blocks = [
|
|
1325
1409
|
"Sideboard conversation context (restored after compaction or a new session):",
|
|
@@ -3486,7 +3570,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3486
3570
|
});
|
|
3487
3571
|
await requireAgent(resolved.agent);
|
|
3488
3572
|
if (input.cowboy) {
|
|
3489
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
3573
|
+
const { cowboyModeEnabled } = await import("./app-settings-VMOTQORT.js");
|
|
3490
3574
|
if (!cowboyModeEnabled()) {
|
|
3491
3575
|
throw new Error(
|
|
3492
3576
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -3544,7 +3628,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3544
3628
|
let sourceIsFork = false;
|
|
3545
3629
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
3546
3630
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
3547
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
3631
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-IC2V7CNB.js");
|
|
3548
3632
|
const task = await ensureAbleTimeTask({
|
|
3549
3633
|
title: title?.trim() || "Untitled work",
|
|
3550
3634
|
description: input.prompt?.trim() || void 0
|
|
@@ -3608,10 +3692,11 @@ async function createThread(input, _onSetupLine) {
|
|
|
3608
3692
|
throw new Error("Use adoptThread() for adopt sources");
|
|
3609
3693
|
}
|
|
3610
3694
|
const team = allocateTeamSlug(repoPath);
|
|
3695
|
+
const slug = sourceType === "ticket" ? worktreeSlugForTicket(persistedSourceRef, team.slug) : team.slug;
|
|
3611
3696
|
const { branchName, worktreePath } = await createThreadWorktree({
|
|
3612
3697
|
repoPath,
|
|
3613
3698
|
sourceRef,
|
|
3614
|
-
slug
|
|
3699
|
+
slug
|
|
3615
3700
|
});
|
|
3616
3701
|
copyConfiguredFiles(repoPath, worktreePath);
|
|
3617
3702
|
const explicitTitle = title?.trim();
|
|
@@ -3641,7 +3726,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3641
3726
|
return readThread(thread.id) ?? thread;
|
|
3642
3727
|
}
|
|
3643
3728
|
async function listLinearIssues(agent, repoPath) {
|
|
3644
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3729
|
+
const { getAdapter: getAdapter2 } = await import("./agents-GOBVOXFG.js");
|
|
3645
3730
|
await requireAgent(agent, { requireLinear: true });
|
|
3646
3731
|
const adapter = getAdapter2(agent);
|
|
3647
3732
|
if (!adapter.listLinearIssues) {
|
|
@@ -4063,7 +4148,7 @@ async function adoptThread(input) {
|
|
|
4063
4148
|
messages: input.messages ?? []
|
|
4064
4149
|
});
|
|
4065
4150
|
writeThread(thread);
|
|
4066
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
4151
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-A7C3WA54.js");
|
|
4067
4152
|
await ensureWorkspace2(repoPath);
|
|
4068
4153
|
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
|
|
4069
4154
|
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
@@ -5748,7 +5833,7 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
5748
5833
|
}
|
|
5749
5834
|
|
|
5750
5835
|
// src/agents/instructions.ts
|
|
5751
|
-
import { existsSync as existsSync16
|
|
5836
|
+
import { existsSync as existsSync16 } from "fs";
|
|
5752
5837
|
import { join as join15 } from "path";
|
|
5753
5838
|
|
|
5754
5839
|
// src/skills/detached-job-path.ts
|
|
@@ -5794,12 +5879,17 @@ function normPath(p) {
|
|
|
5794
5879
|
function formatRenameBranchDirective(thread, opts) {
|
|
5795
5880
|
if (!isPlaceholderBranch(thread.branchName, thread.worktreePath)) return null;
|
|
5796
5881
|
const dir = worktreeNameFromPath(thread.worktreePath);
|
|
5882
|
+
const ticket = thread.sourceType === "ticket" ? ticketSlugForBranch(thread.sourceRef ?? "") : null;
|
|
5883
|
+
const example = ticket ? `\`feat/${ticket}-dark-mode\` or \`fix/${ticket}-panel-width\`` : "`fix/panel-width` or `feat/dark-mode`";
|
|
5797
5884
|
const lines = [
|
|
5798
5885
|
"Branch naming (do this early in the turn):",
|
|
5799
|
-
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable
|
|
5800
|
-
|
|
5886
|
+
`- Current branch \`${thread.branchName}\` is a temporary placeholder. The worktree folder \`${dir}\` is a stable nickname \u2014 do not rename or leave that directory.`,
|
|
5887
|
+
`- Rename the git branch to a short kebab-case name that describes this task (what you are changing), e.g. ${example}:`,
|
|
5801
5888
|
" `git branch -m <new-name>`",
|
|
5802
5889
|
"- Prefer Conventional Commits style prefixes when they fit (`fix/`, `feat/`, `chore/`, `docs/`).",
|
|
5890
|
+
...ticket ? [
|
|
5891
|
+
`- Keep ticket \`${ticket}\` in the new branch name so the issue stays findable.`
|
|
5892
|
+
] : [],
|
|
5803
5893
|
"- Never push this placeholder to main/master."
|
|
5804
5894
|
];
|
|
5805
5895
|
const custom = opts?.customPrompt?.trim();
|
|
@@ -5833,67 +5923,38 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
5833
5923
|
lines.push(
|
|
5834
5924
|
"- Always use this worktree's `origin` remote (`git remote get-url origin` from this cwd). Never push to or open PRs against `upstream` (template remotes)."
|
|
5835
5925
|
);
|
|
5836
|
-
lines.push(
|
|
5837
|
-
"- Push with `git push -u origin HEAD` (or the current branch name). Do not `git push upstream`."
|
|
5838
|
-
);
|
|
5839
|
-
lines.push("");
|
|
5840
5926
|
lines.push(formatGitAuthModeDirective(opts?.gitAuthMode ?? "auto"));
|
|
5841
5927
|
lines.push(
|
|
5842
|
-
"-
|
|
5843
|
-
);
|
|
5844
|
-
lines.push(
|
|
5845
|
-
"- Prefer a concise imperative title (Conventional Commits style when it fits: feat:/fix:/chore:/docs:). Body should summarize intent, key changes, and test notes."
|
|
5928
|
+
"- PR title/body and commit messages state what the change does and why (inspect the diff/commits and the user request) \u2014 never the worktree nickname or placeholder branch. Concise imperative title (Conventional Commits when it fits: feat:/fix:/chore:/docs:); body = intent, key changes, test notes."
|
|
5846
5929
|
);
|
|
5847
5930
|
lines.push(
|
|
5848
|
-
"-
|
|
5931
|
+
"- Stay on this thread branch. Never push to main/master or merge locally into the main checkout. Merge the PR only when this turn is a Merge PR request or the user explicitly asked \u2014 via GitHub from this worktree (`gh pr merge` / `gh stack merge`)."
|
|
5849
5932
|
);
|
|
5850
5933
|
if (thread.prUrl) {
|
|
5851
5934
|
lines.push(
|
|
5852
5935
|
`- A PR already exists (${thread.prUrl}). Update it (push + edit title/body if the purpose drifted) instead of opening a duplicate.`
|
|
5853
5936
|
);
|
|
5854
|
-
} else if (opts?.githubSlug) {
|
|
5855
|
-
lines.push(
|
|
5856
|
-
`- Prefer a draft PR first: \`gh pr create --draft -R ${opts.githubSlug}\` (or update via \`gh pr edit -R ${opts.githubSlug}\`) once the change set is coherent. Always pass \`-R ${opts.githubSlug}\` (this worktree's origin). Bare \`gh pr create\` may target upstream instead of origin on dual-remote checkouts. Mark ready for review only when asked. Title/body must reflect the change purpose, not the worktree name. If GitHub rejects the GraphQL body as too long, retry with a short \`--body-file\` (limit 65,536 characters) \u2014 do not paste a changelog or diff into \`--body\`.`
|
|
5857
|
-
);
|
|
5858
5937
|
} else {
|
|
5938
|
+
const slug = opts?.githubSlug ?? "<origin-owner/name>";
|
|
5939
|
+
const resolve = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
|
|
5859
5940
|
lines.push(
|
|
5860
|
-
|
|
5941
|
+
`- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${resolve} Mark ready for review only when asked. If GitHub rejects the body as too long, retry with a short \`--body-file\` \u2014 do not paste a changelog or diff into \`--body\`.`
|
|
5861
5942
|
);
|
|
5862
5943
|
}
|
|
5863
|
-
lines.push("");
|
|
5864
|
-
lines.push(
|
|
5865
|
-
"Short git requests from the Sideboard UI are complete instructions \u2014 expand them using the rules above without asking for clarification:"
|
|
5866
|
-
);
|
|
5867
|
-
lines.push(
|
|
5868
|
-
'- "Commit and push." \u2192 commit any uncommitted work with a purpose-stating message, then push to origin (updates an existing PR if one is linked). Do not start a checks loop unless they gave a goal.'
|
|
5869
|
-
);
|
|
5870
|
-
lines.push(
|
|
5871
|
-
'- "Commit, push, and open a draft PR." \u2192 commit, push, then create a draft PR with `gh pr create --draft -R \u2026` (title/body from the change purpose).'
|
|
5872
|
-
);
|
|
5873
|
-
lines.push(
|
|
5874
|
-
'- "Commit, push, and open a PR in the browser." \u2192 commit, push, then `gh pr create --web -R \u2026`.'
|
|
5875
|
-
);
|
|
5876
|
-
lines.push(
|
|
5877
|
-
'- "Fix CI: <name>." \u2192 investigate that failing check, fix it, commit, and push. Loop only if they gave a goal to keep going until it passes.'
|
|
5878
|
-
);
|
|
5879
|
-
lines.push(
|
|
5880
|
-
'- "Merge the remote branch (<base>) into your branch and resolve conflicts. Then, commit and push your changes." \u2192 fetch the PR base, merge it into this branch, resolve conflicts carefully, commit, and push until the PR is mergeable.'
|
|
5881
|
-
);
|
|
5882
5944
|
lines.push(
|
|
5883
|
-
'- "
|
|
5945
|
+
'- Sideboard git buttons send short phrases ("Commit and push.", "Merge PR.", \u2026) with their meaning attached \u2014 act on them without asking for clarification. If the user gives a goal (Greptile 5/5, CI green, until checks pass), you get the watch-fix-push playbook with that request.'
|
|
5884
5946
|
);
|
|
5885
|
-
lines.push(
|
|
5886
|
-
'- "Merge PR." \u2192 merge this thread\'s open pull request on GitHub (this phrase is the explicit ask). If `gh stack view` shows a stack, use `gh stack merge`; otherwise `gh pr merge` (respect repo defaults / squash vs merge). Do not force-push main/master or merge locally into the main checkout.'
|
|
5887
|
-
);
|
|
5888
|
-
lines.push("");
|
|
5889
|
-
lines.push(formatPrGateDirective());
|
|
5890
5947
|
lines.push("");
|
|
5891
|
-
lines.push(formatProcessGuideDirective());
|
|
5948
|
+
lines.push(formatProcessGuideDirective({ worktreePath: thread.worktreePath }));
|
|
5892
5949
|
return lines.join("\n");
|
|
5893
5950
|
}
|
|
5894
5951
|
function formatWorktreeReminder() {
|
|
5895
5952
|
return "Sideboard worktree: 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.";
|
|
5896
5953
|
}
|
|
5954
|
+
var PR_GOAL_RE = /greptile|\bci\b.*\b(green|pass)|checks?\s+(pass|green)|until\s+.*\b(pass|green|merge|clean)|\bfix ci\b|watch[- ]fix[- ]push/i;
|
|
5955
|
+
function mentionsPrGoal(prompt) {
|
|
5956
|
+
return PR_GOAL_RE.test(prompt);
|
|
5957
|
+
}
|
|
5897
5958
|
var GITHUB_TICKET_REF = /^(?:#?\d+|gh-\d+)$/i;
|
|
5898
5959
|
var KEYED_TICKET_REF = /^(?:[A-Z][A-Z0-9]{0,9}-\d+|[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12})$/i;
|
|
5899
5960
|
function issueTicketFromThread(thread, preferredSource = "github") {
|
|
@@ -5984,29 +6045,27 @@ function formatPrGateDirective() {
|
|
|
5984
6045
|
"- Greptile 5/5: wait for the greptile check; read the latest `N/5` from the PR body or Greptile\u2019s most recently *updated* issue comment; also fetch unresolved review comments / the \u201CPrompt to fix all with AI\u201D block. Done = **5/5 and zero unresolved Greptile comments**. If Greptile is idle, comment `@greptile review`. Cap about 5 iterations, then report leftovers. Do not merge unless asked."
|
|
5985
6046
|
].join("\n");
|
|
5986
6047
|
}
|
|
5987
|
-
function formatProcessGuideDirective() {
|
|
6048
|
+
function formatProcessGuideDirective(opts) {
|
|
6049
|
+
const worktree = opts?.worktreePath?.trim();
|
|
6050
|
+
const hasGraphSkill = !!worktree && existsSync16(join15(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
6051
|
+
const hasReviewSkill = !!worktree && existsSync16(join15(worktree, ".claude/skills/review/SKILL.md"));
|
|
5988
6052
|
return [
|
|
5989
6053
|
"Process guides (recurring work only):",
|
|
5990
|
-
"-
|
|
5991
|
-
"- If `.claude/skills
|
|
5992
|
-
"-
|
|
5993
|
-
"- Merge-readiness notes: if `.claude/skills/review/SKILL.md` already exists, edit it. Otherwise write them to `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
|
|
5994
|
-
"- Do not write new skills under `.sideboard/skills/` (that folder only \u2014 other `.sideboard/` files such as settings.toml are fine). Point Codex/OpenCode at the Claude skill from `AGENTS.md`. Optional: symlink `.cursor/skills/<name>` to the Claude skill.",
|
|
6054
|
+
hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
|
|
6055
|
+
"- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill; Sideboard `/name`, Claude Code, and `attach` all load it). Not under `.sideboard/skills/`. Point Codex/OpenCode at it from `AGENTS.md`.",
|
|
6056
|
+
hasReviewSkill ? "- Merge-readiness notes go in `.claude/skills/review/SKILL.md` (edit it; do not create another review skill)." : "- Merge-readiness notes go in `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
|
|
5995
6057
|
"- Skip a guide for a one-off. If a matching skill exists, follow it. Same miss twice \u2192 edit the skill, do not patch around it."
|
|
5996
|
-
].join("\n");
|
|
6058
|
+
].filter(Boolean).join("\n");
|
|
5997
6059
|
}
|
|
5998
6060
|
function formatLongRunningDirective(opts) {
|
|
5999
6061
|
const invoke = formatDetachedJobInvoke(opts?.scriptPath);
|
|
6000
6062
|
return [
|
|
6001
|
-
"Long-running jobs (mandatory when a command may run more than ~30s):",
|
|
6002
|
-
"A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted
|
|
6003
|
-
|
|
6004
|
-
|
|
6005
|
-
"-
|
|
6006
|
-
|
|
6007
|
-
`- If it is hanging, producing no useful output, or doing the wrong thing: MCP \`stop_job\` (same id, optional reason) or \`${invoke} stop <id>\`. Do not loop forever. Do not stop a pack/test/deploy that is clearly making progress.`,
|
|
6008
|
-
"- Do not end the turn with \u201CI\u2019ll let you know when it\u2019s done.\u201D Stay in the loop until stillRunning is false (or you stopped it).",
|
|
6009
|
-
"- ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
|
|
6063
|
+
"Long-running jobs (mandatory when a command may run more than ~30s \u2014 pack, test, deploy, `gh pr checks --watch`):",
|
|
6064
|
+
"A Sideboard worktree turn SIGTERMs the agent shell (and its process group) when the user sends another message or the turn is interrupted; `block_until_ms: 0` is not enough. Detach instead, and never ask the human to poll.",
|
|
6065
|
+
`- Start once: \`${invoke} start <id> -- <command> [args...]\` (cwd = this worktree; same tool as \`scripts/detached-job.cjs\` when the worktree has it). If JSON says already-running, do not start again.`,
|
|
6066
|
+
"- Immediately `present_artifact` `type=log` with `artifact_id=<id>` and `status=running`, then loop Sideboard MCP `wait_for_job` (returns in ~45s). stillRunning \u2192 present the same id with `content=delta` only \u2192 wait again. Shell fallback: the same helper with `wait <id>`.",
|
|
6067
|
+
"- Hanging, no useful output, or the wrong thing \u2192 `stop_job` (or the helper with `stop <id>`). Do not stop a pack/test/deploy that is clearly making progress.",
|
|
6068
|
+
"- Stay in the loop until stillRunning is false (or you stopped it). ok \u2192 finish the task. failed / stopped \u2192 read the log, fix or narrow the command, start once.",
|
|
6010
6069
|
"State: `.context/.sideboard/detached-jobs/<id>/` (local scratch). Full guide: `/long-running` (always available)."
|
|
6011
6070
|
].join("\n");
|
|
6012
6071
|
}
|
|
@@ -6016,97 +6075,16 @@ function formatLongRunningReminder(opts) {
|
|
|
6016
6075
|
}
|
|
6017
6076
|
function formatArtifactDirective() {
|
|
6018
6077
|
return [
|
|
6019
|
-
"Sideboard side column (desktop UI)
|
|
6020
|
-
"
|
|
6021
|
-
"
|
|
6022
|
-
"
|
|
6023
|
-
"
|
|
6024
|
-
"```html",
|
|
6025
|
-
"<!DOCTYPE html><html><head><title>Demo</title></head><body><h1>Hi</h1></body></html>",
|
|
6026
|
-
"```",
|
|
6027
|
-
"2) Or call Sideboard MCP `present_artifact` with title, type (html|svg|markdown|react|log), and content \u2014 not both a fence and this tool for the same body.",
|
|
6028
|
-
" type=log is append-only: same `artifact_id`, `content` = new lines only (plus optional status/phase). Do not resend the full log or wrap it in HTML.",
|
|
6029
|
-
"CMS / JSON Schema forms & tables (Brightsy or any schema+schemaUi source):",
|
|
6030
|
-
"3) Call Sideboard MCP `present_schema` when the user needs to filter, edit, publish, or persist rows \u2014 including after you already showed a markdown table, if they then ask for an editable table. If they only need to read the data, a markdown table is enough. When you do call it, pass title, mode (table|form), and either:",
|
|
6031
|
-
" - datasource=brightsy + resource_id (record type UUID) after fetching types via Brightsy MCP, or",
|
|
6032
|
-
" - datasource=inline + resource: { id, title, schema, schemaUi } and optional records/record.",
|
|
6033
|
-
"Files / media browser (CMS file manager column):",
|
|
6034
|
-
"4) Call Sideboard MCP `present_files` with optional title, path, and datasource (brightsy|memory).",
|
|
6035
|
-
" Opens the Files column for browse/upload/pick. Do NOT say a file manager UI is missing.",
|
|
6036
|
-
"Multiple-choice questions:",
|
|
6037
|
-
"5) Call Sideboard MCP `ask_user` only when work is blocked on choosing among a few concrete options (approach forks, which API, auth vs cookies). First write a short chat message that explains the decision and what each option means (tradeoffs, when to pick it). Include a description on every option. After calling, stop and wait for their next message with answers. If you are asking a real multiple-choice, use ask_user rather than chat bullets so Sideboard shows the composer picker.",
|
|
6038
|
-
"Do not call ask_user for greetings, check-ins, \u201Chello\u201D, open-ended how-can-I-help, or to invent a menu of possible next tasks \u2014 reply in chat. If one option is the obvious default, proceed without asking.",
|
|
6039
|
-
"Never say artifacts, CMS UI, or the Files column are unavailable. present_schema is for interactive list/edit/publish (use it when they ask to edit, even if chat already had a markdown table); present_files for storage UI; html fences for standalone pages; ask_user only for those blocked predefined-option questions."
|
|
6078
|
+
"Sideboard side column (desktop UI) \u2014 Sideboard MCP tools present_artifact, present_schema, present_files, ask_user (see their descriptions). claude.ai\u2019s \u201CArtifact\u201D tool does not exist here; never say artifacts, the CMS UI, or the Files column are unavailable.",
|
|
6079
|
+
"- Standalone documents: a fenced block tagged `html` (preferred), `svg`, or `markdown` containing the FULL document opens the side column by itself. Use that or present_artifact \u2014 never both for the same body.",
|
|
6080
|
+
"- present_artifact type=log appends: same artifact_id, content = new lines only (plus status/phase). Do not resend the full log or wrap it in HTML.",
|
|
6081
|
+
"- Data: a markdown table is enough to read. Call present_schema only when the user needs to filter/edit/publish/persist rows \u2014 including when they ask for an editable table after you already showed markdown. Never re-present rows you already wrote just to display them.",
|
|
6082
|
+
"- ask_user only when work is blocked on a few concrete options (approach fork, which API, auth vs cookies): first a short chat message explaining the decision and each option, then the call (description on every option), then stop and wait. Not for greetings, check-ins, or an invented menu of next tasks \u2014 reply in chat. If one option is the obvious default, proceed."
|
|
6040
6083
|
].join("\n");
|
|
6041
6084
|
}
|
|
6042
6085
|
function formatUiReminder() {
|
|
6043
6086
|
return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos or \u201Cwhat next?\u201D) \u2014 reply in chat. Do not say artifacts/CMS UI are unavailable.";
|
|
6044
6087
|
}
|
|
6045
|
-
var FILES_BY_AGENT = {
|
|
6046
|
-
claude: [
|
|
6047
|
-
"CLAUDE.md",
|
|
6048
|
-
".claude/CLAUDE.md",
|
|
6049
|
-
"CLAUDE.local.md",
|
|
6050
|
-
"AGENTS.md",
|
|
6051
|
-
"AGENT.md"
|
|
6052
|
-
],
|
|
6053
|
-
codex: ["AGENTS.md", "AGENT.md", ".codex/AGENTS.md", "CLAUDE.md"],
|
|
6054
|
-
opencode: ["AGENTS.md", "AGENT.md", "OPENCODE.md", "CLAUDE.md"],
|
|
6055
|
-
brightsy: ["AGENTS.md", "AGENT.md", "CLAUDE.md"],
|
|
6056
|
-
cursor: ["AGENTS.md", "AGENT.md", ".cursor/rules", "CLAUDE.md"]
|
|
6057
|
-
};
|
|
6058
|
-
var MAX_CHARS_PER_FILE = 48e3;
|
|
6059
|
-
function loadAgentInstructions(worktreePath, agent) {
|
|
6060
|
-
const candidates = FILES_BY_AGENT[agent] ?? FILES_BY_AGENT.claude;
|
|
6061
|
-
const seenPaths = /* @__PURE__ */ new Set();
|
|
6062
|
-
const seenBodies = /* @__PURE__ */ new Set();
|
|
6063
|
-
const out = [];
|
|
6064
|
-
for (const rel of candidates) {
|
|
6065
|
-
if (seenPaths.has(rel)) continue;
|
|
6066
|
-
const abs = join15(worktreePath, rel);
|
|
6067
|
-
if (!existsSync16(abs)) continue;
|
|
6068
|
-
try {
|
|
6069
|
-
if (!statSync4(abs).isFile()) continue;
|
|
6070
|
-
let content = readFileSync12(abs, "utf8");
|
|
6071
|
-
if (!content.trim()) continue;
|
|
6072
|
-
if (content.length > MAX_CHARS_PER_FILE) {
|
|
6073
|
-
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
6074
|
-
|
|
6075
|
-
\u2026(truncated)`;
|
|
6076
|
-
}
|
|
6077
|
-
const body = content.trim().replace(/\r\n/g, "\n");
|
|
6078
|
-
if (seenBodies.has(body)) continue;
|
|
6079
|
-
seenPaths.add(rel);
|
|
6080
|
-
seenBodies.add(body);
|
|
6081
|
-
out.push({ relativePath: rel, content });
|
|
6082
|
-
} catch {
|
|
6083
|
-
}
|
|
6084
|
-
}
|
|
6085
|
-
return out;
|
|
6086
|
-
}
|
|
6087
|
-
function formatAgentInstructions(files) {
|
|
6088
|
-
if (files.length === 0) return null;
|
|
6089
|
-
const parts = [
|
|
6090
|
-
"Project agent instructions (from the worktree \u2014 follow these):",
|
|
6091
|
-
""
|
|
6092
|
-
];
|
|
6093
|
-
for (const f of files) {
|
|
6094
|
-
parts.push(`## ${f.relativePath}`);
|
|
6095
|
-
parts.push("");
|
|
6096
|
-
parts.push(f.content.trim());
|
|
6097
|
-
parts.push("");
|
|
6098
|
-
parts.push("---");
|
|
6099
|
-
parts.push("");
|
|
6100
|
-
}
|
|
6101
|
-
return parts.join("\n").trimEnd();
|
|
6102
|
-
}
|
|
6103
|
-
function withAgentInstructions(prompt, files) {
|
|
6104
|
-
const prefix = formatAgentInstructions(files);
|
|
6105
|
-
if (!prefix) return prompt;
|
|
6106
|
-
return `${prefix}
|
|
6107
|
-
|
|
6108
|
-
${prompt}`;
|
|
6109
|
-
}
|
|
6110
6088
|
|
|
6111
6089
|
// src/integrations/optional-services.ts
|
|
6112
6090
|
var OPTIONAL_SERVICE_IDS = ["vercel", "supabase", "posthog", "sentry"];
|
|
@@ -6405,7 +6383,7 @@ async function syncThreadBranchFromGit(threadId) {
|
|
|
6405
6383
|
|
|
6406
6384
|
// src/store/schedules.ts
|
|
6407
6385
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
6408
|
-
import { existsSync as existsSync17, readFileSync as
|
|
6386
|
+
import { existsSync as existsSync17, readFileSync as readFileSync12 } from "fs";
|
|
6409
6387
|
import { join as join16 } from "path";
|
|
6410
6388
|
import { Cron } from "croner";
|
|
6411
6389
|
var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
|
|
@@ -6524,7 +6502,7 @@ function readAll() {
|
|
|
6524
6502
|
const path = schedulesPath();
|
|
6525
6503
|
if (!existsSync17(path)) return [];
|
|
6526
6504
|
try {
|
|
6527
|
-
const parsed = JSON.parse(
|
|
6505
|
+
const parsed = JSON.parse(readFileSync12(path, "utf8"));
|
|
6528
6506
|
if (!Array.isArray(parsed)) return [];
|
|
6529
6507
|
return parsed.map((row) => {
|
|
6530
6508
|
try {
|
|
@@ -6650,7 +6628,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6650
6628
|
${prompt}`;
|
|
6651
6629
|
}
|
|
6652
6630
|
async function defaultDeps() {
|
|
6653
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6631
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-UZSFTDKA.js");
|
|
6654
6632
|
const orch = getOrchestrator2();
|
|
6655
6633
|
return {
|
|
6656
6634
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -6660,7 +6638,7 @@ async function defaultDeps() {
|
|
|
6660
6638
|
}
|
|
6661
6639
|
function pickAgent(schedule) {
|
|
6662
6640
|
if (schedule.agent) return schedule.agent;
|
|
6663
|
-
return coerceOrchestratorAgent(
|
|
6641
|
+
return coerceOrchestratorAgent(resolveOrchestratorDefaults().agent);
|
|
6664
6642
|
}
|
|
6665
6643
|
async function fireSchedule(id) {
|
|
6666
6644
|
const schedule = getSchedule(id);
|
|
@@ -6912,7 +6890,7 @@ var Orchestrator = class {
|
|
|
6912
6890
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
6913
6891
|
});
|
|
6914
6892
|
}
|
|
6915
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
6893
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-VMOTQORT.js");
|
|
6916
6894
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
6917
6895
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
6918
6896
|
}
|
|
@@ -7191,7 +7169,7 @@ var Orchestrator = class {
|
|
|
7191
7169
|
}
|
|
7192
7170
|
await setup;
|
|
7193
7171
|
if (skipSetup) return;
|
|
7194
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
7172
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-VMOTQORT.js");
|
|
7195
7173
|
if (autoRunAfterSetupEnabled()) {
|
|
7196
7174
|
try {
|
|
7197
7175
|
await this.startDev(threadId);
|
|
@@ -7474,17 +7452,21 @@ var Orchestrator = class {
|
|
|
7474
7452
|
const slackReplyContext = formatSlackRepliesForTurn(
|
|
7475
7453
|
pendingSlackExternalReplies(thread.messages)
|
|
7476
7454
|
);
|
|
7477
|
-
const
|
|
7478
|
-
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
7479
|
-
orchestrationReminder,
|
|
7455
|
+
const turnReminders = [
|
|
7480
7456
|
worktreeReminder,
|
|
7481
7457
|
optionalServicesReminder,
|
|
7482
7458
|
issueToolsReminder,
|
|
7483
7459
|
viewerContextReminder,
|
|
7484
7460
|
artifactReminder,
|
|
7485
|
-
longRunningReminder
|
|
7461
|
+
longRunningReminder
|
|
7462
|
+
].filter(Boolean).join("\n\n") || void 0;
|
|
7463
|
+
const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(expandedPrompt) ? formatPrGateDirective() : null;
|
|
7464
|
+
const agentPrompt = [
|
|
7465
|
+
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
7466
|
+
orchestrationReminder,
|
|
7467
|
+
prGateDirective,
|
|
7486
7468
|
slackReplyContext,
|
|
7487
|
-
expandedPrompt
|
|
7469
|
+
expandCanonicalGitRequest(expandedPrompt)
|
|
7488
7470
|
].filter(Boolean).join("\n\n");
|
|
7489
7471
|
if (thread.attachments.length > 0) {
|
|
7490
7472
|
updateThread(threadId, { attachments: [] });
|
|
@@ -7502,7 +7484,7 @@ var Orchestrator = class {
|
|
|
7502
7484
|
}
|
|
7503
7485
|
const isBrightsy = fresh.agent === "brightsy";
|
|
7504
7486
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
7505
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-
|
|
7487
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-VMOTQORT.js");
|
|
7506
7488
|
const gitAuthMode = getGithubGitAuthMode();
|
|
7507
7489
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
7508
7490
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -7574,7 +7556,7 @@ var Orchestrator = class {
|
|
|
7574
7556
|
const stderrTail = [];
|
|
7575
7557
|
const handle = await spawnAgentTurn(
|
|
7576
7558
|
fresh,
|
|
7577
|
-
{ cachedPrefix, prompt: agentPrompt },
|
|
7559
|
+
{ cachedPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
|
|
7578
7560
|
(event) => {
|
|
7579
7561
|
this.emit({ type: "turn_output", threadId, event });
|
|
7580
7562
|
noteTurnLiveEvent(threadId, event);
|
|
@@ -7683,7 +7665,7 @@ var Orchestrator = class {
|
|
|
7683
7665
|
].filter(Boolean).join("\n\n---\n\n");
|
|
7684
7666
|
const retryHandle = await spawnAgentTurn(
|
|
7685
7667
|
retryThread,
|
|
7686
|
-
{ cachedPrefix: retryPrefix, prompt: agentPrompt },
|
|
7668
|
+
{ cachedPrefix: retryPrefix, prompt: agentPrompt, systemPrompt: turnReminders },
|
|
7687
7669
|
(event) => {
|
|
7688
7670
|
this.emit({ type: "turn_output", threadId, event });
|
|
7689
7671
|
if (event.type === "session_id") {
|
|
@@ -8414,7 +8396,7 @@ var Orchestrator = class {
|
|
|
8414
8396
|
updateThread(thread.id, { title: meta.title });
|
|
8415
8397
|
}
|
|
8416
8398
|
}
|
|
8417
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
8399
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-VMOTQORT.js");
|
|
8418
8400
|
const latest = this.requireThread(thread.id);
|
|
8419
8401
|
if (!shouldAutoArchiveOnPrMerge({
|
|
8420
8402
|
previousPrState: prevState || null,
|
|
@@ -8731,7 +8713,7 @@ var Orchestrator = class {
|
|
|
8731
8713
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
8732
8714
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
8733
8715
|
try {
|
|
8734
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
8716
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-A7C3WA54.js");
|
|
8735
8717
|
await ensureWorkspace2(thread.repoPath);
|
|
8736
8718
|
} catch {
|
|
8737
8719
|
}
|
|
@@ -8758,7 +8740,7 @@ var Orchestrator = class {
|
|
|
8758
8740
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
8759
8741
|
} catch {
|
|
8760
8742
|
}
|
|
8761
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
8743
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-VMOTQORT.js");
|
|
8762
8744
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
8763
8745
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
8764
8746
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -8785,7 +8767,7 @@ var Orchestrator = class {
|
|
|
8785
8767
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
8786
8768
|
);
|
|
8787
8769
|
}
|
|
8788
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
8770
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-PODE23PD.js");
|
|
8789
8771
|
const slug = thread.worktreePath.split("/").pop();
|
|
8790
8772
|
const dest = thread.worktreePath;
|
|
8791
8773
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -8895,7 +8877,7 @@ async function startOrchestration(opts) {
|
|
|
8895
8877
|
sourceRef: "default",
|
|
8896
8878
|
...createOpts
|
|
8897
8879
|
}).catch(async () => {
|
|
8898
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
8880
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-PODE23PD.js");
|
|
8899
8881
|
const repo = await resolveRepoRoot2(repoPath);
|
|
8900
8882
|
const def = await resolveDefaultBranch2(repo);
|
|
8901
8883
|
return orch.createThread({
|
|
@@ -8982,6 +8964,8 @@ export {
|
|
|
8982
8964
|
shouldCompactContext,
|
|
8983
8965
|
splitForCompaction,
|
|
8984
8966
|
formatMessagesAsTranscript,
|
|
8967
|
+
SEED_MAX_CHARS,
|
|
8968
|
+
SEED_FULL_TOOL_MESSAGES,
|
|
8985
8969
|
buildSessionSeed,
|
|
8986
8970
|
BRIGHTSY_SUMMARIZE_CONTEXT_TOOL,
|
|
8987
8971
|
extractBrightsyContextSummary,
|
|
@@ -9119,6 +9103,7 @@ export {
|
|
|
9119
9103
|
formatRenameBranchDirective,
|
|
9120
9104
|
formatWorktreeDirective,
|
|
9121
9105
|
formatWorktreeReminder,
|
|
9106
|
+
mentionsPrGoal,
|
|
9122
9107
|
issueTicketFromThread,
|
|
9123
9108
|
linearTicketIdFromThread,
|
|
9124
9109
|
formatIssueToolsDirective,
|
|
@@ -9131,9 +9116,6 @@ export {
|
|
|
9131
9116
|
formatLongRunningReminder,
|
|
9132
9117
|
formatArtifactDirective,
|
|
9133
9118
|
formatUiReminder,
|
|
9134
|
-
loadAgentInstructions,
|
|
9135
|
-
formatAgentInstructions,
|
|
9136
|
-
withAgentInstructions,
|
|
9137
9119
|
OPTIONAL_SERVICE_IDS,
|
|
9138
9120
|
OPTIONAL_SERVICES,
|
|
9139
9121
|
optionalServiceSpec,
|