@sideboard-ai/core 0.1.124 → 0.1.127
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{agents-DPR2TDNF.js → agents-7BUQY2WX.js} +6 -6
- package/dist/{agents-DCXXLTXF.js → agents-X2I3RNCY.js} +6 -6
- package/dist/{app-settings-YFWV7MOG.js → app-settings-6RPALX4J.js} +7 -1
- package/dist/{app-settings-IKFWZDUK.js → app-settings-E7NEQY7D.js} +7 -1
- package/dist/{chunk-SDCPQL27.js → chunk-DLM5LSQW.js} +484 -93
- package/dist/{chunk-RG737OWT.js → chunk-G6X6UFJO.js} +2 -0
- package/dist/{chunk-HPAWHIZ3.js → chunk-HLJUNJBF.js} +2 -0
- package/dist/{chunk-OHEFHIG3.js → chunk-HRSBZIXS.js} +14 -6
- package/dist/{chunk-KWGP6RZM.js → chunk-HULESWLI.js} +4 -4
- package/dist/{chunk-FXQPY2KU.js → chunk-HUYEU4GS.js} +26 -4
- package/dist/{chunk-2X7I6MDW.js → chunk-HZPO3SSZ.js} +11 -8
- package/dist/{chunk-O43IRQ2Y.js → chunk-MNL4FSKY.js} +4 -4
- package/dist/{chunk-7Y3AYQWT.js → chunk-NV73AO7Q.js} +4 -4
- package/dist/{chunk-TRTWH6C2.js → chunk-RSFCB23A.js} +11 -8
- package/dist/{chunk-RBVVWBVB.js → chunk-SYLTXDRF.js} +2 -2
- package/dist/{chunk-MZDAEI3Y.js → chunk-T7KJQJAX.js} +496 -109
- package/dist/{chunk-UAVZ2JSO.js → chunk-UDQI3N47.js} +14 -6
- package/dist/{chunk-HZLE6LJJ.js → chunk-VE22NWBD.js} +2 -2
- package/dist/{chunk-JNAIKICO.js → chunk-ZMUOPTKZ.js} +4 -4
- package/dist/{chunk-BMIRX64H.js → chunk-ZND6XV6J.js} +26 -4
- package/dist/{coordinator-prompt-AZ3WRDNC.js → coordinator-prompt-MEEUOEF2.js} +4 -4
- package/dist/{coordinator-prompt-LEU62W25.js → coordinator-prompt-SPJSGAQS.js} +4 -4
- package/dist/{global-workspace-U5UOVXKQ.js → global-workspace-BMWP7YZC.js} +5 -5
- package/dist/{global-workspace-4YNYDMLQ.js → global-workspace-KNESLWKG.js} +5 -5
- package/dist/index.cjs +1208 -236
- package/dist/index.d.cts +303 -103
- package/dist/index.d.ts +303 -103
- package/dist/index.js +671 -129
- package/dist/mcp/run-stdio.cjs +1054 -194
- package/dist/mcp/run-stdio.js +554 -114
- package/dist/{orchestrator-VJQ5EWZZ.js → orchestrator-3JLPPTCF.js} +8 -8
- package/dist/{orchestrator-JS3EHI4E.js → orchestrator-6GUCE4LY.js} +8 -8
- package/dist/{thread-store-JR235AWK.js → thread-store-5MLYY35S.js} +1 -1
- package/dist/{thread-store-PMH3BMB6.js → thread-store-F6BCARQG.js} +1 -1
- package/dist/{workspaces-ICK433ZV.js → workspaces-HSYRYJYV.js} +6 -6
- package/dist/{workspaces-POWKTH2D.js → workspaces-O4QZOASB.js} +6 -6
- package/dist/{worktree-CMGBTVN4.js → worktree-ERHC7Q4F.js} +5 -3
- package/dist/{worktree-T57RD7BQ.js → worktree-JVGSLSLJ.js} +5 -3
- package/package.json +1 -1
|
@@ -18,13 +18,13 @@ import {
|
|
|
18
18
|
stripBrightsyNdjsonNoise,
|
|
19
19
|
sumUsageList,
|
|
20
20
|
toolDescription
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-NV73AO7Q.js";
|
|
22
22
|
import {
|
|
23
23
|
addWorkspace,
|
|
24
24
|
ensureWorkspace,
|
|
25
25
|
removeWorkspace,
|
|
26
26
|
syncWorkspacesFromThreads
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-VE22NWBD.js";
|
|
28
28
|
import {
|
|
29
29
|
assertOrchestratorCapableAgent,
|
|
30
30
|
coerceOrchestratorAgent,
|
|
@@ -37,14 +37,14 @@ import {
|
|
|
37
37
|
isOrchestratorThread,
|
|
38
38
|
isSlackCoordinatorThread,
|
|
39
39
|
orchestratorSessionPoisonedByBuiltins
|
|
40
|
-
} from "./chunk-
|
|
40
|
+
} from "./chunk-HULESWLI.js";
|
|
41
41
|
import {
|
|
42
42
|
SLACK_REPLY_FORMATTING,
|
|
43
43
|
coordinatorSystemPrompt,
|
|
44
44
|
coordinatorTurnReminder,
|
|
45
45
|
enrichWorkspacesWithGithub,
|
|
46
46
|
ensureGlobalCoordinatorCwd
|
|
47
|
-
} from "./chunk-
|
|
47
|
+
} from "./chunk-HZPO3SSZ.js";
|
|
48
48
|
import {
|
|
49
49
|
extractPresentedPlan,
|
|
50
50
|
readPlanFile,
|
|
@@ -72,6 +72,7 @@ import {
|
|
|
72
72
|
addPrStackLayer,
|
|
73
73
|
allocateTeamName,
|
|
74
74
|
allocateTeamSlug,
|
|
75
|
+
canonicalizeRepoPath,
|
|
75
76
|
commitAll,
|
|
76
77
|
createExistingBranchWorktree,
|
|
77
78
|
createOrUpdatePr,
|
|
@@ -109,8 +110,9 @@ import {
|
|
|
109
110
|
takenSlugsFromThread,
|
|
110
111
|
threadDisplayLabel,
|
|
111
112
|
withRepoGitLock,
|
|
113
|
+
worktreeDisplayLabelForGroup,
|
|
112
114
|
worktreeNameFromPath
|
|
113
|
-
} from "./chunk-
|
|
115
|
+
} from "./chunk-UDQI3N47.js";
|
|
114
116
|
import {
|
|
115
117
|
ATTACHMENTS_DIR,
|
|
116
118
|
LEGACY_ATTACHMENTS_DIR,
|
|
@@ -128,7 +130,7 @@ import {
|
|
|
128
130
|
resolveVaultKey,
|
|
129
131
|
updateAdvancedSettings,
|
|
130
132
|
writeSecureJson
|
|
131
|
-
} from "./chunk-
|
|
133
|
+
} from "./chunk-HUYEU4GS.js";
|
|
132
134
|
import {
|
|
133
135
|
stripNestedElectronEnv
|
|
134
136
|
} from "./chunk-4TR3HZFT.js";
|
|
@@ -146,7 +148,7 @@ import {
|
|
|
146
148
|
updateThread,
|
|
147
149
|
withThreadLock,
|
|
148
150
|
writeThread
|
|
149
|
-
} from "./chunk-
|
|
151
|
+
} from "./chunk-HLJUNJBF.js";
|
|
150
152
|
import {
|
|
151
153
|
appDataDir,
|
|
152
154
|
findConventionSetup,
|
|
@@ -364,26 +366,9 @@ function storePath3() {
|
|
|
364
366
|
function watchId(teamId, channelId, ts) {
|
|
365
367
|
return `${teamId}:${channelId}:${ts}`;
|
|
366
368
|
}
|
|
367
|
-
function badgeId(teamId, userId) {
|
|
368
|
-
return `${teamId}:${userId}`;
|
|
369
|
-
}
|
|
370
369
|
function slackArchiveUrl(channelId, ts) {
|
|
371
370
|
return `https://slack.com/archives/${channelId}/p${ts.replace(".", "")}`;
|
|
372
371
|
}
|
|
373
|
-
function initialsFromName(name) {
|
|
374
|
-
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
375
|
-
if (parts.length === 0) return "?";
|
|
376
|
-
if (parts.length === 1) {
|
|
377
|
-
const w = parts[0];
|
|
378
|
-
return (w.slice(0, 2) || "?").toUpperCase();
|
|
379
|
-
}
|
|
380
|
-
return `${parts[0][0] ?? ""}${parts[parts.length - 1][0] ?? ""}`.toUpperCase();
|
|
381
|
-
}
|
|
382
|
-
function hueFromId(id) {
|
|
383
|
-
let h = 0;
|
|
384
|
-
for (const c of id) h = h * 31 + c.charCodeAt(0) >>> 0;
|
|
385
|
-
return h % 360;
|
|
386
|
-
}
|
|
387
372
|
function tsNewer(a, b) {
|
|
388
373
|
return Number(a) > Number(b);
|
|
389
374
|
}
|
|
@@ -456,7 +441,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
456
441
|
await continueOnReply(threadId, prompt);
|
|
457
442
|
return;
|
|
458
443
|
}
|
|
459
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
444
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-6GUCE4LY.js");
|
|
460
445
|
await getOrchestrator2().send(threadId, prompt);
|
|
461
446
|
} catch {
|
|
462
447
|
}
|
|
@@ -540,7 +525,6 @@ function recordSlackOutboundWatch(input) {
|
|
|
540
525
|
sourceThreadId: input.sourceThreadId?.trim() || void 0,
|
|
541
526
|
postedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
542
527
|
lastSeenTs: ts,
|
|
543
|
-
unread: false,
|
|
544
528
|
permalink: slackArchiveUrl(channelId, ts),
|
|
545
529
|
injectedReplyTs: [],
|
|
546
530
|
replies: []
|
|
@@ -627,49 +611,9 @@ async function fetchMessages(token, watch, fetchImpl) {
|
|
|
627
611
|
}
|
|
628
612
|
return out;
|
|
629
613
|
}
|
|
630
|
-
function
|
|
631
|
-
const unread = readStore3().filter((w) => w.unread && w.replyUserId && w.permalink);
|
|
632
|
-
const byUser = /* @__PURE__ */ new Map();
|
|
633
|
-
for (const w of unread) {
|
|
634
|
-
const id = badgeId(w.teamId, w.replyUserId);
|
|
635
|
-
const prev = byUser.get(id);
|
|
636
|
-
if (!prev || tsNewer(w.replyTs || "", prev.replyTs || "")) {
|
|
637
|
-
byUser.set(id, w);
|
|
638
|
-
}
|
|
639
|
-
}
|
|
640
|
-
return [...byUser.entries()].map(([id, w]) => {
|
|
641
|
-
const userName = w.replyUserName || w.toLabel || "Slack";
|
|
642
|
-
return {
|
|
643
|
-
id,
|
|
644
|
-
userId: w.replyUserId,
|
|
645
|
-
userName,
|
|
646
|
-
initials: initialsFromName(userName),
|
|
647
|
-
hue: hueFromId(w.replyUserId),
|
|
648
|
-
permalink: w.permalink || slackArchiveUrl(w.channelId, w.replyTs || w.ts),
|
|
649
|
-
label: w.toLabel,
|
|
650
|
-
preview: w.replyPreview,
|
|
651
|
-
repliedAt: w.replyTs || w.postedAt
|
|
652
|
-
};
|
|
653
|
-
}).sort((a, b) => b.repliedAt.localeCompare(a.repliedAt));
|
|
654
|
-
}
|
|
655
|
-
function dismissSlackReplyBadge(badgeKey) {
|
|
656
|
-
const key = badgeKey.trim();
|
|
657
|
-
const watches = readStore3().map((w) => {
|
|
658
|
-
if (!w.unread || !w.replyUserId) return w;
|
|
659
|
-
if (badgeId(w.teamId, w.replyUserId) !== key) return w;
|
|
660
|
-
return { ...w, unread: false };
|
|
661
|
-
});
|
|
662
|
-
writeStore2(watches);
|
|
663
|
-
return listSlackReplyBadges();
|
|
664
|
-
}
|
|
665
|
-
function permalinkForSlackReplyBadge(badgeKey) {
|
|
666
|
-
return listSlackReplyBadges().find((b) => b.id === badgeKey)?.permalink ?? null;
|
|
667
|
-
}
|
|
668
|
-
async function refreshSlackReplyBadges(opts) {
|
|
614
|
+
async function pollSlackOutboundWatches(opts) {
|
|
669
615
|
const now = opts?.now ?? Date.now();
|
|
670
|
-
if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS)
|
|
671
|
-
return listSlackReplyBadges();
|
|
672
|
-
}
|
|
616
|
+
if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS) return;
|
|
673
617
|
lastPollMs = now;
|
|
674
618
|
const existing = readStore3();
|
|
675
619
|
let watches = pruneWatches(existing, now);
|
|
@@ -690,9 +634,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
690
634
|
const injected = new Set(watch.injectedReplyTs ?? []);
|
|
691
635
|
const collected = [...watch.replies ?? []];
|
|
692
636
|
let lastSeenTs = watch.lastSeenTs;
|
|
693
|
-
let latestUser;
|
|
694
637
|
let latestName;
|
|
695
|
-
let latestText = "";
|
|
696
638
|
let latestPermalink = watch.permalink;
|
|
697
639
|
let newlyInjected = 0;
|
|
698
640
|
for (const msg of replies) {
|
|
@@ -718,9 +660,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
718
660
|
text: msg.text ?? ""
|
|
719
661
|
};
|
|
720
662
|
if (!collected.some((r) => r.ts === ts)) collected.push(reply);
|
|
721
|
-
latestUser = user;
|
|
722
663
|
latestName = replyUserName;
|
|
723
|
-
latestText = reply.text;
|
|
724
664
|
latestPermalink = permalink;
|
|
725
665
|
if (injected.has(ts)) {
|
|
726
666
|
lastSeenTs = ts;
|
|
@@ -751,11 +691,6 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
751
691
|
watches[i] = {
|
|
752
692
|
...watch,
|
|
753
693
|
lastSeenTs,
|
|
754
|
-
unread: true,
|
|
755
|
-
replyUserId: latestUser,
|
|
756
|
-
replyUserName: latestName,
|
|
757
|
-
replyTs: lastSeenTs,
|
|
758
|
-
replyPreview: latestText.slice(0, 140),
|
|
759
694
|
permalink: latestPermalink,
|
|
760
695
|
injectedReplyTs: [...injected],
|
|
761
696
|
replies: collected.slice(-MAX_REPLIES_PER_WATCH)
|
|
@@ -763,7 +698,6 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
763
698
|
changed = true;
|
|
764
699
|
}
|
|
765
700
|
if (changed) writeStore2(watches);
|
|
766
|
-
return listSlackReplyBadges();
|
|
767
701
|
}
|
|
768
702
|
|
|
769
703
|
// src/orchestrator/orchestrator.ts
|
|
@@ -787,9 +721,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
787
721
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
788
722
|
);
|
|
789
723
|
}
|
|
790
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
724
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-BMWP7YZC.js");
|
|
791
725
|
if (isGlobalThread2(thread)) {
|
|
792
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
726
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-MEEUOEF2.js");
|
|
793
727
|
ensureGlobalCoordinatorCwd2(
|
|
794
728
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
795
729
|
);
|
|
@@ -1355,6 +1289,7 @@ function worktreeBindingFrom(from) {
|
|
|
1355
1289
|
prUrl: from.prUrl,
|
|
1356
1290
|
prTitle: from.prTitle,
|
|
1357
1291
|
prState: from.prState,
|
|
1292
|
+
prIsDraft: from.prIsDraft,
|
|
1358
1293
|
skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
|
|
1359
1294
|
stackId: from.stackId,
|
|
1360
1295
|
stackLayer: from.stackLayer,
|
|
@@ -2362,8 +2297,425 @@ async function requireAgent(agent, opts) {
|
|
|
2362
2297
|
return status;
|
|
2363
2298
|
}
|
|
2364
2299
|
|
|
2300
|
+
// src/board/home-board.ts
|
|
2301
|
+
var GLOBAL_WORKSPACE_ID = "__global__";
|
|
2302
|
+
function isHomeBoardThread(thread) {
|
|
2303
|
+
if (thread.sourceType === "orchestration") return false;
|
|
2304
|
+
if (thread.repoPath === GLOBAL_WORKSPACE_ID) return false;
|
|
2305
|
+
return true;
|
|
2306
|
+
}
|
|
2307
|
+
var BOARD_COLUMN_DEFS = [
|
|
2308
|
+
{ id: "new", title: "New" },
|
|
2309
|
+
{ id: "draft", title: "Draft" },
|
|
2310
|
+
{ id: "review", title: "Review" },
|
|
2311
|
+
{ id: "done", title: "Merged" }
|
|
2312
|
+
];
|
|
2313
|
+
var HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
|
|
2314
|
+
function isOpenPrState(prUrl, prState) {
|
|
2315
|
+
if (!prUrl?.trim()) return false;
|
|
2316
|
+
const state = (prState ?? "OPEN").trim().toUpperCase();
|
|
2317
|
+
return state !== "MERGED" && state !== "CLOSED";
|
|
2318
|
+
}
|
|
2319
|
+
function isMergedPrState(prUrl, prState) {
|
|
2320
|
+
if (!prUrl?.trim()) return false;
|
|
2321
|
+
return (prState ?? "").trim().toUpperCase() === "MERGED";
|
|
2322
|
+
}
|
|
2323
|
+
function groupHomeBoardWorktrees(threads) {
|
|
2324
|
+
const map = /* @__PURE__ */ new Map();
|
|
2325
|
+
for (const t of threads) {
|
|
2326
|
+
const key = normalizeWorktreePath(t.worktreePath);
|
|
2327
|
+
const list = map.get(key) ?? [];
|
|
2328
|
+
list.push(t);
|
|
2329
|
+
map.set(key, list);
|
|
2330
|
+
}
|
|
2331
|
+
return [...map.values()].map((list) => list.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))).sort((a, b) => (b[0]?.updatedAt ?? "").localeCompare(a[0]?.updatedAt ?? ""));
|
|
2332
|
+
}
|
|
2333
|
+
function classifyWorktreeColumn(group) {
|
|
2334
|
+
if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
|
|
2335
|
+
if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && !t.prIsDraft)) {
|
|
2336
|
+
return "review";
|
|
2337
|
+
}
|
|
2338
|
+
if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && t.prIsDraft)) {
|
|
2339
|
+
return "draft";
|
|
2340
|
+
}
|
|
2341
|
+
return "new";
|
|
2342
|
+
}
|
|
2343
|
+
function worktreeBoardStatus(group) {
|
|
2344
|
+
const order = ["running", "queued", "error", "broken"];
|
|
2345
|
+
for (const status of order) {
|
|
2346
|
+
if (group.some((t) => t.status === status)) return status;
|
|
2347
|
+
}
|
|
2348
|
+
return group[0]?.status ?? "idle";
|
|
2349
|
+
}
|
|
2350
|
+
function normalizeIssueKey(value) {
|
|
2351
|
+
return value.trim().toLowerCase().replace(/^#/, "");
|
|
2352
|
+
}
|
|
2353
|
+
function threadMatchesIssue(thread, issue) {
|
|
2354
|
+
const identRaw = issue.identifier.trim().toLowerCase();
|
|
2355
|
+
const identKey = normalizeIssueKey(issue.identifier);
|
|
2356
|
+
const title = issue.title.trim().toLowerCase();
|
|
2357
|
+
const refRaw = (thread.sourceRef ?? "").trim().toLowerCase();
|
|
2358
|
+
const refKey = normalizeIssueKey(thread.sourceRef ?? "");
|
|
2359
|
+
const threadTitle = (thread.title ?? "").trim().toLowerCase();
|
|
2360
|
+
if (thread.sourceType === "ticket" && identKey && refKey === identKey) return true;
|
|
2361
|
+
if (identRaw && (refRaw === identRaw || threadTitle.includes(identRaw))) return true;
|
|
2362
|
+
if (title && threadTitle === title) return true;
|
|
2363
|
+
return false;
|
|
2364
|
+
}
|
|
2365
|
+
function dedupeBoardIssues(issues) {
|
|
2366
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2367
|
+
const out = [];
|
|
2368
|
+
for (const issue of issues) {
|
|
2369
|
+
const key = [
|
|
2370
|
+
issue.repoPath,
|
|
2371
|
+
issue.provider ?? "",
|
|
2372
|
+
issue.id || issue.identifier
|
|
2373
|
+
].join(":");
|
|
2374
|
+
if (seen.has(key)) continue;
|
|
2375
|
+
seen.add(key);
|
|
2376
|
+
out.push(issue);
|
|
2377
|
+
}
|
|
2378
|
+
return out;
|
|
2379
|
+
}
|
|
2380
|
+
function issueNeedsWorkspacePick(provider, workspaceCount) {
|
|
2381
|
+
if (workspaceCount <= 1) return false;
|
|
2382
|
+
return provider !== "github";
|
|
2383
|
+
}
|
|
2384
|
+
function boardPrKey(pr) {
|
|
2385
|
+
return pr.url?.trim() || `${pr.repoPath}::${pr.number}`;
|
|
2386
|
+
}
|
|
2387
|
+
function urlsMatch(a, b) {
|
|
2388
|
+
const norm = (u) => u.trim().replace(/\/+$/, "").toLowerCase();
|
|
2389
|
+
return Boolean(a && b && norm(a) === norm(b));
|
|
2390
|
+
}
|
|
2391
|
+
function threadMatchesPr(thread, pr) {
|
|
2392
|
+
const num = String(pr.number);
|
|
2393
|
+
if (thread.sourceType === "pr" && normalizeIssueKey(thread.sourceRef ?? "") === num) {
|
|
2394
|
+
return true;
|
|
2395
|
+
}
|
|
2396
|
+
if (thread.prUrl && pr.url && urlsMatch(thread.prUrl, pr.url)) return true;
|
|
2397
|
+
const head = pr.headRefName.trim().toLowerCase();
|
|
2398
|
+
if (!head) return false;
|
|
2399
|
+
const branch = (thread.branchName ?? "").trim().toLowerCase();
|
|
2400
|
+
const ref = (thread.sourceRef ?? "").trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "").toLowerCase();
|
|
2401
|
+
if (branch === head) return true;
|
|
2402
|
+
if (!ref || /^(main|master|develop|development|trunk|default|head)$/.test(ref)) {
|
|
2403
|
+
return false;
|
|
2404
|
+
}
|
|
2405
|
+
return ref === head;
|
|
2406
|
+
}
|
|
2407
|
+
function normalizeBranchRef(value) {
|
|
2408
|
+
return value.trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "").toLowerCase();
|
|
2409
|
+
}
|
|
2410
|
+
function threadMatchesBranch(thread, pin) {
|
|
2411
|
+
if (pin.repoPath && thread.repoPath && pin.repoPath !== thread.repoPath) return false;
|
|
2412
|
+
const head = normalizeBranchRef(pin.ref === "default" ? "" : pin.ref);
|
|
2413
|
+
if (!head) {
|
|
2414
|
+
return thread.sourceType === "branch" && pin.repoPath === thread.repoPath;
|
|
2415
|
+
}
|
|
2416
|
+
const branch = normalizeBranchRef(thread.branchName ?? "");
|
|
2417
|
+
const ref = normalizeBranchRef(thread.sourceRef ?? "");
|
|
2418
|
+
return branch === head || ref === head;
|
|
2419
|
+
}
|
|
2420
|
+
function sameRepoPath(a, b) {
|
|
2421
|
+
return a.replace(/\/+$/, "") === b.replace(/\/+$/, "");
|
|
2422
|
+
}
|
|
2423
|
+
var DEFAULTISH_BRANCH = /^(main|master|develop|development|trunk|default|head)$/;
|
|
2424
|
+
function isDefaultBranchCreateRef(ref) {
|
|
2425
|
+
const head = normalizeBranchRef(ref);
|
|
2426
|
+
return !head || DEFAULTISH_BRANCH.test(head);
|
|
2427
|
+
}
|
|
2428
|
+
function findLiveThreadForCreate(input, threads) {
|
|
2429
|
+
const live = threads.filter(
|
|
2430
|
+
(t) => t.status !== "archived" && sameRepoPath(t.repoPath, input.repoPath)
|
|
2431
|
+
);
|
|
2432
|
+
if (input.cowboy) {
|
|
2433
|
+
return live.find((t) => t.cowboy);
|
|
2434
|
+
}
|
|
2435
|
+
if (input.sourceType === "ticket") {
|
|
2436
|
+
return live.find(
|
|
2437
|
+
(t) => threadMatchesIssue(t, {
|
|
2438
|
+
identifier: input.sourceRef,
|
|
2439
|
+
title: input.title ?? ""
|
|
2440
|
+
})
|
|
2441
|
+
);
|
|
2442
|
+
}
|
|
2443
|
+
if (input.sourceType === "pr") {
|
|
2444
|
+
const number = Number(normalizeIssueKey(input.sourceRef));
|
|
2445
|
+
return live.find(
|
|
2446
|
+
(t) => threadMatchesPr(t, {
|
|
2447
|
+
number: Number.isFinite(number) ? number : -1,
|
|
2448
|
+
title: input.title ?? "",
|
|
2449
|
+
url: "",
|
|
2450
|
+
headRefName: ""
|
|
2451
|
+
})
|
|
2452
|
+
);
|
|
2453
|
+
}
|
|
2454
|
+
if (input.sourceType === "branch") {
|
|
2455
|
+
if (isDefaultBranchCreateRef(input.sourceRef)) return void 0;
|
|
2456
|
+
return live.find(
|
|
2457
|
+
(t) => threadMatchesBranch(t, {
|
|
2458
|
+
ref: input.sourceRef,
|
|
2459
|
+
repoPath: input.repoPath
|
|
2460
|
+
})
|
|
2461
|
+
);
|
|
2462
|
+
}
|
|
2463
|
+
return void 0;
|
|
2464
|
+
}
|
|
2465
|
+
function boardPinIdentity(pin) {
|
|
2466
|
+
const ref = normalizeIssueKey(pin.ref);
|
|
2467
|
+
if (pin.kind === "ticket" && (pin.provider === "linear" || !pin.repoPath)) {
|
|
2468
|
+
return `ticket:account:${ref}`;
|
|
2469
|
+
}
|
|
2470
|
+
return `${pin.kind}:${pin.repoPath}:${ref}`;
|
|
2471
|
+
}
|
|
2472
|
+
function findBoardPin(pins, kind, ref, repoPath = "") {
|
|
2473
|
+
const key = normalizeIssueKey(ref);
|
|
2474
|
+
const matches = pins.filter(
|
|
2475
|
+
(pin) => pin.kind === kind && normalizeIssueKey(pin.ref) === key
|
|
2476
|
+
);
|
|
2477
|
+
if (repoPath) {
|
|
2478
|
+
const scoped = matches.filter((pin) => pin.repoPath === repoPath);
|
|
2479
|
+
if (scoped[0]) return scoped[0];
|
|
2480
|
+
}
|
|
2481
|
+
return matches[0];
|
|
2482
|
+
}
|
|
2483
|
+
function syncBoardPins(pins, issues, prs) {
|
|
2484
|
+
return pins.map((pin) => {
|
|
2485
|
+
if (pin.kind === "ticket") {
|
|
2486
|
+
const issue = findBoardIssue(issues, pin.ref, pin.repoPath);
|
|
2487
|
+
if (!issue) {
|
|
2488
|
+
return { ...pin, remoteState: pin.remoteState || "stale" };
|
|
2489
|
+
}
|
|
2490
|
+
return {
|
|
2491
|
+
...pin,
|
|
2492
|
+
title: issue.title || pin.title,
|
|
2493
|
+
url: issue.url || pin.url,
|
|
2494
|
+
labels: issue.labels,
|
|
2495
|
+
provider: issue.provider ?? pin.provider,
|
|
2496
|
+
assignee: issue.assignee ?? pin.assignee,
|
|
2497
|
+
cycle: issue.cycle?.name ?? pin.cycle,
|
|
2498
|
+
teamKey: issue.teamKey ?? pin.teamKey,
|
|
2499
|
+
remoteState: "open",
|
|
2500
|
+
needsWorkspacePick: issue.needsWorkspacePick
|
|
2501
|
+
};
|
|
2502
|
+
}
|
|
2503
|
+
if (pin.kind === "pr") {
|
|
2504
|
+
const pr = findBoardPr(prs, pin.ref, pin.repoPath);
|
|
2505
|
+
if (!pr) {
|
|
2506
|
+
return { ...pin, remoteState: pin.remoteState === "open" ? "stale" : pin.remoteState || "stale" };
|
|
2507
|
+
}
|
|
2508
|
+
return {
|
|
2509
|
+
...pin,
|
|
2510
|
+
title: pr.title || pin.title,
|
|
2511
|
+
url: pr.url || pin.url,
|
|
2512
|
+
headRefName: pr.headRefName || pin.headRefName,
|
|
2513
|
+
author: prAuthorLogin(pr) || pin.author,
|
|
2514
|
+
remoteState: "open"
|
|
2515
|
+
};
|
|
2516
|
+
}
|
|
2517
|
+
return pin;
|
|
2518
|
+
});
|
|
2519
|
+
}
|
|
2520
|
+
function dedupeBoardPrs(prs) {
|
|
2521
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2522
|
+
const out = [];
|
|
2523
|
+
for (const pr of prs) {
|
|
2524
|
+
const key = boardPrKey(pr);
|
|
2525
|
+
if (seen.has(key)) continue;
|
|
2526
|
+
seen.add(key);
|
|
2527
|
+
out.push(pr);
|
|
2528
|
+
}
|
|
2529
|
+
return out.sort((a, b) => b.number - a.number);
|
|
2530
|
+
}
|
|
2531
|
+
var BOARD_PAGE_SIZE = 40;
|
|
2532
|
+
function tokenizeQuery(query) {
|
|
2533
|
+
return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
2534
|
+
}
|
|
2535
|
+
function haystackMatches(haystack, tokens) {
|
|
2536
|
+
if (tokens.length === 0) return true;
|
|
2537
|
+
const h = haystack.toLowerCase();
|
|
2538
|
+
return tokens.every((token) => h.includes(token));
|
|
2539
|
+
}
|
|
2540
|
+
function prAuthorLogin(pr) {
|
|
2541
|
+
return pr.author?.login?.trim() ?? "";
|
|
2542
|
+
}
|
|
2543
|
+
function threadSearchText(thread, workspaceName = "") {
|
|
2544
|
+
return [
|
|
2545
|
+
thread.title,
|
|
2546
|
+
thread.sourceRef,
|
|
2547
|
+
thread.sourceType,
|
|
2548
|
+
thread.agent,
|
|
2549
|
+
thread.status,
|
|
2550
|
+
thread.branchName,
|
|
2551
|
+
thread.prUrl ?? "",
|
|
2552
|
+
workspaceName,
|
|
2553
|
+
thread.repoPath
|
|
2554
|
+
].join(" ");
|
|
2555
|
+
}
|
|
2556
|
+
function inWorkspace(repoPath, filterRepoPath) {
|
|
2557
|
+
if (!filterRepoPath) return true;
|
|
2558
|
+
return repoPath === filterRepoPath;
|
|
2559
|
+
}
|
|
2560
|
+
function visiblePage(items, shown) {
|
|
2561
|
+
const n = Math.max(0, shown);
|
|
2562
|
+
return {
|
|
2563
|
+
visible: items.slice(0, n),
|
|
2564
|
+
hidden: Math.max(0, items.length - n)
|
|
2565
|
+
};
|
|
2566
|
+
}
|
|
2567
|
+
function emptyColumns() {
|
|
2568
|
+
return {
|
|
2569
|
+
backlog: [],
|
|
2570
|
+
queued: [],
|
|
2571
|
+
running: [],
|
|
2572
|
+
new: [],
|
|
2573
|
+
draft: [],
|
|
2574
|
+
review: [],
|
|
2575
|
+
done: []
|
|
2576
|
+
};
|
|
2577
|
+
}
|
|
2578
|
+
function emptyHidden() {
|
|
2579
|
+
return {
|
|
2580
|
+
backlog: 0,
|
|
2581
|
+
queued: 0,
|
|
2582
|
+
running: 0,
|
|
2583
|
+
new: 0,
|
|
2584
|
+
draft: 0,
|
|
2585
|
+
review: 0,
|
|
2586
|
+
done: 0
|
|
2587
|
+
};
|
|
2588
|
+
}
|
|
2589
|
+
function findBoardIssue(issues, ref, repoPath = "") {
|
|
2590
|
+
const key = normalizeIssueKey(ref);
|
|
2591
|
+
if (!key) return void 0;
|
|
2592
|
+
const matches = issues.filter((issue) => normalizeIssueKey(issue.identifier) === key);
|
|
2593
|
+
if (repoPath) {
|
|
2594
|
+
const scoped = matches.filter((issue) => issue.repoPath === repoPath);
|
|
2595
|
+
if (scoped[0]) return scoped[0];
|
|
2596
|
+
}
|
|
2597
|
+
return matches[0];
|
|
2598
|
+
}
|
|
2599
|
+
function findBoardPr(prs, ref, repoPath = "") {
|
|
2600
|
+
const num = Number(normalizeIssueKey(ref));
|
|
2601
|
+
if (!Number.isFinite(num)) return void 0;
|
|
2602
|
+
const matches = prs.filter((pr) => pr.number === num);
|
|
2603
|
+
if (repoPath) {
|
|
2604
|
+
const scoped = matches.filter((pr) => pr.repoPath === repoPath);
|
|
2605
|
+
if (scoped[0]) return scoped[0];
|
|
2606
|
+
}
|
|
2607
|
+
return matches[0];
|
|
2608
|
+
}
|
|
2609
|
+
function toThreadCard(group) {
|
|
2610
|
+
const thread = group[0];
|
|
2611
|
+
const withPr = group.find((t) => t.prUrl?.trim()) ?? thread;
|
|
2612
|
+
return {
|
|
2613
|
+
kind: "thread",
|
|
2614
|
+
id: thread.id,
|
|
2615
|
+
title: worktreeDisplayLabelForGroup(group),
|
|
2616
|
+
status: worktreeBoardStatus(group),
|
|
2617
|
+
agent: thread.agent,
|
|
2618
|
+
sourceType: thread.sourceType,
|
|
2619
|
+
sourceRef: thread.sourceRef,
|
|
2620
|
+
repoPath: thread.repoPath,
|
|
2621
|
+
prUrl: withPr.prUrl,
|
|
2622
|
+
link: `sideboard://thread/${thread.id}`,
|
|
2623
|
+
...group.length > 1 ? { chatCount: group.length } : {}
|
|
2624
|
+
};
|
|
2625
|
+
}
|
|
2626
|
+
function threadMatchesKind(thread, kind) {
|
|
2627
|
+
if (kind === "all" || kind === "threads") return true;
|
|
2628
|
+
if (kind === "tickets") return thread.sourceType === "ticket";
|
|
2629
|
+
if (kind === "prs") return thread.sourceType === "pr";
|
|
2630
|
+
if (kind === "branches") return thread.sourceType === "branch" || thread.sourceType === "adopt";
|
|
2631
|
+
return true;
|
|
2632
|
+
}
|
|
2633
|
+
function assembleHomeBoard(input) {
|
|
2634
|
+
const tokens = tokenizeQuery(input.query ?? "");
|
|
2635
|
+
const repo = input.repoPath?.trim() ?? "";
|
|
2636
|
+
const kind = input.kind ?? "all";
|
|
2637
|
+
const limit = Math.max(1, input.limit ?? BOARD_PAGE_SIZE);
|
|
2638
|
+
const wsName = input.workspaceName ?? (() => "");
|
|
2639
|
+
const byUpdated = (a, b) => b.updatedAt.localeCompare(a.updatedAt);
|
|
2640
|
+
const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t)).sort(byUpdated);
|
|
2641
|
+
const columns = emptyColumns();
|
|
2642
|
+
const hidden = emptyHidden();
|
|
2643
|
+
const totals = {
|
|
2644
|
+
backlog: 0,
|
|
2645
|
+
queued: 0,
|
|
2646
|
+
running: 0,
|
|
2647
|
+
new: 0,
|
|
2648
|
+
draft: 0,
|
|
2649
|
+
review: 0,
|
|
2650
|
+
done: 0,
|
|
2651
|
+
tickets: 0,
|
|
2652
|
+
prs: 0,
|
|
2653
|
+
branches: 0,
|
|
2654
|
+
threads: 0
|
|
2655
|
+
};
|
|
2656
|
+
const byCol = {
|
|
2657
|
+
queued: [],
|
|
2658
|
+
running: [],
|
|
2659
|
+
new: [],
|
|
2660
|
+
draft: [],
|
|
2661
|
+
review: [],
|
|
2662
|
+
done: []
|
|
2663
|
+
};
|
|
2664
|
+
for (const group of groupHomeBoardWorktrees(live)) {
|
|
2665
|
+
if (!group.some((t) => threadMatchesKind(t, kind))) continue;
|
|
2666
|
+
const col = classifyWorktreeColumn(group);
|
|
2667
|
+
if (col === "backlog") continue;
|
|
2668
|
+
const primary = group[0];
|
|
2669
|
+
if (!inWorkspace(primary.repoPath, repo)) continue;
|
|
2670
|
+
const hay = group.map((t) => threadSearchText(t, wsName(t.repoPath))).join(" ");
|
|
2671
|
+
if (!haystackMatches(hay, tokens)) continue;
|
|
2672
|
+
byCol[col].push(group);
|
|
2673
|
+
}
|
|
2674
|
+
const flat = [...Object.values(byCol)].flatMap((groups) => groups.map((g) => g[0]));
|
|
2675
|
+
totals.tickets = flat.filter((t) => t.sourceType === "ticket").length;
|
|
2676
|
+
totals.prs = flat.filter((t) => t.sourceType === "pr").length;
|
|
2677
|
+
totals.branches = flat.filter((t) => t.sourceType === "branch" || t.sourceType === "adopt").length;
|
|
2678
|
+
totals.threads = Object.values(byCol).reduce((n, list) => n + list.length, 0);
|
|
2679
|
+
for (const col of Object.keys(byCol)) {
|
|
2680
|
+
const cards = byCol[col].map(toThreadCard);
|
|
2681
|
+
totals[col] = cards.length;
|
|
2682
|
+
const page = visiblePage(cards, limit);
|
|
2683
|
+
columns[col] = page.visible;
|
|
2684
|
+
hidden[col] = page.hidden;
|
|
2685
|
+
}
|
|
2686
|
+
if (input.column) {
|
|
2687
|
+
for (const col of Object.keys(columns)) {
|
|
2688
|
+
if (col === input.column) continue;
|
|
2689
|
+
columns[col] = [];
|
|
2690
|
+
hidden[col] = 0;
|
|
2691
|
+
}
|
|
2692
|
+
}
|
|
2693
|
+
return { columns, hidden, totals };
|
|
2694
|
+
}
|
|
2695
|
+
var HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). create_thread reuses a live worktree for the same ticket, PR, or named branch \u2014 do not recreate it. Columns are the path to merge: New (no PR) \u2192 Draft (draft PR) \u2192 Review (open PR) \u2192 Merged. Archive removes the card to Settings \u2192 History. Queued/running are activity on the card, not columns. Orchestration chats stay in the sidebar. Do not invent status.";
|
|
2696
|
+
|
|
2365
2697
|
// src/threads/create.ts
|
|
2366
2698
|
async function createThread(input, _onSetupLine) {
|
|
2699
|
+
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
2700
|
+
if (!existsSync7(repoPath)) {
|
|
2701
|
+
throw new Error(`Repo not found: ${repoPath}`);
|
|
2702
|
+
}
|
|
2703
|
+
if (input.reuseExisting !== false) {
|
|
2704
|
+
const existing = findLiveThreadForCreate(
|
|
2705
|
+
{
|
|
2706
|
+
sourceType: input.sourceType,
|
|
2707
|
+
sourceRef: input.sourceRef,
|
|
2708
|
+
repoPath,
|
|
2709
|
+
title: input.title,
|
|
2710
|
+
cowboy: input.cowboy
|
|
2711
|
+
},
|
|
2712
|
+
listThreads({ includeArchived: false }).map((t) => ({
|
|
2713
|
+
...t,
|
|
2714
|
+
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
2715
|
+
}))
|
|
2716
|
+
);
|
|
2717
|
+
if (existing) return readThread(existing.id) ?? existing;
|
|
2718
|
+
}
|
|
2367
2719
|
const resolved = resolveNewThreadOptions({
|
|
2368
2720
|
agent: input.agent,
|
|
2369
2721
|
model: input.model,
|
|
@@ -2371,12 +2723,8 @@ async function createThread(input, _onSetupLine) {
|
|
|
2371
2723
|
fast: input.fast
|
|
2372
2724
|
});
|
|
2373
2725
|
await requireAgent(resolved.agent);
|
|
2374
|
-
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
2375
|
-
if (!existsSync7(repoPath)) {
|
|
2376
|
-
throw new Error(`Repo not found: ${repoPath}`);
|
|
2377
|
-
}
|
|
2378
2726
|
if (input.cowboy) {
|
|
2379
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
2727
|
+
const { cowboyModeEnabled } = await import("./app-settings-6RPALX4J.js");
|
|
2380
2728
|
if (!cowboyModeEnabled()) {
|
|
2381
2729
|
throw new Error(
|
|
2382
2730
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -2487,7 +2835,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2487
2835
|
return readThread(thread.id) ?? thread;
|
|
2488
2836
|
}
|
|
2489
2837
|
async function listLinearIssues(agent, repoPath) {
|
|
2490
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
2838
|
+
const { getAdapter: getAdapter2 } = await import("./agents-X2I3RNCY.js");
|
|
2491
2839
|
await requireAgent(agent, { requireLinear: true });
|
|
2492
2840
|
const adapter = getAdapter2(agent);
|
|
2493
2841
|
if (!adapter.listLinearIssues) {
|
|
@@ -2673,7 +3021,8 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
2673
3021
|
planMode: from.planMode,
|
|
2674
3022
|
title: input.title?.trim() || void 0,
|
|
2675
3023
|
parentThreadId: from.id,
|
|
2676
|
-
attachments: [attachment]
|
|
3024
|
+
attachments: [attachment],
|
|
3025
|
+
reuseExisting: false
|
|
2677
3026
|
},
|
|
2678
3027
|
onSetupLine
|
|
2679
3028
|
);
|
|
@@ -2753,7 +3102,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
2753
3102
|
"",
|
|
2754
3103
|
`## Instructions`,
|
|
2755
3104
|
`- Continue fleet orchestration from this handoff.`,
|
|
2756
|
-
`- Prefer Sideboard MCP (list_threads, get_thread, send_to_thread, \u2026) for live status.`,
|
|
3105
|
+
`- Prefer Sideboard MCP (list_board, list_threads, get_thread, send_to_thread, \u2026) for live status.`,
|
|
2757
3106
|
`- Leave model Auto unless there is a specific reason to pin one.`,
|
|
2758
3107
|
`- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
|
|
2759
3108
|
].join("\n");
|
|
@@ -2766,9 +3115,9 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
2766
3115
|
}
|
|
2767
3116
|
var QUOTA_CONTINUE_PROMPT = (fromAgent, fallback) => [
|
|
2768
3117
|
`${fromAgent} hit a session/usage limit. Continue this orchestration on ${fallback} using the attached handoff.`,
|
|
2769
|
-
"Call list_threads for live fleet status, then proceed with the goal. Leave model Auto unless needed."
|
|
3118
|
+
"Call list_board or list_threads for live fleet status, then proceed with the goal. Leave model Auto unless needed."
|
|
2770
3119
|
].join(" ");
|
|
2771
|
-
var QUOTA_RESUME_PROMPT = "Session/usage limit window should have reset. Continue the orchestration from where you left off. Use list_threads for fleet status.";
|
|
3120
|
+
var QUOTA_RESUME_PROMPT = "Session/usage limit window should have reset. Continue the orchestration from where you left off. Use list_board or list_threads for fleet status.";
|
|
2772
3121
|
function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
2773
3122
|
const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
|
|
2774
3123
|
const tab = createChatTab({
|
|
@@ -2883,7 +3232,7 @@ async function adoptThread(input) {
|
|
|
2883
3232
|
messages: input.messages ?? []
|
|
2884
3233
|
});
|
|
2885
3234
|
writeThread(thread);
|
|
2886
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
3235
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-O4QZOASB.js");
|
|
2887
3236
|
await ensureWorkspace2(repoPath);
|
|
2888
3237
|
return thread;
|
|
2889
3238
|
}
|
|
@@ -5156,7 +5505,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
5156
5505
|
${prompt}`;
|
|
5157
5506
|
}
|
|
5158
5507
|
async function defaultDeps() {
|
|
5159
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
5508
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-6GUCE4LY.js");
|
|
5160
5509
|
const orch = getOrchestrator2();
|
|
5161
5510
|
return {
|
|
5162
5511
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -5310,7 +5659,7 @@ var Orchestrator = class {
|
|
|
5310
5659
|
maxConcurrent;
|
|
5311
5660
|
runningCount = 0;
|
|
5312
5661
|
constructor(opts) {
|
|
5313
|
-
this.maxConcurrent = opts?.maxConcurrent ??
|
|
5662
|
+
this.maxConcurrent = opts?.maxConcurrent ?? 5;
|
|
5314
5663
|
}
|
|
5315
5664
|
on(listener) {
|
|
5316
5665
|
this.events.on("event", listener);
|
|
@@ -5376,7 +5725,7 @@ var Orchestrator = class {
|
|
|
5376
5725
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
5377
5726
|
});
|
|
5378
5727
|
}
|
|
5379
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
5728
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-6RPALX4J.js");
|
|
5380
5729
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
5381
5730
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
5382
5731
|
}
|
|
@@ -5527,7 +5876,23 @@ var Orchestrator = class {
|
|
|
5527
5876
|
return findThreadByRef(idOrRef) ?? readThread(idOrRef);
|
|
5528
5877
|
}
|
|
5529
5878
|
async createThread(input) {
|
|
5879
|
+
const prior = new Set(
|
|
5880
|
+
listThreads({ includeArchived: false }).map((t) => t.id)
|
|
5881
|
+
);
|
|
5530
5882
|
const thread = await createThread(input);
|
|
5883
|
+
if (prior.has(thread.id)) {
|
|
5884
|
+
if (input.prompt?.trim()) {
|
|
5885
|
+
try {
|
|
5886
|
+
await this.send(thread.id, input.prompt.trim());
|
|
5887
|
+
} catch (err) {
|
|
5888
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
5889
|
+
updateThread(thread.id, {
|
|
5890
|
+
lastError: `First prompt failed: ${message}`
|
|
5891
|
+
});
|
|
5892
|
+
}
|
|
5893
|
+
}
|
|
5894
|
+
return thread;
|
|
5895
|
+
}
|
|
5531
5896
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
5532
5897
|
void this.finishCreateThread(thread.id, input.prompt?.trim() || void 0);
|
|
5533
5898
|
return thread;
|
|
@@ -5548,7 +5913,7 @@ var Orchestrator = class {
|
|
|
5548
5913
|
}
|
|
5549
5914
|
await setup;
|
|
5550
5915
|
if (skipSetup) return;
|
|
5551
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
5916
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-6RPALX4J.js");
|
|
5552
5917
|
if (autoRunAfterSetupEnabled()) {
|
|
5553
5918
|
try {
|
|
5554
5919
|
await this.startDev(threadId);
|
|
@@ -5833,7 +6198,7 @@ var Orchestrator = class {
|
|
|
5833
6198
|
}
|
|
5834
6199
|
const isBrightsy = fresh.agent === "brightsy";
|
|
5835
6200
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
5836
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-
|
|
6201
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-6RPALX4J.js");
|
|
5837
6202
|
const gitAuthMode = getGithubGitAuthMode();
|
|
5838
6203
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
5839
6204
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -6370,7 +6735,8 @@ var Orchestrator = class {
|
|
|
6370
6735
|
agent,
|
|
6371
6736
|
repoPath: opts.repoPath,
|
|
6372
6737
|
title: opts.title ? `${opts.title} (${agent})` : `best-of-n: ${opts.prompt.slice(0, 48)} (${agent})`,
|
|
6373
|
-
prompt: opts.prompt
|
|
6738
|
+
prompt: opts.prompt,
|
|
6739
|
+
reuseExisting: false
|
|
6374
6740
|
});
|
|
6375
6741
|
created.push(thread);
|
|
6376
6742
|
}
|
|
@@ -6607,6 +6973,8 @@ var Orchestrator = class {
|
|
|
6607
6973
|
if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
|
|
6608
6974
|
if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
|
|
6609
6975
|
if (nextState && nextState !== prevState) patch.prState = nextState;
|
|
6976
|
+
const nextDraft = Boolean(meta.isDraft) && nextState !== "MERGED" && nextState !== "CLOSED";
|
|
6977
|
+
if (nextDraft !== Boolean(thread.prIsDraft)) patch.prIsDraft = nextDraft;
|
|
6610
6978
|
if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
|
|
6611
6979
|
patch.skipAutoArchiveOnMerge = false;
|
|
6612
6980
|
}
|
|
@@ -6617,7 +6985,7 @@ var Orchestrator = class {
|
|
|
6617
6985
|
updateThread(thread.id, { title: meta.title });
|
|
6618
6986
|
}
|
|
6619
6987
|
}
|
|
6620
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
6988
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-6RPALX4J.js");
|
|
6621
6989
|
const latest = this.requireThread(thread.id);
|
|
6622
6990
|
if (!shouldAutoArchiveOnPrMerge({
|
|
6623
6991
|
previousPrState: prevState || null,
|
|
@@ -6631,7 +6999,7 @@ var Orchestrator = class {
|
|
|
6631
6999
|
}
|
|
6632
7000
|
const siblings = threadsSharingWorktree(latest.worktreePath);
|
|
6633
7001
|
for (const t of siblings) {
|
|
6634
|
-
const sibPatch = { prState: "MERGED" };
|
|
7002
|
+
const sibPatch = { prState: "MERGED", prIsDraft: false };
|
|
6635
7003
|
if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
|
|
6636
7004
|
if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
|
|
6637
7005
|
if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
|
|
@@ -6805,10 +7173,15 @@ var Orchestrator = class {
|
|
|
6805
7173
|
web: action === "create-web"
|
|
6806
7174
|
});
|
|
6807
7175
|
if (!url) return;
|
|
6808
|
-
const patch = {
|
|
7176
|
+
const patch = {
|
|
7177
|
+
prUrl: url,
|
|
7178
|
+
prTitle: meta.title,
|
|
7179
|
+
prIsDraft: action === "create-draft"
|
|
7180
|
+
};
|
|
6809
7181
|
try {
|
|
6810
7182
|
const fetched = await getPrMeta(cwd, url);
|
|
6811
7183
|
if (fetched?.title) patch.prTitle = fetched.title;
|
|
7184
|
+
if (fetched) patch.prIsDraft = Boolean(fetched.isDraft);
|
|
6812
7185
|
} catch {
|
|
6813
7186
|
}
|
|
6814
7187
|
updateThread(thread.id, patch);
|
|
@@ -6922,7 +7295,7 @@ var Orchestrator = class {
|
|
|
6922
7295
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
6923
7296
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
6924
7297
|
try {
|
|
6925
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
7298
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-O4QZOASB.js");
|
|
6926
7299
|
await ensureWorkspace2(thread.repoPath);
|
|
6927
7300
|
} catch {
|
|
6928
7301
|
}
|
|
@@ -6949,7 +7322,7 @@ var Orchestrator = class {
|
|
|
6949
7322
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
6950
7323
|
} catch {
|
|
6951
7324
|
}
|
|
6952
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
7325
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-6RPALX4J.js");
|
|
6953
7326
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
6954
7327
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
6955
7328
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -6976,7 +7349,7 @@ var Orchestrator = class {
|
|
|
6976
7349
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
6977
7350
|
);
|
|
6978
7351
|
}
|
|
6979
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
7352
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-JVGSLSLJ.js");
|
|
6980
7353
|
const slug = thread.worktreePath.split("/").pop();
|
|
6981
7354
|
const dest = thread.worktreePath;
|
|
6982
7355
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -7084,7 +7457,7 @@ async function startOrchestration(opts) {
|
|
|
7084
7457
|
sourceRef: "default",
|
|
7085
7458
|
...createOpts
|
|
7086
7459
|
}).catch(async () => {
|
|
7087
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
7460
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-JVGSLSLJ.js");
|
|
7088
7461
|
const repo = await resolveRepoRoot2(repoPath);
|
|
7089
7462
|
const def = await resolveDefaultBranch2(repo);
|
|
7090
7463
|
return orch.createThread({
|
|
@@ -7094,7 +7467,7 @@ async function startOrchestration(opts) {
|
|
|
7094
7467
|
repoPath: repo
|
|
7095
7468
|
});
|
|
7096
7469
|
});
|
|
7097
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
7470
|
+
const { updateThread: upd } = await import("./thread-store-5MLYY35S.js");
|
|
7098
7471
|
const updated = upd(thread.id, {
|
|
7099
7472
|
sourceType: "orchestration",
|
|
7100
7473
|
sourceRef: goal
|
|
@@ -7145,10 +7518,7 @@ export {
|
|
|
7145
7518
|
formatSlackReplyContinuePrompt,
|
|
7146
7519
|
listSlackOutboundWatches,
|
|
7147
7520
|
recordSlackOutboundWatch,
|
|
7148
|
-
|
|
7149
|
-
dismissSlackReplyBadge,
|
|
7150
|
-
permalinkForSlackReplyBadge,
|
|
7151
|
-
refreshSlackReplyBadges,
|
|
7521
|
+
pollSlackOutboundWatches,
|
|
7152
7522
|
applyPromptCacheTtlEnv,
|
|
7153
7523
|
spawnAgentTurn,
|
|
7154
7524
|
AGENT_GIT_ACTIONS,
|
|
@@ -7219,6 +7589,23 @@ export {
|
|
|
7219
7589
|
cloneRepoIntoSideboard,
|
|
7220
7590
|
detectAgents,
|
|
7221
7591
|
requireAgent,
|
|
7592
|
+
isHomeBoardThread,
|
|
7593
|
+
BOARD_COLUMN_DEFS,
|
|
7594
|
+
HOME_BOARD_CACHE_TTL_MS,
|
|
7595
|
+
groupHomeBoardWorktrees,
|
|
7596
|
+
classifyWorktreeColumn,
|
|
7597
|
+
worktreeBoardStatus,
|
|
7598
|
+
dedupeBoardIssues,
|
|
7599
|
+
issueNeedsWorkspacePick,
|
|
7600
|
+
findLiveThreadForCreate,
|
|
7601
|
+
boardPinIdentity,
|
|
7602
|
+
findBoardPin,
|
|
7603
|
+
syncBoardPins,
|
|
7604
|
+
dedupeBoardPrs,
|
|
7605
|
+
findBoardIssue,
|
|
7606
|
+
findBoardPr,
|
|
7607
|
+
assembleHomeBoard,
|
|
7608
|
+
HOME_BOARD_AGENT_HINT,
|
|
7222
7609
|
createThread,
|
|
7223
7610
|
listLinearIssues,
|
|
7224
7611
|
isCowboyThread,
|