@sideboard-ai/core 0.1.211 → 0.1.213
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-GQANI7M5.js → agents-HETHRRZJ.js} +4 -4
- package/dist/{agents-A2U3K7VK.js → agents-WBDDLRBY.js} +4 -4
- package/dist/{chunk-JJ3ONQ4Q.js → chunk-3IMSQNTS.js} +12 -2
- package/dist/{chunk-IA5IPGZI.js → chunk-7MTVRNP4.js} +3 -3
- package/dist/{chunk-KZUA4QG2.js → chunk-C32SBNA3.js} +198 -97
- package/dist/{chunk-ERNK7AWM.js → chunk-D2IKXMF3.js} +196 -96
- package/dist/{chunk-IRCAWYTN.js → chunk-DFTVZEZY.js} +3 -3
- package/dist/{chunk-2PE6SZCM.js → chunk-FNGXKY5W.js} +2 -2
- package/dist/{chunk-GHKFSBES.js → chunk-HY2GFZ5S.js} +12 -2
- package/dist/{chunk-WNVQJZ7P.js → chunk-KFD2OXCE.js} +2 -2
- package/dist/{chunk-NRKDRQM3.js → chunk-NI243N27.js} +1 -1
- package/dist/{chunk-VPQXJYIW.js → chunk-XYKVRRC2.js} +1 -1
- package/dist/{coordinator-prompt-LMTMWCPN.js → coordinator-prompt-FQX6ALAI.js} +3 -3
- package/dist/{coordinator-prompt-EHRDZ2ZU.js → coordinator-prompt-LE2GQZ2X.js} +3 -3
- package/dist/{global-workspace-NG2TBUI5.js → global-workspace-6P236KKG.js} +3 -3
- package/dist/{global-workspace-RHABXQWB.js → global-workspace-KT3FRHZL.js} +3 -3
- package/dist/index.cjs +210 -88
- package/dist/index.d.cts +61 -6
- package/dist/index.d.ts +61 -6
- package/dist/index.js +11 -5
- package/dist/mcp/run-stdio.cjs +204 -88
- package/dist/mcp/run-stdio.js +5 -5
- package/dist/{orchestrator-NZO4PVFH.js → orchestrator-MI7A5DQZ.js} +7 -5
- package/dist/{orchestrator-QMGH4V4K.js → orchestrator-WVZPTHBV.js} +7 -5
- package/dist/{thread-store-MSMBQ3V4.js → thread-store-KDPPXJJ3.js} +3 -1
- package/dist/{thread-store-4M6WETL6.js → thread-store-N6WQIWZ4.js} +3 -1
- package/dist/{workspaces-VIUUE4RT.js → workspaces-KM7KTLVO.js} +3 -3
- package/dist/{workspaces-FRR6Y4BY.js → workspaces-R5LJCJRB.js} +3 -3
- package/dist/{worktree-GKUOHXXB.js → worktree-MDMTCAHX.js} +2 -2
- package/dist/{worktree-3MEG62KB.js → worktree-VXRI7LYM.js} +2 -2
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
resolveQuotaFallbackAgent,
|
|
25
25
|
stripBrightsyNdjsonNoise,
|
|
26
26
|
toolDescription
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-DFTVZEZY.js";
|
|
28
28
|
import {
|
|
29
29
|
SLACK_REPLY_FORMATTING,
|
|
30
30
|
addWorkspace,
|
|
@@ -47,7 +47,7 @@ import {
|
|
|
47
47
|
stageAbsolutePathsAsAttachments,
|
|
48
48
|
stageBuffersAsAttachments,
|
|
49
49
|
syncWorkspacesFromThreads
|
|
50
|
-
} from "./chunk-
|
|
50
|
+
} from "./chunk-FNGXKY5W.js";
|
|
51
51
|
import {
|
|
52
52
|
addPrStackLayer,
|
|
53
53
|
allocateTeamName,
|
|
@@ -97,7 +97,7 @@ import {
|
|
|
97
97
|
worktreeDisplayLabelForGroup,
|
|
98
98
|
worktreeNameFromPath,
|
|
99
99
|
worktreeSlugForTicket
|
|
100
|
-
} from "./chunk-
|
|
100
|
+
} from "./chunk-NI243N27.js";
|
|
101
101
|
import {
|
|
102
102
|
ATTACHMENTS_DIR,
|
|
103
103
|
DETACHED_JOBS_DIR,
|
|
@@ -189,7 +189,7 @@ import {
|
|
|
189
189
|
updateThread,
|
|
190
190
|
withThreadLock,
|
|
191
191
|
writeThread
|
|
192
|
-
} from "./chunk-
|
|
192
|
+
} from "./chunk-3IMSQNTS.js";
|
|
193
193
|
import {
|
|
194
194
|
appDataDir,
|
|
195
195
|
findConventionSetup,
|
|
@@ -483,7 +483,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
483
483
|
await continueOnReply(threadId, prompt);
|
|
484
484
|
return;
|
|
485
485
|
}
|
|
486
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
486
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-WVZPTHBV.js");
|
|
487
487
|
await getOrchestrator2().send(threadId, prompt);
|
|
488
488
|
} catch {
|
|
489
489
|
}
|
|
@@ -817,9 +817,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
817
817
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
818
818
|
);
|
|
819
819
|
}
|
|
820
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
820
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-6P236KKG.js");
|
|
821
821
|
if (isGlobalThread2(thread)) {
|
|
822
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
822
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-FQX6ALAI.js");
|
|
823
823
|
ensureGlobalCoordinatorCwd2(
|
|
824
824
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
825
825
|
);
|
|
@@ -2377,6 +2377,29 @@ ${line}` : line;
|
|
|
2377
2377
|
}
|
|
2378
2378
|
var memory = /* @__PURE__ */ new Map();
|
|
2379
2379
|
var persistTimers = /* @__PURE__ */ new Map();
|
|
2380
|
+
function fromSnapshot(snap) {
|
|
2381
|
+
return {
|
|
2382
|
+
chunks: snap.output ? [snap.output] : [],
|
|
2383
|
+
length: snap.output.length,
|
|
2384
|
+
running: snap.running,
|
|
2385
|
+
exitCode: snap.exitCode,
|
|
2386
|
+
source: snap.source
|
|
2387
|
+
};
|
|
2388
|
+
}
|
|
2389
|
+
function materialize(mem) {
|
|
2390
|
+
let output = mem.chunks.join("\n");
|
|
2391
|
+
if (output.length > MAX_SETUP_LOG_CHARS) {
|
|
2392
|
+
output = appendSetupOutput("", output);
|
|
2393
|
+
mem.chunks = [output];
|
|
2394
|
+
mem.length = output.length;
|
|
2395
|
+
}
|
|
2396
|
+
return {
|
|
2397
|
+
output,
|
|
2398
|
+
running: mem.running,
|
|
2399
|
+
exitCode: mem.exitCode,
|
|
2400
|
+
source: mem.source
|
|
2401
|
+
};
|
|
2402
|
+
}
|
|
2380
2403
|
function setupLogPath(threadId) {
|
|
2381
2404
|
return join7(threadsDir(), `${threadId}.setup.log.json`);
|
|
2382
2405
|
}
|
|
@@ -2395,20 +2418,22 @@ function mergeSetupOutput(prev, incoming) {
|
|
|
2395
2418
|
if (incoming.startsWith(prev) || incoming.endsWith(prev)) return incoming;
|
|
2396
2419
|
return incoming.length >= prev.length ? incoming : prev;
|
|
2397
2420
|
}
|
|
2398
|
-
|
|
2399
|
-
return { ...snap };
|
|
2400
|
-
}
|
|
2421
|
+
var PERSIST_DEBOUNCE_MS = 500;
|
|
2401
2422
|
function persistNow(threadId) {
|
|
2402
2423
|
const timer = persistTimers.get(threadId);
|
|
2403
2424
|
if (timer) {
|
|
2404
2425
|
clearTimeout(timer);
|
|
2405
2426
|
persistTimers.delete(threadId);
|
|
2406
2427
|
}
|
|
2407
|
-
const
|
|
2408
|
-
if (!
|
|
2428
|
+
const mem = memory.get(threadId);
|
|
2429
|
+
if (!mem) return;
|
|
2409
2430
|
try {
|
|
2410
|
-
writeFileSync2(
|
|
2411
|
-
|
|
2431
|
+
writeFileSync2(
|
|
2432
|
+
setupLogPath(threadId),
|
|
2433
|
+
`${JSON.stringify(materialize(mem))}
|
|
2434
|
+
`,
|
|
2435
|
+
"utf8"
|
|
2436
|
+
);
|
|
2412
2437
|
} catch {
|
|
2413
2438
|
}
|
|
2414
2439
|
}
|
|
@@ -2419,7 +2444,7 @@ function schedulePersist(threadId) {
|
|
|
2419
2444
|
setTimeout(() => {
|
|
2420
2445
|
persistTimers.delete(threadId);
|
|
2421
2446
|
persistNow(threadId);
|
|
2422
|
-
},
|
|
2447
|
+
}, PERSIST_DEBOUNCE_MS)
|
|
2423
2448
|
);
|
|
2424
2449
|
}
|
|
2425
2450
|
function loadFromDisk(threadId) {
|
|
@@ -2437,49 +2462,50 @@ function loadFromDisk(threadId) {
|
|
|
2437
2462
|
return null;
|
|
2438
2463
|
}
|
|
2439
2464
|
}
|
|
2465
|
+
function memFor(threadId) {
|
|
2466
|
+
const cached = memory.get(threadId);
|
|
2467
|
+
if (cached) return cached;
|
|
2468
|
+
const mem = fromSnapshot(loadFromDisk(threadId) ?? emptySetupLog());
|
|
2469
|
+
memory.set(threadId, mem);
|
|
2470
|
+
return mem;
|
|
2471
|
+
}
|
|
2440
2472
|
function readSetupLog(threadId) {
|
|
2441
2473
|
const cached = memory.get(threadId);
|
|
2442
|
-
if (cached) return
|
|
2474
|
+
if (cached) return materialize(cached);
|
|
2443
2475
|
const disk = loadFromDisk(threadId);
|
|
2444
2476
|
if (disk) {
|
|
2445
|
-
memory.set(threadId, disk);
|
|
2446
|
-
return
|
|
2477
|
+
memory.set(threadId, fromSnapshot(disk));
|
|
2478
|
+
return disk;
|
|
2447
2479
|
}
|
|
2448
2480
|
return emptySetupLog();
|
|
2449
2481
|
}
|
|
2450
2482
|
function beginSetupLog(threadId) {
|
|
2451
|
-
const
|
|
2452
|
-
|
|
2483
|
+
const mem = {
|
|
2484
|
+
chunks: [],
|
|
2485
|
+
length: 0,
|
|
2453
2486
|
running: true,
|
|
2454
2487
|
exitCode: null,
|
|
2455
2488
|
source: null
|
|
2456
2489
|
};
|
|
2457
|
-
memory.set(threadId,
|
|
2490
|
+
memory.set(threadId, mem);
|
|
2458
2491
|
persistNow(threadId);
|
|
2459
|
-
return
|
|
2492
|
+
return materialize(mem);
|
|
2460
2493
|
}
|
|
2461
2494
|
function appendSetupLog(threadId, line) {
|
|
2462
|
-
const
|
|
2463
|
-
|
|
2464
|
-
|
|
2465
|
-
|
|
2466
|
-
|
|
2467
|
-
};
|
|
2468
|
-
memory.set(threadId, snap);
|
|
2495
|
+
const mem = memFor(threadId);
|
|
2496
|
+
mem.chunks.push(line);
|
|
2497
|
+
mem.length += line.length + 1;
|
|
2498
|
+
mem.running = true;
|
|
2499
|
+
if (mem.length > MAX_SETUP_LOG_CHARS * 2) materialize(mem);
|
|
2469
2500
|
schedulePersist(threadId);
|
|
2470
|
-
return clone(snap);
|
|
2471
2501
|
}
|
|
2472
2502
|
function finishSetupLog(threadId, exitCode, source) {
|
|
2473
|
-
const
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
exitCode,
|
|
2478
|
-
source: source ?? current.source
|
|
2479
|
-
};
|
|
2480
|
-
memory.set(threadId, snap);
|
|
2503
|
+
const mem = memFor(threadId);
|
|
2504
|
+
mem.running = false;
|
|
2505
|
+
mem.exitCode = exitCode;
|
|
2506
|
+
mem.source = source ?? mem.source;
|
|
2481
2507
|
persistNow(threadId);
|
|
2482
|
-
return
|
|
2508
|
+
return materialize(mem);
|
|
2483
2509
|
}
|
|
2484
2510
|
|
|
2485
2511
|
// src/git/orphan-cleanup.ts
|
|
@@ -4039,7 +4065,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
4039
4065
|
return readThread(thread.id) ?? thread;
|
|
4040
4066
|
}
|
|
4041
4067
|
async function listLinearIssues(agent, repoPath) {
|
|
4042
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
4068
|
+
const { getAdapter: getAdapter2 } = await import("./agents-HETHRRZJ.js");
|
|
4043
4069
|
await requireAgent(agent, { requireLinear: true });
|
|
4044
4070
|
const adapter = getAdapter2(agent);
|
|
4045
4071
|
if (!adapter.listLinearIssues) {
|
|
@@ -4071,6 +4097,33 @@ function shouldRemoveWorktreeOnTeardown(thread) {
|
|
|
4071
4097
|
return !isCowboyThread(thread) && !isPrimaryCheckoutThread(thread);
|
|
4072
4098
|
}
|
|
4073
4099
|
|
|
4100
|
+
// src/util/line-coalescer.ts
|
|
4101
|
+
function createLineCoalescer(onChunk, opts) {
|
|
4102
|
+
const delayMs = opts?.delayMs ?? 50;
|
|
4103
|
+
const maxLines = opts?.maxLines ?? 200;
|
|
4104
|
+
let buffer = [];
|
|
4105
|
+
let timer = null;
|
|
4106
|
+
const flush2 = () => {
|
|
4107
|
+
if (timer) {
|
|
4108
|
+
clearTimeout(timer);
|
|
4109
|
+
timer = null;
|
|
4110
|
+
}
|
|
4111
|
+
if (buffer.length === 0) return;
|
|
4112
|
+
const chunk = buffer.join("\n");
|
|
4113
|
+
buffer = [];
|
|
4114
|
+
onChunk(chunk);
|
|
4115
|
+
};
|
|
4116
|
+
const push = (line) => {
|
|
4117
|
+
buffer.push(line);
|
|
4118
|
+
if (buffer.length >= maxLines) {
|
|
4119
|
+
flush2();
|
|
4120
|
+
return;
|
|
4121
|
+
}
|
|
4122
|
+
if (!timer) timer = setTimeout(flush2, delayMs);
|
|
4123
|
+
};
|
|
4124
|
+
return { push, flush: flush2 };
|
|
4125
|
+
}
|
|
4126
|
+
|
|
4074
4127
|
// src/store/turn-live.ts
|
|
4075
4128
|
import {
|
|
4076
4129
|
existsSync as existsSync11,
|
|
@@ -4485,7 +4538,7 @@ async function adoptThread(input) {
|
|
|
4485
4538
|
messages: input.messages ?? []
|
|
4486
4539
|
});
|
|
4487
4540
|
writeThread(thread);
|
|
4488
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
4541
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-R5LJCJRB.js");
|
|
4489
4542
|
await ensureWorkspace2(repoPath);
|
|
4490
4543
|
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
|
|
4491
4544
|
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
@@ -5705,6 +5758,29 @@ function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
|
5705
5758
|
writeFileSync6(abs, content, "utf8");
|
|
5706
5759
|
return { path: relativePath };
|
|
5707
5760
|
}
|
|
5761
|
+
async function getWorktreeDirtyStat(worktreePath) {
|
|
5762
|
+
const status = await inspectGitWorktree(worktreePath);
|
|
5763
|
+
if (status !== "ok") {
|
|
5764
|
+
return { additions: 0, deletions: 0, dirty: false };
|
|
5765
|
+
}
|
|
5766
|
+
const head = await git(["rev-parse", "--verify", "HEAD"], worktreePath, {
|
|
5767
|
+
reject: false,
|
|
5768
|
+
timeoutMs: 4e3
|
|
5769
|
+
});
|
|
5770
|
+
if (head.exitCode !== 0) {
|
|
5771
|
+
return { additions: 0, deletions: 0, dirty: await isDirty(worktreePath) };
|
|
5772
|
+
}
|
|
5773
|
+
const [num, dirty] = await Promise.all([
|
|
5774
|
+
gitDiff(["--numstat", "HEAD"], worktreePath, { timeoutMs: 4e3 }),
|
|
5775
|
+
isDirty(worktreePath)
|
|
5776
|
+
]);
|
|
5777
|
+
const counts = statFromNumstat(num.stdout);
|
|
5778
|
+
return {
|
|
5779
|
+
additions: counts.additions,
|
|
5780
|
+
deletions: counts.deletions,
|
|
5781
|
+
dirty: dirty || counts.additions > 0 || counts.deletions > 0
|
|
5782
|
+
};
|
|
5783
|
+
}
|
|
5708
5784
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
5709
5785
|
const full = await getDiff(worktreePath, repoPath, {
|
|
5710
5786
|
maxHunkChars: opts?.maxHunkChars ?? 2e3,
|
|
@@ -6251,9 +6327,7 @@ function consumeComposerAttachments(thread) {
|
|
|
6251
6327
|
};
|
|
6252
6328
|
}
|
|
6253
6329
|
function takePendingTurnAttachments(thread) {
|
|
6254
|
-
|
|
6255
|
-
if (pending.length > 0) return [...pending];
|
|
6256
|
-
return thread.attachments.length > 0 ? [...thread.attachments] : [];
|
|
6330
|
+
return [...thread.pendingTurnAttachments ?? []];
|
|
6257
6331
|
}
|
|
6258
6332
|
function alignQueueAttachments(queueLength, existing) {
|
|
6259
6333
|
const next = (existing ?? []).slice(0, queueLength).map((slot) => [...slot ?? []]);
|
|
@@ -7123,7 +7197,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
7123
7197
|
${prompt}`;
|
|
7124
7198
|
}
|
|
7125
7199
|
async function defaultDeps() {
|
|
7126
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
7200
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-WVZPTHBV.js");
|
|
7127
7201
|
const orch = getOrchestrator2();
|
|
7128
7202
|
return {
|
|
7129
7203
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -7254,6 +7328,7 @@ function resolveOrchChildFollowUp(requested) {
|
|
|
7254
7328
|
return followUpBehavior();
|
|
7255
7329
|
}
|
|
7256
7330
|
var STALE_AGENT_PID_WAIT_MS = 2500;
|
|
7331
|
+
var LIGHT_RECONCILE_THROTTLE_MS = 1e4;
|
|
7257
7332
|
function writeLiveStatus(threadId, status, lastError) {
|
|
7258
7333
|
const latest = readThread(threadId);
|
|
7259
7334
|
if (!latest || latest.status === "archived") return latest;
|
|
@@ -7268,6 +7343,8 @@ var Orchestrator = class {
|
|
|
7268
7343
|
startingTurns = /* @__PURE__ */ new Set();
|
|
7269
7344
|
/** Last sync thread-file read for false-stop heal (throttled per thread). */
|
|
7270
7345
|
lastReconcileHealAt = /* @__PURE__ */ new Map();
|
|
7346
|
+
/** Per-repo timestamp of the last `reconcile(repo, { light: true })`. */
|
|
7347
|
+
lightReconcileAt = /* @__PURE__ */ new Map();
|
|
7271
7348
|
/**
|
|
7272
7349
|
* Threads intentionally force-stopped. Prevents runTurn from re-asserting
|
|
7273
7350
|
* `running` after spawn, and from overwriting `stopped` with idle/error when
|
|
@@ -7353,6 +7430,20 @@ var Orchestrator = class {
|
|
|
7353
7430
|
async reconcile(repoPath, opts) {
|
|
7354
7431
|
const reclaimStaleTurns = opts?.reclaimStaleTurns === true;
|
|
7355
7432
|
const drainQueues = opts?.drainQueues !== false;
|
|
7433
|
+
if (opts?.light && repoPath) {
|
|
7434
|
+
const last = this.lightReconcileAt.get(repoPath) ?? 0;
|
|
7435
|
+
if (Date.now() - last < LIGHT_RECONCILE_THROTTLE_MS) return;
|
|
7436
|
+
this.lightReconcileAt.set(repoPath, Date.now());
|
|
7437
|
+
for (const thread of listThreads()) {
|
|
7438
|
+
if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
|
|
7439
|
+
if (!existsSync19(thread.worktreePath)) {
|
|
7440
|
+
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
7441
|
+
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
7442
|
+
}
|
|
7443
|
+
}
|
|
7444
|
+
await this.reconcileOrphans([repoPath]);
|
|
7445
|
+
return;
|
|
7446
|
+
}
|
|
7356
7447
|
healOrchestrationSoccerTitles();
|
|
7357
7448
|
for (const thread of listThreads({ includeArchived: true })) {
|
|
7358
7449
|
if (thread.status === "archived") continue;
|
|
@@ -7385,6 +7476,21 @@ var Orchestrator = class {
|
|
|
7385
7476
|
}
|
|
7386
7477
|
}
|
|
7387
7478
|
const repoPaths = (repoPath ? [repoPath] : [...new Set(listThreads({ includeArchived: true }).map((t) => t.repoPath))]).filter((p) => !isGlobalRepoPath(p));
|
|
7479
|
+
await this.reconcileOrphans(repoPaths);
|
|
7480
|
+
try {
|
|
7481
|
+
if (shouldRunHistoryCleanup()) {
|
|
7482
|
+
cleanupArchivedHistory();
|
|
7483
|
+
}
|
|
7484
|
+
} catch {
|
|
7485
|
+
}
|
|
7486
|
+
if (drainQueues) {
|
|
7487
|
+
this.adoptPersistedQueues();
|
|
7488
|
+
}
|
|
7489
|
+
this.schedulePendingQuotaResumes();
|
|
7490
|
+
armSchedules();
|
|
7491
|
+
}
|
|
7492
|
+
/** Surface (and, when enabled, clean up) worktrees git knows about but no thread owns. */
|
|
7493
|
+
async reconcileOrphans(repoPaths) {
|
|
7388
7494
|
try {
|
|
7389
7495
|
const orphans = await findOrphanWorktrees(repoPaths);
|
|
7390
7496
|
if (orphans.length) {
|
|
@@ -7399,17 +7505,6 @@ var Orchestrator = class {
|
|
|
7399
7505
|
}
|
|
7400
7506
|
} catch {
|
|
7401
7507
|
}
|
|
7402
|
-
try {
|
|
7403
|
-
if (shouldRunHistoryCleanup()) {
|
|
7404
|
-
cleanupArchivedHistory();
|
|
7405
|
-
}
|
|
7406
|
-
} catch {
|
|
7407
|
-
}
|
|
7408
|
-
if (drainQueues) {
|
|
7409
|
-
this.adoptPersistedQueues();
|
|
7410
|
-
}
|
|
7411
|
-
this.schedulePendingQuotaResumes();
|
|
7412
|
-
armSchedules();
|
|
7413
7508
|
}
|
|
7414
7509
|
/**
|
|
7415
7510
|
* Adopt queues persisted by another process (MCP stdio / CLI) into this
|
|
@@ -7643,7 +7738,7 @@ var Orchestrator = class {
|
|
|
7643
7738
|
return listThreads({ includeArchived });
|
|
7644
7739
|
}
|
|
7645
7740
|
getThread(idOrRef) {
|
|
7646
|
-
return
|
|
7741
|
+
return readThread(idOrRef) ?? findThreadByRef(idOrRef);
|
|
7647
7742
|
}
|
|
7648
7743
|
async createThread(input) {
|
|
7649
7744
|
const prior = new Set(
|
|
@@ -7814,9 +7909,11 @@ var Orchestrator = class {
|
|
|
7814
7909
|
const inFlight = this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id);
|
|
7815
7910
|
updateThread(thread.id, {
|
|
7816
7911
|
...removed,
|
|
7817
|
-
//
|
|
7818
|
-
//
|
|
7819
|
-
|
|
7912
|
+
// Follow-up files live on queueAttachments. pendingTurnAttachments is
|
|
7913
|
+
// the in-flight / just-dequeued snapshot — do not wipe it when a
|
|
7914
|
+
// later follow-up is removed. Only drop a leftover bag when nothing
|
|
7915
|
+
// is running and the queue is empty (legacy sends that never drained).
|
|
7916
|
+
...stillQueued || inFlight ? {} : { pendingTurnAttachments: [] },
|
|
7820
7917
|
status: !stillQueued && !inFlight && current.status === "queued" ? "idle" : current.status
|
|
7821
7918
|
});
|
|
7822
7919
|
this.emit({ type: "queue_changed", threadId: thread.id, queue: removed.queue });
|
|
@@ -7898,7 +7995,9 @@ var Orchestrator = class {
|
|
|
7898
7995
|
updateThread(threadId, {
|
|
7899
7996
|
queue: shifted.queue,
|
|
7900
7997
|
queueAttachments: shifted.queueAttachments,
|
|
7901
|
-
|
|
7998
|
+
// Always write the snapshot, including [] for text-only, so
|
|
7999
|
+
// takePending cannot fall back to leftover pending or composer files.
|
|
8000
|
+
pendingTurnAttachments: shifted.attachments
|
|
7902
8001
|
});
|
|
7903
8002
|
this.emit({ type: "queue_changed", threadId, queue: shifted.queue });
|
|
7904
8003
|
await this.runTurn(threadId, shifted.prompt);
|
|
@@ -7946,7 +8045,6 @@ var Orchestrator = class {
|
|
|
7946
8045
|
thread = this.requireThread(threadId);
|
|
7947
8046
|
}
|
|
7948
8047
|
const autoContinue = isJobContinuePrompt(prompt) || prompt.trim().startsWith("The previous agent process ended before it finished.");
|
|
7949
|
-
const parkedSnapshot = thread.pendingTurnAttachments ?? [];
|
|
7950
8048
|
const parked = takePendingTurnAttachments(thread);
|
|
7951
8049
|
const sentAttachments = !autoContinue && parked.length > 0 ? parked : void 0;
|
|
7952
8050
|
appendMessage(threadId, {
|
|
@@ -7962,7 +8060,7 @@ var Orchestrator = class {
|
|
|
7962
8060
|
thread.worktreePath,
|
|
7963
8061
|
gitPrompt,
|
|
7964
8062
|
{
|
|
7965
|
-
attachments: autoContinue ? [] : sentAttachments ??
|
|
8063
|
+
attachments: autoContinue ? [] : sentAttachments ?? []
|
|
7966
8064
|
}
|
|
7967
8065
|
);
|
|
7968
8066
|
const slackInbound = /^(Slack DM|Slack @mention)(?:\n|$)/.test(
|
|
@@ -8016,10 +8114,7 @@ var Orchestrator = class {
|
|
|
8016
8114
|
expandedPrompt
|
|
8017
8115
|
].filter(Boolean).join("\n\n");
|
|
8018
8116
|
if (!autoContinue && sentAttachments) {
|
|
8019
|
-
updateThread(
|
|
8020
|
-
threadId,
|
|
8021
|
-
parkedSnapshot.length > 0 ? { pendingTurnAttachments: [] } : { attachments: [], pendingTurnAttachments: [] }
|
|
8022
|
-
);
|
|
8117
|
+
updateThread(threadId, { pendingTurnAttachments: [] });
|
|
8023
8118
|
}
|
|
8024
8119
|
const adapter = getAdapter(thread.agent);
|
|
8025
8120
|
const resolved = await adapter.resolveSessionId(thread.worktreePath, thread.sessionId);
|
|
@@ -8499,17 +8594,18 @@ var Orchestrator = class {
|
|
|
8499
8594
|
}
|
|
8500
8595
|
}
|
|
8501
8596
|
}
|
|
8597
|
+
const runOutput = createLineCoalescer((chunk) => {
|
|
8598
|
+
this.emit({
|
|
8599
|
+
type: "run_output",
|
|
8600
|
+
threadId: thread.id,
|
|
8601
|
+
scriptName: resolvedName,
|
|
8602
|
+
line: chunk
|
|
8603
|
+
});
|
|
8604
|
+
});
|
|
8502
8605
|
const handle = await startDevServer(
|
|
8503
8606
|
thread.repoPath,
|
|
8504
8607
|
thread.worktreePath,
|
|
8505
|
-
|
|
8506
|
-
this.emit({
|
|
8507
|
-
type: "run_output",
|
|
8508
|
-
threadId: thread.id,
|
|
8509
|
-
scriptName: resolvedName,
|
|
8510
|
-
line
|
|
8511
|
-
});
|
|
8512
|
-
},
|
|
8608
|
+
runOutput.push,
|
|
8513
8609
|
{ scriptName: resolvedName }
|
|
8514
8610
|
);
|
|
8515
8611
|
if (!handle) {
|
|
@@ -8555,6 +8651,7 @@ var Orchestrator = class {
|
|
|
8555
8651
|
scriptName: resolvedName
|
|
8556
8652
|
});
|
|
8557
8653
|
void handle.done.then(() => {
|
|
8654
|
+
runOutput.flush();
|
|
8558
8655
|
this.processes.delete(runKey);
|
|
8559
8656
|
if (isDefault) this.processes.delete(worktreeDevProcessKey(thread.worktreePath));
|
|
8560
8657
|
const latest = mergeWorktreeActiveRuns(threadsSharingWorktree(thread.worktreePath));
|
|
@@ -8640,9 +8737,14 @@ var Orchestrator = class {
|
|
|
8640
8737
|
(t) => this.processes.has(`${t.id}:setup`)
|
|
8641
8738
|
);
|
|
8642
8739
|
}
|
|
8643
|
-
|
|
8740
|
+
/**
|
|
8741
|
+
* The worktree-keyed log is canonical (`resolveWorktreeSetupLog` prefers it
|
|
8742
|
+
* whenever it has output/running/exitCode); per-chat keys only exist for
|
|
8743
|
+
* records that predate it. Writing one key halves the sync persists during
|
|
8744
|
+
* `pnpm install`.
|
|
8745
|
+
*/
|
|
8746
|
+
writeSetupLog(worktreePath, fn) {
|
|
8644
8747
|
fn(setupLogKeyForWorktree(worktreePath));
|
|
8645
|
-
fn(threadId);
|
|
8646
8748
|
}
|
|
8647
8749
|
async runSetup(threadRef, opts) {
|
|
8648
8750
|
const thread = this.requireThread(threadRef);
|
|
@@ -8657,14 +8759,18 @@ var Orchestrator = class {
|
|
|
8657
8759
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
8658
8760
|
kill: () => abort.abort()
|
|
8659
8761
|
});
|
|
8660
|
-
this.writeSetupLog(thread.
|
|
8762
|
+
this.writeSetupLog(thread.worktreePath, beginSetupLog);
|
|
8661
8763
|
this.emit({ type: "setup_started", threadId: thread.id });
|
|
8764
|
+
const output = createLineCoalescer((chunk) => {
|
|
8765
|
+
this.writeSetupLog(thread.worktreePath, (logKey) => appendSetupLog(logKey, chunk));
|
|
8766
|
+
this.emit({ type: "setup_output", threadId: thread.id, line: chunk });
|
|
8767
|
+
});
|
|
8662
8768
|
let finished = false;
|
|
8663
8769
|
const finish = (exitCode, source) => {
|
|
8664
8770
|
if (finished) return;
|
|
8665
8771
|
finished = true;
|
|
8772
|
+
output.flush();
|
|
8666
8773
|
this.writeSetupLog(
|
|
8667
|
-
thread.id,
|
|
8668
8774
|
thread.worktreePath,
|
|
8669
8775
|
(logKey) => finishSetupLog(logKey, exitCode, source)
|
|
8670
8776
|
);
|
|
@@ -8674,24 +8780,12 @@ var Orchestrator = class {
|
|
|
8674
8780
|
const setup = await runWorkspaceSetup(
|
|
8675
8781
|
thread.repoPath,
|
|
8676
8782
|
thread.worktreePath,
|
|
8677
|
-
|
|
8678
|
-
this.writeSetupLog(
|
|
8679
|
-
thread.id,
|
|
8680
|
-
thread.worktreePath,
|
|
8681
|
-
(logKey) => appendSetupLog(logKey, line)
|
|
8682
|
-
);
|
|
8683
|
-
this.emit({ type: "setup_output", threadId: thread.id, line });
|
|
8684
|
-
},
|
|
8783
|
+
output.push,
|
|
8685
8784
|
{ signal: abort.signal }
|
|
8686
8785
|
);
|
|
8687
8786
|
if (!setup.ran) {
|
|
8688
8787
|
const line = "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)";
|
|
8689
|
-
|
|
8690
|
-
thread.id,
|
|
8691
|
-
thread.worktreePath,
|
|
8692
|
-
(logKey) => appendSetupLog(logKey, line)
|
|
8693
|
-
);
|
|
8694
|
-
this.emit({ type: "setup_output", threadId: thread.id, line });
|
|
8788
|
+
output.push(line);
|
|
8695
8789
|
finish(null, null);
|
|
8696
8790
|
throw new Error(line);
|
|
8697
8791
|
}
|
|
@@ -8897,6 +8991,11 @@ var Orchestrator = class {
|
|
|
8897
8991
|
lastTurnBase: this.turnBaselines.get(thread.id) ?? null
|
|
8898
8992
|
});
|
|
8899
8993
|
}
|
|
8994
|
+
async worktreeDirtyStat(threadRef) {
|
|
8995
|
+
const thread = this.requireThread(threadRef);
|
|
8996
|
+
this.assertNotGlobal(thread, "Diff");
|
|
8997
|
+
return getWorktreeDirtyStat(thread.worktreePath);
|
|
8998
|
+
}
|
|
8900
8999
|
async diffSummary(threadRef) {
|
|
8901
9000
|
const thread = this.requireThread(threadRef);
|
|
8902
9001
|
this.assertNotGlobal(thread, "Diff");
|
|
@@ -9345,7 +9444,7 @@ var Orchestrator = class {
|
|
|
9345
9444
|
this.enforceHistoryRetention();
|
|
9346
9445
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
9347
9446
|
try {
|
|
9348
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
9447
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-R5LJCJRB.js");
|
|
9349
9448
|
await ensureWorkspace2(thread.repoPath);
|
|
9350
9449
|
} catch {
|
|
9351
9450
|
}
|
|
@@ -9399,7 +9498,7 @@ var Orchestrator = class {
|
|
|
9399
9498
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
9400
9499
|
);
|
|
9401
9500
|
}
|
|
9402
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
9501
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-MDMTCAHX.js");
|
|
9403
9502
|
const slug = thread.worktreePath.split("/").pop();
|
|
9404
9503
|
const dest = thread.worktreePath;
|
|
9405
9504
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -9509,7 +9608,7 @@ async function startOrchestration(opts) {
|
|
|
9509
9608
|
sourceRef: "default",
|
|
9510
9609
|
...createOpts
|
|
9511
9610
|
}).catch(async () => {
|
|
9512
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
9611
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-MDMTCAHX.js");
|
|
9513
9612
|
const repo = await resolveRepoRoot2(repoPath);
|
|
9514
9613
|
const def = await resolveDefaultBranch2(repo);
|
|
9515
9614
|
return orch.createThread({
|
|
@@ -9519,7 +9618,7 @@ async function startOrchestration(opts) {
|
|
|
9519
9618
|
repoPath: repo
|
|
9520
9619
|
});
|
|
9521
9620
|
});
|
|
9522
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
9621
|
+
const { updateThread: upd } = await import("./thread-store-N6WQIWZ4.js");
|
|
9523
9622
|
const updated = upd(thread.id, {
|
|
9524
9623
|
sourceType: "orchestration",
|
|
9525
9624
|
sourceRef: goal
|
|
@@ -9725,6 +9824,7 @@ export {
|
|
|
9725
9824
|
readWorktreeFileForUpload,
|
|
9726
9825
|
readWorktreeFile,
|
|
9727
9826
|
writeWorktreeFile,
|
|
9827
|
+
getWorktreeDirtyStat,
|
|
9728
9828
|
getDiffSummary,
|
|
9729
9829
|
previewLand,
|
|
9730
9830
|
confirmLand,
|
|
@@ -9778,6 +9878,7 @@ export {
|
|
|
9778
9878
|
waitForPidExit,
|
|
9779
9879
|
resolveSendFollowUp,
|
|
9780
9880
|
resolveOrchChildFollowUp,
|
|
9881
|
+
LIGHT_RECONCILE_THROTTLE_MS,
|
|
9781
9882
|
Orchestrator,
|
|
9782
9883
|
getOrchestrator,
|
|
9783
9884
|
startOrchestration,
|