@sideboard-ai/core 0.1.172 → 0.1.174
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-CTWLBPCV.js → agents-LMPVUPOH.js} +3 -3
- package/dist/{agents-7UTRNLXQ.js → agents-ZWYRGFZB.js} +3 -3
- package/dist/{chunk-QYZYDO3F.js → chunk-7JIYKYLL.js} +26 -5
- package/dist/{chunk-PXNOT6NV.js → chunk-7O53GXTA.js} +26 -5
- package/dist/{chunk-3F7AXVIL.js → chunk-CUA4S537.js} +3 -3
- package/dist/{chunk-QYJS7LYE.js → chunk-HJPGIETB.js} +204 -145
- package/dist/{chunk-6X6KMUI2.js → chunk-TPPZXZTA.js} +3 -3
- package/dist/{chunk-234EKD2F.js → chunk-VCVBICMZ.js} +1 -1
- package/dist/{chunk-ZTVBIBLB.js → chunk-YEPVWJ3R.js} +200 -143
- package/dist/{chunk-2RM6BZQ2.js → chunk-ZY7K4T37.js} +1 -1
- package/dist/{coordinator-prompt-PM6MPYYB.js → coordinator-prompt-K3HXEPFD.js} +2 -2
- package/dist/{coordinator-prompt-7CTI6HRH.js → coordinator-prompt-LJKA2ODR.js} +2 -2
- package/dist/{global-workspace-CRJ6ZVIY.js → global-workspace-KA7T26F5.js} +2 -2
- package/dist/{global-workspace-CMYSFRCM.js → global-workspace-VDFSU3DD.js} +2 -2
- package/dist/index.cjs +324 -238
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +6 -6
- package/dist/mcp/run-stdio.cjs +336 -250
- package/dist/mcp/run-stdio.js +4 -4
- package/dist/{orchestrator-RW4IVITI.js → orchestrator-DMSSC4SV.js} +4 -4
- package/dist/{orchestrator-VPT4SXXD.js → orchestrator-VMUZJFTZ.js} +4 -4
- package/dist/{workspaces-L73MCDFA.js → workspaces-GOGBPATJ.js} +2 -2
- package/dist/{workspaces-UYSD2STS.js → workspaces-UR7YEFMZ.js} +2 -2
- package/dist/{worktree-SQD3DBYC.js → worktree-LC4VRWDM.js} +1 -1
- package/dist/{worktree-WVEDT3FM.js → worktree-UTDBQXSS.js} +1 -1
- package/package.json +1 -1
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
stripBrightsyNdjsonNoise,
|
|
25
25
|
sumUsageList,
|
|
26
26
|
toolDescription
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-CUA4S537.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-ZY7K4T37.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-7JIYKYLL.js";
|
|
101
101
|
import {
|
|
102
102
|
ATTACHMENTS_DIR,
|
|
103
103
|
DETACHED_JOBS_DIR,
|
|
@@ -466,7 +466,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
466
466
|
await continueOnReply(threadId, prompt);
|
|
467
467
|
return;
|
|
468
468
|
}
|
|
469
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
469
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-VMUZJFTZ.js");
|
|
470
470
|
await getOrchestrator2().send(threadId, prompt);
|
|
471
471
|
} catch {
|
|
472
472
|
}
|
|
@@ -726,11 +726,63 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
726
726
|
}
|
|
727
727
|
|
|
728
728
|
// src/orchestrator/orchestrator.ts
|
|
729
|
-
import { existsSync as
|
|
729
|
+
import { existsSync as existsSync19 } from "fs";
|
|
730
730
|
|
|
731
731
|
// src/agents/spawn.ts
|
|
732
732
|
import { createInterface } from "readline";
|
|
733
733
|
import { execa } from "execa";
|
|
734
|
+
|
|
735
|
+
// src/hook/worktree-pkg-cache.ts
|
|
736
|
+
import { existsSync as existsSync3, mkdirSync } from "fs";
|
|
737
|
+
import { join as join4 } from "path";
|
|
738
|
+
var WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
|
|
739
|
+
function worktreePkgCacheRoot(worktreePath) {
|
|
740
|
+
return join4(worktreePath, WORKTREE_PKG_CACHE_REL);
|
|
741
|
+
}
|
|
742
|
+
function worktreePkgCacheEnv(worktreePath) {
|
|
743
|
+
const root = worktreePkgCacheRoot(worktreePath);
|
|
744
|
+
const store = join4(root, "pnpm-store");
|
|
745
|
+
const pnpmCache = join4(root, "pnpm");
|
|
746
|
+
const npmCache = join4(root, "npm");
|
|
747
|
+
const nodeGyp = join4(root, "node-gyp");
|
|
748
|
+
const electron = join4(root, "electron");
|
|
749
|
+
return {
|
|
750
|
+
npm_config_store_dir: store,
|
|
751
|
+
PNPM_STORE_DIR: store,
|
|
752
|
+
npm_config_cache_dir: pnpmCache,
|
|
753
|
+
npm_config_cache: npmCache,
|
|
754
|
+
npm_config_devdir: nodeGyp,
|
|
755
|
+
// @electron/get — do not set ELECTRON_CACHE (stripNestedElectronEnv).
|
|
756
|
+
electron_config_cache: electron
|
|
757
|
+
};
|
|
758
|
+
}
|
|
759
|
+
function isSet(value) {
|
|
760
|
+
return value != null && value.trim() !== "";
|
|
761
|
+
}
|
|
762
|
+
function fillGroup(env, keys, values) {
|
|
763
|
+
if (keys.some((key) => isSet(env[key]))) return;
|
|
764
|
+
for (const key of keys) {
|
|
765
|
+
const value = values[key];
|
|
766
|
+
if (value) env[key] = value;
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
function ensureWorktreePkgCacheDirs(worktreePath) {
|
|
770
|
+
if (!existsSync3(worktreePath)) return;
|
|
771
|
+
mkdirSync(worktreePkgCacheRoot(worktreePath), { recursive: true });
|
|
772
|
+
}
|
|
773
|
+
function applyWorktreePkgCacheEnv(env, worktreePath) {
|
|
774
|
+
const cwd = worktreePath.trim();
|
|
775
|
+
if (!cwd) return;
|
|
776
|
+
const next = worktreePkgCacheEnv(cwd);
|
|
777
|
+
fillGroup(env, ["npm_config_store_dir", "PNPM_STORE_DIR"], next);
|
|
778
|
+
fillGroup(env, ["npm_config_cache_dir"], next);
|
|
779
|
+
fillGroup(env, ["npm_config_cache"], next);
|
|
780
|
+
fillGroup(env, ["npm_config_devdir"], next);
|
|
781
|
+
fillGroup(env, ["electron_config_cache"], next);
|
|
782
|
+
ensureWorktreePkgCacheDirs(cwd);
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// src/agents/spawn.ts
|
|
734
786
|
function applyPromptCacheTtlEnv(agent, env) {
|
|
735
787
|
if (agent === "claude" && env.FORCE_PROMPT_CACHING_5M !== "1") {
|
|
736
788
|
env.ENABLE_PROMPT_CACHING_1H ??= "1";
|
|
@@ -748,9 +800,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
748
800
|
`Cannot spawn ${thread.agent}: thread ${thread.id} has no worktreePath`
|
|
749
801
|
);
|
|
750
802
|
}
|
|
751
|
-
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-
|
|
803
|
+
const { isGlobalThread: isGlobalThread2 } = await import("./global-workspace-VDFSU3DD.js");
|
|
752
804
|
if (isGlobalThread2(thread)) {
|
|
753
|
-
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-
|
|
805
|
+
const { ensureGlobalCoordinatorCwd: ensureGlobalCoordinatorCwd2 } = await import("./coordinator-prompt-LJKA2ODR.js");
|
|
754
806
|
ensureGlobalCoordinatorCwd2(
|
|
755
807
|
isOrchestratorThread(thread) ? { orchestratorThreadId: thread.id } : void 0
|
|
756
808
|
);
|
|
@@ -768,6 +820,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
768
820
|
const env = childEnvWithAppSettings(cmd.env);
|
|
769
821
|
applyPromptCacheTtlEnv(thread.agent, env);
|
|
770
822
|
applyAgentRunnerHeapEnv(env);
|
|
823
|
+
if (!isOrchestratorThread(thread)) {
|
|
824
|
+
applyWorktreePkgCacheEnv(env, thread.worktreePath);
|
|
825
|
+
}
|
|
771
826
|
try {
|
|
772
827
|
if (isOrchestratorThread(thread)) {
|
|
773
828
|
mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
|
|
@@ -1024,20 +1079,20 @@ function shouldAutoArchiveOnPrMerge(opts) {
|
|
|
1024
1079
|
// src/hook/conductor.ts
|
|
1025
1080
|
import {
|
|
1026
1081
|
copyFileSync,
|
|
1027
|
-
existsSync as
|
|
1028
|
-
mkdirSync as
|
|
1082
|
+
existsSync as existsSync5,
|
|
1083
|
+
mkdirSync as mkdirSync3,
|
|
1029
1084
|
readdirSync,
|
|
1030
1085
|
readFileSync as readFileSync4
|
|
1031
1086
|
} from "fs";
|
|
1032
1087
|
import { createServer } from "net";
|
|
1033
|
-
import { basename, dirname as dirname2, join as
|
|
1088
|
+
import { basename, dirname as dirname2, join as join6 } from "path";
|
|
1034
1089
|
import { execa as execa2 } from "execa";
|
|
1035
1090
|
import { createInterface as createInterface2 } from "readline";
|
|
1036
1091
|
|
|
1037
1092
|
// src/review/request-review.ts
|
|
1038
1093
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1039
|
-
import { existsSync as
|
|
1040
|
-
import { dirname, join as
|
|
1094
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
1095
|
+
import { dirname, join as join5 } from "path";
|
|
1041
1096
|
|
|
1042
1097
|
// src/threads/chat-tabs.ts
|
|
1043
1098
|
import { randomUUID } from "crypto";
|
|
@@ -1326,7 +1381,7 @@ function buildSessionSeed(messages, opts) {
|
|
|
1326
1381
|
for (let i = blocks.length - 1; i >= 0; i--) {
|
|
1327
1382
|
if (keep[i]) continue;
|
|
1328
1383
|
const next = used + blocks[i].length + 2;
|
|
1329
|
-
if (next > maxChars && used > 0)
|
|
1384
|
+
if (next > maxChars && used > 0) continue;
|
|
1330
1385
|
keep[i] = true;
|
|
1331
1386
|
used = next;
|
|
1332
1387
|
}
|
|
@@ -1753,7 +1808,7 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
1753
1808
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
1754
1809
|
}
|
|
1755
1810
|
function readTextIfPresent(abs) {
|
|
1756
|
-
if (!
|
|
1811
|
+
if (!existsSync4(abs)) return null;
|
|
1757
1812
|
try {
|
|
1758
1813
|
const content = readFileSync3(abs, "utf8");
|
|
1759
1814
|
return content.trim() ? content : null;
|
|
@@ -1762,12 +1817,12 @@ function readTextIfPresent(abs) {
|
|
|
1762
1817
|
}
|
|
1763
1818
|
}
|
|
1764
1819
|
function readLocalGuidelines(worktreePath) {
|
|
1765
|
-
const localAbs =
|
|
1820
|
+
const localAbs = join5(worktreePath, REVIEW_REQUEST_PATH);
|
|
1766
1821
|
const localContent = readTextIfPresent(localAbs);
|
|
1767
1822
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
1768
1823
|
return { path: REVIEW_REQUEST_PATH, content: localContent };
|
|
1769
1824
|
}
|
|
1770
|
-
const legacyAbs =
|
|
1825
|
+
const legacyAbs = join5(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
1771
1826
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
1772
1827
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
1773
1828
|
return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
|
|
@@ -1791,27 +1846,27 @@ function contextGuidelines(content, source) {
|
|
|
1791
1846
|
};
|
|
1792
1847
|
}
|
|
1793
1848
|
function writeContextGuidelines(worktreePath, content) {
|
|
1794
|
-
const abs =
|
|
1795
|
-
|
|
1849
|
+
const abs = join5(worktreePath, CONTEXT_REVIEW_PATH);
|
|
1850
|
+
mkdirSync2(dirname(abs), { recursive: true });
|
|
1796
1851
|
const body = content.endsWith("\n") ? content : `${content}
|
|
1797
1852
|
`;
|
|
1798
1853
|
writeFileSync(abs, body, "utf8");
|
|
1799
1854
|
return body;
|
|
1800
1855
|
}
|
|
1801
1856
|
function readSideboardReview(worktreePath, repoPath) {
|
|
1802
|
-
const fromWorktree = readTextIfPresent(
|
|
1857
|
+
const fromWorktree = readTextIfPresent(join5(worktreePath, REPO_REVIEW_PATH));
|
|
1803
1858
|
if (fromWorktree) return fromWorktree;
|
|
1804
1859
|
const repo = repoPath?.replace(/\/+$/, "");
|
|
1805
1860
|
const wt = worktreePath.replace(/\/+$/, "");
|
|
1806
1861
|
if (!repo || repo === wt) return null;
|
|
1807
|
-
return readTextIfPresent(
|
|
1862
|
+
return readTextIfPresent(join5(repo, REPO_REVIEW_PATH));
|
|
1808
1863
|
}
|
|
1809
1864
|
function ensureReviewGuidelinesFile(worktreePath, repoPath) {
|
|
1810
|
-
const skillContent = readTextIfPresent(
|
|
1865
|
+
const skillContent = readTextIfPresent(join5(worktreePath, REVIEW_SKILL_PATH));
|
|
1811
1866
|
if (skillContent) {
|
|
1812
1867
|
return { ...skillGuidelines(skillContent, "skill"), wrote: false };
|
|
1813
1868
|
}
|
|
1814
|
-
const contextContent = readTextIfPresent(
|
|
1869
|
+
const contextContent = readTextIfPresent(join5(worktreePath, CONTEXT_REVIEW_PATH));
|
|
1815
1870
|
if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
|
|
1816
1871
|
return { ...contextGuidelines(contextContent, "local"), wrote: false };
|
|
1817
1872
|
}
|
|
@@ -1849,7 +1904,7 @@ function buildReviewRequestAttachment(content, opts) {
|
|
|
1849
1904
|
};
|
|
1850
1905
|
}
|
|
1851
1906
|
function readExistingReviewRequestFile(worktreePath) {
|
|
1852
|
-
return readTextIfPresent(
|
|
1907
|
+
return readTextIfPresent(join5(worktreePath, REVIEW_SKILL_PATH)) ?? readTextIfPresent(join5(worktreePath, CONTEXT_REVIEW_PATH)) ?? readTextIfPresent(join5(worktreePath, REPO_REVIEW_PATH)) ?? readTextIfPresent(join5(worktreePath, REVIEW_REQUEST_PATH)) ?? readTextIfPresent(join5(worktreePath, LEGACY_REVIEW_REQUEST_PATH));
|
|
1853
1908
|
}
|
|
1854
1909
|
async function requestReview(threadRef, send) {
|
|
1855
1910
|
const from = findThreadByRef(threadRef);
|
|
@@ -1884,8 +1939,8 @@ function matchSimpleGlob(pattern, name) {
|
|
|
1884
1939
|
return new RegExp(`^${escaped}$`).test(name);
|
|
1885
1940
|
}
|
|
1886
1941
|
function readWorktreeInclude(repoPath) {
|
|
1887
|
-
const path =
|
|
1888
|
-
if (!
|
|
1942
|
+
const path = join6(repoPath, ".worktreeinclude");
|
|
1943
|
+
if (!existsSync5(path)) return [];
|
|
1889
1944
|
return readFileSync4(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
1890
1945
|
}
|
|
1891
1946
|
function resolveFilesToCopy(repoPath) {
|
|
@@ -1925,10 +1980,10 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
1925
1980
|
const patterns = resolveFilesToCopy(repoPath);
|
|
1926
1981
|
const copied = [];
|
|
1927
1982
|
for (const rel of patterns) {
|
|
1928
|
-
const src =
|
|
1929
|
-
if (!
|
|
1930
|
-
const dest =
|
|
1931
|
-
|
|
1983
|
+
const src = join6(repoPath, rel);
|
|
1984
|
+
if (!existsSync5(src)) continue;
|
|
1985
|
+
const dest = join6(worktreePath, rel);
|
|
1986
|
+
mkdirSync3(dirname2(dest), { recursive: true });
|
|
1932
1987
|
copyFileSync(src, dest);
|
|
1933
1988
|
copied.push(rel);
|
|
1934
1989
|
}
|
|
@@ -1988,6 +2043,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
1988
2043
|
env[`CONDUCTOR_PORT_${i}`] = String(p);
|
|
1989
2044
|
}
|
|
1990
2045
|
}
|
|
2046
|
+
applyWorktreePkgCacheEnv(env, opts.worktreePath);
|
|
1991
2047
|
return env;
|
|
1992
2048
|
}
|
|
1993
2049
|
function pipeLines(stream, onLine) {
|
|
@@ -2229,8 +2285,8 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
2229
2285
|
}
|
|
2230
2286
|
|
|
2231
2287
|
// src/store/setup-log.ts
|
|
2232
|
-
import { existsSync as
|
|
2233
|
-
import { join as
|
|
2288
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
2289
|
+
import { join as join7 } from "path";
|
|
2234
2290
|
var EMPTY = {
|
|
2235
2291
|
output: "",
|
|
2236
2292
|
running: false,
|
|
@@ -2240,7 +2296,7 @@ var EMPTY = {
|
|
|
2240
2296
|
var memory = /* @__PURE__ */ new Map();
|
|
2241
2297
|
var persistTimers = /* @__PURE__ */ new Map();
|
|
2242
2298
|
function setupLogPath(threadId) {
|
|
2243
|
-
return
|
|
2299
|
+
return join7(threadsDir(), `${threadId}.setup.log.json`);
|
|
2244
2300
|
}
|
|
2245
2301
|
function emptySetupLog() {
|
|
2246
2302
|
return { ...EMPTY };
|
|
@@ -2282,7 +2338,7 @@ function schedulePersist(threadId) {
|
|
|
2282
2338
|
}
|
|
2283
2339
|
function loadFromDisk(threadId) {
|
|
2284
2340
|
const path = setupLogPath(threadId);
|
|
2285
|
-
if (!
|
|
2341
|
+
if (!existsSync6(path)) return null;
|
|
2286
2342
|
try {
|
|
2287
2343
|
const raw = JSON.parse(readFileSync5(path, "utf8"));
|
|
2288
2344
|
return {
|
|
@@ -2342,8 +2398,8 @@ function finishSetupLog(threadId, exitCode, source) {
|
|
|
2342
2398
|
}
|
|
2343
2399
|
|
|
2344
2400
|
// src/git/orphan-cleanup.ts
|
|
2345
|
-
import { existsSync as
|
|
2346
|
-
import { join as
|
|
2401
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync } from "fs";
|
|
2402
|
+
import { join as join8 } from "path";
|
|
2347
2403
|
function isSideboardWorktreePath(path) {
|
|
2348
2404
|
return path.includes("/.sideboard/worktrees/") || path.includes("/sideboard/workspaces/");
|
|
2349
2405
|
}
|
|
@@ -2354,7 +2410,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2354
2410
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
2355
2411
|
);
|
|
2356
2412
|
const homeRoot = sideboardWorkspacesDir();
|
|
2357
|
-
if (
|
|
2413
|
+
if (existsSync7(homeRoot)) {
|
|
2358
2414
|
try {
|
|
2359
2415
|
for (const entry of readdirSync2(homeRoot, { withFileTypes: true })) {
|
|
2360
2416
|
if (!entry.isDirectory()) continue;
|
|
@@ -2366,7 +2422,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2366
2422
|
const orphans = [];
|
|
2367
2423
|
const seen = /* @__PURE__ */ new Set();
|
|
2368
2424
|
for (const repoPath of repos) {
|
|
2369
|
-
if (!repoPath || !
|
|
2425
|
+
if (!repoPath || !existsSync7(repoPath)) continue;
|
|
2370
2426
|
try {
|
|
2371
2427
|
const wts = await listWorktrees(repoPath);
|
|
2372
2428
|
for (const wt of wts) {
|
|
@@ -2387,12 +2443,12 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2387
2443
|
}
|
|
2388
2444
|
try {
|
|
2389
2445
|
const root = worktreesRoot(repoPath);
|
|
2390
|
-
if (
|
|
2446
|
+
if (existsSync7(root)) {
|
|
2391
2447
|
for (const entry of readdirSync2(root, { withFileTypes: true })) {
|
|
2392
2448
|
if (!entry.isDirectory()) continue;
|
|
2393
|
-
const path =
|
|
2449
|
+
const path = join8(root, entry.name).replace(/\/$/, "");
|
|
2394
2450
|
if (known.has(path) || seen.has(path)) continue;
|
|
2395
|
-
if (!
|
|
2451
|
+
if (!existsSync7(join8(path, ".git"))) continue;
|
|
2396
2452
|
seen.add(path);
|
|
2397
2453
|
let mtimeMs = 0;
|
|
2398
2454
|
try {
|
|
@@ -2541,8 +2597,8 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
2541
2597
|
}
|
|
2542
2598
|
|
|
2543
2599
|
// src/git/clone-repo.ts
|
|
2544
|
-
import { existsSync as
|
|
2545
|
-
import { basename as basename2, join as
|
|
2600
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2601
|
+
import { basename as basename2, join as join9 } from "path";
|
|
2546
2602
|
import { execa as execa4 } from "execa";
|
|
2547
2603
|
async function cloneRepoIntoSideboard(opts) {
|
|
2548
2604
|
const url = opts.url.trim();
|
|
@@ -2553,8 +2609,8 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
2553
2609
|
name = leaf || "repo";
|
|
2554
2610
|
}
|
|
2555
2611
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
2556
|
-
const dest =
|
|
2557
|
-
if (
|
|
2612
|
+
const dest = join9(sideboardReposDir(), name);
|
|
2613
|
+
if (existsSync8(dest)) {
|
|
2558
2614
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
2559
2615
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
2560
2616
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -2572,9 +2628,9 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
2572
2628
|
|
|
2573
2629
|
// src/store/desktop-host.ts
|
|
2574
2630
|
import { readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
2575
|
-
import { join as
|
|
2631
|
+
import { join as join10 } from "path";
|
|
2576
2632
|
function desktopHostPidPath() {
|
|
2577
|
-
return
|
|
2633
|
+
return join10(appDataDir(), "desktop-host.pid");
|
|
2578
2634
|
}
|
|
2579
2635
|
function claimDesktopHost(pid = process.pid) {
|
|
2580
2636
|
writeFileSync3(desktopHostPidPath(), `${pid}
|
|
@@ -2658,13 +2714,13 @@ function notifyParentOfChildHalt(child, status, send) {
|
|
|
2658
2714
|
// src/mcp/wait-for-job.ts
|
|
2659
2715
|
import {
|
|
2660
2716
|
appendFileSync,
|
|
2661
|
-
existsSync as
|
|
2662
|
-
mkdirSync as
|
|
2717
|
+
existsSync as existsSync9,
|
|
2718
|
+
mkdirSync as mkdirSync4,
|
|
2663
2719
|
readdirSync as readdirSync3,
|
|
2664
2720
|
readFileSync as readFileSync7,
|
|
2665
2721
|
writeFileSync as writeFileSync4
|
|
2666
2722
|
} from "fs";
|
|
2667
|
-
import { dirname as dirname3, join as
|
|
2723
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
2668
2724
|
|
|
2669
2725
|
// src/mcp/wait-for-turn.ts
|
|
2670
2726
|
var MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
|
|
@@ -2714,7 +2770,7 @@ function jobAlive(pid) {
|
|
|
2714
2770
|
}
|
|
2715
2771
|
function processGroupAlive(pgid) {
|
|
2716
2772
|
if (process.platform === "win32") return false;
|
|
2717
|
-
if (!Number.isInteger(pgid) || pgid <=
|
|
2773
|
+
if (!Number.isInteger(pgid) || pgid <= 1) return false;
|
|
2718
2774
|
try {
|
|
2719
2775
|
process.kill(-pgid, 0);
|
|
2720
2776
|
return true;
|
|
@@ -2727,23 +2783,23 @@ function jobTreeAlive(pid) {
|
|
|
2727
2783
|
return jobAlive(pid) || processGroupAlive(pid);
|
|
2728
2784
|
}
|
|
2729
2785
|
function readIntFile(file) {
|
|
2730
|
-
if (!
|
|
2786
|
+
if (!existsSync9(file)) return null;
|
|
2731
2787
|
const n = Number.parseInt(readFileSync7(file, "utf8").trim(), 10);
|
|
2732
2788
|
return Number.isInteger(n) ? n : null;
|
|
2733
2789
|
}
|
|
2734
2790
|
function jobDir(root, id, legacy = false) {
|
|
2735
|
-
return
|
|
2791
|
+
return join11(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
|
|
2736
2792
|
}
|
|
2737
2793
|
function resolveJobDir(root, id) {
|
|
2738
2794
|
const modern = jobDir(root, id, false);
|
|
2739
|
-
if (
|
|
2795
|
+
if (existsSync9(modern)) return modern;
|
|
2740
2796
|
const legacy = jobDir(root, id, true);
|
|
2741
|
-
if (
|
|
2797
|
+
if (existsSync9(legacy)) return legacy;
|
|
2742
2798
|
return modern;
|
|
2743
2799
|
}
|
|
2744
2800
|
function listJobIdsIn(root, rel) {
|
|
2745
|
-
const dir =
|
|
2746
|
-
if (!
|
|
2801
|
+
const dir = join11(root, rel);
|
|
2802
|
+
if (!existsSync9(dir)) return [];
|
|
2747
2803
|
return readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
|
|
2748
2804
|
}
|
|
2749
2805
|
function listRunningDetachedJobs(worktreePath) {
|
|
@@ -2756,8 +2812,8 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
2756
2812
|
const running = [];
|
|
2757
2813
|
for (const id of ids) {
|
|
2758
2814
|
const dir = resolveJobDir(root, id);
|
|
2759
|
-
const pid = readIntFile(
|
|
2760
|
-
if (
|
|
2815
|
+
const pid = readIntFile(join11(dir, "pid"));
|
|
2816
|
+
if (jobTreeAlive(pid)) running.push(id);
|
|
2761
2817
|
}
|
|
2762
2818
|
return running.sort();
|
|
2763
2819
|
}
|
|
@@ -2809,12 +2865,12 @@ function planJobContinue(opts) {
|
|
|
2809
2865
|
return { action: "none" };
|
|
2810
2866
|
}
|
|
2811
2867
|
function tailProgress(logFile, maxLines = 12) {
|
|
2812
|
-
if (!
|
|
2868
|
+
if (!existsSync9(logFile)) return "(no log yet)";
|
|
2813
2869
|
const lines = readFileSync7(logFile, "utf8").split("\n");
|
|
2814
2870
|
return lines.slice(-maxLines).join("\n");
|
|
2815
2871
|
}
|
|
2816
2872
|
function readLogLines(file) {
|
|
2817
|
-
if (!
|
|
2873
|
+
if (!existsSync9(file)) return [];
|
|
2818
2874
|
const lines = readFileSync7(file, "utf8").split("\n");
|
|
2819
2875
|
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
2820
2876
|
return lines;
|
|
@@ -2826,15 +2882,15 @@ function takeDelta(logFile, cursorFile) {
|
|
|
2826
2882
|
return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
|
|
2827
2883
|
}
|
|
2828
2884
|
function snapshotJob(dir) {
|
|
2829
|
-
const pid = readIntFile(
|
|
2885
|
+
const pid = readIntFile(join11(dir, "pid"));
|
|
2830
2886
|
const running = jobTreeAlive(pid);
|
|
2831
2887
|
return {
|
|
2832
2888
|
pid,
|
|
2833
2889
|
running,
|
|
2834
|
-
exitCode: readIntFile(
|
|
2835
|
-
log:
|
|
2836
|
-
cursor:
|
|
2837
|
-
progress: tailProgress(
|
|
2890
|
+
exitCode: readIntFile(join11(dir, "exit")),
|
|
2891
|
+
log: join11(dir, "log"),
|
|
2892
|
+
cursor: join11(dir, "present.cursor"),
|
|
2893
|
+
progress: tailProgress(join11(dir, "log"))
|
|
2838
2894
|
};
|
|
2839
2895
|
}
|
|
2840
2896
|
function toResult(id, snap, extra) {
|
|
@@ -2843,7 +2899,7 @@ function toResult(id, snap, extra) {
|
|
|
2843
2899
|
const stillRunning = snap.running && !ok;
|
|
2844
2900
|
const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
|
|
2845
2901
|
try {
|
|
2846
|
-
|
|
2902
|
+
mkdirSync4(dirname3(snap.cursor), { recursive: true });
|
|
2847
2903
|
writeFileSync4(snap.cursor, `${nextCursor}
|
|
2848
2904
|
`);
|
|
2849
2905
|
} catch {
|
|
@@ -2871,7 +2927,7 @@ async function waitForDetachedJob(cwd, id, opts) {
|
|
|
2871
2927
|
const dir = resolveJobDir(root, jobId);
|
|
2872
2928
|
const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
|
|
2873
2929
|
const sleep = opts?.sleep ?? sleepMs;
|
|
2874
|
-
if (!
|
|
2930
|
+
if (!existsSync9(dir)) {
|
|
2875
2931
|
return {
|
|
2876
2932
|
stillRunning: false,
|
|
2877
2933
|
ok: false,
|
|
@@ -2917,7 +2973,7 @@ function killProcessTree(pid, signal) {
|
|
|
2917
2973
|
}
|
|
2918
2974
|
function appendJobLog(logFile, line) {
|
|
2919
2975
|
try {
|
|
2920
|
-
|
|
2976
|
+
mkdirSync4(dirname3(logFile), { recursive: true });
|
|
2921
2977
|
const body = line.endsWith("\n") ? line : `${line}
|
|
2922
2978
|
`;
|
|
2923
2979
|
appendFileSync(logFile, body);
|
|
@@ -2930,7 +2986,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
2930
2986
|
const dir = resolveJobDir(root, jobId);
|
|
2931
2987
|
const sleep = opts?.sleep ?? sleepMs;
|
|
2932
2988
|
const why = opts?.reason?.trim() ?? "";
|
|
2933
|
-
if (!
|
|
2989
|
+
if (!existsSync9(dir)) {
|
|
2934
2990
|
return {
|
|
2935
2991
|
stillRunning: false,
|
|
2936
2992
|
ok: false,
|
|
@@ -2966,8 +3022,8 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
2966
3022
|
killProcessTree(targetPid, "SIGKILL");
|
|
2967
3023
|
await sleep(100);
|
|
2968
3024
|
}
|
|
2969
|
-
const exitFile =
|
|
2970
|
-
if (!
|
|
3025
|
+
const exitFile = join11(dir, "exit");
|
|
3026
|
+
if (!existsSync9(exitFile)) {
|
|
2971
3027
|
try {
|
|
2972
3028
|
writeFileSync4(exitFile, "1\n");
|
|
2973
3029
|
} catch {
|
|
@@ -2991,7 +3047,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
2991
3047
|
}
|
|
2992
3048
|
|
|
2993
3049
|
// src/threads/create.ts
|
|
2994
|
-
import { existsSync as
|
|
3050
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2995
3051
|
|
|
2996
3052
|
// src/detect/detect.ts
|
|
2997
3053
|
async function detectAgents() {
|
|
@@ -3553,7 +3609,7 @@ function reuseLiveThread(input, repoPath, match) {
|
|
|
3553
3609
|
}
|
|
3554
3610
|
async function createThread(input, _onSetupLine) {
|
|
3555
3611
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
3556
|
-
if (!
|
|
3612
|
+
if (!existsSync10(repoPath)) {
|
|
3557
3613
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
3558
3614
|
}
|
|
3559
3615
|
const reused = reuseLiveThread(input, repoPath, {
|
|
@@ -3726,7 +3782,7 @@ async function createThread(input, _onSetupLine) {
|
|
|
3726
3782
|
return readThread(thread.id) ?? thread;
|
|
3727
3783
|
}
|
|
3728
3784
|
async function listLinearIssues(agent, repoPath) {
|
|
3729
|
-
const { getAdapter: getAdapter2 } = await import("./agents-
|
|
3785
|
+
const { getAdapter: getAdapter2 } = await import("./agents-ZWYRGFZB.js");
|
|
3730
3786
|
await requireAgent(agent, { requireLinear: true });
|
|
3731
3787
|
const adapter = getAdapter2(agent);
|
|
3732
3788
|
if (!adapter.listLinearIssues) {
|
|
@@ -3760,7 +3816,7 @@ function shouldRemoveWorktreeOnTeardown(thread) {
|
|
|
3760
3816
|
|
|
3761
3817
|
// src/store/turn-live.ts
|
|
3762
3818
|
import {
|
|
3763
|
-
existsSync as
|
|
3819
|
+
existsSync as existsSync11,
|
|
3764
3820
|
renameSync,
|
|
3765
3821
|
unlinkSync as unlinkSync2,
|
|
3766
3822
|
writeFileSync as writeFileSync5,
|
|
@@ -3852,7 +3908,7 @@ function writeTurnLive(threadId, progress) {
|
|
|
3852
3908
|
}
|
|
3853
3909
|
function readTurnLive(threadId) {
|
|
3854
3910
|
const path = threadLivePath(threadId);
|
|
3855
|
-
if (!
|
|
3911
|
+
if (!existsSync11(path)) return null;
|
|
3856
3912
|
try {
|
|
3857
3913
|
const raw = JSON.parse(readFileSync8(path, "utf8"));
|
|
3858
3914
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
@@ -3866,7 +3922,7 @@ function clearTurnLive(threadId) {
|
|
|
3866
3922
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
3867
3923
|
buffers.delete(threadId);
|
|
3868
3924
|
const path = threadLivePath(threadId);
|
|
3869
|
-
if (!
|
|
3925
|
+
if (!existsSync11(path)) return;
|
|
3870
3926
|
try {
|
|
3871
3927
|
unlinkSync2(path);
|
|
3872
3928
|
} catch {
|
|
@@ -4054,26 +4110,26 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
4054
4110
|
import { execFileSync } from "child_process";
|
|
4055
4111
|
import {
|
|
4056
4112
|
copyFileSync as copyFileSync2,
|
|
4057
|
-
existsSync as
|
|
4113
|
+
existsSync as existsSync12,
|
|
4058
4114
|
mkdtempSync,
|
|
4059
4115
|
readdirSync as readdirSync4,
|
|
4060
4116
|
readFileSync as readFileSync9,
|
|
4061
4117
|
rmSync
|
|
4062
4118
|
} from "fs";
|
|
4063
4119
|
import { tmpdir } from "os";
|
|
4064
|
-
import { join as
|
|
4120
|
+
import { join as join12 } from "path";
|
|
4065
4121
|
import { createRequire } from "module";
|
|
4066
|
-
var CONDUCTOR_APP_SUPPORT =
|
|
4122
|
+
var CONDUCTOR_APP_SUPPORT = join12(
|
|
4067
4123
|
process.env.HOME ?? "",
|
|
4068
4124
|
"Library",
|
|
4069
4125
|
"Application Support",
|
|
4070
4126
|
"com.conductor.app"
|
|
4071
4127
|
);
|
|
4072
|
-
var CONDUCTOR_DB =
|
|
4073
|
-
var CURSOR_SDK_STORE =
|
|
4128
|
+
var CONDUCTOR_DB = join12(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
4129
|
+
var CURSOR_SDK_STORE = join12(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
4074
4130
|
function thisModuleFile() {
|
|
4075
4131
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
4076
|
-
return cjsFile || process.argv[1] ||
|
|
4132
|
+
return cjsFile || process.argv[1] || join12(process.cwd(), "package.json");
|
|
4077
4133
|
}
|
|
4078
4134
|
function openReadonlySqlite(file) {
|
|
4079
4135
|
const req = createRequire(thisModuleFile());
|
|
@@ -4091,7 +4147,7 @@ function mapAgentType(raw) {
|
|
|
4091
4147
|
return null;
|
|
4092
4148
|
}
|
|
4093
4149
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
4094
|
-
if (!workspacePath || !
|
|
4150
|
+
if (!workspacePath || !existsSync12(CURSOR_SDK_STORE)) return null;
|
|
4095
4151
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
4096
4152
|
let best = null;
|
|
4097
4153
|
let hashes;
|
|
@@ -4101,8 +4157,8 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
4101
4157
|
return null;
|
|
4102
4158
|
}
|
|
4103
4159
|
for (const hash of hashes) {
|
|
4104
|
-
const agentsFile =
|
|
4105
|
-
if (!
|
|
4160
|
+
const agentsFile = join12(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
4161
|
+
if (!existsSync12(agentsFile)) continue;
|
|
4106
4162
|
let text;
|
|
4107
4163
|
try {
|
|
4108
4164
|
text = readFileSync9(agentsFile, "utf8");
|
|
@@ -4129,7 +4185,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
4129
4185
|
return best?.agentId ?? null;
|
|
4130
4186
|
}
|
|
4131
4187
|
async function adoptThread(input) {
|
|
4132
|
-
if (!
|
|
4188
|
+
if (!existsSync12(input.worktreePath)) {
|
|
4133
4189
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
4134
4190
|
}
|
|
4135
4191
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -4148,7 +4204,7 @@ async function adoptThread(input) {
|
|
|
4148
4204
|
messages: input.messages ?? []
|
|
4149
4205
|
});
|
|
4150
4206
|
writeThread(thread);
|
|
4151
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
4207
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-UR7YEFMZ.js");
|
|
4152
4208
|
await ensureWorkspace2(repoPath);
|
|
4153
4209
|
const { ensureWorktreeSideboardIgnored: ensureWorktreeSideboardIgnored2 } = await import("./worktree-exclude-X54WSOXM.js");
|
|
4154
4210
|
await ensureWorktreeSideboardIgnored2(input.worktreePath);
|
|
@@ -4158,16 +4214,16 @@ function conductorDbPath() {
|
|
|
4158
4214
|
return CONDUCTOR_DB;
|
|
4159
4215
|
}
|
|
4160
4216
|
function listConductorWorkspaces() {
|
|
4161
|
-
if (!
|
|
4217
|
+
if (!existsSync12(CONDUCTOR_DB)) {
|
|
4162
4218
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
4163
4219
|
}
|
|
4164
|
-
const tmp = mkdtempSync(
|
|
4165
|
-
const snapshot =
|
|
4220
|
+
const tmp = mkdtempSync(join12(tmpdir(), "sideboard-conductor-"));
|
|
4221
|
+
const snapshot = join12(tmp, "conductor.db");
|
|
4166
4222
|
try {
|
|
4167
4223
|
copyFileSync2(CONDUCTOR_DB, snapshot);
|
|
4168
4224
|
for (const suffix of ["-wal", "-shm"]) {
|
|
4169
4225
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
4170
|
-
if (
|
|
4226
|
+
if (existsSync12(src)) {
|
|
4171
4227
|
try {
|
|
4172
4228
|
copyFileSync2(src, `${snapshot}${suffix}`);
|
|
4173
4229
|
} catch {
|
|
@@ -4249,16 +4305,16 @@ function listConductorWorkspaces() {
|
|
|
4249
4305
|
}
|
|
4250
4306
|
}
|
|
4251
4307
|
function importConductorWorkspace(workspaceId) {
|
|
4252
|
-
if (!
|
|
4308
|
+
if (!existsSync12(CONDUCTOR_DB)) {
|
|
4253
4309
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
4254
4310
|
}
|
|
4255
|
-
const tmp = mkdtempSync(
|
|
4256
|
-
const snapshot =
|
|
4311
|
+
const tmp = mkdtempSync(join12(tmpdir(), "sideboard-conductor-"));
|
|
4312
|
+
const snapshot = join12(tmp, "conductor.db");
|
|
4257
4313
|
try {
|
|
4258
4314
|
copyFileSync2(CONDUCTOR_DB, snapshot);
|
|
4259
4315
|
for (const suffix of ["-wal", "-shm"]) {
|
|
4260
4316
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
4261
|
-
if (
|
|
4317
|
+
if (existsSync12(src)) {
|
|
4262
4318
|
try {
|
|
4263
4319
|
copyFileSync2(src, `${snapshot}${suffix}`);
|
|
4264
4320
|
} catch {
|
|
@@ -4278,7 +4334,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
4278
4334
|
).get(workspaceId);
|
|
4279
4335
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
4280
4336
|
const worktreePath = String(row.workspacePath);
|
|
4281
|
-
if (!
|
|
4337
|
+
if (!existsSync12(worktreePath)) {
|
|
4282
4338
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
4283
4339
|
}
|
|
4284
4340
|
let sessionId = null;
|
|
@@ -4349,7 +4405,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
4349
4405
|
}
|
|
4350
4406
|
|
|
4351
4407
|
// src/threads/stack-layers.ts
|
|
4352
|
-
import { existsSync as
|
|
4408
|
+
import { existsSync as existsSync13 } from "fs";
|
|
4353
4409
|
function stackIdFrom(stack) {
|
|
4354
4410
|
if (stack.stackNumber != null) return `gh-stack-${stack.stackNumber}`;
|
|
4355
4411
|
const key = stack.layers.map((l) => l.branchName).join("|");
|
|
@@ -4412,7 +4468,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
4412
4468
|
let createdWorktree = false;
|
|
4413
4469
|
const trees = await listWorktrees(repoPath);
|
|
4414
4470
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
4415
|
-
if (checkedOut?.path &&
|
|
4471
|
+
if (checkedOut?.path && existsSync13(checkedOut.path)) {
|
|
4416
4472
|
if (input.reuseExistingWorktree !== false) {
|
|
4417
4473
|
worktreePath = checkedOut.path;
|
|
4418
4474
|
} else {
|
|
@@ -4554,7 +4610,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
4554
4610
|
async function createPrStack(input, onSetupLine) {
|
|
4555
4611
|
await requireAgent(input.agent);
|
|
4556
4612
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
4557
|
-
if (!
|
|
4613
|
+
if (!existsSync13(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
4558
4614
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
4559
4615
|
const status = await detectGhStack(repoPath);
|
|
4560
4616
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -4621,7 +4677,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
4621
4677
|
}
|
|
4622
4678
|
}
|
|
4623
4679
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
4624
|
-
if (!claimed.has(bootstrap.worktreePath) &&
|
|
4680
|
+
if (!claimed.has(bootstrap.worktreePath) && existsSync13(bootstrap.worktreePath)) {
|
|
4625
4681
|
try {
|
|
4626
4682
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
4627
4683
|
deleteBranch: bootstrap.branchName
|
|
@@ -4643,10 +4699,10 @@ function stackAgentDefaultsFrom(input) {
|
|
|
4643
4699
|
}
|
|
4644
4700
|
|
|
4645
4701
|
// src/diff/diff.ts
|
|
4646
|
-
import { existsSync as
|
|
4647
|
-
import { dirname as dirname4, join as
|
|
4702
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
4703
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
4648
4704
|
async function inspectGitWorktree(worktreePath) {
|
|
4649
|
-
if (!worktreePath || !
|
|
4705
|
+
if (!worktreePath || !existsSync14(worktreePath)) return "missing_worktree";
|
|
4650
4706
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
4651
4707
|
reject: false
|
|
4652
4708
|
});
|
|
@@ -4654,7 +4710,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
4654
4710
|
return "ok";
|
|
4655
4711
|
}
|
|
4656
4712
|
async function initializeGitRepository(worktreePath) {
|
|
4657
|
-
if (!worktreePath || !
|
|
4713
|
+
if (!worktreePath || !existsSync14(worktreePath)) {
|
|
4658
4714
|
throw new Error("Worktree not found");
|
|
4659
4715
|
}
|
|
4660
4716
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -4790,7 +4846,7 @@ new file mode 100644
|
|
|
4790
4846
|
};
|
|
4791
4847
|
}
|
|
4792
4848
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
4793
|
-
const abs =
|
|
4849
|
+
const abs = join13(worktreePath, path);
|
|
4794
4850
|
try {
|
|
4795
4851
|
const st = statSync2(abs);
|
|
4796
4852
|
if (st.isFile() && st.size > maxHunk) {
|
|
@@ -5295,7 +5351,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
5295
5351
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
5296
5352
|
assertSafeRelativePath(relativePath);
|
|
5297
5353
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
5298
|
-
const abs =
|
|
5354
|
+
const abs = join13(worktreePath, relativePath);
|
|
5299
5355
|
const st = statSync2(abs);
|
|
5300
5356
|
if (!st.isFile()) {
|
|
5301
5357
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -5315,7 +5371,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
5315
5371
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
5316
5372
|
assertSafeRelativePath(relativePath);
|
|
5317
5373
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
5318
|
-
const abs =
|
|
5374
|
+
const abs = join13(worktreePath, relativePath);
|
|
5319
5375
|
const st = statSync2(abs);
|
|
5320
5376
|
if (!st.isFile()) {
|
|
5321
5377
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -5363,8 +5419,8 @@ function assertSafeRelativePath(relativePath) {
|
|
|
5363
5419
|
}
|
|
5364
5420
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
5365
5421
|
assertSafeRelativePath(relativePath);
|
|
5366
|
-
const abs =
|
|
5367
|
-
|
|
5422
|
+
const abs = join13(worktreePath, relativePath);
|
|
5423
|
+
mkdirSync5(dirname4(abs), { recursive: true });
|
|
5368
5424
|
writeFileSync6(abs, content, "utf8");
|
|
5369
5425
|
return { path: relativePath };
|
|
5370
5426
|
}
|
|
@@ -5490,9 +5546,9 @@ async function confirmLand(thread, opts) {
|
|
|
5490
5546
|
}
|
|
5491
5547
|
|
|
5492
5548
|
// src/skills/discover.ts
|
|
5493
|
-
import { existsSync as
|
|
5549
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
|
|
5494
5550
|
import { homedir } from "os";
|
|
5495
|
-
import { join as
|
|
5551
|
+
import { join as join14 } from "path";
|
|
5496
5552
|
|
|
5497
5553
|
// src/skills/bundled/long-running.ts
|
|
5498
5554
|
var LONG_RUNNING_SKILL_COMMAND = "long-running";
|
|
@@ -5648,7 +5704,7 @@ function readSkill(skillMd, source) {
|
|
|
5648
5704
|
}
|
|
5649
5705
|
}
|
|
5650
5706
|
function scanSkillsDir(dir, source, out) {
|
|
5651
|
-
if (!
|
|
5707
|
+
if (!existsSync15(dir)) return;
|
|
5652
5708
|
let entries;
|
|
5653
5709
|
try {
|
|
5654
5710
|
entries = readdirSync5(dir);
|
|
@@ -5657,8 +5713,8 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5657
5713
|
}
|
|
5658
5714
|
for (const entry of entries) {
|
|
5659
5715
|
if (entry.startsWith(".")) continue;
|
|
5660
|
-
const skillMd =
|
|
5661
|
-
if (!
|
|
5716
|
+
const skillMd = join14(dir, entry, "SKILL.md");
|
|
5717
|
+
if (!existsSync15(skillMd)) continue;
|
|
5662
5718
|
try {
|
|
5663
5719
|
if (!statSync3(skillMd).isFile()) continue;
|
|
5664
5720
|
} catch {
|
|
@@ -5669,7 +5725,7 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5669
5725
|
}
|
|
5670
5726
|
}
|
|
5671
5727
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
5672
|
-
if (!
|
|
5728
|
+
if (!existsSync15(pluginsRoot)) return;
|
|
5673
5729
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
5674
5730
|
if (depth > 7) return;
|
|
5675
5731
|
let entries;
|
|
@@ -5679,12 +5735,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
5679
5735
|
return;
|
|
5680
5736
|
}
|
|
5681
5737
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
5682
|
-
const skill = readSkill(
|
|
5738
|
+
const skill = readSkill(join14(dir, "SKILL.md"), "cli");
|
|
5683
5739
|
if (skill) out.push(skill);
|
|
5684
5740
|
}
|
|
5685
5741
|
for (const entry of entries) {
|
|
5686
5742
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
5687
|
-
const full =
|
|
5743
|
+
const full = join14(dir, entry);
|
|
5688
5744
|
try {
|
|
5689
5745
|
if (!statSync3(full).isDirectory()) continue;
|
|
5690
5746
|
} catch {
|
|
@@ -5704,17 +5760,17 @@ function discoverSkills(worktreePath) {
|
|
|
5704
5760
|
const home = homedir();
|
|
5705
5761
|
const collected = [];
|
|
5706
5762
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
5707
|
-
scanSkillsDir(
|
|
5763
|
+
scanSkillsDir(join14(worktreePath, rel), "workspace", collected);
|
|
5708
5764
|
}
|
|
5709
5765
|
for (const abs of [
|
|
5710
|
-
|
|
5711
|
-
|
|
5712
|
-
|
|
5713
|
-
|
|
5766
|
+
join14(home, ".claude/skills"),
|
|
5767
|
+
join14(home, ".cursor/skills"),
|
|
5768
|
+
join14(home, ".sideboard/skills"),
|
|
5769
|
+
join14(home, ".brightsy/skills")
|
|
5714
5770
|
]) {
|
|
5715
5771
|
scanSkillsDir(abs, "user", collected);
|
|
5716
5772
|
}
|
|
5717
|
-
scanClaudePluginSkills(
|
|
5773
|
+
scanClaudePluginSkills(join14(home, ".claude/plugins"), collected);
|
|
5718
5774
|
collected.push(...bundledSkills());
|
|
5719
5775
|
const rank = {
|
|
5720
5776
|
workspace: 0,
|
|
@@ -5833,18 +5889,18 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
5833
5889
|
}
|
|
5834
5890
|
|
|
5835
5891
|
// src/agents/instructions.ts
|
|
5836
|
-
import { existsSync as
|
|
5837
|
-
import { join as
|
|
5892
|
+
import { existsSync as existsSync17 } from "fs";
|
|
5893
|
+
import { join as join16 } from "path";
|
|
5838
5894
|
|
|
5839
5895
|
// src/skills/detached-job-path.ts
|
|
5840
|
-
import { existsSync as
|
|
5841
|
-
import { dirname as dirname5, join as
|
|
5896
|
+
import { existsSync as existsSync16 } from "fs";
|
|
5897
|
+
import { dirname as dirname5, join as join15 } from "path";
|
|
5842
5898
|
import { fileURLToPath } from "url";
|
|
5843
5899
|
var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
|
|
5844
5900
|
function detachedJobScriptIn(dir) {
|
|
5845
5901
|
for (const name of DETACHED_JOB_FILENAMES) {
|
|
5846
|
-
const script =
|
|
5847
|
-
if (
|
|
5902
|
+
const script = join15(dir, "scripts", name);
|
|
5903
|
+
if (existsSync16(script)) return script;
|
|
5848
5904
|
}
|
|
5849
5905
|
return null;
|
|
5850
5906
|
}
|
|
@@ -6047,11 +6103,13 @@ function formatPrGateDirective() {
|
|
|
6047
6103
|
}
|
|
6048
6104
|
function formatProcessGuideDirective(opts) {
|
|
6049
6105
|
const worktree = opts?.worktreePath?.trim();
|
|
6050
|
-
const hasGraphSkill = !!worktree &&
|
|
6051
|
-
const hasReviewSkill = !!worktree &&
|
|
6106
|
+
const hasGraphSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
6107
|
+
const hasReviewSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/review/SKILL.md"));
|
|
6108
|
+
const hasInstallSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/worktree-install/SKILL.md"));
|
|
6052
6109
|
return [
|
|
6053
6110
|
"Process guides (recurring work only):",
|
|
6054
6111
|
hasGraphSkill ? "- Migrations, ports, batch fixes, and other fan-out: follow `.claude/skills/graph-engineering/SKILL.md` (`/graph-engineering`). Judge first; state on disk; grow the rulebook; do not patch around it." : null,
|
|
6112
|
+
hasInstallSkill ? "- After merge-from-main / lockfile change, or a hung `pnpm install`: follow `.claude/skills/worktree-install/SKILL.md` (`/worktree-install`). Use the worktree-local store Sideboard already set; do not share `~/.pnpm-store` across concurrent worktrees." : null,
|
|
6055
6113
|
"- If this same shape of work will happen again, write `.claude/skills/<kebab-name>/SKILL.md` in this worktree (Claude Code project skill; Sideboard `/name`, Claude Code, and `attach` all load it). Not under `.sideboard/skills/`. Point Codex/OpenCode at it from `AGENTS.md`.",
|
|
6056
6114
|
hasReviewSkill ? "- Merge-readiness notes go in `.claude/skills/review/SKILL.md` (edit it; do not create another review skill)." : "- Merge-readiness notes go in `.context/review.md` (copied from `.sideboard/review.md` when that file exists). Do not create a review skill.",
|
|
6057
6115
|
"- Skip a guide for a one-off. If a matching skill exists, follow it. Same miss twice \u2192 edit the skill, do not patch around it."
|
|
@@ -6383,8 +6441,8 @@ async function syncThreadBranchFromGit(threadId) {
|
|
|
6383
6441
|
|
|
6384
6442
|
// src/store/schedules.ts
|
|
6385
6443
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
6386
|
-
import { existsSync as
|
|
6387
|
-
import { join as
|
|
6444
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
6445
|
+
import { join as join17 } from "path";
|
|
6388
6446
|
import { Cron } from "croner";
|
|
6389
6447
|
var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
|
|
6390
6448
|
var UNIT_MS = {
|
|
@@ -6394,7 +6452,7 @@ var UNIT_MS = {
|
|
|
6394
6452
|
d: 864e5
|
|
6395
6453
|
};
|
|
6396
6454
|
function schedulesPath() {
|
|
6397
|
-
return
|
|
6455
|
+
return join17(appDataDir(), "schedules.json");
|
|
6398
6456
|
}
|
|
6399
6457
|
function parseDurationMs(every) {
|
|
6400
6458
|
const m = every.trim().match(DURATION_RE);
|
|
@@ -6500,7 +6558,7 @@ function normalizeTask(raw) {
|
|
|
6500
6558
|
}
|
|
6501
6559
|
function readAll() {
|
|
6502
6560
|
const path = schedulesPath();
|
|
6503
|
-
if (!
|
|
6561
|
+
if (!existsSync18(path)) return [];
|
|
6504
6562
|
try {
|
|
6505
6563
|
const parsed = JSON.parse(readFileSync12(path, "utf8"));
|
|
6506
6564
|
if (!Array.isArray(parsed)) return [];
|
|
@@ -6628,7 +6686,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6628
6686
|
${prompt}`;
|
|
6629
6687
|
}
|
|
6630
6688
|
async function defaultDeps() {
|
|
6631
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6689
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-VMUZJFTZ.js");
|
|
6632
6690
|
const orch = getOrchestrator2();
|
|
6633
6691
|
return {
|
|
6634
6692
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -6871,7 +6929,7 @@ var Orchestrator = class {
|
|
|
6871
6929
|
}
|
|
6872
6930
|
continue;
|
|
6873
6931
|
}
|
|
6874
|
-
if (!
|
|
6932
|
+
if (!existsSync19(thread.worktreePath)) {
|
|
6875
6933
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
6876
6934
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
6877
6935
|
continue;
|
|
@@ -7416,9 +7474,10 @@ var Orchestrator = class {
|
|
|
7416
7474
|
ts: (/* @__PURE__ */ new Date()).toISOString()
|
|
7417
7475
|
});
|
|
7418
7476
|
thread = this.requireThread(threadId);
|
|
7477
|
+
const gitPrompt = expandCanonicalGitRequest(prompt);
|
|
7419
7478
|
const { agentPrompt: expandedPrompt } = expandComposerPrompt(
|
|
7420
7479
|
thread.worktreePath,
|
|
7421
|
-
|
|
7480
|
+
gitPrompt,
|
|
7422
7481
|
{
|
|
7423
7482
|
attachments: sentAttachments ?? thread.attachments
|
|
7424
7483
|
}
|
|
@@ -7460,13 +7519,13 @@ var Orchestrator = class {
|
|
|
7460
7519
|
artifactReminder,
|
|
7461
7520
|
longRunningReminder
|
|
7462
7521
|
].filter(Boolean).join("\n\n") || void 0;
|
|
7463
|
-
const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(
|
|
7522
|
+
const prGateDirective = thread.agent !== "brightsy" && !isOrchestratorThread(thread) && mentionsPrGoal(prompt) ? formatPrGateDirective() : null;
|
|
7464
7523
|
const agentPrompt = [
|
|
7465
7524
|
thread.planMode ? PLAN_MODE_INSTRUCTION : null,
|
|
7466
7525
|
orchestrationReminder,
|
|
7467
7526
|
prGateDirective,
|
|
7468
7527
|
slackReplyContext,
|
|
7469
|
-
|
|
7528
|
+
expandedPrompt
|
|
7470
7529
|
].filter(Boolean).join("\n\n");
|
|
7471
7530
|
if (thread.attachments.length > 0) {
|
|
7472
7531
|
updateThread(threadId, { attachments: [] });
|
|
@@ -8713,7 +8772,7 @@ var Orchestrator = class {
|
|
|
8713
8772
|
this.emit({ type: "status_changed", threadId: archived.id, status: "archived" });
|
|
8714
8773
|
if (thread.repoPath && !isGlobalRepoPath(thread.repoPath)) {
|
|
8715
8774
|
try {
|
|
8716
|
-
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-
|
|
8775
|
+
const { ensureWorkspace: ensureWorkspace2 } = await import("./workspaces-UR7YEFMZ.js");
|
|
8717
8776
|
await ensureWorkspace2(thread.repoPath);
|
|
8718
8777
|
} catch {
|
|
8719
8778
|
}
|
|
@@ -8761,13 +8820,13 @@ var Orchestrator = class {
|
|
|
8761
8820
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
8762
8821
|
return restored2;
|
|
8763
8822
|
}
|
|
8764
|
-
if (!
|
|
8823
|
+
if (!existsSync19(thread.worktreePath)) {
|
|
8765
8824
|
if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
|
|
8766
8825
|
throw new Error(
|
|
8767
8826
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
8768
8827
|
);
|
|
8769
8828
|
}
|
|
8770
|
-
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-
|
|
8829
|
+
const { createThreadWorktree: createThreadWorktree2 } = await import("./worktree-UTDBQXSS.js");
|
|
8771
8830
|
const slug = thread.worktreePath.split("/").pop();
|
|
8772
8831
|
const dest = thread.worktreePath;
|
|
8773
8832
|
await withRepoGitLock(thread.repoPath, async () => {
|
|
@@ -8877,7 +8936,7 @@ async function startOrchestration(opts) {
|
|
|
8877
8936
|
sourceRef: "default",
|
|
8878
8937
|
...createOpts
|
|
8879
8938
|
}).catch(async () => {
|
|
8880
|
-
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-
|
|
8939
|
+
const { resolveDefaultBranch: resolveDefaultBranch2, resolveRepoRoot: resolveRepoRoot2 } = await import("./worktree-UTDBQXSS.js");
|
|
8881
8940
|
const repo = await resolveRepoRoot2(repoPath);
|
|
8882
8941
|
const def = await resolveDefaultBranch2(repo);
|
|
8883
8942
|
return orch.createThread({
|