@sideboard-ai/core 0.1.152 → 0.1.155
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{abletime-223A3LY6.js → abletime-H7LPGIP2.js} +3 -3
- package/dist/{abletime-CLC5UJC2.js → abletime-JSTJLXAW.js} +3 -3
- package/dist/agents/cursor-runner.js +2 -2
- package/dist/{agents-CUKWIM34.js → agents-V24DYZI4.js} +8 -9
- package/dist/{agents-VHXCBBBD.js → agents-YVW75KBO.js} +8 -9
- package/dist/{app-settings-3CHCNIMD.js → app-settings-H3INSR67.js} +38 -4
- package/dist/{app-settings-J3JBCUOT.js → app-settings-VRQI3FIE.js} +38 -4
- package/dist/{caffeinate-hold-NBRUWYXO.js → caffeinate-hold-DBKMRZZO.js} +2 -2
- package/dist/{caffeinate-hold-X3JNPR42.js → caffeinate-hold-SK2QISPE.js} +2 -2
- package/dist/chunk-2F63IMCL.js +959 -0
- package/dist/{chunk-4XNSGDXE.js → chunk-3BWVOUQG.js} +244 -1
- package/dist/{chunk-7BQNSUR2.js → chunk-46ZTBUVJ.js} +364 -200
- package/dist/{chunk-EY6QXPPO.js → chunk-4THE3EY7.js} +6 -6
- package/dist/{chunk-TUGKX5BD.js → chunk-7UURXPKD.js} +1 -1
- package/dist/{chunk-DCOZABNT.js → chunk-AO35MGOE.js} +1 -1
- package/dist/{chunk-3JBMACYX.js → chunk-CJQLPPEJ.js} +387 -15
- package/dist/{chunk-CZD4NRDZ.js → chunk-D7EGJ3EI.js} +244 -1
- package/dist/{chunk-QZQEXME2.js → chunk-EFVFB2AH.js} +1 -1
- package/dist/{chunk-B7XK37WZ.js → chunk-FDCFXMDG.js} +1 -1
- package/dist/{chunk-6X7Z34XE.js → chunk-J2OKVOBM.js} +410 -188
- package/dist/{chunk-WLV7TRMR.js → chunk-JOK4XWBG.js} +1 -1
- package/dist/{chunk-BD2ICC4D.js → chunk-JTJHOYCU.js} +1 -1
- package/dist/{chunk-GE7M3QTE.js → chunk-LQMFCS54.js} +387 -15
- package/dist/{chunk-G7SIQFBQ.js → chunk-LZ6QMEQC.js} +1 -1
- package/dist/{chunk-EUXOHTUK.js → chunk-LZQULFIT.js} +1 -1
- package/dist/{chunk-KLBOWJ74.js → chunk-OCQPTUR7.js} +1 -1
- package/dist/{chunk-GFQ57XAX.js → chunk-QZEZXYVV.js} +13 -13
- package/dist/chunk-RNC3GR6L.js +905 -0
- package/dist/{chunk-VHX673DI.js → chunk-WLPXZFRE.js} +1 -1
- package/dist/{chunk-7F4XE6UG.js → chunk-XD2BAANL.js} +5 -5
- package/dist/{connected-teams-XO766HB4.js → connected-teams-DBWAMP7G.js} +2 -2
- package/dist/{connected-teams-I2WZZZFA.js → connected-teams-WGONUQOF.js} +2 -2
- package/dist/{coordinator-prompt-WGFRYCHE.js → coordinator-prompt-7FHKCWXB.js} +5 -5
- package/dist/{coordinator-prompt-TBX4MOFM.js → coordinator-prompt-KX2FVVYT.js} +5 -5
- package/dist/{cursor-recover-NOQYOFRF.js → cursor-recover-L5MD6MBO.js} +1 -1
- package/dist/{cursor-recover-QSLWEZNA.js → cursor-recover-NDMLLNYX.js} +2 -2
- package/dist/{global-workspace-IY5QAV5C.js → global-workspace-2BRRKSDN.js} +5 -6
- package/dist/{global-workspace-BHLUJ46D.js → global-workspace-4LHCZ2DC.js} +5 -6
- package/dist/index.cjs +1889 -777
- package/dist/index.d.cts +222 -12
- package/dist/index.d.ts +222 -12
- package/dist/index.js +304 -108
- package/dist/mcp/run-stdio.cjs +1747 -1240
- package/dist/mcp/run-stdio.js +232 -80
- package/dist/{orchestrator-256DFPSX.js → orchestrator-3FWEKDAQ.js} +9 -11
- package/dist/{orchestrator-NUA6SEV7.js → orchestrator-HC7XVGJB.js} +10 -12
- package/dist/{paths-UMEDHOS5.js → paths-53TLA7VQ.js} +1 -1
- package/dist/{paths-QCI3MTO5.js → paths-RRCLNSJB.js} +1 -1
- package/dist/{thread-store-WGASXXXR.js → thread-store-KBFBHT5G.js} +2 -2
- package/dist/{thread-store-57ZLHR3A.js → thread-store-MVQU6HPJ.js} +2 -2
- package/dist/{workspaces-4FSXVIZM.js → workspaces-5UNDTN4G.js} +5 -7
- package/dist/{workspaces-NECIQTAO.js → workspaces-MQYNZXUK.js} +5 -7
- package/dist/{worktree-HTUM35NT.js → worktree-PEWDAX5O.js} +4 -4
- package/dist/{worktree-DPIREDFR.js → worktree-T4SWFSTT.js} +4 -4
- package/package.json +1 -1
- package/dist/chunk-2U6QF3PT.js +0 -211
- package/dist/chunk-67TIJ7S5.js +0 -122
- package/dist/chunk-7TIUOYBK.js +0 -213
- package/dist/chunk-G4MTYUWS.js +0 -592
- package/dist/chunk-K2ANSHUO.js +0 -120
- package/dist/chunk-SN6CMKF6.js +0 -538
|
@@ -24,18 +24,19 @@ import {
|
|
|
24
24
|
stripBrightsyNdjsonNoise,
|
|
25
25
|
sumUsageList,
|
|
26
26
|
toolDescription
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-QZEZXYVV.js";
|
|
28
28
|
import {
|
|
29
|
+
SLACK_REPLY_FORMATTING,
|
|
29
30
|
addWorkspace,
|
|
30
|
-
ensureWorkspace,
|
|
31
|
-
removeWorkspace,
|
|
32
|
-
syncWorkspacesFromThreads
|
|
33
|
-
} from "./chunk-K2ANSHUO.js";
|
|
34
|
-
import {
|
|
35
31
|
assertOrchestratorCapableAgent,
|
|
36
32
|
attachmentsFromWorktreePaths,
|
|
37
33
|
coerceOrchestratorAgent,
|
|
34
|
+
coordinatorSystemPrompt,
|
|
35
|
+
coordinatorTurnReminder,
|
|
38
36
|
createGlobalChat,
|
|
37
|
+
enrichWorkspacesWithGithub,
|
|
38
|
+
ensureGlobalCoordinatorCwd,
|
|
39
|
+
ensureWorkspace,
|
|
39
40
|
healOrchestrationSoccerTitles,
|
|
40
41
|
isCloudCoordinatorThread,
|
|
41
42
|
isGlobalRepoPath,
|
|
@@ -45,16 +46,11 @@ import {
|
|
|
45
46
|
isSlackCoordinatorThread,
|
|
46
47
|
orchestratorSessionPoisonedByBuiltins,
|
|
47
48
|
persistPendingFileAttachments,
|
|
49
|
+
removeWorkspace,
|
|
48
50
|
stageAbsolutePathsAsAttachments,
|
|
49
|
-
stageBuffersAsAttachments
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
SLACK_REPLY_FORMATTING,
|
|
53
|
-
coordinatorSystemPrompt,
|
|
54
|
-
coordinatorTurnReminder,
|
|
55
|
-
enrichWorkspacesWithGithub,
|
|
56
|
-
ensureGlobalCoordinatorCwd
|
|
57
|
-
} from "./chunk-2U6QF3PT.js";
|
|
51
|
+
stageBuffersAsAttachments,
|
|
52
|
+
syncWorkspacesFromThreads
|
|
53
|
+
} from "./chunk-2F63IMCL.js";
|
|
58
54
|
import {
|
|
59
55
|
addPrStackLayer,
|
|
60
56
|
allocateTeamName,
|
|
@@ -102,7 +98,7 @@ import {
|
|
|
102
98
|
withRepoGitLock,
|
|
103
99
|
worktreeDisplayLabelForGroup,
|
|
104
100
|
worktreeNameFromPath
|
|
105
|
-
} from "./chunk-
|
|
101
|
+
} from "./chunk-LQMFCS54.js";
|
|
106
102
|
import {
|
|
107
103
|
ATTACHMENTS_DIR,
|
|
108
104
|
LEGACY_ATTACHMENTS_DIR
|
|
@@ -143,13 +139,13 @@ import {
|
|
|
143
139
|
saveAppSettings,
|
|
144
140
|
updateAdvancedSettings,
|
|
145
141
|
writeSecureJson
|
|
146
|
-
} from "./chunk-
|
|
142
|
+
} from "./chunk-3BWVOUQG.js";
|
|
147
143
|
import {
|
|
148
144
|
stripNestedElectronEnv
|
|
149
145
|
} from "./chunk-4TR3HZFT.js";
|
|
150
146
|
import {
|
|
151
147
|
releaseCaffeinateHoldForThread
|
|
152
|
-
} from "./chunk-
|
|
148
|
+
} from "./chunk-AO35MGOE.js";
|
|
153
149
|
import {
|
|
154
150
|
writePrivateFile
|
|
155
151
|
} from "./chunk-JT7R45JB.js";
|
|
@@ -164,7 +160,7 @@ import {
|
|
|
164
160
|
updateThread,
|
|
165
161
|
withThreadLock,
|
|
166
162
|
writeThread
|
|
167
|
-
} from "./chunk-
|
|
163
|
+
} from "./chunk-7UURXPKD.js";
|
|
168
164
|
import {
|
|
169
165
|
appDataDir,
|
|
170
166
|
findConventionSetup,
|
|
@@ -174,9 +170,10 @@ import {
|
|
|
174
170
|
sideboardReposDir,
|
|
175
171
|
sideboardWorkspacesDir,
|
|
176
172
|
threadLivePath,
|
|
173
|
+
threadsDir,
|
|
177
174
|
workspaceSettingsSourceLabel,
|
|
178
175
|
worktreesRoot
|
|
179
|
-
} from "./chunk-
|
|
176
|
+
} from "./chunk-EFVFB2AH.js";
|
|
180
177
|
import {
|
|
181
178
|
ensureWorktreeSideboardIgnored
|
|
182
179
|
} from "./chunk-QQKDGPUI.js";
|
|
@@ -460,7 +457,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
460
457
|
await continueOnReply(threadId, prompt);
|
|
461
458
|
return;
|
|
462
459
|
}
|
|
463
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
460
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-HC7XVGJB.js");
|
|
464
461
|
await getOrchestrator2().send(threadId, prompt);
|
|
465
462
|
} catch {
|
|
466
463
|
}
|
|
@@ -720,7 +717,7 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
720
717
|
}
|
|
721
718
|
|
|
722
719
|
// src/orchestrator/orchestrator.ts
|
|
723
|
-
import { existsSync as
|
|
720
|
+
import { existsSync as existsSync17 } from "fs";
|
|
724
721
|
|
|
725
722
|
// src/agents/spawn.ts
|
|
726
723
|
import { createInterface } from "readline";
|
|
@@ -740,9 +737,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
740
737
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
741
738
|
);
|
|
742
739
|
}
|
|
743
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
740
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-2BRRKSDN.js");
|
|
744
741
|
if (isGlobalThread2(thread)) {
|
|
745
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
742
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-7FHKCWXB.js");
|
|
746
743
|
ensureGlobalCoordinatorCwd2(
|
|
747
744
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
748
745
|
);
|
|
@@ -1997,6 +1994,8 @@ async function attachAbort(handle, signal) {
|
|
|
1997
1994
|
async function runSetupScript(repoPath, worktreePath, onLine, opts) {
|
|
1998
1995
|
const settings = loadWorkspaceSettings(worktreePath, repoPath);
|
|
1999
1996
|
if (!settings?.setup) return { ran: false, exitCode: null, source: null };
|
|
1997
|
+
const source = workspaceSettingsSourceLabel(worktreePath, repoPath);
|
|
1998
|
+
onLine?.(`[setup] ${source ?? "settings.toml"}`);
|
|
2000
1999
|
const handle = await spawnWorkspaceScript(settings.setup, {
|
|
2001
2000
|
worktreePath,
|
|
2002
2001
|
repoPath,
|
|
@@ -2007,7 +2006,7 @@ async function runSetupScript(repoPath, worktreePath, onLine, opts) {
|
|
|
2007
2006
|
return {
|
|
2008
2007
|
ran: true,
|
|
2009
2008
|
exitCode,
|
|
2010
|
-
source
|
|
2009
|
+
source,
|
|
2011
2010
|
kill: handle.kill
|
|
2012
2011
|
};
|
|
2013
2012
|
}
|
|
@@ -2136,9 +2135,122 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
2136
2135
|
};
|
|
2137
2136
|
}
|
|
2138
2137
|
|
|
2139
|
-
// src/
|
|
2140
|
-
import { existsSync as existsSync5,
|
|
2138
|
+
// src/store/setup-log.ts
|
|
2139
|
+
import { existsSync as existsSync5, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
2141
2140
|
import { join as join6 } from "path";
|
|
2141
|
+
var EMPTY = {
|
|
2142
|
+
output: "",
|
|
2143
|
+
running: false,
|
|
2144
|
+
exitCode: null,
|
|
2145
|
+
source: null
|
|
2146
|
+
};
|
|
2147
|
+
var memory = /* @__PURE__ */ new Map();
|
|
2148
|
+
var persistTimers = /* @__PURE__ */ new Map();
|
|
2149
|
+
function setupLogPath(threadId) {
|
|
2150
|
+
return join6(threadsDir(), `${threadId}.setup.log.json`);
|
|
2151
|
+
}
|
|
2152
|
+
function emptySetupLog() {
|
|
2153
|
+
return { ...EMPTY };
|
|
2154
|
+
}
|
|
2155
|
+
function mergeSetupOutput(prev, incoming) {
|
|
2156
|
+
if (!prev) return incoming;
|
|
2157
|
+
if (!incoming) return prev;
|
|
2158
|
+
if (prev === incoming) return prev;
|
|
2159
|
+
if (prev.startsWith(incoming) || prev.endsWith(incoming)) return prev;
|
|
2160
|
+
if (incoming.startsWith(prev) || incoming.endsWith(prev)) return incoming;
|
|
2161
|
+
return incoming.length >= prev.length ? incoming : prev;
|
|
2162
|
+
}
|
|
2163
|
+
function clone(snap) {
|
|
2164
|
+
return { ...snap };
|
|
2165
|
+
}
|
|
2166
|
+
function persistNow(threadId) {
|
|
2167
|
+
const timer = persistTimers.get(threadId);
|
|
2168
|
+
if (timer) {
|
|
2169
|
+
clearTimeout(timer);
|
|
2170
|
+
persistTimers.delete(threadId);
|
|
2171
|
+
}
|
|
2172
|
+
const snap = memory.get(threadId);
|
|
2173
|
+
if (!snap) return;
|
|
2174
|
+
try {
|
|
2175
|
+
writeFileSync2(setupLogPath(threadId), `${JSON.stringify(snap)}
|
|
2176
|
+
`, "utf8");
|
|
2177
|
+
} catch {
|
|
2178
|
+
}
|
|
2179
|
+
}
|
|
2180
|
+
function schedulePersist(threadId) {
|
|
2181
|
+
if (persistTimers.has(threadId)) return;
|
|
2182
|
+
persistTimers.set(
|
|
2183
|
+
threadId,
|
|
2184
|
+
setTimeout(() => {
|
|
2185
|
+
persistTimers.delete(threadId);
|
|
2186
|
+
persistNow(threadId);
|
|
2187
|
+
}, 100)
|
|
2188
|
+
);
|
|
2189
|
+
}
|
|
2190
|
+
function loadFromDisk(threadId) {
|
|
2191
|
+
const path = setupLogPath(threadId);
|
|
2192
|
+
if (!existsSync5(path)) return null;
|
|
2193
|
+
try {
|
|
2194
|
+
const raw = JSON.parse(readFileSync5(path, "utf8"));
|
|
2195
|
+
return {
|
|
2196
|
+
output: typeof raw.output === "string" ? raw.output : "",
|
|
2197
|
+
running: Boolean(raw.running),
|
|
2198
|
+
exitCode: typeof raw.exitCode === "number" ? raw.exitCode : null,
|
|
2199
|
+
source: typeof raw.source === "string" ? raw.source : null
|
|
2200
|
+
};
|
|
2201
|
+
} catch {
|
|
2202
|
+
return null;
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
function readSetupLog(threadId) {
|
|
2206
|
+
const cached = memory.get(threadId);
|
|
2207
|
+
if (cached) return clone(cached);
|
|
2208
|
+
const disk = loadFromDisk(threadId);
|
|
2209
|
+
if (disk) {
|
|
2210
|
+
memory.set(threadId, disk);
|
|
2211
|
+
return clone(disk);
|
|
2212
|
+
}
|
|
2213
|
+
return emptySetupLog();
|
|
2214
|
+
}
|
|
2215
|
+
function beginSetupLog(threadId) {
|
|
2216
|
+
const snap = {
|
|
2217
|
+
output: "",
|
|
2218
|
+
running: true,
|
|
2219
|
+
exitCode: null,
|
|
2220
|
+
source: null
|
|
2221
|
+
};
|
|
2222
|
+
memory.set(threadId, snap);
|
|
2223
|
+
persistNow(threadId);
|
|
2224
|
+
return clone(snap);
|
|
2225
|
+
}
|
|
2226
|
+
function appendSetupLog(threadId, line) {
|
|
2227
|
+
const current = memory.get(threadId) ?? readSetupLog(threadId);
|
|
2228
|
+
const snap = {
|
|
2229
|
+
...current,
|
|
2230
|
+
output: current.output ? `${current.output}
|
|
2231
|
+
${line}` : line,
|
|
2232
|
+
running: true
|
|
2233
|
+
};
|
|
2234
|
+
memory.set(threadId, snap);
|
|
2235
|
+
schedulePersist(threadId);
|
|
2236
|
+
return clone(snap);
|
|
2237
|
+
}
|
|
2238
|
+
function finishSetupLog(threadId, exitCode, source) {
|
|
2239
|
+
const current = memory.get(threadId) ?? readSetupLog(threadId);
|
|
2240
|
+
const snap = {
|
|
2241
|
+
...current,
|
|
2242
|
+
running: false,
|
|
2243
|
+
exitCode,
|
|
2244
|
+
source: source ?? current.source
|
|
2245
|
+
};
|
|
2246
|
+
memory.set(threadId, snap);
|
|
2247
|
+
persistNow(threadId);
|
|
2248
|
+
return clone(snap);
|
|
2249
|
+
}
|
|
2250
|
+
|
|
2251
|
+
// src/git/orphan-cleanup.ts
|
|
2252
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, statSync } from "fs";
|
|
2253
|
+
import { join as join7 } from "path";
|
|
2142
2254
|
function isSideboardWorktreePath(path) {
|
|
2143
2255
|
return path.includes("/.sideboard/worktrees/") || path.includes("/sideboard/workspaces/");
|
|
2144
2256
|
}
|
|
@@ -2149,7 +2261,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2149
2261
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
2150
2262
|
);
|
|
2151
2263
|
const homeRoot = sideboardWorkspacesDir();
|
|
2152
|
-
if (
|
|
2264
|
+
if (existsSync6(homeRoot)) {
|
|
2153
2265
|
try {
|
|
2154
2266
|
for (const entry of readdirSync2(homeRoot, { withFileTypes: true })) {
|
|
2155
2267
|
if (!entry.isDirectory()) continue;
|
|
@@ -2161,7 +2273,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2161
2273
|
const orphans = [];
|
|
2162
2274
|
const seen = /* @__PURE__ */ new Set();
|
|
2163
2275
|
for (const repoPath of repos) {
|
|
2164
|
-
if (!repoPath || !
|
|
2276
|
+
if (!repoPath || !existsSync6(repoPath)) continue;
|
|
2165
2277
|
try {
|
|
2166
2278
|
const wts = await listWorktrees(repoPath);
|
|
2167
2279
|
for (const wt of wts) {
|
|
@@ -2182,12 +2294,12 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2182
2294
|
}
|
|
2183
2295
|
try {
|
|
2184
2296
|
const root = worktreesRoot(repoPath);
|
|
2185
|
-
if (
|
|
2297
|
+
if (existsSync6(root)) {
|
|
2186
2298
|
for (const entry of readdirSync2(root, { withFileTypes: true })) {
|
|
2187
2299
|
if (!entry.isDirectory()) continue;
|
|
2188
|
-
const path =
|
|
2300
|
+
const path = join7(root, entry.name).replace(/\/$/, "");
|
|
2189
2301
|
if (known.has(path) || seen.has(path)) continue;
|
|
2190
|
-
if (!
|
|
2302
|
+
if (!existsSync6(join7(path, ".git"))) continue;
|
|
2191
2303
|
seen.add(path);
|
|
2192
2304
|
let mtimeMs = 0;
|
|
2193
2305
|
try {
|
|
@@ -2336,8 +2448,8 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
2336
2448
|
}
|
|
2337
2449
|
|
|
2338
2450
|
// src/git/clone-repo.ts
|
|
2339
|
-
import { existsSync as
|
|
2340
|
-
import { basename as basename2, join as
|
|
2451
|
+
import { existsSync as existsSync7 } from "fs";
|
|
2452
|
+
import { basename as basename2, join as join8 } from "path";
|
|
2341
2453
|
import { execa as execa4 } from "execa";
|
|
2342
2454
|
async function cloneRepoIntoSideboard(opts) {
|
|
2343
2455
|
const url = opts.url.trim();
|
|
@@ -2348,8 +2460,8 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
2348
2460
|
name = leaf || "repo";
|
|
2349
2461
|
}
|
|
2350
2462
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
2351
|
-
const dest =
|
|
2352
|
-
if (
|
|
2463
|
+
const dest = join8(sideboardReposDir(), name);
|
|
2464
|
+
if (existsSync7(dest)) {
|
|
2353
2465
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
2354
2466
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
2355
2467
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -2366,13 +2478,13 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
2366
2478
|
}
|
|
2367
2479
|
|
|
2368
2480
|
// src/store/desktop-host.ts
|
|
2369
|
-
import { readFileSync as
|
|
2370
|
-
import { join as
|
|
2481
|
+
import { readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
2482
|
+
import { join as join9 } from "path";
|
|
2371
2483
|
function desktopHostPidPath() {
|
|
2372
|
-
return
|
|
2484
|
+
return join9(appDataDir(), "desktop-host.pid");
|
|
2373
2485
|
}
|
|
2374
2486
|
function claimDesktopHost(pid = process.pid) {
|
|
2375
|
-
|
|
2487
|
+
writeFileSync3(desktopHostPidPath(), `${pid}
|
|
2376
2488
|
`, "utf8");
|
|
2377
2489
|
}
|
|
2378
2490
|
function releaseDesktopHost(pid = process.pid) {
|
|
@@ -2384,7 +2496,7 @@ function releaseDesktopHost(pid = process.pid) {
|
|
|
2384
2496
|
}
|
|
2385
2497
|
function readDesktopHostPid() {
|
|
2386
2498
|
try {
|
|
2387
|
-
const pid = Number.parseInt(
|
|
2499
|
+
const pid = Number.parseInt(readFileSync6(desktopHostPidPath(), "utf8").trim(), 10);
|
|
2388
2500
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
2389
2501
|
return pid;
|
|
2390
2502
|
} catch {
|
|
@@ -2451,7 +2563,7 @@ function notifyParentOfChildHalt(child, status, send) {
|
|
|
2451
2563
|
}
|
|
2452
2564
|
|
|
2453
2565
|
// src/threads/create.ts
|
|
2454
|
-
import { existsSync as
|
|
2566
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2455
2567
|
|
|
2456
2568
|
// src/detect/detect.ts
|
|
2457
2569
|
async function detectAgents() {
|
|
@@ -2622,12 +2734,19 @@ function urlsMatch(a, b) {
|
|
|
2622
2734
|
const norm = (u) => u.trim().replace(/\/+$/, "").toLowerCase();
|
|
2623
2735
|
return Boolean(a && b && norm(a) === norm(b));
|
|
2624
2736
|
}
|
|
2737
|
+
function threadPrUrlMatchesNumber(thread, number) {
|
|
2738
|
+
if (!Number.isFinite(number) || number < 1) return false;
|
|
2739
|
+
const url = (thread.prUrl ?? "").trim();
|
|
2740
|
+
if (!url) return false;
|
|
2741
|
+
return new RegExp(`/pull/${number}(?:/|$|[?#])`, "i").test(url);
|
|
2742
|
+
}
|
|
2625
2743
|
function threadMatchesPr(thread, pr) {
|
|
2626
2744
|
const num = String(pr.number);
|
|
2627
2745
|
if (thread.sourceType === "pr" && normalizeIssueKey(thread.sourceRef ?? "") === num) {
|
|
2628
2746
|
return true;
|
|
2629
2747
|
}
|
|
2630
2748
|
if (thread.prUrl && pr.url && urlsMatch(thread.prUrl, pr.url)) return true;
|
|
2749
|
+
if (threadPrUrlMatchesNumber(thread, pr.number)) return true;
|
|
2631
2750
|
const head = pr.headRefName.trim().toLowerCase();
|
|
2632
2751
|
if (!head) return false;
|
|
2633
2752
|
const branch = (thread.branchName ?? "").trim().toLowerCase();
|
|
@@ -2680,22 +2799,65 @@ function findLiveThreadForCreate(input, threads) {
|
|
|
2680
2799
|
(t) => threadMatchesPr(t, {
|
|
2681
2800
|
number: Number.isFinite(number) ? number : -1,
|
|
2682
2801
|
title: input.title ?? "",
|
|
2683
|
-
url: "",
|
|
2684
|
-
headRefName: ""
|
|
2802
|
+
url: input.prUrl ?? "",
|
|
2803
|
+
headRefName: input.headRefName ?? ""
|
|
2685
2804
|
})
|
|
2686
2805
|
);
|
|
2687
2806
|
}
|
|
2688
2807
|
if (input.sourceType === "branch") {
|
|
2689
2808
|
if (isDefaultBranchCreateRef(input.sourceRef)) return void 0;
|
|
2690
|
-
|
|
2809
|
+
const byBranch = live.find(
|
|
2691
2810
|
(t) => threadMatchesBranch(t, {
|
|
2692
2811
|
ref: input.sourceRef,
|
|
2693
2812
|
repoPath: input.repoPath
|
|
2694
2813
|
})
|
|
2695
2814
|
);
|
|
2815
|
+
if (byBranch) return byBranch;
|
|
2816
|
+
if (input.prUrl || input.headRefName) {
|
|
2817
|
+
const number = Number(normalizeIssueKey(input.sourceRef));
|
|
2818
|
+
return live.find(
|
|
2819
|
+
(t) => threadMatchesPr(t, {
|
|
2820
|
+
number: Number.isFinite(number) ? number : -1,
|
|
2821
|
+
title: input.title ?? "",
|
|
2822
|
+
url: input.prUrl ?? "",
|
|
2823
|
+
headRefName: input.headRefName ?? input.sourceRef
|
|
2824
|
+
})
|
|
2825
|
+
);
|
|
2826
|
+
}
|
|
2827
|
+
return void 0;
|
|
2696
2828
|
}
|
|
2697
2829
|
return void 0;
|
|
2698
2830
|
}
|
|
2831
|
+
function findLiveThreadForCreateSource(source, threads, prs) {
|
|
2832
|
+
const found = findLiveThreadForCreate(
|
|
2833
|
+
{
|
|
2834
|
+
sourceType: source.kind,
|
|
2835
|
+
sourceRef: source.ref,
|
|
2836
|
+
repoPath: source.repoPath,
|
|
2837
|
+
title: source.title,
|
|
2838
|
+
prUrl: source.url,
|
|
2839
|
+
headRefName: source.headRefName
|
|
2840
|
+
},
|
|
2841
|
+
threads
|
|
2842
|
+
);
|
|
2843
|
+
if (found) return found;
|
|
2844
|
+
if (source.kind !== "branch" || !prs?.length) return void 0;
|
|
2845
|
+
if (isDefaultBranchCreateRef(source.ref)) return void 0;
|
|
2846
|
+
const head = normalizeBranchRef(source.ref);
|
|
2847
|
+
const pr = prs.find((p) => normalizeBranchRef(p.headRefName) === head);
|
|
2848
|
+
if (!pr) return void 0;
|
|
2849
|
+
return findLiveThreadForCreate(
|
|
2850
|
+
{
|
|
2851
|
+
sourceType: "pr",
|
|
2852
|
+
sourceRef: String(pr.number),
|
|
2853
|
+
repoPath: source.repoPath,
|
|
2854
|
+
title: pr.title,
|
|
2855
|
+
prUrl: pr.url,
|
|
2856
|
+
headRefName: pr.headRefName
|
|
2857
|
+
},
|
|
2858
|
+
threads
|
|
2859
|
+
);
|
|
2860
|
+
}
|
|
2699
2861
|
function boardPinIdentity(pin) {
|
|
2700
2862
|
const ref = normalizeIssueKey(pin.ref);
|
|
2701
2863
|
if (pin.kind === "ticket" && (pin.provider === "linear" || !pin.repoPath)) {
|
|
@@ -2925,42 +3087,53 @@ function assembleHomeBoard(input) {
|
|
|
2925
3087
|
}
|
|
2926
3088
|
return { columns, hidden, totals };
|
|
2927
3089
|
}
|
|
2928
|
-
var HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards).
|
|
3090
|
+
var HOME_BOARD_AGENT_HINT = "Home is a Kanban of worktrees (one card per checkout; sibling chat tabs nest as inner cards). Do not create a second worktree for a ticket, PR, or named branch that already has a live checkout \u2014 create_thread / start_board_card return that thread (alreadyStarted). Creating from the default branch still opens a new isolated worktree. 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.";
|
|
2929
3091
|
|
|
2930
3092
|
// src/threads/create.ts
|
|
2931
3093
|
function persistCreateAttachments(worktreePath, attachments) {
|
|
2932
3094
|
return persistPendingFileAttachments(worktreePath, attachments ?? []);
|
|
2933
3095
|
}
|
|
3096
|
+
function liveThreadsForCreate() {
|
|
3097
|
+
return listThreads({ includeArchived: false }).map((t) => ({
|
|
3098
|
+
...t,
|
|
3099
|
+
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
3100
|
+
}));
|
|
3101
|
+
}
|
|
3102
|
+
function reuseLiveThread(input, repoPath, match) {
|
|
3103
|
+
if (input.reuseExisting === false) return void 0;
|
|
3104
|
+
const existing = findLiveThreadForCreate(
|
|
3105
|
+
{
|
|
3106
|
+
sourceType: match.sourceType,
|
|
3107
|
+
sourceRef: match.sourceRef,
|
|
3108
|
+
repoPath,
|
|
3109
|
+
title: match.title ?? input.title,
|
|
3110
|
+
cowboy: input.cowboy,
|
|
3111
|
+
prUrl: match.prUrl,
|
|
3112
|
+
headRefName: match.headRefName
|
|
3113
|
+
},
|
|
3114
|
+
liveThreadsForCreate()
|
|
3115
|
+
);
|
|
3116
|
+
if (!existing) return void 0;
|
|
3117
|
+
const thread = readThread(existing.id) ?? existing;
|
|
3118
|
+
if (!input.attachments?.length) return thread;
|
|
3119
|
+
return updateThread(thread.id, {
|
|
3120
|
+
attachments: persistCreateAttachments(thread.worktreePath, [
|
|
3121
|
+
...thread.attachments,
|
|
3122
|
+
...input.attachments
|
|
3123
|
+
])
|
|
3124
|
+
});
|
|
3125
|
+
}
|
|
2934
3126
|
async function createThread(input, _onSetupLine) {
|
|
2935
3127
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
2936
|
-
if (!
|
|
3128
|
+
if (!existsSync8(repoPath)) {
|
|
2937
3129
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
2938
3130
|
}
|
|
2939
|
-
|
|
2940
|
-
|
|
2941
|
-
|
|
2942
|
-
|
|
2943
|
-
|
|
2944
|
-
|
|
2945
|
-
title: input.title,
|
|
2946
|
-
cowboy: input.cowboy
|
|
2947
|
-
},
|
|
2948
|
-
listThreads({ includeArchived: false }).map((t) => ({
|
|
2949
|
-
...t,
|
|
2950
|
-
repoPath: canonicalizeRepoPath(t.repoPath)
|
|
2951
|
-
}))
|
|
2952
|
-
);
|
|
2953
|
-
if (existing) {
|
|
2954
|
-
const thread2 = readThread(existing.id) ?? existing;
|
|
2955
|
-
if (!input.attachments?.length) return thread2;
|
|
2956
|
-
return updateThread(thread2.id, {
|
|
2957
|
-
attachments: persistCreateAttachments(thread2.worktreePath, [
|
|
2958
|
-
...thread2.attachments,
|
|
2959
|
-
...input.attachments
|
|
2960
|
-
])
|
|
2961
|
-
});
|
|
2962
|
-
}
|
|
2963
|
-
}
|
|
3131
|
+
const reused = reuseLiveThread(input, repoPath, {
|
|
3132
|
+
sourceType: input.sourceType,
|
|
3133
|
+
sourceRef: input.sourceRef,
|
|
3134
|
+
title: input.title
|
|
3135
|
+
});
|
|
3136
|
+
if (reused) return reused;
|
|
2964
3137
|
const resolved = resolveNewThreadOptions({
|
|
2965
3138
|
agent: input.agent,
|
|
2966
3139
|
model: input.model,
|
|
@@ -2969,7 +3142,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
2969
3142
|
});
|
|
2970
3143
|
await requireAgent(resolved.agent);
|
|
2971
3144
|
if (input.cowboy) {
|
|
2972
|
-
const { cowboyModeEnabled } = await import("./app-settings-
|
|
3145
|
+
const { cowboyModeEnabled } = await import("./app-settings-H3INSR67.js");
|
|
2973
3146
|
if (!cowboyModeEnabled()) {
|
|
2974
3147
|
throw new Error(
|
|
2975
3148
|
"Cowboy mode is off. Enable it in Settings \u2192 Advanced."
|
|
@@ -3027,7 +3200,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3027
3200
|
let sourceIsFork = false;
|
|
3028
3201
|
if (!input.cowboy && sourceType === "branch" && (!sourceRef || sourceRef === "HEAD" || sourceRef === "default")) {
|
|
3029
3202
|
if (isAbleTimeConnected() && getIssueSource() === "abletime") {
|
|
3030
|
-
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-
|
|
3203
|
+
const { ensureAbleTimeTask, issueAttachmentForAbleTimeTask } = await import("./abletime-H7LPGIP2.js");
|
|
3031
3204
|
const task = await ensureAbleTimeTask({
|
|
3032
3205
|
title: title?.trim() || "Untitled work",
|
|
3033
3206
|
description: input.prompt?.trim() || void 0
|
|
@@ -3037,6 +3210,12 @@ async function createThread(input, _onSetupLine) {
|
|
|
3037
3210
|
persistedSourceRef = task.identifier;
|
|
3038
3211
|
title = title?.trim() || task.title;
|
|
3039
3212
|
attachments = [...attachments, issueAttachmentForAbleTimeTask(task)];
|
|
3213
|
+
const reusedTicket = reuseLiveThread(
|
|
3214
|
+
{ ...input, sourceType: "ticket", sourceRef, title, attachments },
|
|
3215
|
+
repoPath,
|
|
3216
|
+
{ sourceType: "ticket", sourceRef, title }
|
|
3217
|
+
);
|
|
3218
|
+
if (reusedTicket) return reusedTicket;
|
|
3040
3219
|
}
|
|
3041
3220
|
}
|
|
3042
3221
|
let prUrl = null;
|
|
@@ -3046,6 +3225,14 @@ async function createThread(input, _onSetupLine) {
|
|
|
3046
3225
|
if (!Number.isFinite(num)) throw new Error(`Invalid PR number: ${input.sourceRef}`);
|
|
3047
3226
|
const pr = await getPr(repoPath, num);
|
|
3048
3227
|
if (!pr) throw new Error(`PR #${num} not found`);
|
|
3228
|
+
const reusedPr = reuseLiveThread(input, repoPath, {
|
|
3229
|
+
sourceType: "pr",
|
|
3230
|
+
sourceRef: String(pr.number),
|
|
3231
|
+
title: input.title ?? pr.title,
|
|
3232
|
+
prUrl: pr.url,
|
|
3233
|
+
headRefName: pr.headRefName
|
|
3234
|
+
});
|
|
3235
|
+
if (reusedPr) return reusedPr;
|
|
3049
3236
|
sourceIsFork = pr.isCrossRepository;
|
|
3050
3237
|
prUrl = pr.url;
|
|
3051
3238
|
const localFetchBranch = `sideboard-pr-${pr.number}`;
|
|
@@ -3058,9 +3245,19 @@ async function createThread(input, _onSetupLine) {
|
|
|
3058
3245
|
sourceRef = await resolveDefaultBranch(repoPath);
|
|
3059
3246
|
} else {
|
|
3060
3247
|
const existing = await getPrForHeadBranch(repoPath, sourceRef);
|
|
3061
|
-
if (existing
|
|
3062
|
-
|
|
3063
|
-
|
|
3248
|
+
if (existing) {
|
|
3249
|
+
const reusedPr = reuseLiveThread(input, repoPath, {
|
|
3250
|
+
sourceType: "pr",
|
|
3251
|
+
sourceRef: String(existing.number),
|
|
3252
|
+
title: input.title ?? existing.title,
|
|
3253
|
+
prUrl: existing.url,
|
|
3254
|
+
headRefName: existing.headRefName
|
|
3255
|
+
});
|
|
3256
|
+
if (reusedPr) return reusedPr;
|
|
3257
|
+
if (existing.url) {
|
|
3258
|
+
prUrl = existing.url;
|
|
3259
|
+
prTitle = existing.title;
|
|
3260
|
+
}
|
|
3064
3261
|
}
|
|
3065
3262
|
}
|
|
3066
3263
|
} else if (sourceType === "adopt") {
|
|
@@ -3100,7 +3297,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3100
3297
|
return readThread(thread.id) ?? thread;
|
|
3101
3298
|
}
|
|
3102
3299
|
async function listLinearIssues(agent, repoPath) {
|
|
3103
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3300
|
+
const { getAdapter: getAdapter2 } = await import("./agents-YVW75KBO.js");
|
|
3104
3301
|
await requireAgent(agent, { requireLinear: true });
|
|
3105
3302
|
const adapter = getAdapter2(agent);
|
|
3106
3303
|
if (!adapter.listLinearIssues) {
|
|
@@ -3123,11 +3320,11 @@ function shouldRemoveWorktreeOnTeardown(thread) {
|
|
|
3123
3320
|
|
|
3124
3321
|
// src/store/turn-live.ts
|
|
3125
3322
|
import {
|
|
3126
|
-
existsSync as
|
|
3323
|
+
existsSync as existsSync9,
|
|
3127
3324
|
renameSync,
|
|
3128
3325
|
unlinkSync as unlinkSync2,
|
|
3129
|
-
writeFileSync as
|
|
3130
|
-
readFileSync as
|
|
3326
|
+
writeFileSync as writeFileSync4,
|
|
3327
|
+
readFileSync as readFileSync7
|
|
3131
3328
|
} from "fs";
|
|
3132
3329
|
var buffers = /* @__PURE__ */ new Map();
|
|
3133
3330
|
var FLUSH_MS = 800;
|
|
@@ -3204,7 +3401,7 @@ function writeTurnLive(threadId, progress) {
|
|
|
3204
3401
|
const path = threadLivePath(threadId);
|
|
3205
3402
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
3206
3403
|
try {
|
|
3207
|
-
|
|
3404
|
+
writeFileSync4(tmp, JSON.stringify(progress), "utf8");
|
|
3208
3405
|
renameSync(tmp, path);
|
|
3209
3406
|
} catch {
|
|
3210
3407
|
try {
|
|
@@ -3215,9 +3412,9 @@ function writeTurnLive(threadId, progress) {
|
|
|
3215
3412
|
}
|
|
3216
3413
|
function readTurnLive(threadId) {
|
|
3217
3414
|
const path = threadLivePath(threadId);
|
|
3218
|
-
if (!
|
|
3415
|
+
if (!existsSync9(path)) return null;
|
|
3219
3416
|
try {
|
|
3220
|
-
const raw = JSON.parse(
|
|
3417
|
+
const raw = JSON.parse(readFileSync7(path, "utf8"));
|
|
3221
3418
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
3222
3419
|
return raw;
|
|
3223
3420
|
} catch {
|
|
@@ -3229,7 +3426,7 @@ function clearTurnLive(threadId) {
|
|
|
3229
3426
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
3230
3427
|
buffers.delete(threadId);
|
|
3231
3428
|
const path = threadLivePath(threadId);
|
|
3232
|
-
if (!
|
|
3429
|
+
if (!existsSync9(path)) return;
|
|
3233
3430
|
try {
|
|
3234
3431
|
unlinkSync2(path);
|
|
3235
3432
|
} catch {
|
|
@@ -3254,9 +3451,13 @@ function shouldReadThreadToHealReconcile(eventType, lastCheckAt, now) {
|
|
|
3254
3451
|
// src/orchestrator/setup-last-error.ts
|
|
3255
3452
|
function shouldStampSetupLastError(opts) {
|
|
3256
3453
|
if (opts.turnInFlight) return false;
|
|
3257
|
-
if (opts.status === "running") return false;
|
|
3454
|
+
if (opts.status === "running" || opts.status === "queued") return false;
|
|
3455
|
+
if (opts.hasQueuedPrompt) return false;
|
|
3258
3456
|
return true;
|
|
3259
3457
|
}
|
|
3458
|
+
function isSetupLastError(err) {
|
|
3459
|
+
return /^Setup (exited|failed)\b/i.test(err?.trim() ?? "");
|
|
3460
|
+
}
|
|
3260
3461
|
function isStaleLastErrorDuringTurn(err) {
|
|
3261
3462
|
return Boolean(err?.trim());
|
|
3262
3463
|
}
|
|
@@ -3413,26 +3614,26 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
3413
3614
|
import { execFileSync } from "child_process";
|
|
3414
3615
|
import {
|
|
3415
3616
|
copyFileSync as copyFileSync2,
|
|
3416
|
-
existsSync as
|
|
3617
|
+
existsSync as existsSync10,
|
|
3417
3618
|
mkdtempSync,
|
|
3418
3619
|
readdirSync as readdirSync3,
|
|
3419
|
-
readFileSync as
|
|
3620
|
+
readFileSync as readFileSync8,
|
|
3420
3621
|
rmSync
|
|
3421
3622
|
} from "fs";
|
|
3422
3623
|
import { tmpdir } from "os";
|
|
3423
|
-
import { join as
|
|
3624
|
+
import { join as join10 } from "path";
|
|
3424
3625
|
import { createRequire } from "module";
|
|
3425
|
-
var CONDUCTOR_APP_SUPPORT =
|
|
3626
|
+
var CONDUCTOR_APP_SUPPORT = join10(
|
|
3426
3627
|
process.env.HOME ?? "",
|
|
3427
3628
|
"Library",
|
|
3428
3629
|
"Application Support",
|
|
3429
3630
|
"com.conductor.app"
|
|
3430
3631
|
);
|
|
3431
|
-
var CONDUCTOR_DB =
|
|
3432
|
-
var CURSOR_SDK_STORE =
|
|
3632
|
+
var CONDUCTOR_DB = join10(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
3633
|
+
var CURSOR_SDK_STORE = join10(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
3433
3634
|
function thisModuleFile() {
|
|
3434
3635
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
3435
|
-
return cjsFile || process.argv[1] ||
|
|
3636
|
+
return cjsFile || process.argv[1] || join10(process.cwd(), "package.json");
|
|
3436
3637
|
}
|
|
3437
3638
|
function openReadonlySqlite(file) {
|
|
3438
3639
|
const req = createRequire(thisModuleFile());
|
|
@@ -3450,7 +3651,7 @@ function mapAgentType(raw) {
|
|
|
3450
3651
|
return null;
|
|
3451
3652
|
}
|
|
3452
3653
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
3453
|
-
if (!workspacePath || !
|
|
3654
|
+
if (!workspacePath || !existsSync10(CURSOR_SDK_STORE)) return null;
|
|
3454
3655
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
3455
3656
|
let best = null;
|
|
3456
3657
|
let hashes;
|
|
@@ -3460,11 +3661,11 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
3460
3661
|
return null;
|
|
3461
3662
|
}
|
|
3462
3663
|
for (const hash of hashes) {
|
|
3463
|
-
const agentsFile =
|
|
3464
|
-
if (!
|
|
3664
|
+
const agentsFile = join10(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
3665
|
+
if (!existsSync10(agentsFile)) continue;
|
|
3465
3666
|
let text;
|
|
3466
3667
|
try {
|
|
3467
|
-
text =
|
|
3668
|
+
text = readFileSync8(agentsFile, "utf8");
|
|
3468
3669
|
} catch {
|
|
3469
3670
|
continue;
|
|
3470
3671
|
}
|
|
@@ -3488,7 +3689,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
3488
3689
|
return best?.agentId ?? null;
|
|
3489
3690
|
}
|
|
3490
3691
|
async function adoptThread(input) {
|
|
3491
|
-
if (!
|
|
3692
|
+
if (!existsSync10(input.worktreePath)) {
|
|
3492
3693
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
3493
3694
|
}
|
|
3494
3695
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -3507,7 +3708,7 @@ async function adoptThread(input) {
|
|
|
3507
3708
|
messages: input.messages ?? []
|
|
3508
3709
|
});
|
|
3509
3710
|
writeThread(thread);
|
|
3510
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
3711
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-5UNDTN4G.js");
|
|
3511
3712
|
await ensureWorkspace2(repoPath);
|
|
3512
3713
|
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
|
|
3513
3714
|
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
@@ -3517,16 +3718,16 @@ function conductorDbPath() {
|
|
|
3517
3718
|
return CONDUCTOR_DB;
|
|
3518
3719
|
}
|
|
3519
3720
|
function listConductorWorkspaces() {
|
|
3520
|
-
if (!
|
|
3721
|
+
if (!existsSync10(CONDUCTOR_DB)) {
|
|
3521
3722
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
3522
3723
|
}
|
|
3523
|
-
const tmp = mkdtempSync(
|
|
3524
|
-
const snapshot =
|
|
3724
|
+
const tmp = mkdtempSync(join10(tmpdir(), "sideboard-conductor-"));
|
|
3725
|
+
const snapshot = join10(tmp, "conductor.db");
|
|
3525
3726
|
try {
|
|
3526
3727
|
copyFileSync2(CONDUCTOR_DB, snapshot);
|
|
3527
3728
|
for (const suffix of ["-wal", "-shm"]) {
|
|
3528
3729
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
3529
|
-
if (
|
|
3730
|
+
if (existsSync10(src)) {
|
|
3530
3731
|
try {
|
|
3531
3732
|
copyFileSync2(src, `${snapshot}${suffix}`);
|
|
3532
3733
|
} catch {
|
|
@@ -3608,16 +3809,16 @@ function listConductorWorkspaces() {
|
|
|
3608
3809
|
}
|
|
3609
3810
|
}
|
|
3610
3811
|
function importConductorWorkspace(workspaceId) {
|
|
3611
|
-
if (!
|
|
3812
|
+
if (!existsSync10(CONDUCTOR_DB)) {
|
|
3612
3813
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
3613
3814
|
}
|
|
3614
|
-
const tmp = mkdtempSync(
|
|
3615
|
-
const snapshot =
|
|
3815
|
+
const tmp = mkdtempSync(join10(tmpdir(), "sideboard-conductor-"));
|
|
3816
|
+
const snapshot = join10(tmp, "conductor.db");
|
|
3616
3817
|
try {
|
|
3617
3818
|
copyFileSync2(CONDUCTOR_DB, snapshot);
|
|
3618
3819
|
for (const suffix of ["-wal", "-shm"]) {
|
|
3619
3820
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
3620
|
-
if (
|
|
3821
|
+
if (existsSync10(src)) {
|
|
3621
3822
|
try {
|
|
3622
3823
|
copyFileSync2(src, `${snapshot}${suffix}`);
|
|
3623
3824
|
} catch {
|
|
@@ -3637,7 +3838,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
3637
3838
|
).get(workspaceId);
|
|
3638
3839
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
3639
3840
|
const worktreePath = String(row.workspacePath);
|
|
3640
|
-
if (!
|
|
3841
|
+
if (!existsSync10(worktreePath)) {
|
|
3641
3842
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
3642
3843
|
}
|
|
3643
3844
|
let sessionId = null;
|
|
@@ -3708,7 +3909,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
3708
3909
|
}
|
|
3709
3910
|
|
|
3710
3911
|
// src/threads/stack-layers.ts
|
|
3711
|
-
import { existsSync as
|
|
3912
|
+
import { existsSync as existsSync11 } from "fs";
|
|
3712
3913
|
function stackIdFrom(stack) {
|
|
3713
3914
|
if (stack.stackNumber != null) return `gh-stack-${stack.stackNumber}`;
|
|
3714
3915
|
const key = stack.layers.map((l) => l.branchName).join("|");
|
|
@@ -3771,7 +3972,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
3771
3972
|
let createdWorktree = false;
|
|
3772
3973
|
const trees = await listWorktrees(repoPath);
|
|
3773
3974
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
3774
|
-
if (checkedOut?.path &&
|
|
3975
|
+
if (checkedOut?.path && existsSync11(checkedOut.path)) {
|
|
3775
3976
|
if (input.reuseExistingWorktree !== false) {
|
|
3776
3977
|
worktreePath = checkedOut.path;
|
|
3777
3978
|
} else {
|
|
@@ -3913,7 +4114,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
3913
4114
|
async function createPrStack(input, onSetupLine) {
|
|
3914
4115
|
await requireAgent(input.agent);
|
|
3915
4116
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
3916
|
-
if (!
|
|
4117
|
+
if (!existsSync11(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
3917
4118
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
3918
4119
|
const status = await detectGhStack(repoPath);
|
|
3919
4120
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -3980,7 +4181,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
3980
4181
|
}
|
|
3981
4182
|
}
|
|
3982
4183
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
3983
|
-
if (!claimed.has(bootstrap.worktreePath) &&
|
|
4184
|
+
if (!claimed.has(bootstrap.worktreePath) && existsSync11(bootstrap.worktreePath)) {
|
|
3984
4185
|
try {
|
|
3985
4186
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
3986
4187
|
deleteBranch: bootstrap.branchName
|
|
@@ -4002,10 +4203,10 @@ function stackAgentDefaultsFrom(input) {
|
|
|
4002
4203
|
}
|
|
4003
4204
|
|
|
4004
4205
|
// src/diff/diff.ts
|
|
4005
|
-
import { existsSync as
|
|
4006
|
-
import { dirname as dirname3, join as
|
|
4206
|
+
import { existsSync as existsSync12, mkdirSync as mkdirSync3, readFileSync as readFileSync9, statSync as statSync2, writeFileSync as writeFileSync5 } from "fs";
|
|
4207
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
4007
4208
|
async function inspectGitWorktree(worktreePath) {
|
|
4008
|
-
if (!worktreePath || !
|
|
4209
|
+
if (!worktreePath || !existsSync12(worktreePath)) return "missing_worktree";
|
|
4009
4210
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
4010
4211
|
reject: false
|
|
4011
4212
|
});
|
|
@@ -4013,7 +4214,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
4013
4214
|
return "ok";
|
|
4014
4215
|
}
|
|
4015
4216
|
async function initializeGitRepository(worktreePath) {
|
|
4016
|
-
if (!worktreePath || !
|
|
4217
|
+
if (!worktreePath || !existsSync12(worktreePath)) {
|
|
4017
4218
|
throw new Error("Worktree not found");
|
|
4018
4219
|
}
|
|
4019
4220
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -4149,11 +4350,11 @@ new file mode 100644
|
|
|
4149
4350
|
};
|
|
4150
4351
|
}
|
|
4151
4352
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
4152
|
-
const abs =
|
|
4353
|
+
const abs = join11(worktreePath, path);
|
|
4153
4354
|
try {
|
|
4154
4355
|
const st = statSync2(abs);
|
|
4155
4356
|
if (st.isFile() && st.size > maxHunk) {
|
|
4156
|
-
const buf =
|
|
4357
|
+
const buf = readFileSync9(abs).subarray(0, maxHunk);
|
|
4157
4358
|
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
4158
4359
|
}
|
|
4159
4360
|
} catch {
|
|
@@ -4654,7 +4855,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
4654
4855
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
4655
4856
|
assertSafeRelativePath(relativePath);
|
|
4656
4857
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
4657
|
-
const abs =
|
|
4858
|
+
const abs = join11(worktreePath, relativePath);
|
|
4658
4859
|
const st = statSync2(abs);
|
|
4659
4860
|
if (!st.isFile()) {
|
|
4660
4861
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -4664,7 +4865,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
4664
4865
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
4665
4866
|
);
|
|
4666
4867
|
}
|
|
4667
|
-
const buf =
|
|
4868
|
+
const buf = readFileSync9(abs);
|
|
4668
4869
|
return {
|
|
4669
4870
|
path: relativePath,
|
|
4670
4871
|
contentBase64: buf.toString("base64"),
|
|
@@ -4674,12 +4875,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
4674
4875
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
4675
4876
|
assertSafeRelativePath(relativePath);
|
|
4676
4877
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
4677
|
-
const abs =
|
|
4878
|
+
const abs = join11(worktreePath, relativePath);
|
|
4678
4879
|
const st = statSync2(abs);
|
|
4679
4880
|
if (!st.isFile()) {
|
|
4680
4881
|
throw new Error(`Not a file: ${relativePath}`);
|
|
4681
4882
|
}
|
|
4682
|
-
const buf =
|
|
4883
|
+
const buf = readFileSync9(abs);
|
|
4683
4884
|
if (isImageRelativePath(relativePath)) {
|
|
4684
4885
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
4685
4886
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -4722,9 +4923,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
4722
4923
|
}
|
|
4723
4924
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
4724
4925
|
assertSafeRelativePath(relativePath);
|
|
4725
|
-
const abs =
|
|
4926
|
+
const abs = join11(worktreePath, relativePath);
|
|
4726
4927
|
mkdirSync3(dirname3(abs), { recursive: true });
|
|
4727
|
-
|
|
4928
|
+
writeFileSync5(abs, content, "utf8");
|
|
4728
4929
|
return { path: relativePath };
|
|
4729
4930
|
}
|
|
4730
4931
|
async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
@@ -4849,9 +5050,9 @@ async function confirmLand(thread, opts) {
|
|
|
4849
5050
|
}
|
|
4850
5051
|
|
|
4851
5052
|
// src/skills/discover.ts
|
|
4852
|
-
import { existsSync as
|
|
5053
|
+
import { existsSync as existsSync13, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync3 } from "fs";
|
|
4853
5054
|
import { homedir } from "os";
|
|
4854
|
-
import { join as
|
|
5055
|
+
import { join as join12 } from "path";
|
|
4855
5056
|
|
|
4856
5057
|
// src/skills/bundled/long-running.ts
|
|
4857
5058
|
var LONG_RUNNING_SKILL_COMMAND = "long-running";
|
|
@@ -4980,7 +5181,7 @@ function parseFrontmatter(content) {
|
|
|
4980
5181
|
}
|
|
4981
5182
|
function readSkill(skillMd, source) {
|
|
4982
5183
|
try {
|
|
4983
|
-
const content =
|
|
5184
|
+
const content = readFileSync10(skillMd, "utf8");
|
|
4984
5185
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
4985
5186
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
4986
5187
|
const name = fmName || dirName;
|
|
@@ -4999,7 +5200,7 @@ function readSkill(skillMd, source) {
|
|
|
4999
5200
|
}
|
|
5000
5201
|
}
|
|
5001
5202
|
function scanSkillsDir(dir, source, out) {
|
|
5002
|
-
if (!
|
|
5203
|
+
if (!existsSync13(dir)) return;
|
|
5003
5204
|
let entries;
|
|
5004
5205
|
try {
|
|
5005
5206
|
entries = readdirSync4(dir);
|
|
@@ -5008,8 +5209,8 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5008
5209
|
}
|
|
5009
5210
|
for (const entry of entries) {
|
|
5010
5211
|
if (entry.startsWith(".")) continue;
|
|
5011
|
-
const skillMd =
|
|
5012
|
-
if (!
|
|
5212
|
+
const skillMd = join12(dir, entry, "SKILL.md");
|
|
5213
|
+
if (!existsSync13(skillMd)) continue;
|
|
5013
5214
|
try {
|
|
5014
5215
|
if (!statSync3(skillMd).isFile()) continue;
|
|
5015
5216
|
} catch {
|
|
@@ -5020,7 +5221,7 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5020
5221
|
}
|
|
5021
5222
|
}
|
|
5022
5223
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
5023
|
-
if (!
|
|
5224
|
+
if (!existsSync13(pluginsRoot)) return;
|
|
5024
5225
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
5025
5226
|
if (depth > 7) return;
|
|
5026
5227
|
let entries;
|
|
@@ -5030,12 +5231,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
5030
5231
|
return;
|
|
5031
5232
|
}
|
|
5032
5233
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
5033
|
-
const skill = readSkill(
|
|
5234
|
+
const skill = readSkill(join12(dir, "SKILL.md"), "cli");
|
|
5034
5235
|
if (skill) out.push(skill);
|
|
5035
5236
|
}
|
|
5036
5237
|
for (const entry of entries) {
|
|
5037
5238
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
5038
|
-
const full =
|
|
5239
|
+
const full = join12(dir, entry);
|
|
5039
5240
|
try {
|
|
5040
5241
|
if (!statSync3(full).isDirectory()) continue;
|
|
5041
5242
|
} catch {
|
|
@@ -5055,17 +5256,17 @@ function discoverSkills(worktreePath) {
|
|
|
5055
5256
|
const home = homedir();
|
|
5056
5257
|
const collected = [];
|
|
5057
5258
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
5058
|
-
scanSkillsDir(
|
|
5259
|
+
scanSkillsDir(join12(worktreePath, rel), "workspace", collected);
|
|
5059
5260
|
}
|
|
5060
5261
|
for (const abs of [
|
|
5061
|
-
|
|
5062
|
-
|
|
5063
|
-
|
|
5064
|
-
|
|
5262
|
+
join12(home, ".claude/skills"),
|
|
5263
|
+
join12(home, ".cursor/skills"),
|
|
5264
|
+
join12(home, ".sideboard/skills"),
|
|
5265
|
+
join12(home, ".brightsy/skills")
|
|
5065
5266
|
]) {
|
|
5066
5267
|
scanSkillsDir(abs, "user", collected);
|
|
5067
5268
|
}
|
|
5068
|
-
scanClaudePluginSkills(
|
|
5269
|
+
scanClaudePluginSkills(join12(home, ".claude/plugins"), collected);
|
|
5069
5270
|
collected.push(...bundledSkills());
|
|
5070
5271
|
const rank = {
|
|
5071
5272
|
workspace: 0,
|
|
@@ -5091,7 +5292,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
5091
5292
|
\u2026(truncated)` : body;
|
|
5092
5293
|
}
|
|
5093
5294
|
}
|
|
5094
|
-
const raw =
|
|
5295
|
+
const raw = readFileSync10(skillPath, "utf8");
|
|
5095
5296
|
if (raw.startsWith("---")) {
|
|
5096
5297
|
const end = raw.indexOf("\n---", 3);
|
|
5097
5298
|
if (end >= 0) {
|
|
@@ -5184,26 +5385,26 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
5184
5385
|
}
|
|
5185
5386
|
|
|
5186
5387
|
// src/agents/instructions.ts
|
|
5187
|
-
import { existsSync as
|
|
5188
|
-
import { join as
|
|
5388
|
+
import { existsSync as existsSync15, readFileSync as readFileSync11, statSync as statSync4 } from "fs";
|
|
5389
|
+
import { join as join14 } from "path";
|
|
5189
5390
|
|
|
5190
5391
|
// src/skills/detached-job-path.ts
|
|
5191
|
-
import { existsSync as
|
|
5192
|
-
import { dirname as dirname4, join as
|
|
5392
|
+
import { existsSync as existsSync14 } from "fs";
|
|
5393
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
5193
5394
|
import { fileURLToPath } from "url";
|
|
5194
5395
|
function packagedDetachedJobPath() {
|
|
5195
5396
|
const dir = packagedMcpDir();
|
|
5196
5397
|
if (!dir) return null;
|
|
5197
|
-
const script =
|
|
5198
|
-
return
|
|
5398
|
+
const script = join13(dir, "scripts", "detached-job.js");
|
|
5399
|
+
return existsSync14(script) ? script : null;
|
|
5199
5400
|
}
|
|
5200
5401
|
function resolveDetachedJobScript() {
|
|
5201
5402
|
const packaged = packagedDetachedJobPath();
|
|
5202
5403
|
if (packaged) return packaged;
|
|
5203
5404
|
let dir = dirname4(fileURLToPath(import.meta.url));
|
|
5204
5405
|
for (let i = 0; i < 8; i++) {
|
|
5205
|
-
const candidate =
|
|
5206
|
-
if (
|
|
5406
|
+
const candidate = join13(dir, "scripts", "detached-job.js");
|
|
5407
|
+
if (existsSync14(candidate)) return candidate;
|
|
5207
5408
|
const parent = dirname4(dir);
|
|
5208
5409
|
if (parent === dir) break;
|
|
5209
5410
|
dir = parent;
|
|
@@ -5408,11 +5609,11 @@ function loadAgentInstructions(worktreePath, agent) {
|
|
|
5408
5609
|
const out = [];
|
|
5409
5610
|
for (const rel of candidates) {
|
|
5410
5611
|
if (seenPaths.has(rel)) continue;
|
|
5411
|
-
const abs =
|
|
5412
|
-
if (!
|
|
5612
|
+
const abs = join14(worktreePath, rel);
|
|
5613
|
+
if (!existsSync15(abs)) continue;
|
|
5413
5614
|
try {
|
|
5414
5615
|
if (!statSync4(abs).isFile()) continue;
|
|
5415
|
-
let content =
|
|
5616
|
+
let content = readFileSync11(abs, "utf8");
|
|
5416
5617
|
if (!content.trim()) continue;
|
|
5417
5618
|
if (content.length > MAX_CHARS_PER_FILE) {
|
|
5418
5619
|
content = `${content.slice(0, MAX_CHARS_PER_FILE)}
|
|
@@ -5732,8 +5933,8 @@ async function syncThreadBranchFromGit(threadId) {
|
|
|
5732
5933
|
|
|
5733
5934
|
// src/store/schedules.ts
|
|
5734
5935
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
5735
|
-
import { existsSync as
|
|
5736
|
-
import { join as
|
|
5936
|
+
import { existsSync as existsSync16, readFileSync as readFileSync12 } from "fs";
|
|
5937
|
+
import { join as join15 } from "path";
|
|
5737
5938
|
import { Cron } from "croner";
|
|
5738
5939
|
var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
|
|
5739
5940
|
var UNIT_MS = {
|
|
@@ -5743,7 +5944,7 @@ var UNIT_MS = {
|
|
|
5743
5944
|
d: 864e5
|
|
5744
5945
|
};
|
|
5745
5946
|
function schedulesPath() {
|
|
5746
|
-
return
|
|
5947
|
+
return join15(appDataDir(), "schedules.json");
|
|
5747
5948
|
}
|
|
5748
5949
|
function parseDurationMs(every) {
|
|
5749
5950
|
const m = every.trim().match(DURATION_RE);
|
|
@@ -5849,9 +6050,9 @@ function normalizeTask(raw) {
|
|
|
5849
6050
|
}
|
|
5850
6051
|
function readAll() {
|
|
5851
6052
|
const path = schedulesPath();
|
|
5852
|
-
if (!
|
|
6053
|
+
if (!existsSync16(path)) return [];
|
|
5853
6054
|
try {
|
|
5854
|
-
const parsed = JSON.parse(
|
|
6055
|
+
const parsed = JSON.parse(readFileSync12(path, "utf8"));
|
|
5855
6056
|
if (!Array.isArray(parsed)) return [];
|
|
5856
6057
|
return parsed.map((row) => {
|
|
5857
6058
|
try {
|
|
@@ -5977,7 +6178,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
5977
6178
|
${prompt}`;
|
|
5978
6179
|
}
|
|
5979
6180
|
async function defaultDeps() {
|
|
5980
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6181
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-HC7XVGJB.js");
|
|
5981
6182
|
const orch = getOrchestrator2();
|
|
5982
6183
|
return {
|
|
5983
6184
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -6217,7 +6418,7 @@ var Orchestrator = class {
|
|
|
6217
6418
|
}
|
|
6218
6419
|
continue;
|
|
6219
6420
|
}
|
|
6220
|
-
if (!
|
|
6421
|
+
if (!existsSync17(thread.worktreePath)) {
|
|
6221
6422
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
6222
6423
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
6223
6424
|
continue;
|
|
@@ -6236,7 +6437,7 @@ var Orchestrator = class {
|
|
|
6236
6437
|
orphans: orphans.map((o) => ({ path: o.path, repoPath: o.repoPath }))
|
|
6237
6438
|
});
|
|
6238
6439
|
}
|
|
6239
|
-
const { autoCleanupOrphansEnabled } = await import("./app-settings-
|
|
6440
|
+
const { autoCleanupOrphansEnabled } = await import("./app-settings-H3INSR67.js");
|
|
6240
6441
|
if (autoCleanupOrphansEnabled() && shouldRunWorktreeCleanup() && orphans.length > 0) {
|
|
6241
6442
|
await cleanupOrphanWorktrees({ repoPaths });
|
|
6242
6443
|
}
|
|
@@ -6476,7 +6677,7 @@ var Orchestrator = class {
|
|
|
6476
6677
|
}
|
|
6477
6678
|
await setup;
|
|
6478
6679
|
if (skipSetup) return;
|
|
6479
|
-
const { autoRunAfterSetupEnabled } = await import("./app-settings-
|
|
6680
|
+
const { autoRunAfterSetupEnabled } = await import("./app-settings-H3INSR67.js");
|
|
6480
6681
|
if (autoRunAfterSetupEnabled()) {
|
|
6481
6682
|
try {
|
|
6482
6683
|
await this.startDev(threadId);
|
|
@@ -6487,21 +6688,11 @@ var Orchestrator = class {
|
|
|
6487
6688
|
/** Run workspace setup after a new worktree is created (no-op if none configured). */
|
|
6488
6689
|
async runSetupAfterCreate(threadId) {
|
|
6489
6690
|
try {
|
|
6490
|
-
await this.runSetup(threadId);
|
|
6691
|
+
await this.runSetup(threadId, { stampLastError: false });
|
|
6491
6692
|
} catch (err) {
|
|
6492
6693
|
const message = err instanceof Error ? err.message : String(err);
|
|
6493
6694
|
if (/no setup script/i.test(message)) return;
|
|
6494
6695
|
if (/already running/i.test(message)) return;
|
|
6495
|
-
const live = readThread(threadId);
|
|
6496
|
-
if (!shouldStampSetupLastError({
|
|
6497
|
-
turnInFlight: this.activeTurns.has(threadId) || this.startingTurns.has(threadId),
|
|
6498
|
-
status: live?.status
|
|
6499
|
-
})) {
|
|
6500
|
-
return;
|
|
6501
|
-
}
|
|
6502
|
-
updateThread(threadId, {
|
|
6503
|
-
lastError: `Setup failed: ${message}`
|
|
6504
|
-
});
|
|
6505
6696
|
}
|
|
6506
6697
|
}
|
|
6507
6698
|
listWorkspaces() {
|
|
@@ -6784,7 +6975,7 @@ var Orchestrator = class {
|
|
|
6784
6975
|
}
|
|
6785
6976
|
const isBrightsy = fresh.agent === "brightsy";
|
|
6786
6977
|
const isOrchestration = isOrchestratorThread(fresh);
|
|
6787
|
-
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-
|
|
6978
|
+
const { autoRenameBranchEnabled, getGithubGitAuthMode } = await import("./app-settings-H3INSR67.js");
|
|
6788
6979
|
const gitAuthMode = getGithubGitAuthMode();
|
|
6789
6980
|
const worktreeDirective = isBrightsy || isOrchestration ? null : formatWorktreeDirective(fresh, {
|
|
6790
6981
|
githubSlug: await resolveGithubRepoSlug(fresh.worktreePath).catch(
|
|
@@ -6890,7 +7081,7 @@ var Orchestrator = class {
|
|
|
6890
7081
|
if (!this.stoppedTurns.has(threadId) && this.requireThread(threadId).agent === "cursor" && exitCode !== 0 && !assistantText && parts.length === 0) {
|
|
6891
7082
|
const sessionId = result.sessionId || this.requireThread(threadId).sessionId || "";
|
|
6892
7083
|
if (sessionId) {
|
|
6893
|
-
const { recoverFinishedCursorRun } = await import("./cursor-recover-
|
|
7084
|
+
const { recoverFinishedCursorRun } = await import("./cursor-recover-NDMLLNYX.js");
|
|
6894
7085
|
for (let i = 0; i < 8; i++) {
|
|
6895
7086
|
const recovered = recoverFinishedCursorRun({
|
|
6896
7087
|
agentId: sessionId,
|
|
@@ -7280,7 +7471,16 @@ var Orchestrator = class {
|
|
|
7280
7471
|
getActiveRuns(threadRef) {
|
|
7281
7472
|
return this.requireThread(threadRef).activeRuns ?? [];
|
|
7282
7473
|
}
|
|
7283
|
-
|
|
7474
|
+
getSetupLog(threadRef) {
|
|
7475
|
+
const thread = this.getThread(threadRef);
|
|
7476
|
+
if (!thread) return readSetupLog(threadRef);
|
|
7477
|
+
const snap = readSetupLog(thread.id);
|
|
7478
|
+
if (snap.running && !this.processes.has(`${thread.id}:setup`)) {
|
|
7479
|
+
return { ...snap, running: false };
|
|
7480
|
+
}
|
|
7481
|
+
return snap;
|
|
7482
|
+
}
|
|
7483
|
+
async runSetup(threadRef, opts) {
|
|
7284
7484
|
const thread = this.requireThread(threadRef);
|
|
7285
7485
|
this.assertNotGlobal(thread, "Setup");
|
|
7286
7486
|
const key = `${thread.id}:setup`;
|
|
@@ -7293,34 +7493,49 @@ var Orchestrator = class {
|
|
|
7293
7493
|
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7294
7494
|
kill: () => abort.abort()
|
|
7295
7495
|
});
|
|
7496
|
+
beginSetupLog(thread.id);
|
|
7296
7497
|
this.emit({ type: "setup_started", threadId: thread.id });
|
|
7498
|
+
let finished = false;
|
|
7499
|
+
const finish = (exitCode, source) => {
|
|
7500
|
+
if (finished) return;
|
|
7501
|
+
finished = true;
|
|
7502
|
+
finishSetupLog(thread.id, exitCode, source);
|
|
7503
|
+
this.emit({ type: "setup_finished", threadId: thread.id, exitCode });
|
|
7504
|
+
};
|
|
7297
7505
|
try {
|
|
7298
7506
|
const setup = await runWorkspaceSetup(
|
|
7299
7507
|
thread.repoPath,
|
|
7300
7508
|
thread.worktreePath,
|
|
7301
7509
|
(line) => {
|
|
7510
|
+
appendSetupLog(thread.id, line);
|
|
7302
7511
|
this.emit({ type: "setup_output", threadId: thread.id, line });
|
|
7303
7512
|
},
|
|
7304
7513
|
{ signal: abort.signal }
|
|
7305
7514
|
);
|
|
7306
7515
|
if (!setup.ran) {
|
|
7307
|
-
|
|
7308
|
-
|
|
7309
|
-
);
|
|
7516
|
+
const line = "No setup script in .sideboard/settings.toml, .conductor/settings.toml, .cursor/worktrees.json, or script/setup (bin/setup, scripts/setup)";
|
|
7517
|
+
appendSetupLog(thread.id, line);
|
|
7518
|
+
this.emit({ type: "setup_output", threadId: thread.id, line });
|
|
7519
|
+
finish(null, null);
|
|
7520
|
+
throw new Error(line);
|
|
7310
7521
|
}
|
|
7311
7522
|
if (setup.exitCode !== 0 && setup.exitCode !== null) {
|
|
7312
7523
|
const live = readThread(thread.id);
|
|
7313
|
-
if (shouldStampSetupLastError({
|
|
7524
|
+
if ((opts?.stampLastError ?? true) && shouldStampSetupLastError({
|
|
7314
7525
|
turnInFlight: this.activeTurns.has(thread.id) || this.startingTurns.has(thread.id),
|
|
7315
|
-
status: live?.status
|
|
7526
|
+
status: live?.status,
|
|
7527
|
+
hasQueuedPrompt: Boolean(live?.queue?.length)
|
|
7316
7528
|
})) {
|
|
7317
7529
|
updateThread(thread.id, {
|
|
7318
7530
|
lastError: `Setup exited ${setup.exitCode}`
|
|
7319
7531
|
});
|
|
7320
7532
|
}
|
|
7321
7533
|
}
|
|
7322
|
-
|
|
7534
|
+
finish(setup.exitCode, setup.source);
|
|
7323
7535
|
return { exitCode: setup.exitCode, source: setup.source };
|
|
7536
|
+
} catch (err) {
|
|
7537
|
+
finish(null, null);
|
|
7538
|
+
throw err;
|
|
7324
7539
|
} finally {
|
|
7325
7540
|
this.processes.delete(key);
|
|
7326
7541
|
}
|
|
@@ -7647,7 +7862,7 @@ var Orchestrator = class {
|
|
|
7647
7862
|
updateThread(thread.id, { title: meta.title });
|
|
7648
7863
|
}
|
|
7649
7864
|
}
|
|
7650
|
-
const { autoArchiveOnMergeEnabled } = await import("./app-settings-
|
|
7865
|
+
const { autoArchiveOnMergeEnabled } = await import("./app-settings-H3INSR67.js");
|
|
7651
7866
|
const latest = this.requireThread(thread.id);
|
|
7652
7867
|
if (!shouldAutoArchiveOnPrMerge({
|
|
7653
7868
|
previousPrState: prevState || null,
|
|
@@ -7964,7 +8179,7 @@ var Orchestrator = class {
|
|
|
7964
8179
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
7965
8180
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
7966
8181
|
try {
|
|
7967
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
8182
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-5UNDTN4G.js");
|
|
7968
8183
|
await ensureWorkspace2(thread.repoPath);
|
|
7969
8184
|
} catch {
|
|
7970
8185
|
}
|
|
@@ -7991,7 +8206,7 @@ var Orchestrator = class {
|
|
|
7991
8206
|
await runArchiveScript(thread.repoPath, thread.worktreePath);
|
|
7992
8207
|
} catch {
|
|
7993
8208
|
}
|
|
7994
|
-
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-
|
|
8209
|
+
const { deleteBranchOnPurgeEnabled } = await import("./app-settings-H3INSR67.js");
|
|
7995
8210
|
const deleteBranch = opts?.deleteBranch ?? deleteBranchOnPurgeEnabled();
|
|
7996
8211
|
await removeWorktree(thread.repoPath, thread.worktreePath, {
|
|
7997
8212
|
deleteBranch: deleteBranch ? thread.branchName : void 0
|
|
@@ -8006,19 +8221,19 @@ var Orchestrator = class {
|
|
|
8006
8221
|
throw new Error("Thread is not archived");
|
|
8007
8222
|
}
|
|
8008
8223
|
if (isGlobalThread(thread)) {
|
|
8009
|
-
const { globalAgentCwd } = await import("./paths-
|
|
8224
|
+
const { globalAgentCwd } = await import("./paths-53TLA7VQ.js");
|
|
8010
8225
|
updateThread(thread.id, { worktreePath: globalAgentCwd() });
|
|
8011
8226
|
const restored2 = setStatus(thread.id, "idle");
|
|
8012
8227
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
8013
8228
|
return restored2;
|
|
8014
8229
|
}
|
|
8015
|
-
if (!
|
|
8230
|
+
if (!existsSync17(thread.worktreePath)) {
|
|
8016
8231
|
if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
|
|
8017
8232
|
throw new Error(
|
|
8018
8233
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
8019
8234
|
);
|
|
8020
8235
|
}
|
|
8021
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
8236
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-T4SWFSTT.js");
|
|
8022
8237
|
const slug = thread.worktreePath.split("/").pop();
|
|
8023
8238
|
const dest = thread.worktreePath;
|
|
8024
8239
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -8128,7 +8343,7 @@ async function startOrchestration(opts) {
|
|
|
8128
8343
|
sourceRef: "default",
|
|
8129
8344
|
...createOpts
|
|
8130
8345
|
}).catch(async () => {
|
|
8131
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
8346
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-T4SWFSTT.js");
|
|
8132
8347
|
const repo = await resolveRepoRoot2(repoPath);
|
|
8133
8348
|
const def = await resolveDefaultBranch2(repo);
|
|
8134
8349
|
return orch.createThread({
|
|
@@ -8138,7 +8353,7 @@ async function startOrchestration(opts) {
|
|
|
8138
8353
|
repoPath: repo
|
|
8139
8354
|
});
|
|
8140
8355
|
});
|
|
8141
|
-
const { updateThread: upd } = await import("./thread-store-
|
|
8356
|
+
const { updateThread: upd } = await import("./thread-store-KBFBHT5G.js");
|
|
8142
8357
|
const updated = upd(thread.id, {
|
|
8143
8358
|
sourceType: "orchestration",
|
|
8144
8359
|
sourceRef: goal
|
|
@@ -8150,6 +8365,9 @@ async function startOrchestration(opts) {
|
|
|
8150
8365
|
}
|
|
8151
8366
|
|
|
8152
8367
|
export {
|
|
8368
|
+
emptySetupLog,
|
|
8369
|
+
mergeSetupOutput,
|
|
8370
|
+
readSetupLog,
|
|
8153
8371
|
schedulesPath,
|
|
8154
8372
|
parseDurationMs,
|
|
8155
8373
|
defaultScheduleName,
|
|
@@ -8284,6 +8502,7 @@ export {
|
|
|
8284
8502
|
issueNeedsWorkspacePick,
|
|
8285
8503
|
isAccountWideIssueSource,
|
|
8286
8504
|
findLiveThreadForCreate,
|
|
8505
|
+
findLiveThreadForCreateSource,
|
|
8287
8506
|
boardPinIdentity,
|
|
8288
8507
|
findBoardPin,
|
|
8289
8508
|
syncBoardPins,
|
|
@@ -8298,6 +8517,9 @@ export {
|
|
|
8298
8517
|
isPrimaryCheckoutThread,
|
|
8299
8518
|
shouldRemoveWorktreeOnTeardown,
|
|
8300
8519
|
readTurnLive,
|
|
8520
|
+
shouldStampSetupLastError,
|
|
8521
|
+
isSetupLastError,
|
|
8522
|
+
isStaleLastErrorDuringTurn,
|
|
8301
8523
|
forkThreadWorktree,
|
|
8302
8524
|
resolveConductorCursorAgentId,
|
|
8303
8525
|
adoptThread,
|