@sideboard-ai/core 0.1.172 → 0.1.173
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/{chunk-ZTVBIBLB.js → chunk-SKKEJZEX.js} +184 -128
- package/dist/{chunk-QYJS7LYE.js → chunk-WE34LOLO.js} +187 -129
- package/dist/index.cjs +289 -225
- package/dist/index.d.cts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +1 -1
- package/dist/mcp/run-stdio.cjs +303 -239
- package/dist/mcp/run-stdio.js +1 -1
- package/dist/{orchestrator-VPT4SXXD.js → orchestrator-PEOUSLAY.js} +1 -1
- package/dist/{orchestrator-RW4IVITI.js → orchestrator-QBB2RELD.js} +1 -1
- package/package.json +1 -1
|
@@ -401,7 +401,7 @@ async function continueSourceThread(threadId, prompt) {
|
|
|
401
401
|
await continueOnReply(threadId, prompt);
|
|
402
402
|
return;
|
|
403
403
|
}
|
|
404
|
-
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-
|
|
404
|
+
const { getOrchestrator: getOrchestrator2 } = await import("./orchestrator-QBB2RELD.js");
|
|
405
405
|
await getOrchestrator2().send(threadId, prompt);
|
|
406
406
|
} catch {
|
|
407
407
|
}
|
|
@@ -661,12 +661,62 @@ async function pollSlackOutboundWatches(opts) {
|
|
|
661
661
|
}
|
|
662
662
|
|
|
663
663
|
// src/orchestrator/orchestrator.ts
|
|
664
|
-
import { existsSync as
|
|
664
|
+
import { existsSync as existsSync19 } from "fs";
|
|
665
665
|
|
|
666
666
|
// src/agents/spawn.ts
|
|
667
667
|
import { createInterface } from "readline";
|
|
668
668
|
import { execa } from "execa";
|
|
669
669
|
|
|
670
|
+
// src/hook/worktree-pkg-cache.ts
|
|
671
|
+
import { existsSync as existsSync3, mkdirSync } from "fs";
|
|
672
|
+
import { join as join4 } from "path";
|
|
673
|
+
var WORKTREE_PKG_CACHE_REL = ".context/.sideboard/pkg-cache";
|
|
674
|
+
function worktreePkgCacheRoot(worktreePath) {
|
|
675
|
+
return join4(worktreePath, WORKTREE_PKG_CACHE_REL);
|
|
676
|
+
}
|
|
677
|
+
function worktreePkgCacheEnv(worktreePath) {
|
|
678
|
+
const root = worktreePkgCacheRoot(worktreePath);
|
|
679
|
+
const store = join4(root, "pnpm-store");
|
|
680
|
+
const pnpmCache = join4(root, "pnpm");
|
|
681
|
+
const npmCache = join4(root, "npm");
|
|
682
|
+
const nodeGyp = join4(root, "node-gyp");
|
|
683
|
+
const electron = join4(root, "electron");
|
|
684
|
+
return {
|
|
685
|
+
npm_config_store_dir: store,
|
|
686
|
+
PNPM_STORE_DIR: store,
|
|
687
|
+
npm_config_cache_dir: pnpmCache,
|
|
688
|
+
npm_config_cache: npmCache,
|
|
689
|
+
npm_config_devdir: nodeGyp,
|
|
690
|
+
// @electron/get — do not set ELECTRON_CACHE (stripNestedElectronEnv).
|
|
691
|
+
electron_config_cache: electron
|
|
692
|
+
};
|
|
693
|
+
}
|
|
694
|
+
function isSet(value) {
|
|
695
|
+
return value != null && value.trim() !== "";
|
|
696
|
+
}
|
|
697
|
+
function fillGroup(env, keys, values) {
|
|
698
|
+
if (keys.some((key) => isSet(env[key]))) return;
|
|
699
|
+
for (const key of keys) {
|
|
700
|
+
const value = values[key];
|
|
701
|
+
if (value) env[key] = value;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
function ensureWorktreePkgCacheDirs(worktreePath) {
|
|
705
|
+
if (!existsSync3(worktreePath)) return;
|
|
706
|
+
mkdirSync(worktreePkgCacheRoot(worktreePath), { recursive: true });
|
|
707
|
+
}
|
|
708
|
+
function applyWorktreePkgCacheEnv(env, worktreePath) {
|
|
709
|
+
const cwd = worktreePath.trim();
|
|
710
|
+
if (!cwd) return;
|
|
711
|
+
const next = worktreePkgCacheEnv(cwd);
|
|
712
|
+
fillGroup(env, ["npm_config_store_dir", "PNPM_STORE_DIR"], next);
|
|
713
|
+
fillGroup(env, ["npm_config_cache_dir"], next);
|
|
714
|
+
fillGroup(env, ["npm_config_cache"], next);
|
|
715
|
+
fillGroup(env, ["npm_config_devdir"], next);
|
|
716
|
+
fillGroup(env, ["electron_config_cache"], next);
|
|
717
|
+
ensureWorktreePkgCacheDirs(cwd);
|
|
718
|
+
}
|
|
719
|
+
|
|
670
720
|
// src/agents/cursor-stream-coalesce.ts
|
|
671
721
|
function isTextEvent(event) {
|
|
672
722
|
return event.type === "stdout" || event.type === "thinking";
|
|
@@ -764,6 +814,9 @@ async function spawnAgentTurn(thread, input, onEvent) {
|
|
|
764
814
|
const env = childEnvWithAppSettings(cmd.env);
|
|
765
815
|
applyPromptCacheTtlEnv(thread.agent, env);
|
|
766
816
|
applyAgentRunnerHeapEnv(env);
|
|
817
|
+
if (!isOrchestratorThread(thread)) {
|
|
818
|
+
applyWorktreePkgCacheEnv(env, thread.worktreePath);
|
|
819
|
+
}
|
|
767
820
|
try {
|
|
768
821
|
if (isOrchestratorThread(thread)) {
|
|
769
822
|
mergeAgentGitAuthEnv(env, await resolveAgentGitAuthEnv(env));
|
|
@@ -1020,20 +1073,20 @@ function shouldAutoArchiveOnPrMerge(opts) {
|
|
|
1020
1073
|
// src/hook/conductor.ts
|
|
1021
1074
|
import {
|
|
1022
1075
|
copyFileSync,
|
|
1023
|
-
existsSync as
|
|
1024
|
-
mkdirSync as
|
|
1076
|
+
existsSync as existsSync5,
|
|
1077
|
+
mkdirSync as mkdirSync3,
|
|
1025
1078
|
readdirSync,
|
|
1026
1079
|
readFileSync as readFileSync4
|
|
1027
1080
|
} from "fs";
|
|
1028
1081
|
import { createServer } from "net";
|
|
1029
|
-
import { basename, dirname as dirname2, join as
|
|
1082
|
+
import { basename, dirname as dirname2, join as join6 } from "path";
|
|
1030
1083
|
import { execa as execa2 } from "execa";
|
|
1031
1084
|
import { createInterface as createInterface2 } from "readline";
|
|
1032
1085
|
|
|
1033
1086
|
// src/review/request-review.ts
|
|
1034
1087
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
1035
|
-
import { existsSync as
|
|
1036
|
-
import { dirname, join as
|
|
1088
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync3, writeFileSync } from "fs";
|
|
1089
|
+
import { dirname, join as join5 } from "path";
|
|
1037
1090
|
|
|
1038
1091
|
// src/threads/chat-tabs.ts
|
|
1039
1092
|
import { randomUUID } from "crypto";
|
|
@@ -1706,7 +1759,7 @@ function shouldRefreshReviewRequestTemplate(content) {
|
|
|
1706
1759
|
return LEGACY_REVIEW_TEMPLATE_MARKERS.every((m) => trimmed.includes(m));
|
|
1707
1760
|
}
|
|
1708
1761
|
function readTextIfPresent(abs) {
|
|
1709
|
-
if (!
|
|
1762
|
+
if (!existsSync4(abs)) return null;
|
|
1710
1763
|
try {
|
|
1711
1764
|
const content = readFileSync3(abs, "utf8");
|
|
1712
1765
|
return content.trim() ? content : null;
|
|
@@ -1715,12 +1768,12 @@ function readTextIfPresent(abs) {
|
|
|
1715
1768
|
}
|
|
1716
1769
|
}
|
|
1717
1770
|
function readLocalGuidelines(worktreePath) {
|
|
1718
|
-
const localAbs =
|
|
1771
|
+
const localAbs = join5(worktreePath, REVIEW_REQUEST_PATH);
|
|
1719
1772
|
const localContent = readTextIfPresent(localAbs);
|
|
1720
1773
|
if (localContent && !shouldRefreshReviewRequestTemplate(localContent)) {
|
|
1721
1774
|
return { path: REVIEW_REQUEST_PATH, content: localContent };
|
|
1722
1775
|
}
|
|
1723
|
-
const legacyAbs =
|
|
1776
|
+
const legacyAbs = join5(worktreePath, LEGACY_REVIEW_REQUEST_PATH);
|
|
1724
1777
|
const legacyContent = readTextIfPresent(legacyAbs);
|
|
1725
1778
|
if (legacyContent && !shouldRefreshReviewRequestTemplate(legacyContent)) {
|
|
1726
1779
|
return { path: LEGACY_REVIEW_REQUEST_PATH, content: legacyContent };
|
|
@@ -1744,27 +1797,27 @@ function contextGuidelines(content, source) {
|
|
|
1744
1797
|
};
|
|
1745
1798
|
}
|
|
1746
1799
|
function writeContextGuidelines(worktreePath, content) {
|
|
1747
|
-
const abs =
|
|
1748
|
-
|
|
1800
|
+
const abs = join5(worktreePath, CONTEXT_REVIEW_PATH);
|
|
1801
|
+
mkdirSync2(dirname(abs), { recursive: true });
|
|
1749
1802
|
const body = content.endsWith("\n") ? content : `${content}
|
|
1750
1803
|
`;
|
|
1751
1804
|
writeFileSync(abs, body, "utf8");
|
|
1752
1805
|
return body;
|
|
1753
1806
|
}
|
|
1754
1807
|
function readSideboardReview(worktreePath, repoPath) {
|
|
1755
|
-
const fromWorktree = readTextIfPresent(
|
|
1808
|
+
const fromWorktree = readTextIfPresent(join5(worktreePath, REPO_REVIEW_PATH));
|
|
1756
1809
|
if (fromWorktree) return fromWorktree;
|
|
1757
1810
|
const repo = repoPath?.replace(/\/+$/, "");
|
|
1758
1811
|
const wt = worktreePath.replace(/\/+$/, "");
|
|
1759
1812
|
if (!repo || repo === wt) return null;
|
|
1760
|
-
return readTextIfPresent(
|
|
1813
|
+
return readTextIfPresent(join5(repo, REPO_REVIEW_PATH));
|
|
1761
1814
|
}
|
|
1762
1815
|
function ensureReviewGuidelinesFile(worktreePath, repoPath) {
|
|
1763
|
-
const skillContent = readTextIfPresent(
|
|
1816
|
+
const skillContent = readTextIfPresent(join5(worktreePath, REVIEW_SKILL_PATH));
|
|
1764
1817
|
if (skillContent) {
|
|
1765
1818
|
return { ...skillGuidelines(skillContent, "skill"), wrote: false };
|
|
1766
1819
|
}
|
|
1767
|
-
const contextContent = readTextIfPresent(
|
|
1820
|
+
const contextContent = readTextIfPresent(join5(worktreePath, CONTEXT_REVIEW_PATH));
|
|
1768
1821
|
if (contextContent && !shouldRefreshReviewRequestTemplate(contextContent)) {
|
|
1769
1822
|
return { ...contextGuidelines(contextContent, "local"), wrote: false };
|
|
1770
1823
|
}
|
|
@@ -1827,8 +1880,8 @@ function matchSimpleGlob(pattern, name) {
|
|
|
1827
1880
|
return new RegExp(`^${escaped}$`).test(name);
|
|
1828
1881
|
}
|
|
1829
1882
|
function readWorktreeInclude(repoPath) {
|
|
1830
|
-
const path =
|
|
1831
|
-
if (!
|
|
1883
|
+
const path = join6(repoPath, ".worktreeinclude");
|
|
1884
|
+
if (!existsSync5(path)) return [];
|
|
1832
1885
|
return readFileSync4(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
1833
1886
|
}
|
|
1834
1887
|
function resolveFilesToCopy(repoPath) {
|
|
@@ -1868,10 +1921,10 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
1868
1921
|
const patterns = resolveFilesToCopy(repoPath);
|
|
1869
1922
|
const copied = [];
|
|
1870
1923
|
for (const rel of patterns) {
|
|
1871
|
-
const src =
|
|
1872
|
-
if (!
|
|
1873
|
-
const dest =
|
|
1874
|
-
|
|
1924
|
+
const src = join6(repoPath, rel);
|
|
1925
|
+
if (!existsSync5(src)) continue;
|
|
1926
|
+
const dest = join6(worktreePath, rel);
|
|
1927
|
+
mkdirSync3(dirname2(dest), { recursive: true });
|
|
1875
1928
|
copyFileSync(src, dest);
|
|
1876
1929
|
copied.push(rel);
|
|
1877
1930
|
}
|
|
@@ -1931,6 +1984,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
1931
1984
|
env[`CONDUCTOR_PORT_${i}`] = String(p);
|
|
1932
1985
|
}
|
|
1933
1986
|
}
|
|
1987
|
+
applyWorktreePkgCacheEnv(env, opts.worktreePath);
|
|
1934
1988
|
return env;
|
|
1935
1989
|
}
|
|
1936
1990
|
function pipeLines(stream, onLine) {
|
|
@@ -2172,8 +2226,8 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
2172
2226
|
}
|
|
2173
2227
|
|
|
2174
2228
|
// src/store/setup-log.ts
|
|
2175
|
-
import { existsSync as
|
|
2176
|
-
import { join as
|
|
2229
|
+
import { existsSync as existsSync6, readFileSync as readFileSync5, writeFileSync as writeFileSync2 } from "fs";
|
|
2230
|
+
import { join as join7 } from "path";
|
|
2177
2231
|
var EMPTY = {
|
|
2178
2232
|
output: "",
|
|
2179
2233
|
running: false,
|
|
@@ -2183,7 +2237,7 @@ var EMPTY = {
|
|
|
2183
2237
|
var memory = /* @__PURE__ */ new Map();
|
|
2184
2238
|
var persistTimers = /* @__PURE__ */ new Map();
|
|
2185
2239
|
function setupLogPath(threadId) {
|
|
2186
|
-
return
|
|
2240
|
+
return join7(threadsDir(), `${threadId}.setup.log.json`);
|
|
2187
2241
|
}
|
|
2188
2242
|
function emptySetupLog() {
|
|
2189
2243
|
return { ...EMPTY };
|
|
@@ -2217,7 +2271,7 @@ function schedulePersist(threadId) {
|
|
|
2217
2271
|
}
|
|
2218
2272
|
function loadFromDisk(threadId) {
|
|
2219
2273
|
const path = setupLogPath(threadId);
|
|
2220
|
-
if (!
|
|
2274
|
+
if (!existsSync6(path)) return null;
|
|
2221
2275
|
try {
|
|
2222
2276
|
const raw = JSON.parse(readFileSync5(path, "utf8"));
|
|
2223
2277
|
return {
|
|
@@ -2277,8 +2331,8 @@ function finishSetupLog(threadId, exitCode, source) {
|
|
|
2277
2331
|
}
|
|
2278
2332
|
|
|
2279
2333
|
// src/git/orphan-cleanup.ts
|
|
2280
|
-
import { existsSync as
|
|
2281
|
-
import { join as
|
|
2334
|
+
import { existsSync as existsSync7, readdirSync as readdirSync2, statSync } from "fs";
|
|
2335
|
+
import { join as join8 } from "path";
|
|
2282
2336
|
function isSideboardWorktreePath(path) {
|
|
2283
2337
|
return path.includes("/.sideboard/worktrees/") || path.includes("/sideboard/workspaces/");
|
|
2284
2338
|
}
|
|
@@ -2289,7 +2343,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2289
2343
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
2290
2344
|
);
|
|
2291
2345
|
const homeRoot = sideboardWorkspacesDir();
|
|
2292
|
-
if (
|
|
2346
|
+
if (existsSync7(homeRoot)) {
|
|
2293
2347
|
try {
|
|
2294
2348
|
for (const entry of readdirSync2(homeRoot, { withFileTypes: true })) {
|
|
2295
2349
|
if (!entry.isDirectory()) continue;
|
|
@@ -2301,7 +2355,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2301
2355
|
const orphans = [];
|
|
2302
2356
|
const seen = /* @__PURE__ */ new Set();
|
|
2303
2357
|
for (const repoPath of repos) {
|
|
2304
|
-
if (!repoPath || !
|
|
2358
|
+
if (!repoPath || !existsSync7(repoPath)) continue;
|
|
2305
2359
|
try {
|
|
2306
2360
|
const wts = await listWorktrees(repoPath);
|
|
2307
2361
|
for (const wt of wts) {
|
|
@@ -2322,12 +2376,12 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
2322
2376
|
}
|
|
2323
2377
|
try {
|
|
2324
2378
|
const root = worktreesRoot(repoPath);
|
|
2325
|
-
if (
|
|
2379
|
+
if (existsSync7(root)) {
|
|
2326
2380
|
for (const entry of readdirSync2(root, { withFileTypes: true })) {
|
|
2327
2381
|
if (!entry.isDirectory()) continue;
|
|
2328
|
-
const path =
|
|
2382
|
+
const path = join8(root, entry.name).replace(/\/$/, "");
|
|
2329
2383
|
if (known.has(path) || seen.has(path)) continue;
|
|
2330
|
-
if (!
|
|
2384
|
+
if (!existsSync7(join8(path, ".git"))) continue;
|
|
2331
2385
|
seen.add(path);
|
|
2332
2386
|
let mtimeMs = 0;
|
|
2333
2387
|
try {
|
|
@@ -2467,8 +2521,8 @@ async function applyThreadIntoMain(thread, opts) {
|
|
|
2467
2521
|
}
|
|
2468
2522
|
|
|
2469
2523
|
// src/git/clone-repo.ts
|
|
2470
|
-
import { existsSync as
|
|
2471
|
-
import { basename as basename2, join as
|
|
2524
|
+
import { existsSync as existsSync8 } from "fs";
|
|
2525
|
+
import { basename as basename2, join as join9 } from "path";
|
|
2472
2526
|
import { execa as execa4 } from "execa";
|
|
2473
2527
|
async function cloneRepoIntoSideboard(opts) {
|
|
2474
2528
|
const url = opts.url.trim();
|
|
@@ -2479,8 +2533,8 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
2479
2533
|
name = leaf || "repo";
|
|
2480
2534
|
}
|
|
2481
2535
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
2482
|
-
const dest =
|
|
2483
|
-
if (
|
|
2536
|
+
const dest = join9(sideboardReposDir(), name);
|
|
2537
|
+
if (existsSync8(dest)) {
|
|
2484
2538
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
2485
2539
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
2486
2540
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -2498,9 +2552,9 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
2498
2552
|
|
|
2499
2553
|
// src/store/desktop-host.ts
|
|
2500
2554
|
import { readFileSync as readFileSync6, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
|
|
2501
|
-
import { join as
|
|
2555
|
+
import { join as join10 } from "path";
|
|
2502
2556
|
function desktopHostPidPath() {
|
|
2503
|
-
return
|
|
2557
|
+
return join10(appDataDir(), "desktop-host.pid");
|
|
2504
2558
|
}
|
|
2505
2559
|
function readDesktopHostPid() {
|
|
2506
2560
|
try {
|
|
@@ -2573,13 +2627,13 @@ function notifyParentOfChildHalt(child, status, send) {
|
|
|
2573
2627
|
// src/mcp/wait-for-job.ts
|
|
2574
2628
|
import {
|
|
2575
2629
|
appendFileSync,
|
|
2576
|
-
existsSync as
|
|
2577
|
-
mkdirSync as
|
|
2630
|
+
existsSync as existsSync9,
|
|
2631
|
+
mkdirSync as mkdirSync4,
|
|
2578
2632
|
readdirSync as readdirSync3,
|
|
2579
2633
|
readFileSync as readFileSync7,
|
|
2580
2634
|
writeFileSync as writeFileSync4
|
|
2581
2635
|
} from "fs";
|
|
2582
|
-
import { dirname as dirname3, join as
|
|
2636
|
+
import { dirname as dirname3, join as join11 } from "path";
|
|
2583
2637
|
|
|
2584
2638
|
// src/mcp/wait-for-turn.ts
|
|
2585
2639
|
var MCP_WAIT_FOR_TURN_MAX_MS = 45e3;
|
|
@@ -2642,23 +2696,23 @@ function jobTreeAlive(pid) {
|
|
|
2642
2696
|
return jobAlive(pid) || processGroupAlive(pid);
|
|
2643
2697
|
}
|
|
2644
2698
|
function readIntFile(file) {
|
|
2645
|
-
if (!
|
|
2699
|
+
if (!existsSync9(file)) return null;
|
|
2646
2700
|
const n = Number.parseInt(readFileSync7(file, "utf8").trim(), 10);
|
|
2647
2701
|
return Number.isInteger(n) ? n : null;
|
|
2648
2702
|
}
|
|
2649
2703
|
function jobDir(root, id, legacy = false) {
|
|
2650
|
-
return
|
|
2704
|
+
return join11(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
|
|
2651
2705
|
}
|
|
2652
2706
|
function resolveJobDir(root, id) {
|
|
2653
2707
|
const modern = jobDir(root, id, false);
|
|
2654
|
-
if (
|
|
2708
|
+
if (existsSync9(modern)) return modern;
|
|
2655
2709
|
const legacy = jobDir(root, id, true);
|
|
2656
|
-
if (
|
|
2710
|
+
if (existsSync9(legacy)) return legacy;
|
|
2657
2711
|
return modern;
|
|
2658
2712
|
}
|
|
2659
2713
|
function listJobIdsIn(root, rel) {
|
|
2660
|
-
const dir =
|
|
2661
|
-
if (!
|
|
2714
|
+
const dir = join11(root, rel);
|
|
2715
|
+
if (!existsSync9(dir)) return [];
|
|
2662
2716
|
return readdirSync3(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
|
|
2663
2717
|
}
|
|
2664
2718
|
function listRunningDetachedJobs(worktreePath) {
|
|
@@ -2671,7 +2725,7 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
2671
2725
|
const running = [];
|
|
2672
2726
|
for (const id of ids) {
|
|
2673
2727
|
const dir = resolveJobDir(root, id);
|
|
2674
|
-
const pid = readIntFile(
|
|
2728
|
+
const pid = readIntFile(join11(dir, "pid"));
|
|
2675
2729
|
if (pid != null && jobAlive(pid)) running.push(id);
|
|
2676
2730
|
}
|
|
2677
2731
|
return running.sort();
|
|
@@ -2724,12 +2778,12 @@ function planJobContinue(opts) {
|
|
|
2724
2778
|
return { action: "none" };
|
|
2725
2779
|
}
|
|
2726
2780
|
function tailProgress(logFile, maxLines = 12) {
|
|
2727
|
-
if (!
|
|
2781
|
+
if (!existsSync9(logFile)) return "(no log yet)";
|
|
2728
2782
|
const lines = readFileSync7(logFile, "utf8").split("\n");
|
|
2729
2783
|
return lines.slice(-maxLines).join("\n");
|
|
2730
2784
|
}
|
|
2731
2785
|
function readLogLines(file) {
|
|
2732
|
-
if (!
|
|
2786
|
+
if (!existsSync9(file)) return [];
|
|
2733
2787
|
const lines = readFileSync7(file, "utf8").split("\n");
|
|
2734
2788
|
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
2735
2789
|
return lines;
|
|
@@ -2741,15 +2795,15 @@ function takeDelta(logFile, cursorFile) {
|
|
|
2741
2795
|
return { delta: lines.slice(start).join("\n"), nextCursor: lines.length };
|
|
2742
2796
|
}
|
|
2743
2797
|
function snapshotJob(dir) {
|
|
2744
|
-
const pid = readIntFile(
|
|
2798
|
+
const pid = readIntFile(join11(dir, "pid"));
|
|
2745
2799
|
const running = jobTreeAlive(pid);
|
|
2746
2800
|
return {
|
|
2747
2801
|
pid,
|
|
2748
2802
|
running,
|
|
2749
|
-
exitCode: readIntFile(
|
|
2750
|
-
log:
|
|
2751
|
-
cursor:
|
|
2752
|
-
progress: tailProgress(
|
|
2803
|
+
exitCode: readIntFile(join11(dir, "exit")),
|
|
2804
|
+
log: join11(dir, "log"),
|
|
2805
|
+
cursor: join11(dir, "present.cursor"),
|
|
2806
|
+
progress: tailProgress(join11(dir, "log"))
|
|
2753
2807
|
};
|
|
2754
2808
|
}
|
|
2755
2809
|
function toResult(id, snap, extra) {
|
|
@@ -2758,7 +2812,7 @@ function toResult(id, snap, extra) {
|
|
|
2758
2812
|
const stillRunning = snap.running && !ok;
|
|
2759
2813
|
const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
|
|
2760
2814
|
try {
|
|
2761
|
-
|
|
2815
|
+
mkdirSync4(dirname3(snap.cursor), { recursive: true });
|
|
2762
2816
|
writeFileSync4(snap.cursor, `${nextCursor}
|
|
2763
2817
|
`);
|
|
2764
2818
|
} catch {
|
|
@@ -2786,7 +2840,7 @@ async function waitForDetachedJob(cwd, id, opts) {
|
|
|
2786
2840
|
const dir = resolveJobDir(root, jobId);
|
|
2787
2841
|
const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
|
|
2788
2842
|
const sleep = opts?.sleep ?? sleepMs;
|
|
2789
|
-
if (!
|
|
2843
|
+
if (!existsSync9(dir)) {
|
|
2790
2844
|
return {
|
|
2791
2845
|
stillRunning: false,
|
|
2792
2846
|
ok: false,
|
|
@@ -2832,7 +2886,7 @@ function killProcessTree(pid, signal) {
|
|
|
2832
2886
|
}
|
|
2833
2887
|
function appendJobLog(logFile, line) {
|
|
2834
2888
|
try {
|
|
2835
|
-
|
|
2889
|
+
mkdirSync4(dirname3(logFile), { recursive: true });
|
|
2836
2890
|
const body = line.endsWith("\n") ? line : `${line}
|
|
2837
2891
|
`;
|
|
2838
2892
|
appendFileSync(logFile, body);
|
|
@@ -2845,7 +2899,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
2845
2899
|
const dir = resolveJobDir(root, jobId);
|
|
2846
2900
|
const sleep = opts?.sleep ?? sleepMs;
|
|
2847
2901
|
const why = opts?.reason?.trim() ?? "";
|
|
2848
|
-
if (!
|
|
2902
|
+
if (!existsSync9(dir)) {
|
|
2849
2903
|
return {
|
|
2850
2904
|
stillRunning: false,
|
|
2851
2905
|
ok: false,
|
|
@@ -2881,8 +2935,8 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
2881
2935
|
killProcessTree(targetPid, "SIGKILL");
|
|
2882
2936
|
await sleep(100);
|
|
2883
2937
|
}
|
|
2884
|
-
const exitFile =
|
|
2885
|
-
if (!
|
|
2938
|
+
const exitFile = join11(dir, "exit");
|
|
2939
|
+
if (!existsSync9(exitFile)) {
|
|
2886
2940
|
try {
|
|
2887
2941
|
writeFileSync4(exitFile, "1\n");
|
|
2888
2942
|
} catch {
|
|
@@ -2906,7 +2960,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
2906
2960
|
}
|
|
2907
2961
|
|
|
2908
2962
|
// src/threads/create.ts
|
|
2909
|
-
import { existsSync as
|
|
2963
|
+
import { existsSync as existsSync10 } from "fs";
|
|
2910
2964
|
|
|
2911
2965
|
// src/detect/detect.ts
|
|
2912
2966
|
var REQUIRE_AGENT_TIMEOUT_MS = 8e3;
|
|
@@ -3426,7 +3480,7 @@ function reuseLiveThread(input, repoPath, match) {
|
|
|
3426
3480
|
}
|
|
3427
3481
|
async function createThread(input, _onSetupLine) {
|
|
3428
3482
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
3429
|
-
if (!
|
|
3483
|
+
if (!existsSync10(repoPath)) {
|
|
3430
3484
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
3431
3485
|
}
|
|
3432
3486
|
const reused = reuseLiveThread(input, repoPath, {
|
|
@@ -3624,7 +3678,7 @@ function shouldRemoveWorktreeOnTeardown(thread) {
|
|
|
3624
3678
|
|
|
3625
3679
|
// src/store/turn-live.ts
|
|
3626
3680
|
import {
|
|
3627
|
-
existsSync as
|
|
3681
|
+
existsSync as existsSync11,
|
|
3628
3682
|
renameSync,
|
|
3629
3683
|
unlinkSync as unlinkSync2,
|
|
3630
3684
|
writeFileSync as writeFileSync5,
|
|
@@ -3716,7 +3770,7 @@ function writeTurnLive(threadId, progress) {
|
|
|
3716
3770
|
}
|
|
3717
3771
|
function readTurnLive(threadId) {
|
|
3718
3772
|
const path = threadLivePath(threadId);
|
|
3719
|
-
if (!
|
|
3773
|
+
if (!existsSync11(path)) return null;
|
|
3720
3774
|
try {
|
|
3721
3775
|
const raw = JSON.parse(readFileSync8(path, "utf8"));
|
|
3722
3776
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
@@ -3730,7 +3784,7 @@ function clearTurnLive(threadId) {
|
|
|
3730
3784
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
3731
3785
|
buffers.delete(threadId);
|
|
3732
3786
|
const path = threadLivePath(threadId);
|
|
3733
|
-
if (!
|
|
3787
|
+
if (!existsSync11(path)) return;
|
|
3734
3788
|
try {
|
|
3735
3789
|
unlinkSync2(path);
|
|
3736
3790
|
} catch {
|
|
@@ -3915,26 +3969,26 @@ function createQuotaFailoverChat(from, fallbackAgent, limitText) {
|
|
|
3915
3969
|
import { execFileSync } from "child_process";
|
|
3916
3970
|
import {
|
|
3917
3971
|
copyFileSync as copyFileSync2,
|
|
3918
|
-
existsSync as
|
|
3972
|
+
existsSync as existsSync12,
|
|
3919
3973
|
mkdtempSync,
|
|
3920
3974
|
readdirSync as readdirSync4,
|
|
3921
3975
|
readFileSync as readFileSync9,
|
|
3922
3976
|
rmSync
|
|
3923
3977
|
} from "fs";
|
|
3924
3978
|
import { tmpdir } from "os";
|
|
3925
|
-
import { join as
|
|
3979
|
+
import { join as join12 } from "path";
|
|
3926
3980
|
import { createRequire } from "module";
|
|
3927
|
-
var CONDUCTOR_APP_SUPPORT =
|
|
3981
|
+
var CONDUCTOR_APP_SUPPORT = join12(
|
|
3928
3982
|
process.env.HOME ?? "",
|
|
3929
3983
|
"Library",
|
|
3930
3984
|
"Application Support",
|
|
3931
3985
|
"com.conductor.app"
|
|
3932
3986
|
);
|
|
3933
|
-
var CONDUCTOR_DB =
|
|
3934
|
-
var CURSOR_SDK_STORE =
|
|
3987
|
+
var CONDUCTOR_DB = join12(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
3988
|
+
var CURSOR_SDK_STORE = join12(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
3935
3989
|
function thisModuleFile() {
|
|
3936
3990
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
3937
|
-
return cjsFile || process.argv[1] ||
|
|
3991
|
+
return cjsFile || process.argv[1] || join12(process.cwd(), "package.json");
|
|
3938
3992
|
}
|
|
3939
3993
|
function openReadonlySqlite(file) {
|
|
3940
3994
|
const req = createRequire(thisModuleFile());
|
|
@@ -3952,7 +4006,7 @@ function mapAgentType(raw) {
|
|
|
3952
4006
|
return null;
|
|
3953
4007
|
}
|
|
3954
4008
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
3955
|
-
if (!workspacePath || !
|
|
4009
|
+
if (!workspacePath || !existsSync12(CURSOR_SDK_STORE)) return null;
|
|
3956
4010
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
3957
4011
|
let best = null;
|
|
3958
4012
|
let hashes;
|
|
@@ -3962,8 +4016,8 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
3962
4016
|
return null;
|
|
3963
4017
|
}
|
|
3964
4018
|
for (const hash of hashes) {
|
|
3965
|
-
const agentsFile =
|
|
3966
|
-
if (!
|
|
4019
|
+
const agentsFile = join12(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
4020
|
+
if (!existsSync12(agentsFile)) continue;
|
|
3967
4021
|
let text;
|
|
3968
4022
|
try {
|
|
3969
4023
|
text = readFileSync9(agentsFile, "utf8");
|
|
@@ -3990,7 +4044,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
3990
4044
|
return best?.agentId ?? null;
|
|
3991
4045
|
}
|
|
3992
4046
|
async function adoptThread(input) {
|
|
3993
|
-
if (!
|
|
4047
|
+
if (!existsSync12(input.worktreePath)) {
|
|
3994
4048
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
3995
4049
|
}
|
|
3996
4050
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -4016,16 +4070,16 @@ async function adoptThread(input) {
|
|
|
4016
4070
|
return thread;
|
|
4017
4071
|
}
|
|
4018
4072
|
function listConductorWorkspaces() {
|
|
4019
|
-
if (!
|
|
4073
|
+
if (!existsSync12(CONDUCTOR_DB)) {
|
|
4020
4074
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
4021
4075
|
}
|
|
4022
|
-
const tmp = mkdtempSync(
|
|
4023
|
-
const snapshot =
|
|
4076
|
+
const tmp = mkdtempSync(join12(tmpdir(), "sideboard-conductor-"));
|
|
4077
|
+
const snapshot = join12(tmp, "conductor.db");
|
|
4024
4078
|
try {
|
|
4025
4079
|
copyFileSync2(CONDUCTOR_DB, snapshot);
|
|
4026
4080
|
for (const suffix of ["-wal", "-shm"]) {
|
|
4027
4081
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
4028
|
-
if (
|
|
4082
|
+
if (existsSync12(src)) {
|
|
4029
4083
|
try {
|
|
4030
4084
|
copyFileSync2(src, `${snapshot}${suffix}`);
|
|
4031
4085
|
} catch {
|
|
@@ -4107,16 +4161,16 @@ function listConductorWorkspaces() {
|
|
|
4107
4161
|
}
|
|
4108
4162
|
}
|
|
4109
4163
|
function importConductorWorkspace(workspaceId) {
|
|
4110
|
-
if (!
|
|
4164
|
+
if (!existsSync12(CONDUCTOR_DB)) {
|
|
4111
4165
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
4112
4166
|
}
|
|
4113
|
-
const tmp = mkdtempSync(
|
|
4114
|
-
const snapshot =
|
|
4167
|
+
const tmp = mkdtempSync(join12(tmpdir(), "sideboard-conductor-"));
|
|
4168
|
+
const snapshot = join12(tmp, "conductor.db");
|
|
4115
4169
|
try {
|
|
4116
4170
|
copyFileSync2(CONDUCTOR_DB, snapshot);
|
|
4117
4171
|
for (const suffix of ["-wal", "-shm"]) {
|
|
4118
4172
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
4119
|
-
if (
|
|
4173
|
+
if (existsSync12(src)) {
|
|
4120
4174
|
try {
|
|
4121
4175
|
copyFileSync2(src, `${snapshot}${suffix}`);
|
|
4122
4176
|
} catch {
|
|
@@ -4136,7 +4190,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
4136
4190
|
).get(workspaceId);
|
|
4137
4191
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
4138
4192
|
const worktreePath = String(row.workspacePath);
|
|
4139
|
-
if (!
|
|
4193
|
+
if (!existsSync12(worktreePath)) {
|
|
4140
4194
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
4141
4195
|
}
|
|
4142
4196
|
let sessionId = null;
|
|
@@ -4207,7 +4261,7 @@ async function importConductorWorkspaceAsync(workspaceId) {
|
|
|
4207
4261
|
}
|
|
4208
4262
|
|
|
4209
4263
|
// src/threads/stack-layers.ts
|
|
4210
|
-
import { existsSync as
|
|
4264
|
+
import { existsSync as existsSync13 } from "fs";
|
|
4211
4265
|
function stackIdFrom(stack) {
|
|
4212
4266
|
if (stack.stackNumber != null) return `gh-stack-${stack.stackNumber}`;
|
|
4213
4267
|
const key = stack.layers.map((l) => l.branchName).join("|");
|
|
@@ -4270,7 +4324,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
4270
4324
|
let createdWorktree = false;
|
|
4271
4325
|
const trees = await listWorktrees(repoPath);
|
|
4272
4326
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
4273
|
-
if (checkedOut?.path &&
|
|
4327
|
+
if (checkedOut?.path && existsSync13(checkedOut.path)) {
|
|
4274
4328
|
if (input.reuseExistingWorktree !== false) {
|
|
4275
4329
|
worktreePath = checkedOut.path;
|
|
4276
4330
|
} else {
|
|
@@ -4412,7 +4466,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
4412
4466
|
async function createPrStack(input, onSetupLine) {
|
|
4413
4467
|
await requireAgent(input.agent);
|
|
4414
4468
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
4415
|
-
if (!
|
|
4469
|
+
if (!existsSync13(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
4416
4470
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
4417
4471
|
const status = await detectGhStack(repoPath);
|
|
4418
4472
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -4479,7 +4533,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
4479
4533
|
}
|
|
4480
4534
|
}
|
|
4481
4535
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
4482
|
-
if (!claimed.has(bootstrap.worktreePath) &&
|
|
4536
|
+
if (!claimed.has(bootstrap.worktreePath) && existsSync13(bootstrap.worktreePath)) {
|
|
4483
4537
|
try {
|
|
4484
4538
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
4485
4539
|
deleteBranch: bootstrap.branchName
|
|
@@ -4491,10 +4545,10 @@ async function createPrStack(input, onSetupLine) {
|
|
|
4491
4545
|
}
|
|
4492
4546
|
|
|
4493
4547
|
// src/diff/diff.ts
|
|
4494
|
-
import { existsSync as
|
|
4495
|
-
import { dirname as dirname4, join as
|
|
4548
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync5, readFileSync as readFileSync10, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
4549
|
+
import { dirname as dirname4, join as join13 } from "path";
|
|
4496
4550
|
async function inspectGitWorktree(worktreePath) {
|
|
4497
|
-
if (!worktreePath || !
|
|
4551
|
+
if (!worktreePath || !existsSync14(worktreePath)) return "missing_worktree";
|
|
4498
4552
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
4499
4553
|
reject: false
|
|
4500
4554
|
});
|
|
@@ -4502,7 +4556,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
4502
4556
|
return "ok";
|
|
4503
4557
|
}
|
|
4504
4558
|
async function initializeGitRepository(worktreePath) {
|
|
4505
|
-
if (!worktreePath || !
|
|
4559
|
+
if (!worktreePath || !existsSync14(worktreePath)) {
|
|
4506
4560
|
throw new Error("Worktree not found");
|
|
4507
4561
|
}
|
|
4508
4562
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -4638,7 +4692,7 @@ new file mode 100644
|
|
|
4638
4692
|
};
|
|
4639
4693
|
}
|
|
4640
4694
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
4641
|
-
const abs =
|
|
4695
|
+
const abs = join13(worktreePath, path);
|
|
4642
4696
|
try {
|
|
4643
4697
|
const st = statSync2(abs);
|
|
4644
4698
|
if (st.isFile() && st.size > maxHunk) {
|
|
@@ -5143,7 +5197,7 @@ var DEFAULT_UPLOAD_MAX_BYTES = 5e7;
|
|
|
5143
5197
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
5144
5198
|
assertSafeRelativePath(relativePath);
|
|
5145
5199
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
5146
|
-
const abs =
|
|
5200
|
+
const abs = join13(worktreePath, relativePath);
|
|
5147
5201
|
const st = statSync2(abs);
|
|
5148
5202
|
if (!st.isFile()) {
|
|
5149
5203
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -5163,7 +5217,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
5163
5217
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
5164
5218
|
assertSafeRelativePath(relativePath);
|
|
5165
5219
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
5166
|
-
const abs =
|
|
5220
|
+
const abs = join13(worktreePath, relativePath);
|
|
5167
5221
|
const st = statSync2(abs);
|
|
5168
5222
|
if (!st.isFile()) {
|
|
5169
5223
|
throw new Error(`Not a file: ${relativePath}`);
|
|
@@ -5211,8 +5265,8 @@ function assertSafeRelativePath(relativePath) {
|
|
|
5211
5265
|
}
|
|
5212
5266
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
5213
5267
|
assertSafeRelativePath(relativePath);
|
|
5214
|
-
const abs =
|
|
5215
|
-
|
|
5268
|
+
const abs = join13(worktreePath, relativePath);
|
|
5269
|
+
mkdirSync5(dirname4(abs), { recursive: true });
|
|
5216
5270
|
writeFileSync6(abs, content, "utf8");
|
|
5217
5271
|
return { path: relativePath };
|
|
5218
5272
|
}
|
|
@@ -5338,9 +5392,9 @@ async function confirmLand(thread, opts) {
|
|
|
5338
5392
|
}
|
|
5339
5393
|
|
|
5340
5394
|
// src/skills/discover.ts
|
|
5341
|
-
import { existsSync as
|
|
5395
|
+
import { existsSync as existsSync15, readdirSync as readdirSync5, readFileSync as readFileSync11, statSync as statSync3 } from "fs";
|
|
5342
5396
|
import { homedir } from "os";
|
|
5343
|
-
import { join as
|
|
5397
|
+
import { join as join14 } from "path";
|
|
5344
5398
|
|
|
5345
5399
|
// src/skills/bundled/long-running.ts
|
|
5346
5400
|
var LONG_RUNNING_SKILL_COMMAND = "long-running";
|
|
@@ -5496,7 +5550,7 @@ function readSkill(skillMd, source) {
|
|
|
5496
5550
|
}
|
|
5497
5551
|
}
|
|
5498
5552
|
function scanSkillsDir(dir, source, out) {
|
|
5499
|
-
if (!
|
|
5553
|
+
if (!existsSync15(dir)) return;
|
|
5500
5554
|
let entries;
|
|
5501
5555
|
try {
|
|
5502
5556
|
entries = readdirSync5(dir);
|
|
@@ -5505,8 +5559,8 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5505
5559
|
}
|
|
5506
5560
|
for (const entry of entries) {
|
|
5507
5561
|
if (entry.startsWith(".")) continue;
|
|
5508
|
-
const skillMd =
|
|
5509
|
-
if (!
|
|
5562
|
+
const skillMd = join14(dir, entry, "SKILL.md");
|
|
5563
|
+
if (!existsSync15(skillMd)) continue;
|
|
5510
5564
|
try {
|
|
5511
5565
|
if (!statSync3(skillMd).isFile()) continue;
|
|
5512
5566
|
} catch {
|
|
@@ -5517,7 +5571,7 @@ function scanSkillsDir(dir, source, out) {
|
|
|
5517
5571
|
}
|
|
5518
5572
|
}
|
|
5519
5573
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
5520
|
-
if (!
|
|
5574
|
+
if (!existsSync15(pluginsRoot)) return;
|
|
5521
5575
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
5522
5576
|
if (depth > 7) return;
|
|
5523
5577
|
let entries;
|
|
@@ -5527,12 +5581,12 @@ function scanClaudePluginSkills(pluginsRoot, out) {
|
|
|
5527
5581
|
return;
|
|
5528
5582
|
}
|
|
5529
5583
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
5530
|
-
const skill = readSkill(
|
|
5584
|
+
const skill = readSkill(join14(dir, "SKILL.md"), "cli");
|
|
5531
5585
|
if (skill) out.push(skill);
|
|
5532
5586
|
}
|
|
5533
5587
|
for (const entry of entries) {
|
|
5534
5588
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
5535
|
-
const full =
|
|
5589
|
+
const full = join14(dir, entry);
|
|
5536
5590
|
try {
|
|
5537
5591
|
if (!statSync3(full).isDirectory()) continue;
|
|
5538
5592
|
} catch {
|
|
@@ -5552,17 +5606,17 @@ function discoverSkills(worktreePath) {
|
|
|
5552
5606
|
const home = homedir();
|
|
5553
5607
|
const collected = [];
|
|
5554
5608
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
5555
|
-
scanSkillsDir(
|
|
5609
|
+
scanSkillsDir(join14(worktreePath, rel), "workspace", collected);
|
|
5556
5610
|
}
|
|
5557
5611
|
for (const abs of [
|
|
5558
|
-
|
|
5559
|
-
|
|
5560
|
-
|
|
5561
|
-
|
|
5612
|
+
join14(home, ".claude/skills"),
|
|
5613
|
+
join14(home, ".cursor/skills"),
|
|
5614
|
+
join14(home, ".sideboard/skills"),
|
|
5615
|
+
join14(home, ".brightsy/skills")
|
|
5562
5616
|
]) {
|
|
5563
5617
|
scanSkillsDir(abs, "user", collected);
|
|
5564
5618
|
}
|
|
5565
|
-
scanClaudePluginSkills(
|
|
5619
|
+
scanClaudePluginSkills(join14(home, ".claude/plugins"), collected);
|
|
5566
5620
|
collected.push(...bundledSkills());
|
|
5567
5621
|
const rank = {
|
|
5568
5622
|
workspace: 0,
|
|
@@ -5681,18 +5735,18 @@ function expandComposerPrompt(worktreePath, prompt, opts) {
|
|
|
5681
5735
|
}
|
|
5682
5736
|
|
|
5683
5737
|
// src/agents/instructions.ts
|
|
5684
|
-
import { existsSync as
|
|
5685
|
-
import { join as
|
|
5738
|
+
import { existsSync as existsSync17 } from "fs";
|
|
5739
|
+
import { join as join16 } from "path";
|
|
5686
5740
|
|
|
5687
5741
|
// src/skills/detached-job-path.ts
|
|
5688
|
-
import { existsSync as
|
|
5689
|
-
import { dirname as dirname5, join as
|
|
5742
|
+
import { existsSync as existsSync16 } from "fs";
|
|
5743
|
+
import { dirname as dirname5, join as join15 } from "path";
|
|
5690
5744
|
import { fileURLToPath } from "url";
|
|
5691
5745
|
var DETACHED_JOB_FILENAMES = ["detached-job.cjs", "detached-job.js"];
|
|
5692
5746
|
function detachedJobScriptIn(dir) {
|
|
5693
5747
|
for (const name of DETACHED_JOB_FILENAMES) {
|
|
5694
|
-
const script =
|
|
5695
|
-
if (
|
|
5748
|
+
const script = join15(dir, "scripts", name);
|
|
5749
|
+
if (existsSync16(script)) return script;
|
|
5696
5750
|
}
|
|
5697
5751
|
return null;
|
|
5698
5752
|
}
|
|
@@ -5873,11 +5927,13 @@ function formatPrGateDirective() {
|
|
|
5873
5927
|
}
|
|
5874
5928
|
function formatProcessGuideDirective(opts) {
|
|
5875
5929
|
const worktree = opts?.worktreePath?.trim();
|
|
5876
|
-
const hasGraphSkill = !!worktree &&
|
|
5877
|
-
const hasReviewSkill = !!worktree &&
|
|
5930
|
+
const hasGraphSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
5931
|
+
const hasReviewSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/review/SKILL.md"));
|
|
5932
|
+
const hasInstallSkill = !!worktree && existsSync17(join16(worktree, ".claude/skills/worktree-install/SKILL.md"));
|
|
5878
5933
|
return [
|
|
5879
5934
|
"Process guides (recurring work only):",
|
|
5880
5935
|
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,
|
|
5936
|
+
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,
|
|
5881
5937
|
"- 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`.",
|
|
5882
5938
|
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.",
|
|
5883
5939
|
"- 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."
|
|
@@ -6047,8 +6103,8 @@ async function syncThreadBranchFromGit(threadId) {
|
|
|
6047
6103
|
|
|
6048
6104
|
// src/store/schedules.ts
|
|
6049
6105
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
6050
|
-
import { existsSync as
|
|
6051
|
-
import { join as
|
|
6106
|
+
import { existsSync as existsSync18, readFileSync as readFileSync12 } from "fs";
|
|
6107
|
+
import { join as join17 } from "path";
|
|
6052
6108
|
import { Cron } from "croner";
|
|
6053
6109
|
var DURATION_RE = /^(\d+)(s|m|h|d)$/i;
|
|
6054
6110
|
var UNIT_MS = {
|
|
@@ -6058,7 +6114,7 @@ var UNIT_MS = {
|
|
|
6058
6114
|
d: 864e5
|
|
6059
6115
|
};
|
|
6060
6116
|
function schedulesPath() {
|
|
6061
|
-
return
|
|
6117
|
+
return join17(appDataDir(), "schedules.json");
|
|
6062
6118
|
}
|
|
6063
6119
|
function parseDurationMs(every) {
|
|
6064
6120
|
const m = every.trim().match(DURATION_RE);
|
|
@@ -6158,7 +6214,7 @@ function normalizeTask(raw) {
|
|
|
6158
6214
|
}
|
|
6159
6215
|
function readAll() {
|
|
6160
6216
|
const path = schedulesPath();
|
|
6161
|
-
if (!
|
|
6217
|
+
if (!existsSync18(path)) return [];
|
|
6162
6218
|
try {
|
|
6163
6219
|
const parsed = JSON.parse(readFileSync12(path, "utf8"));
|
|
6164
6220
|
if (!Array.isArray(parsed)) return [];
|
|
@@ -6283,7 +6339,7 @@ function formatScheduledPrompt(name, prompt) {
|
|
|
6283
6339
|
${prompt}`;
|
|
6284
6340
|
}
|
|
6285
6341
|
async function defaultDeps() {
|
|
6286
|
-
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-
|
|
6342
|
+
const { getOrchestrator: getOrchestrator2, startOrchestration: startOrchestration2 } = await import("./orchestrator-QBB2RELD.js");
|
|
6287
6343
|
const orch = getOrchestrator2();
|
|
6288
6344
|
return {
|
|
6289
6345
|
findThread: (id) => findThreadByRef(id),
|
|
@@ -6526,7 +6582,7 @@ var Orchestrator = class {
|
|
|
6526
6582
|
}
|
|
6527
6583
|
continue;
|
|
6528
6584
|
}
|
|
6529
|
-
if (!
|
|
6585
|
+
if (!existsSync19(thread.worktreePath)) {
|
|
6530
6586
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
6531
6587
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
6532
6588
|
continue;
|
|
@@ -8416,7 +8472,7 @@ var Orchestrator = class {
|
|
|
8416
8472
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
8417
8473
|
return restored2;
|
|
8418
8474
|
}
|
|
8419
|
-
if (!
|
|
8475
|
+
if (!existsSync19(thread.worktreePath)) {
|
|
8420
8476
|
if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
|
|
8421
8477
|
throw new Error(
|
|
8422
8478
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|