@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
|
@@ -29,13 +29,13 @@ import {
|
|
|
29
29
|
summarizeTurnStderr,
|
|
30
30
|
toolDescription,
|
|
31
31
|
turnFailChatText
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-ZMUOPTKZ.js";
|
|
33
33
|
import {
|
|
34
34
|
addWorkspace,
|
|
35
35
|
ensureWorkspace,
|
|
36
36
|
removeWorkspace,
|
|
37
37
|
syncWorkspacesFromThreads
|
|
38
|
-
} from "./chunk-
|
|
38
|
+
} from "./chunk-SYLTXDRF.js";
|
|
39
39
|
import {
|
|
40
40
|
extractPresentedPlan,
|
|
41
41
|
readPlanFile,
|
|
@@ -56,18 +56,19 @@ import {
|
|
|
56
56
|
isOrchestratorThread,
|
|
57
57
|
isSlackCoordinatorThread,
|
|
58
58
|
orchestratorSessionPoisonedByBuiltins
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-MNL4FSKY.js";
|
|
60
60
|
import {
|
|
61
61
|
SLACK_REPLY_FORMATTING,
|
|
62
62
|
coordinatorSystemPrompt,
|
|
63
63
|
coordinatorTurnReminder,
|
|
64
64
|
enrichWorkspacesWithGithub,
|
|
65
65
|
ensureGlobalCoordinatorCwd
|
|
66
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-RSFCB23A.js";
|
|
67
67
|
import {
|
|
68
68
|
addPrStackLayer,
|
|
69
69
|
allocateTeamName,
|
|
70
70
|
allocateTeamSlug,
|
|
71
|
+
canonicalizeRepoPath,
|
|
71
72
|
commitAll,
|
|
72
73
|
createExistingBranchWorktree,
|
|
73
74
|
createOrUpdatePr,
|
|
@@ -105,8 +106,9 @@ import {
|
|
|
105
106
|
takenSlugsFromThread,
|
|
106
107
|
threadDisplayLabel,
|
|
107
108
|
withRepoGitLock,
|
|
109
|
+
worktreeDisplayLabelForGroup,
|
|
108
110
|
worktreeNameFromPath
|
|
109
|
-
} from "./chunk-
|
|
111
|
+
} from "./chunk-HRSBZIXS.js";
|
|
110
112
|
import {
|
|
111
113
|
ATTACHMENTS_DIR,
|
|
112
114
|
LEGACY_ATTACHMENTS_DIR,
|
|
@@ -123,7 +125,7 @@ import {
|
|
|
123
125
|
updateThread,
|
|
124
126
|
withThreadLock,
|
|
125
127
|
writeThread
|
|
126
|
-
} from "./chunk-
|
|
128
|
+
} from "./chunk-G6X6UFJO.js";
|
|
127
129
|
import {
|
|
128
130
|
clearStaleIndexLocks,
|
|
129
131
|
enrichPathWithNpmGlobalBin,
|
|
@@ -145,7 +147,7 @@ import {
|
|
|
145
147
|
stripNestedElectronEnv,
|
|
146
148
|
updateAdvancedSettings,
|
|
147
149
|
writeSecureJson
|
|
148
|
-
} from "./chunk-
|
|
150
|
+
} from "./chunk-ZND6XV6J.js";
|
|
149
151
|
import {
|
|
150
152
|
writePrivateFile
|
|
151
153
|
} from "./chunk-NSTQ6QKD.js";
|
|
@@ -303,26 +305,9 @@ function storePath3() {
|
|
|
303
305
|
function watchId(teamId, channelId, ts) {
|
|
304
306
|
return `${teamId}:${channelId}:${ts}`;
|
|
305
307
|
}
|
|
306
|
-
function badgeId(teamId, userId) {
|
|
307
|
-
return `${teamId}:${userId}`;
|
|
308
|
-
}
|
|
309
308
|
function slackArchiveUrl(channelId, ts) {
|
|
310
309
|
return `https://slack.com/archives/${channelId}/p${ts.replace(".", "")}`;
|
|
311
310
|
}
|
|
312
|
-
function initialsFromName(name) {
|
|
313
|
-
const parts = name.trim().split(/\s+/).filter(Boolean);
|
|
314
|
-
if (parts.length === 0) return "?";
|
|
315
|
-
if (parts.length === 1) {
|
|
316
|
-
const w = parts[0];
|
|
317
|
-
return (w.slice(0, 2) || "?").toUpperCase();
|
|
318
|
-
}
|
|
319
|
-
return `${parts[0][0] ?? ""}${parts[parts.length - 1][0] ?? ""}`.toUpperCase();
|
|
320
|
-
}
|
|
321
|
-
function hueFromId(id) {
|
|
322
|
-
let h = 0;
|
|
323
|
-
for (const c of id) h = h * 31 + c.charCodeAt(0) >>> 0;
|
|
324
|
-
return h % 360;
|
|
325
|
-
}
|
|
326
311
|
function tsNewer(a, b) {
|
|
327
312
|
return Number(a) > Number(b);
|
|
328
313
|
}
|
|
@@ -395,7 +380,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
395
380
|
await continueOnReply(threadId, prompt);
|
|
396
381
|
return;
|
|
397
382
|
}
|
|
398
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
383
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-3JLPPTCF.js");
|
|
399
384
|
await getOrchestrator2().send(threadId, prompt);
|
|
400
385
|
} catch {
|
|
401
386
|
}
|
|
@@ -479,7 +464,6 @@ function recordSlackOutboundWatch(input) {
|
|
|
479
464
|
sourceThreadId: input.sourceThreadId?.trim() || void 0,
|
|
480
465
|
postedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
481
466
|
lastSeenTs: ts,
|
|
482
|
-
unread: false,
|
|
483
467
|
permalink: slackArchiveUrl(channelId, ts),
|
|
484
468
|
injectedReplyTs: [],
|
|
485
469
|
replies: []
|
|
@@ -566,36 +550,9 @@ async function fetchMessages(token, watch, fetchImpl) {
|
|
|
566
550
|
}
|
|
567
551
|
return out;
|
|
568
552
|
}
|
|
569
|
-
function
|
|
570
|
-
const unread = readStore3().filter((w) => w.unread && w.replyUserId && w.permalink);
|
|
571
|
-
const byUser = /* @__PURE__ */ new Map();
|
|
572
|
-
for (const w of unread) {
|
|
573
|
-
const id = badgeId(w.teamId, w.replyUserId);
|
|
574
|
-
const prev = byUser.get(id);
|
|
575
|
-
if (!prev || tsNewer(w.replyTs || "", prev.replyTs || "")) {
|
|
576
|
-
byUser.set(id, w);
|
|
577
|
-
}
|
|
578
|
-
}
|
|
579
|
-
return [...byUser.entries()].map(([id, w]) => {
|
|
580
|
-
const userName = w.replyUserName || w.toLabel || "Slack";
|
|
581
|
-
return {
|
|
582
|
-
id,
|
|
583
|
-
userId: w.replyUserId,
|
|
584
|
-
userName,
|
|
585
|
-
initials: initialsFromName(userName),
|
|
586
|
-
hue: hueFromId(w.replyUserId),
|
|
587
|
-
permalink: w.permalink || slackArchiveUrl(w.channelId, w.replyTs || w.ts),
|
|
588
|
-
label: w.toLabel,
|
|
589
|
-
preview: w.replyPreview,
|
|
590
|
-
repliedAt: w.replyTs || w.postedAt
|
|
591
|
-
};
|
|
592
|
-
}).sort((a, b) => b.repliedAt.localeCompare(a.repliedAt));
|
|
593
|
-
}
|
|
594
|
-
async function refreshSlackReplyBadges(opts) {
|
|
553
|
+
async function pollSlackOutboundWatches(opts) {
|
|
595
554
|
const now = opts?.now ?? Date.now();
|
|
596
|
-
if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS)
|
|
597
|
-
return listSlackReplyBadges();
|
|
598
|
-
}
|
|
555
|
+
if (!opts?.force && now - lastPollMs < POLL_INTERVAL_MS) return;
|
|
599
556
|
lastPollMs = now;
|
|
600
557
|
const existing = readStore3();
|
|
601
558
|
let watches = pruneWatches(existing, now);
|
|
@@ -616,9 +573,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
616
573
|
const injected = new Set(watch.injectedReplyTs ?? []);
|
|
617
574
|
const collected = [...watch.replies ?? []];
|
|
618
575
|
let lastSeenTs = watch.lastSeenTs;
|
|
619
|
-
let latestUser;
|
|
620
576
|
let latestName;
|
|
621
|
-
let latestText = "";
|
|
622
577
|
let latestPermalink = watch.permalink;
|
|
623
578
|
let newlyInjected = 0;
|
|
624
579
|
for (const msg of replies) {
|
|
@@ -644,9 +599,7 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
644
599
|
text: msg.text ?? ""
|
|
645
600
|
};
|
|
646
601
|
if (!collected.some((r) => r.ts === ts)) collected.push(reply);
|
|
647
|
-
latestUser = user;
|
|
648
602
|
latestName = replyUserName;
|
|
649
|
-
latestText = reply.text;
|
|
650
603
|
latestPermalink = permalink;
|
|
651
604
|
if (injected.has(ts)) {
|
|
652
605
|
lastSeenTs = ts;
|
|
@@ -677,11 +630,6 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
677
630
|
watches[i] = {
|
|
678
631
|
...watch,
|
|
679
632
|
lastSeenTs,
|
|
680
|
-
unread: true,
|
|
681
|
-
replyUserId: latestUser,
|
|
682
|
-
replyUserName: latestName,
|
|
683
|
-
replyTs: lastSeenTs,
|
|
684
|
-
replyPreview: latestText.slice(0, 140),
|
|
685
633
|
permalink: latestPermalink,
|
|
686
634
|
injectedReplyTs: [...injected],
|
|
687
635
|
replies: collected.slice(-MAX_REPLIES_PER_WATCH)
|
|
@@ -689,7 +637,6 @@ async function refreshSlackReplyBadges(opts) {
|
|
|
689
637
|
changed = true;
|
|
690
638
|
}
|
|
691
639
|
if (changed) writeStore(watches);
|
|
692
|
-
return listSlackReplyBadges();
|
|
693
640
|
}
|
|
694
641
|
|
|
695
642
|
// src/orchestrator/orchestrator.ts
|
|
@@ -774,9 +721,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
774
721
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
775
722
|
);
|
|
776
723
|
}
|
|
777
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
724
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-KNESLWKG.js");
|
|
778
725
|
if (isGlobalThread2(thread)) {
|
|
779
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
726
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-SPJSGAQS.js");
|
|
780
727
|
ensureGlobalCoordinatorCwd2(
|
|
781
728
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
782
729
|
);
|
|
@@ -1342,6 +1289,7 @@ function worktreeBindingFrom(from) {
|
|
|
1342
1289
|
prUrl: from.prUrl,
|
|
1343
1290
|
prTitle: from.prTitle,
|
|
1344
1291
|
prState: from.prState,
|
|
1292
|
+
prIsDraft: from.prIsDraft,
|
|
1345
1293
|
skipAutoArchiveOnMerge: from.skipAutoArchiveOnMerge,
|
|
1346
1294
|
stackId: from.stackId,
|
|
1347
1295
|
stackLayer: from.stackLayer,
|
|
@@ -2317,8 +2265,418 @@ async function requireAgent(agent, opts) {
|
|
|
2317
2265
|
return status;
|
|
2318
2266
|
}
|
|
2319
2267
|
|
|
2268
|
+
// src/board/home-board.ts
|
|
2269
|
+
var GLOBAL_WORKSPACE_ID = "__global__";
|
|
2270
|
+
function isHomeBoardThread(thread) {
|
|
2271
|
+
if (thread.sourceType === "orchestration") return false;
|
|
2272
|
+
if (thread.repoPath === GLOBAL_WORKSPACE_ID) return false;
|
|
2273
|
+
return true;
|
|
2274
|
+
}
|
|
2275
|
+
var BOARD_COLUMN_DEFS = [
|
|
2276
|
+
{ id: "new", title: "New" },
|
|
2277
|
+
{ id: "draft", title: "Draft" },
|
|
2278
|
+
{ id: "review", title: "Review" },
|
|
2279
|
+
{ id: "done", title: "Merged" }
|
|
2280
|
+
];
|
|
2281
|
+
var HOME_BOARD_CACHE_TTL_MS = 15 * 60 * 1e3;
|
|
2282
|
+
function isOpenPrState(prUrl, prState) {
|
|
2283
|
+
if (!prUrl?.trim()) return false;
|
|
2284
|
+
const state = (prState ?? "OPEN").trim().toUpperCase();
|
|
2285
|
+
return state !== "MERGED" && state !== "CLOSED";
|
|
2286
|
+
}
|
|
2287
|
+
function isMergedPrState(prUrl, prState) {
|
|
2288
|
+
if (!prUrl?.trim()) return false;
|
|
2289
|
+
return (prState ?? "").trim().toUpperCase() === "MERGED";
|
|
2290
|
+
}
|
|
2291
|
+
function groupHomeBoardWorktrees(threads) {
|
|
2292
|
+
const map = /* @__PURE__ */ new Map();
|
|
2293
|
+
for (const t of threads) {
|
|
2294
|
+
const key = normalizeWorktreePath(t.worktreePath);
|
|
2295
|
+
const list = map.get(key) ?? [];
|
|
2296
|
+
list.push(t);
|
|
2297
|
+
map.set(key, list);
|
|
2298
|
+
}
|
|
2299
|
+
return [...map.values()].map((list) => list.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt))).sort((a, b) => (b[0]?.updatedAt ?? "").localeCompare(a[0]?.updatedAt ?? ""));
|
|
2300
|
+
}
|
|
2301
|
+
function classifyWorktreeColumn(group) {
|
|
2302
|
+
if (group.some((t) => isMergedPrState(t.prUrl, t.prState))) return "done";
|
|
2303
|
+
if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && !t.prIsDraft)) {
|
|
2304
|
+
return "review";
|
|
2305
|
+
}
|
|
2306
|
+
if (group.some((t) => isOpenPrState(t.prUrl, t.prState) && t.prIsDraft)) {
|
|
2307
|
+
return "draft";
|
|
2308
|
+
}
|
|
2309
|
+
return "new";
|
|
2310
|
+
}
|
|
2311
|
+
function worktreeBoardStatus(group) {
|
|
2312
|
+
const order = ["running", "queued", "error", "broken"];
|
|
2313
|
+
for (const status of order) {
|
|
2314
|
+
if (group.some((t) => t.status === status)) return status;
|
|
2315
|
+
}
|
|
2316
|
+
return group[0]?.status ?? "idle";
|
|
2317
|
+
}
|
|
2318
|
+
function normalizeIssueKey(value) {
|
|
2319
|
+
return value.trim().toLowerCase().replace(/^#/, "");
|
|
2320
|
+
}
|
|
2321
|
+
function threadMatchesIssue(thread, issue) {
|
|
2322
|
+
const identRaw = issue.identifier.trim().toLowerCase();
|
|
2323
|
+
const identKey = normalizeIssueKey(issue.identifier);
|
|
2324
|
+
const title = issue.title.trim().toLowerCase();
|
|
2325
|
+
const refRaw = (thread.sourceRef ?? "").trim().toLowerCase();
|
|
2326
|
+
const refKey = normalizeIssueKey(thread.sourceRef ?? "");
|
|
2327
|
+
const threadTitle = (thread.title ?? "").trim().toLowerCase();
|
|
2328
|
+
if (thread.sourceType === "ticket" && identKey && refKey === identKey) return true;
|
|
2329
|
+
if (identRaw && (refRaw === identRaw || threadTitle.includes(identRaw))) return true;
|
|
2330
|
+
if (title && threadTitle === title) return true;
|
|
2331
|
+
return false;
|
|
2332
|
+
}
|
|
2333
|
+
function dedupeBoardIssues(issues) {
|
|
2334
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2335
|
+
const out = [];
|
|
2336
|
+
for (const issue of issues) {
|
|
2337
|
+
const key = [
|
|
2338
|
+
issue.repoPath,
|
|
2339
|
+
issue.provider ?? "",
|
|
2340
|
+
issue.id || issue.identifier
|
|
2341
|
+
].join(":");
|
|
2342
|
+
if (seen.has(key)) continue;
|
|
2343
|
+
seen.add(key);
|
|
2344
|
+
out.push(issue);
|
|
2345
|
+
}
|
|
2346
|
+
return out;
|
|
2347
|
+
}
|
|
2348
|
+
function issueNeedsWorkspacePick(provider, workspaceCount) {
|
|
2349
|
+
if (workspaceCount <= 1) return false;
|
|
2350
|
+
return provider !== "github";
|
|
2351
|
+
}
|
|
2352
|
+
function boardPrKey(pr) {
|
|
2353
|
+
return pr.url?.trim() || `${pr.repoPath}::${pr.number}`;
|
|
2354
|
+
}
|
|
2355
|
+
function urlsMatch(a, b) {
|
|
2356
|
+
const norm = (u) => u.trim().replace(/\/+$/, "").toLowerCase();
|
|
2357
|
+
return Boolean(a && b && norm(a) === norm(b));
|
|
2358
|
+
}
|
|
2359
|
+
function threadMatchesPr(thread, pr) {
|
|
2360
|
+
const num = String(pr.number);
|
|
2361
|
+
if (thread.sourceType === "pr" && normalizeIssueKey(thread.sourceRef ?? "") === num) {
|
|
2362
|
+
return true;
|
|
2363
|
+
}
|
|
2364
|
+
if (thread.prUrl && pr.url && urlsMatch(thread.prUrl, pr.url)) return true;
|
|
2365
|
+
const head = pr.headRefName.trim().toLowerCase();
|
|
2366
|
+
if (!head) return false;
|
|
2367
|
+
const branch = (thread.branchName ?? "").trim().toLowerCase();
|
|
2368
|
+
const ref = (thread.sourceRef ?? "").trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "").toLowerCase();
|
|
2369
|
+
if (branch === head) return true;
|
|
2370
|
+
if (!ref || /^(main|master|develop|development|trunk|default|head)$/.test(ref)) {
|
|
2371
|
+
return false;
|
|
2372
|
+
}
|
|
2373
|
+
return ref === head;
|
|
2374
|
+
}
|
|
2375
|
+
function normalizeBranchRef(value) {
|
|
2376
|
+
return value.trim().replace(/^refs\/heads\//, "").replace(/^origin\//, "").toLowerCase();
|
|
2377
|
+
}
|
|
2378
|
+
function threadMatchesBranch(thread, pin) {
|
|
2379
|
+
if (pin.repoPath && thread.repoPath && pin.repoPath !== thread.repoPath) return false;
|
|
2380
|
+
const head = normalizeBranchRef(pin.ref === "default" ? "" : pin.ref);
|
|
2381
|
+
if (!head) {
|
|
2382
|
+
return thread.sourceType === "branch" && pin.repoPath === thread.repoPath;
|
|
2383
|
+
}
|
|
2384
|
+
const branch = normalizeBranchRef(thread.branchName ?? "");
|
|
2385
|
+
const ref = normalizeBranchRef(thread.sourceRef ?? "");
|
|
2386
|
+
return branch === head || ref === head;
|
|
2387
|
+
}
|
|
2388
|
+
function sameRepoPath(a, b) {
|
|
2389
|
+
return a.replace(/\/+$/, "") === b.replace(/\/+$/, "");
|
|
2390
|
+
}
|
|
2391
|
+
var DEFAULTISH_BRANCH = /^(main|master|develop|development|trunk|default|head)$/;
|
|
2392
|
+
function isDefaultBranchCreateRef(ref) {
|
|
2393
|
+
const head = normalizeBranchRef(ref);
|
|
2394
|
+
return !head || DEFAULTISH_BRANCH.test(head);
|
|
2395
|
+
}
|
|
2396
|
+
function findLiveThreadForCreate(input, threads) {
|
|
2397
|
+
const live = threads.filter(
|
|
2398
|
+
(t) => t.status !== "archived" && sameRepoPath(t.repoPath, input.repoPath)
|
|
2399
|
+
);
|
|
2400
|
+
if (input.cowboy) {
|
|
2401
|
+
return live.find((t) => t.cowboy);
|
|
2402
|
+
}
|
|
2403
|
+
if (input.sourceType === "ticket") {
|
|
2404
|
+
return live.find(
|
|
2405
|
+
(t) => threadMatchesIssue(t, {
|
|
2406
|
+
identifier: input.sourceRef,
|
|
2407
|
+
title: input.title ?? ""
|
|
2408
|
+
})
|
|
2409
|
+
);
|
|
2410
|
+
}
|
|
2411
|
+
if (input.sourceType === "pr") {
|
|
2412
|
+
const number = Number(normalizeIssueKey(input.sourceRef));
|
|
2413
|
+
return live.find(
|
|
2414
|
+
(t) => threadMatchesPr(t, {
|
|
2415
|
+
number: Number.isFinite(number) ? number : -1,
|
|
2416
|
+
title: input.title ?? "",
|
|
2417
|
+
url: "",
|
|
2418
|
+
headRefName: ""
|
|
2419
|
+
})
|
|
2420
|
+
);
|
|
2421
|
+
}
|
|
2422
|
+
if (input.sourceType === "branch") {
|
|
2423
|
+
if (isDefaultBranchCreateRef(input.sourceRef)) return void 0;
|
|
2424
|
+
return live.find(
|
|
2425
|
+
(t) => threadMatchesBranch(t, {
|
|
2426
|
+
ref: input.sourceRef,
|
|
2427
|
+
repoPath: input.repoPath
|
|
2428
|
+
})
|
|
2429
|
+
);
|
|
2430
|
+
}
|
|
2431
|
+
return void 0;
|
|
2432
|
+
}
|
|
2433
|
+
function findBoardPin(pins, kind, ref, repoPath = "") {
|
|
2434
|
+
const key = normalizeIssueKey(ref);
|
|
2435
|
+
const matches = pins.filter(
|
|
2436
|
+
(pin) => pin.kind === kind && normalizeIssueKey(pin.ref) === key
|
|
2437
|
+
);
|
|
2438
|
+
if (repoPath) {
|
|
2439
|
+
const scoped = matches.filter((pin) => pin.repoPath === repoPath);
|
|
2440
|
+
if (scoped[0]) return scoped[0];
|
|
2441
|
+
}
|
|
2442
|
+
return matches[0];
|
|
2443
|
+
}
|
|
2444
|
+
function syncBoardPins(pins, issues, prs) {
|
|
2445
|
+
return pins.map((pin) => {
|
|
2446
|
+
if (pin.kind === "ticket") {
|
|
2447
|
+
const issue = findBoardIssue(issues, pin.ref, pin.repoPath);
|
|
2448
|
+
if (!issue) {
|
|
2449
|
+
return { ...pin, remoteState: pin.remoteState || "stale" };
|
|
2450
|
+
}
|
|
2451
|
+
return {
|
|
2452
|
+
...pin,
|
|
2453
|
+
title: issue.title || pin.title,
|
|
2454
|
+
url: issue.url || pin.url,
|
|
2455
|
+
labels: issue.labels,
|
|
2456
|
+
provider: issue.provider ?? pin.provider,
|
|
2457
|
+
assignee: issue.assignee ?? pin.assignee,
|
|
2458
|
+
cycle: issue.cycle?.name ?? pin.cycle,
|
|
2459
|
+
teamKey: issue.teamKey ?? pin.teamKey,
|
|
2460
|
+
remoteState: "open",
|
|
2461
|
+
needsWorkspacePick: issue.needsWorkspacePick
|
|
2462
|
+
};
|
|
2463
|
+
}
|
|
2464
|
+
if (pin.kind === "pr") {
|
|
2465
|
+
const pr = findBoardPr(prs, pin.ref, pin.repoPath);
|
|
2466
|
+
if (!pr) {
|
|
2467
|
+
return { ...pin, remoteState: pin.remoteState === "open" ? "stale" : pin.remoteState || "stale" };
|
|
2468
|
+
}
|
|
2469
|
+
return {
|
|
2470
|
+
...pin,
|
|
2471
|
+
title: pr.title || pin.title,
|
|
2472
|
+
url: pr.url || pin.url,
|
|
2473
|
+
headRefName: pr.headRefName || pin.headRefName,
|
|
2474
|
+
author: prAuthorLogin(pr) || pin.author,
|
|
2475
|
+
remoteState: "open"
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
return pin;
|
|
2479
|
+
});
|
|
2480
|
+
}
|
|
2481
|
+
function dedupeBoardPrs(prs) {
|
|
2482
|
+
const seen = /* @__PURE__ */ new Set();
|
|
2483
|
+
const out = [];
|
|
2484
|
+
for (const pr of prs) {
|
|
2485
|
+
const key = boardPrKey(pr);
|
|
2486
|
+
if (seen.has(key)) continue;
|
|
2487
|
+
seen.add(key);
|
|
2488
|
+
out.push(pr);
|
|
2489
|
+
}
|
|
2490
|
+
return out.sort((a, b) => b.number - a.number);
|
|
2491
|
+
}
|
|
2492
|
+
var BOARD_PAGE_SIZE = 40;
|
|
2493
|
+
function tokenizeQuery(query) {
|
|
2494
|
+
return query.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
2495
|
+
}
|
|
2496
|
+
function haystackMatches(haystack, tokens) {
|
|
2497
|
+
if (tokens.length === 0) return true;
|
|
2498
|
+
const h = haystack.toLowerCase();
|
|
2499
|
+
return tokens.every((token) => h.includes(token));
|
|
2500
|
+
}
|
|
2501
|
+
function prAuthorLogin(pr) {
|
|
2502
|
+
return pr.author?.login?.trim() ?? "";
|
|
2503
|
+
}
|
|
2504
|
+
function threadSearchText(thread, workspaceName = "") {
|
|
2505
|
+
return [
|
|
2506
|
+
thread.title,
|
|
2507
|
+
thread.sourceRef,
|
|
2508
|
+
thread.sourceType,
|
|
2509
|
+
thread.agent,
|
|
2510
|
+
thread.status,
|
|
2511
|
+
thread.branchName,
|
|
2512
|
+
thread.prUrl ?? "",
|
|
2513
|
+
workspaceName,
|
|
2514
|
+
thread.repoPath
|
|
2515
|
+
].join(" ");
|
|
2516
|
+
}
|
|
2517
|
+
function inWorkspace(repoPath, filterRepoPath) {
|
|
2518
|
+
if (!filterRepoPath) return true;
|
|
2519
|
+
return repoPath === filterRepoPath;
|
|
2520
|
+
}
|
|
2521
|
+
function visiblePage(items, shown) {
|
|
2522
|
+
const n = Math.max(0, shown);
|
|
2523
|
+
return {
|
|
2524
|
+
visible: items.slice(0, n),
|
|
2525
|
+
hidden: Math.max(0, items.length - n)
|
|
2526
|
+
};
|
|
2527
|
+
}
|
|
2528
|
+
function emptyColumns() {
|
|
2529
|
+
return {
|
|
2530
|
+
backlog: [],
|
|
2531
|
+
queued: [],
|
|
2532
|
+
running: [],
|
|
2533
|
+
new: [],
|
|
2534
|
+
draft: [],
|
|
2535
|
+
review: [],
|
|
2536
|
+
done: []
|
|
2537
|
+
};
|
|
2538
|
+
}
|
|
2539
|
+
function emptyHidden() {
|
|
2540
|
+
return {
|
|
2541
|
+
backlog: 0,
|
|
2542
|
+
queued: 0,
|
|
2543
|
+
running: 0,
|
|
2544
|
+
new: 0,
|
|
2545
|
+
draft: 0,
|
|
2546
|
+
review: 0,
|
|
2547
|
+
done: 0
|
|
2548
|
+
};
|
|
2549
|
+
}
|
|
2550
|
+
function findBoardIssue(issues, ref, repoPath = "") {
|
|
2551
|
+
const key = normalizeIssueKey(ref);
|
|
2552
|
+
if (!key) return void 0;
|
|
2553
|
+
const matches = issues.filter((issue) => normalizeIssueKey(issue.identifier) === key);
|
|
2554
|
+
if (repoPath) {
|
|
2555
|
+
const scoped = matches.filter((issue) => issue.repoPath === repoPath);
|
|
2556
|
+
if (scoped[0]) return scoped[0];
|
|
2557
|
+
}
|
|
2558
|
+
return matches[0];
|
|
2559
|
+
}
|
|
2560
|
+
function findBoardPr(prs, ref, repoPath = "") {
|
|
2561
|
+
const num = Number(normalizeIssueKey(ref));
|
|
2562
|
+
if (!Number.isFinite(num)) return void 0;
|
|
2563
|
+
const matches = prs.filter((pr) => pr.number === num);
|
|
2564
|
+
if (repoPath) {
|
|
2565
|
+
const scoped = matches.filter((pr) => pr.repoPath === repoPath);
|
|
2566
|
+
if (scoped[0]) return scoped[0];
|
|
2567
|
+
}
|
|
2568
|
+
return matches[0];
|
|
2569
|
+
}
|
|
2570
|
+
function toThreadCard(group) {
|
|
2571
|
+
const thread = group[0];
|
|
2572
|
+
const withPr = group.find((t) => t.prUrl?.trim()) ?? thread;
|
|
2573
|
+
return {
|
|
2574
|
+
kind: "thread",
|
|
2575
|
+
id: thread.id,
|
|
2576
|
+
title: worktreeDisplayLabelForGroup(group),
|
|
2577
|
+
status: worktreeBoardStatus(group),
|
|
2578
|
+
agent: thread.agent,
|
|
2579
|
+
sourceType: thread.sourceType,
|
|
2580
|
+
sourceRef: thread.sourceRef,
|
|
2581
|
+
repoPath: thread.repoPath,
|
|
2582
|
+
prUrl: withPr.prUrl,
|
|
2583
|
+
link: `sideboard://thread/${thread.id}`,
|
|
2584
|
+
...group.length > 1 ? { chatCount: group.length } : {}
|
|
2585
|
+
};
|
|
2586
|
+
}
|
|
2587
|
+
function threadMatchesKind(thread, kind) {
|
|
2588
|
+
if (kind === "all" || kind === "threads") return true;
|
|
2589
|
+
if (kind === "tickets") return thread.sourceType === "ticket";
|
|
2590
|
+
if (kind === "prs") return thread.sourceType === "pr";
|
|
2591
|
+
if (kind === "branches") return thread.sourceType === "branch" || thread.sourceType === "adopt";
|
|
2592
|
+
return true;
|
|
2593
|
+
}
|
|
2594
|
+
function assembleHomeBoard(input) {
|
|
2595
|
+
const tokens = tokenizeQuery(input.query ?? "");
|
|
2596
|
+
const repo = input.repoPath?.trim() ?? "";
|
|
2597
|
+
const kind = input.kind ?? "all";
|
|
2598
|
+
const limit = Math.max(1, input.limit ?? BOARD_PAGE_SIZE);
|
|
2599
|
+
const wsName = input.workspaceName ?? (() => "");
|
|
2600
|
+
const byUpdated = (a, b) => b.updatedAt.localeCompare(a.updatedAt);
|
|
2601
|
+
const live = input.threads.filter((t) => t.status !== "archived" && isHomeBoardThread(t)).sort(byUpdated);
|
|
2602
|
+
const columns = emptyColumns();
|
|
2603
|
+
const hidden = emptyHidden();
|
|
2604
|
+
const totals = {
|
|
2605
|
+
backlog: 0,
|
|
2606
|
+
queued: 0,
|
|
2607
|
+
running: 0,
|
|
2608
|
+
new: 0,
|
|
2609
|
+
draft: 0,
|
|
2610
|
+
review: 0,
|
|
2611
|
+
done: 0,
|
|
2612
|
+
tickets: 0,
|
|
2613
|
+
prs: 0,
|
|
2614
|
+
branches: 0,
|
|
2615
|
+
threads: 0
|
|
2616
|
+
};
|
|
2617
|
+
const byCol = {
|
|
2618
|
+
queued: [],
|
|
2619
|
+
running: [],
|
|
2620
|
+
new: [],
|
|
2621
|
+
draft: [],
|
|
2622
|
+
review: [],
|
|
2623
|
+
done: []
|
|
2624
|
+
};
|
|
2625
|
+
for (const group of groupHomeBoardWorktrees(live)) {
|
|
2626
|
+
if (!group.some((t) => threadMatchesKind(t, kind))) continue;
|
|
2627
|
+
const col = classifyWorktreeColumn(group);
|
|
2628
|
+
if (col === "backlog") continue;
|
|
2629
|
+
const primary = group[0];
|
|
2630
|
+
if (!inWorkspace(primary.repoPath, repo)) continue;
|
|
2631
|
+
const hay = group.map((t) => threadSearchText(t, wsName(t.repoPath))).join(" ");
|
|
2632
|
+
if (!haystackMatches(hay, tokens)) continue;
|
|
2633
|
+
byCol[col].push(group);
|
|
2634
|
+
}
|
|
2635
|
+
const flat = [...Object.values(byCol)].flatMap((groups) => groups.map((g) => g[0]));
|
|
2636
|
+
totals.tickets = flat.filter((t) => t.sourceType === "ticket").length;
|
|
2637
|
+
totals.prs = flat.filter((t) => t.sourceType === "pr").length;
|
|
2638
|
+
totals.branches = flat.filter((t) => t.sourceType === "branch" || t.sourceType === "adopt").length;
|
|
2639
|
+
totals.threads = Object.values(byCol).reduce((n, list) => n + list.length, 0);
|
|
2640
|
+
for (const col of Object.keys(byCol)) {
|
|
2641
|
+
const cards = byCol[col].map(toThreadCard);
|
|
2642
|
+
totals[col] = cards.length;
|
|
2643
|
+
const page = visiblePage(cards, limit);
|
|
2644
|
+
columns[col] = page.visible;
|
|
2645
|
+
hidden[col] = page.hidden;
|
|
2646
|
+
}
|
|
2647
|
+
if (input.column) {
|
|
2648
|
+
for (const col of Object.keys(columns)) {
|
|
2649
|
+
if (col === input.column) continue;
|
|
2650
|
+
columns[col] = [];
|
|
2651
|
+
hidden[col] = 0;
|
|
2652
|
+
}
|
|
2653
|
+
}
|
|
2654
|
+
return { columns, hidden, totals };
|
|
2655
|
+
}
|
|
2656
|
+
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.";
|
|
2657
|
+
|
|
2320
2658
|
// src/threads/create.ts
|
|
2321
2659
|
async function createThread(input, _onSetupLine) {
|
|
2660
|
+
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
2661
|
+
if (!existsSync7(repoPath)) {
|
|
2662
|
+
throw new Error(`Repo not found: ${repoPath}`);
|
|
2663
|
+
}
|
|
2664
|
+
if (input.reuseExisting !== false) {
|
|
2665
|
+
const existing = findLiveThreadForCreate(
|
|
2666
|
+
{
|
|
2667
|
+
sourceType: input.sourceType,
|
|
2668
|
+
sourceRef: input.sourceRef,
|
|
2669
|
+
repoPath,
|
|
2670
|
+
title: input.title,
|
|
2671
|
+
cowboy: input.cowboy
|
|
2672
|
+
},
|
|
2673
|
+
listThreads({ includeArchived: false }).map((t) => ({
|
|
2674
|
+
...t,
|
|
2675
|
+
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
2676
|
+
}))
|
|
2677
|
+
);
|
|
2678
|
+
if (existing) return readThread(existing.id) ?? existing;
|
|
2679
|
+
}
|
|
2322
2680
|
const resolved = resolveNewThreadOptions({
|
|
2323
2681
|
agent: input.agent,
|
|
2324
2682
|
model: input.model,
|
|
@@ -2326,12 +2684,8 @@ async function createThread(input, _onSetupLine) {
|
|
|
2326
2684
|
fast: input.fast
|
|
2327
2685
|
});
|
|
2328
2686
|
await requireAgent(resolved.agent);
|
|
2329
|
-
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
2330
|
-
if (!existsSync7(repoPath)) {
|
|
2331
|
-
throw new Error(`Repo not found: ${repoPath}`);
|
|
2332
|
-
}
|
|
2333
2687
|
if (input.cowboy) {
|
|
2334
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
2688
|
+
const { cowboyModeEnabled } = await import("./app-settings-E7NEQY7D.js");
|
|
2335
2689
|
if (!cowboyModeEnabled()) {
|
|
2336
2690
|
throw new Error(
|
|
2337
2691
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -2442,7 +2796,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2442
2796
|
return readThread(thread.id) ?? thread;
|
|
2443
2797
|
}
|
|
2444
2798
|
async function listLinearIssues(agent, repoPath) {
|
|
2445
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
2799
|
+
const { getAdapter: getAdapter2 } = await import("./agents-7BUQY2WX.js");
|
|
2446
2800
|
await requireAgent(agent, { requireLinear: true });
|
|
2447
2801
|
const adapter = getAdapter2(agent);
|
|
2448
2802
|
if (!adapter.listLinearIssues) {
|
|
@@ -2628,7 +2982,8 @@ async function forkThreadWorktree(input, onSetupLine) {
|
|
|
2628
2982
|
planMode: from.planMode,
|
|
2629
2983
|
title: input.title?.trim() || void 0,
|
|
2630
2984
|
parentThreadId: from.id,
|
|
2631
|
-
attachments: [attachment]
|
|
2985
|
+
attachments: [attachment],
|
|
2986
|
+
reuseExisting: false
|
|
2632
2987
|
},
|
|
2633
2988
|
onSetupLine
|
|
2634
2989
|
);
|
|
@@ -2708,7 +3063,7 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
2708
3063
|
"",
|
|
2709
3064
|
`## Instructions`,
|
|
2710
3065
|
`- Continue fleet orchestration from this handoff.`,
|
|
2711
|
-
`- Prefer Sideboard MCP (list_threads, get_thread, send_to_thread, \u2026) for live status.`,
|
|
3066
|
+
`- Prefer Sideboard MCP (list_board, list_threads, get_thread, send_to_thread, \u2026) for live status.`,
|
|
2712
3067
|
`- Leave model Auto unless there is a specific reason to pin one.`,
|
|
2713
3068
|
`- Do not wait on the limited ${from.agent} account; keep going on ${fallbackAgent}.`
|
|
2714
3069
|
].join("\n");
|
|
@@ -2721,9 +3076,9 @@ function buildQuotaHandoffAttachment(from, limitText, fallbackAgent) {
|
|
|
2721
3076
|
}
|
|
2722
3077
|
var QUOTA_CONTINUE_PROMPT = (fromAgent, fallback) => [
|
|
2723
3078
|
`${fromAgent} hit a session/usage limit. Continue this orchestration on ${fallback} using the attached handoff.`,
|
|
2724
|
-
"Call list_threads for live fleet status, then proceed with the goal. Leave model Auto unless needed."
|
|
3079
|
+
"Call list_board or list_threads for live fleet status, then proceed with the goal. Leave model Auto unless needed."
|
|
2725
3080
|
].join(" ");
|
|
2726
|
-
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.";
|
|
3081
|
+
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.";
|
|
2727
3082
|
function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
2728
3083
|
const handoff = buildQuotaHandoffAttachment(from, limitText, fallbackAgent);
|
|
2729
3084
|
const tab = createChatTab({
|
|
@@ -2838,7 +3193,7 @@ async function adoptThread(input) {
|
|
|
2838
3193
|
messages: input.messages ?? []
|
|
2839
3194
|
});
|
|
2840
3195
|
writeThread(thread);
|
|
2841
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
3196
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-HSYRYJYV.js");
|
|
2842
3197
|
await ensureWorkspace2(repoPath);
|
|
2843
3198
|
return thread;
|
|
2844
3199
|
}
|
|
@@ -4985,7 +5340,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
4985
5340
|
${prompt}`;
|
|
4986
5341
|
}
|
|
4987
5342
|
async function defaultDeps() {
|
|
4988
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
5343
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-3JLPPTCF.js");
|
|
4989
5344
|
const orch = getOrchestrator2();
|
|
4990
5345
|
return {
|
|
4991
5346
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -5139,7 +5494,7 @@ var Orchestrator = class {
|
|
|
5139
5494
|
maxConcurrent;
|
|
5140
5495
|
runningCount = 0;
|
|
5141
5496
|
constructor(opts) {
|
|
5142
|
-
this.maxConcurrent = opts?.maxConcurrent ??
|
|
5497
|
+
this.maxConcurrent = opts?.maxConcurrent ?? 5;
|
|
5143
5498
|
}
|
|
5144
5499
|
on(listener) {
|
|
5145
5500
|
this.events.on("event", listener);
|
|
@@ -5205,7 +5560,7 @@ var Orchestrator = class {
|
|
|
5205
5560
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
5206
5561
|
});
|
|
5207
5562
|
}
|
|
5208
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
5563
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-E7NEQY7D.js");
|
|
5209
5564
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
5210
5565
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
5211
5566
|
}
|
|
@@ -5356,7 +5711,23 @@ var Orchestrator = class {
|
|
|
5356
5711
|
return findThreadByRef(idOrRef) ?? readThread(idOrRef);
|
|
5357
5712
|
}
|
|
5358
5713
|
async createThread(input) {
|
|
5714
|
+
const prior = new Set(
|
|
5715
|
+
listThreads({ includeArchived: false }).map((t) => t.id)
|
|
5716
|
+
);
|
|
5359
5717
|
const thread = await createThread(input);
|
|
5718
|
+
if (prior.has(thread.id)) {
|
|
5719
|
+
if (input.prompt?.trim()) {
|
|
5720
|
+
try {
|
|
5721
|
+
await this.send(thread.id, input.prompt.trim());
|
|
5722
|
+
} catch (err) {
|
|
5723
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
5724
|
+
updateThread(thread.id, {
|
|
5725
|
+
lastError: `First prompt failed: ${message}`
|
|
5726
|
+
});
|
|
5727
|
+
}
|
|
5728
|
+
}
|
|
5729
|
+
return thread;
|
|
5730
|
+
}
|
|
5360
5731
|
this.emit({ type: "status_changed", threadId: thread.id, status: thread.status });
|
|
5361
5732
|
void this.finishCreateThread(thread.id, input.prompt?.trim() || void 0);
|
|
5362
5733
|
return thread;
|
|
@@ -5377,7 +5748,7 @@ var Orchestrator = class {
|
|
|
5377
5748
|
}
|
|
5378
5749
|
await setup;
|
|
5379
5750
|
if (skipSetup) return;
|
|
5380
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
5751
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-E7NEQY7D.js");
|
|
5381
5752
|
if (autoRunAfterSetupEnabled()) {
|
|
5382
5753
|
try {
|
|
5383
5754
|
await this.startDev(threadId);
|
|
@@ -5662,7 +6033,7 @@ var Orchestrator = class {
|
|
|
5662
6033
|
}
|
|
5663
6034
|
const isBrightsy = fresh.agent === "brightsy";
|
|
5664
6035
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
5665
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-
|
|
6036
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-E7NEQY7D.js");
|
|
5666
6037
|
const gitAuthMode = getGithubGitAuthMode();
|
|
5667
6038
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
5668
6039
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -6199,7 +6570,8 @@ var Orchestrator = class {
|
|
|
6199
6570
|
agent,
|
|
6200
6571
|
repoPath: opts.repoPath,
|
|
6201
6572
|
title: opts.title ? `${opts.title} (${agent})` : `best-of-n: ${opts.prompt.slice(0, 48)} (${agent})`,
|
|
6202
|
-
prompt: opts.prompt
|
|
6573
|
+
prompt: opts.prompt,
|
|
6574
|
+
reuseExisting: false
|
|
6203
6575
|
});
|
|
6204
6576
|
created.push(thread);
|
|
6205
6577
|
}
|
|
@@ -6436,6 +6808,8 @@ var Orchestrator = class {
|
|
|
6436
6808
|
if (meta.url && meta.url !== thread.prUrl) patch.prUrl = meta.url;
|
|
6437
6809
|
if (meta.title && meta.title !== thread.prTitle) patch.prTitle = meta.title;
|
|
6438
6810
|
if (nextState && nextState !== prevState) patch.prState = nextState;
|
|
6811
|
+
const nextDraft = Boolean(meta.isDraft) && nextState !== "MERGED" && nextState !== "CLOSED";
|
|
6812
|
+
if (nextDraft !== Boolean(thread.prIsDraft)) patch.prIsDraft = nextDraft;
|
|
6439
6813
|
if (thread.skipAutoArchiveOnMerge && nextState && nextState !== "MERGED" && nextState !== "CLOSED") {
|
|
6440
6814
|
patch.skipAutoArchiveOnMerge = false;
|
|
6441
6815
|
}
|
|
@@ -6446,7 +6820,7 @@ var Orchestrator = class {
|
|
|
6446
6820
|
updateThread(thread.id, { title: meta.title });
|
|
6447
6821
|
}
|
|
6448
6822
|
}
|
|
6449
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
6823
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-E7NEQY7D.js");
|
|
6450
6824
|
const latest = this.requireThread(thread.id);
|
|
6451
6825
|
if (!shouldAutoArchiveOnPrMerge({
|
|
6452
6826
|
previousPrState: prevState || null,
|
|
@@ -6460,7 +6834,7 @@ var Orchestrator = class {
|
|
|
6460
6834
|
}
|
|
6461
6835
|
const siblings = threadsSharingWorktree(latest.worktreePath);
|
|
6462
6836
|
for (const t of siblings) {
|
|
6463
|
-
const sibPatch = { prState: "MERGED" };
|
|
6837
|
+
const sibPatch = { prState: "MERGED", prIsDraft: false };
|
|
6464
6838
|
if (meta.url && meta.url !== t.prUrl) sibPatch.prUrl = meta.url;
|
|
6465
6839
|
if (meta.title && meta.title !== t.prTitle) sibPatch.prTitle = meta.title;
|
|
6466
6840
|
if (Object.keys(sibPatch).length > 0) updateThread(t.id, sibPatch);
|
|
@@ -6634,10 +7008,15 @@ var Orchestrator = class {
|
|
|
6634
7008
|
web: action === "create-web"
|
|
6635
7009
|
});
|
|
6636
7010
|
if (!url) return;
|
|
6637
|
-
const patch = {
|
|
7011
|
+
const patch = {
|
|
7012
|
+
prUrl: url,
|
|
7013
|
+
prTitle: meta.title,
|
|
7014
|
+
prIsDraft: action === "create-draft"
|
|
7015
|
+
};
|
|
6638
7016
|
try {
|
|
6639
7017
|
const fetched = await getPrMeta(cwd, url);
|
|
6640
7018
|
if (fetched?.title) patch.prTitle = fetched.title;
|
|
7019
|
+
if (fetched) patch.prIsDraft = Boolean(fetched.isDraft);
|
|
6641
7020
|
} catch {
|
|
6642
7021
|
}
|
|
6643
7022
|
updateThread(thread.id, patch);
|
|
@@ -6751,7 +7130,7 @@ var Orchestrator = class {
|
|
|
6751
7130
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
6752
7131
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
6753
7132
|
try {
|
|
6754
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
7133
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-HSYRYJYV.js");
|
|
6755
7134
|
await ensureWorkspace2(thread.repoPath);
|
|
6756
7135
|
} catch {
|
|
6757
7136
|
}
|
|
@@ -6778,7 +7157,7 @@ var Orchestrator = class {
|
|
|
6778
7157
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
6779
7158
|
} catch {
|
|
6780
7159
|
}
|
|
6781
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
7160
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-E7NEQY7D.js");
|
|
6782
7161
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
6783
7162
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
6784
7163
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -6805,7 +7184,7 @@ var Orchestrator = class {
|
|
|
6805
7184
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
6806
7185
|
);
|
|
6807
7186
|
}
|
|
6808
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
7187
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-ERHC7Q4F.js");
|
|
6809
7188
|
const slug = thread.worktreePath.split("/").pop();
|
|
6810
7189
|
const dest = thread.worktreePath;
|
|
6811
7190
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -6913,7 +7292,7 @@ async function startOrchestration(opts) {
|
|
|
6913
7292
|
sourceRef: "default",
|
|
6914
7293
|
...createOpts
|
|
6915
7294
|
}).catch(async () => {
|
|
6916
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
7295
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-ERHC7Q4F.js");
|
|
6917
7296
|
const repo = await resolveRepoRoot2(repoPath);
|
|
6918
7297
|
const def = await resolveDefaultBranch2(repo);
|
|
6919
7298
|
return orch.createThread({
|
|
@@ -6923,7 +7302,7 @@ async function startOrchestration(opts) {
|
|
|
6923
7302
|
repoPath: repo
|
|
6924
7303
|
});
|
|
6925
7304
|
});
|
|
6926
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
7305
|
+
const { updateThread: upd } = await import("./thread-store-F6BCARQG.js");
|
|
6927
7306
|
const updated = upd(thread.id, {
|
|
6928
7307
|
sourceType: "orchestration",
|
|
6929
7308
|
sourceRef: goal
|
|
@@ -6941,8 +7320,20 @@ export {
|
|
|
6941
7320
|
requireSlackWorkspace,
|
|
6942
7321
|
listSlackOutboundWatches,
|
|
6943
7322
|
recordSlackOutboundWatch,
|
|
6944
|
-
|
|
7323
|
+
pollSlackOutboundWatches,
|
|
6945
7324
|
AGENT_GIT_ACTIONS,
|
|
7325
|
+
BOARD_COLUMN_DEFS,
|
|
7326
|
+
HOME_BOARD_CACHE_TTL_MS,
|
|
7327
|
+
dedupeBoardIssues,
|
|
7328
|
+
issueNeedsWorkspacePick,
|
|
7329
|
+
findLiveThreadForCreate,
|
|
7330
|
+
findBoardPin,
|
|
7331
|
+
syncBoardPins,
|
|
7332
|
+
dedupeBoardPrs,
|
|
7333
|
+
findBoardIssue,
|
|
7334
|
+
findBoardPr,
|
|
7335
|
+
assembleHomeBoard,
|
|
7336
|
+
HOME_BOARD_AGENT_HINT,
|
|
6946
7337
|
listLinearIssues,
|
|
6947
7338
|
readTurnLive,
|
|
6948
7339
|
resolveScheduleThreadId,
|