@sideboard-ai/core 0.1.238 → 0.1.239
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-E6UJGLPM.js → chunk-CDG4CLWQ.js} +326 -147
- package/dist/{chunk-32DG3DA2.js → chunk-D5SDZSEA.js} +337 -148
- package/dist/index.cjs +501 -295
- package/dist/index.d.cts +33 -2
- package/dist/index.d.ts +33 -2
- package/dist/index.js +22 -2
- package/dist/mcp/run-stdio.cjs +482 -296
- package/dist/mcp/run-stdio.js +2 -2
- package/dist/{orchestrator-AAYKR4AI.js → orchestrator-3ZP4WTQ4.js} +1 -1
- package/dist/{orchestrator-HPMDB2SG.js → orchestrator-R75VDUR2.js} +1 -1
- package/package.json +1 -1
package/dist/mcp/run-stdio.cjs
CHANGED
|
@@ -11236,10 +11236,10 @@ function eventsFromClaudeSystem(obj) {
|
|
|
11236
11236
|
if (subtype === "api_retry") {
|
|
11237
11237
|
const attempt = obj.attempt;
|
|
11238
11238
|
const max = obj.max_retries;
|
|
11239
|
-
const
|
|
11239
|
+
const delay2 = obj.retry_delay_ms;
|
|
11240
11240
|
return {
|
|
11241
11241
|
type: "thinking",
|
|
11242
|
-
data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof
|
|
11242
|
+
data: `API retry ${attempt ?? "?"}/${max ?? "?"}${typeof delay2 === "number" ? ` (wait ${delay2}ms)` : ""}`
|
|
11243
11243
|
};
|
|
11244
11244
|
}
|
|
11245
11245
|
if (subtype === "status") {
|
|
@@ -14525,15 +14525,76 @@ var init_request_review = __esm({
|
|
|
14525
14525
|
}
|
|
14526
14526
|
});
|
|
14527
14527
|
|
|
14528
|
+
// src/hook/worktree-run-ports.ts
|
|
14529
|
+
function worktreeRunPortsPath(worktreePath) {
|
|
14530
|
+
return (0, import_node_path38.join)(worktreePath, RUN_PORTS_REL);
|
|
14531
|
+
}
|
|
14532
|
+
function isPort(value) {
|
|
14533
|
+
return typeof value === "number" && Number.isInteger(value) && value > 0 && value <= 65535;
|
|
14534
|
+
}
|
|
14535
|
+
function parseFile(raw) {
|
|
14536
|
+
try {
|
|
14537
|
+
const parsed = JSON.parse(raw);
|
|
14538
|
+
if (!parsed || typeof parsed !== "object") return {};
|
|
14539
|
+
const scripts = parsed.scripts;
|
|
14540
|
+
if (!scripts || typeof scripts !== "object") return {};
|
|
14541
|
+
const next = {};
|
|
14542
|
+
for (const [name, ports] of Object.entries(scripts)) {
|
|
14543
|
+
if (!name || !Array.isArray(ports)) continue;
|
|
14544
|
+
const cleaned = ports.filter(isPort);
|
|
14545
|
+
if (cleaned.length) next[name] = cleaned;
|
|
14546
|
+
}
|
|
14547
|
+
return { scripts: next };
|
|
14548
|
+
} catch {
|
|
14549
|
+
return {};
|
|
14550
|
+
}
|
|
14551
|
+
}
|
|
14552
|
+
function loadWorktreeRunPorts(worktreePath, scriptName) {
|
|
14553
|
+
if (!worktreePath.trim() || !scriptName.trim()) return null;
|
|
14554
|
+
try {
|
|
14555
|
+
const raw = (0, import_node_fs38.readFileSync)(worktreeRunPortsPath(worktreePath), "utf8");
|
|
14556
|
+
const ports = parseFile(raw).scripts?.[scriptName];
|
|
14557
|
+
return ports?.length ? ports : null;
|
|
14558
|
+
} catch {
|
|
14559
|
+
return null;
|
|
14560
|
+
}
|
|
14561
|
+
}
|
|
14562
|
+
function saveWorktreeRunPorts(worktreePath, scriptName, ports) {
|
|
14563
|
+
if (!worktreePath.trim() || !scriptName.trim()) return;
|
|
14564
|
+
const cleaned = ports.filter(isPort);
|
|
14565
|
+
if (!cleaned.length) return;
|
|
14566
|
+
const path = worktreeRunPortsPath(worktreePath);
|
|
14567
|
+
let current = {};
|
|
14568
|
+
try {
|
|
14569
|
+
current = parseFile((0, import_node_fs38.readFileSync)(path, "utf8"));
|
|
14570
|
+
} catch {
|
|
14571
|
+
current = {};
|
|
14572
|
+
}
|
|
14573
|
+
const scripts = { ...current.scripts ?? {} };
|
|
14574
|
+
scripts[scriptName] = cleaned;
|
|
14575
|
+
(0, import_node_fs38.mkdirSync)((0, import_node_path38.dirname)(path), { recursive: true });
|
|
14576
|
+
(0, import_node_fs38.writeFileSync)(path, `${JSON.stringify({ scripts }, null, 2)}
|
|
14577
|
+
`, "utf8");
|
|
14578
|
+
}
|
|
14579
|
+
var import_node_fs38, import_node_path38, RUN_PORTS_REL;
|
|
14580
|
+
var init_worktree_run_ports = __esm({
|
|
14581
|
+
"src/hook/worktree-run-ports.ts"() {
|
|
14582
|
+
"use strict";
|
|
14583
|
+
import_node_fs38 = require("fs");
|
|
14584
|
+
import_node_path38 = require("path");
|
|
14585
|
+
RUN_PORTS_REL = ".context/.sideboard/run-ports.json";
|
|
14586
|
+
}
|
|
14587
|
+
});
|
|
14588
|
+
|
|
14528
14589
|
// src/hook/conductor.ts
|
|
14529
14590
|
function matchSimpleGlob(pattern, name) {
|
|
14530
14591
|
const escaped = pattern.replace(/[.+^${}()|[\]\\]/g, "\\$&").replace(/\*/g, ".*").replace(/\?/g, ".");
|
|
14531
14592
|
return new RegExp(`^${escaped}$`).test(name);
|
|
14532
14593
|
}
|
|
14533
14594
|
function readWorktreeInclude(repoPath) {
|
|
14534
|
-
const path = (0,
|
|
14535
|
-
if (!(0,
|
|
14536
|
-
return (0,
|
|
14595
|
+
const path = (0, import_node_path39.join)(repoPath, ".worktreeinclude");
|
|
14596
|
+
if (!(0, import_node_fs39.existsSync)(path)) return [];
|
|
14597
|
+
return (0, import_node_fs39.readFileSync)(path, "utf8").split("\n").map((l) => l.trim()).filter((l) => l && !l.startsWith("#"));
|
|
14537
14598
|
}
|
|
14538
14599
|
function resolveFilesToCopy(repoPath) {
|
|
14539
14600
|
const fromInclude = readWorktreeInclude(repoPath);
|
|
@@ -14543,10 +14604,10 @@ function resolveFilesToCopy(repoPath) {
|
|
|
14543
14604
|
if (settings?.fileIncludeGlobs?.length) {
|
|
14544
14605
|
const matched = [];
|
|
14545
14606
|
try {
|
|
14546
|
-
for (const entry of (0,
|
|
14607
|
+
for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
14547
14608
|
if (!entry.isFile()) continue;
|
|
14548
14609
|
for (const glob of settings.fileIncludeGlobs) {
|
|
14549
|
-
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0,
|
|
14610
|
+
if (matchSimpleGlob(glob, entry.name) || matchSimpleGlob((0, import_node_path39.basename)(glob), entry.name)) {
|
|
14550
14611
|
matched.push(entry.name);
|
|
14551
14612
|
break;
|
|
14552
14613
|
}
|
|
@@ -14558,7 +14619,7 @@ function resolveFilesToCopy(repoPath) {
|
|
|
14558
14619
|
}
|
|
14559
14620
|
const defaults = [];
|
|
14560
14621
|
try {
|
|
14561
|
-
for (const entry of (0,
|
|
14622
|
+
for (const entry of (0, import_node_fs39.readdirSync)(repoPath, { withFileTypes: true })) {
|
|
14562
14623
|
if (entry.isFile() && entry.name.startsWith(".env")) {
|
|
14563
14624
|
defaults.push(entry.name);
|
|
14564
14625
|
}
|
|
@@ -14572,11 +14633,11 @@ function copyConfiguredFiles(repoPath, worktreePath) {
|
|
|
14572
14633
|
const patterns = resolveFilesToCopy(repoPath);
|
|
14573
14634
|
const copied = [];
|
|
14574
14635
|
for (const rel of patterns) {
|
|
14575
|
-
const src = (0,
|
|
14576
|
-
if (!(0,
|
|
14577
|
-
const dest = (0,
|
|
14578
|
-
(0,
|
|
14579
|
-
(0,
|
|
14636
|
+
const src = (0, import_node_path39.join)(repoPath, rel);
|
|
14637
|
+
if (!(0, import_node_fs39.existsSync)(src)) continue;
|
|
14638
|
+
const dest = (0, import_node_path39.join)(worktreePath, rel);
|
|
14639
|
+
(0, import_node_fs39.mkdirSync)((0, import_node_path39.dirname)(dest), { recursive: true });
|
|
14640
|
+
(0, import_node_fs39.copyFileSync)(src, dest);
|
|
14580
14641
|
copied.push(rel);
|
|
14581
14642
|
}
|
|
14582
14643
|
return copied;
|
|
@@ -14611,7 +14672,7 @@ function buildWorkspaceScriptEnv(opts, baseEnv) {
|
|
|
14611
14672
|
const env = stripNestedElectronEnv({
|
|
14612
14673
|
...baseEnv ?? process.env
|
|
14613
14674
|
});
|
|
14614
|
-
const name = opts.workspaceName ?? (0,
|
|
14675
|
+
const name = opts.workspaceName ?? (0, import_node_path39.basename)(opts.worktreePath);
|
|
14615
14676
|
const ports = opts.ports ?? [];
|
|
14616
14677
|
const primary = ports[0];
|
|
14617
14678
|
env.SIDEBOARD_WORKSPACE_NAME = name;
|
|
@@ -14651,6 +14712,57 @@ function killableListenerPids(raw, selfPid = process.pid) {
|
|
|
14651
14712
|
}
|
|
14652
14713
|
return pids;
|
|
14653
14714
|
}
|
|
14715
|
+
function listUnixListenerPids(port, selfPid) {
|
|
14716
|
+
try {
|
|
14717
|
+
const raw = (0, import_node_child_process4.execFileSync)("lsof", [`-tiTCP:${port}`, "-sTCP:LISTEN"], {
|
|
14718
|
+
encoding: "utf8",
|
|
14719
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
14720
|
+
timeout: 2e3
|
|
14721
|
+
});
|
|
14722
|
+
return killableListenerPids(raw, selfPid);
|
|
14723
|
+
} catch {
|
|
14724
|
+
return [];
|
|
14725
|
+
}
|
|
14726
|
+
}
|
|
14727
|
+
function listenerCwd(pid) {
|
|
14728
|
+
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
14729
|
+
try {
|
|
14730
|
+
const raw = (0, import_node_child_process4.execFileSync)("lsof", ["-a", "-p", String(pid), "-d", "cwd", "-Fn"], {
|
|
14731
|
+
encoding: "utf8",
|
|
14732
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
14733
|
+
timeout: 2e3
|
|
14734
|
+
});
|
|
14735
|
+
for (const line of raw.split("\n")) {
|
|
14736
|
+
if (line.startsWith("n") && line.length > 1) return line.slice(1);
|
|
14737
|
+
}
|
|
14738
|
+
} catch {
|
|
14739
|
+
}
|
|
14740
|
+
return null;
|
|
14741
|
+
}
|
|
14742
|
+
function realpathOrResolve(path) {
|
|
14743
|
+
try {
|
|
14744
|
+
return (0, import_node_fs39.realpathSync)(path);
|
|
14745
|
+
} catch {
|
|
14746
|
+
return (0, import_node_path39.resolve)(path);
|
|
14747
|
+
}
|
|
14748
|
+
}
|
|
14749
|
+
function isOtherWorktreeListenerCwd(cwd, worktreePath) {
|
|
14750
|
+
const wt = realpathOrResolve(worktreePath);
|
|
14751
|
+
const c = realpathOrResolve(cwd);
|
|
14752
|
+
if (c === wt || c.startsWith(wt + import_node_path39.sep)) return false;
|
|
14753
|
+
const parent = (0, import_node_path39.dirname)(wt);
|
|
14754
|
+
const thisName = (0, import_node_path39.basename)(wt);
|
|
14755
|
+
if (!thisName || c === parent) return false;
|
|
14756
|
+
if (!c.startsWith(parent + import_node_path39.sep)) return false;
|
|
14757
|
+
const first = c.slice(parent.length + 1).split(import_node_path39.sep)[0];
|
|
14758
|
+
return Boolean(first) && first !== thisName;
|
|
14759
|
+
}
|
|
14760
|
+
function signalPid(pid, signal) {
|
|
14761
|
+
try {
|
|
14762
|
+
process.kill(pid, signal);
|
|
14763
|
+
} catch {
|
|
14764
|
+
}
|
|
14765
|
+
}
|
|
14654
14766
|
function killListenersOnPorts(ports) {
|
|
14655
14767
|
const selfPid = process.pid;
|
|
14656
14768
|
for (const port of ports) {
|
|
@@ -14668,26 +14780,32 @@ function killListenersOnPorts(ports) {
|
|
|
14668
14780
|
);
|
|
14669
14781
|
continue;
|
|
14670
14782
|
}
|
|
14671
|
-
|
|
14672
|
-
|
|
14673
|
-
raw = (0, import_node_child_process4.execFileSync)("lsof", [`-tiTCP:${port}`, "-sTCP:LISTEN"], {
|
|
14674
|
-
encoding: "utf8",
|
|
14675
|
-
stdio: ["ignore", "pipe", "ignore"],
|
|
14676
|
-
timeout: 2e3
|
|
14677
|
-
});
|
|
14678
|
-
} catch {
|
|
14679
|
-
continue;
|
|
14680
|
-
}
|
|
14681
|
-
for (const pid of killableListenerPids(raw, selfPid)) {
|
|
14682
|
-
try {
|
|
14683
|
-
process.kill(pid, "SIGTERM");
|
|
14684
|
-
} catch {
|
|
14685
|
-
}
|
|
14783
|
+
for (const pid of listUnixListenerPids(port, selfPid)) {
|
|
14784
|
+
signalPid(pid, "SIGTERM");
|
|
14686
14785
|
}
|
|
14687
14786
|
} catch {
|
|
14688
14787
|
}
|
|
14689
14788
|
}
|
|
14690
14789
|
}
|
|
14790
|
+
function killStaleWorktreeListeners(ports, worktreePath, signal = "SIGTERM") {
|
|
14791
|
+
if (!worktreePath.trim()) {
|
|
14792
|
+
killListenersOnPorts(ports);
|
|
14793
|
+
return;
|
|
14794
|
+
}
|
|
14795
|
+
if (process.platform === "win32") {
|
|
14796
|
+
killListenersOnPorts(ports);
|
|
14797
|
+
return;
|
|
14798
|
+
}
|
|
14799
|
+
const selfPid = process.pid;
|
|
14800
|
+
for (const port of ports) {
|
|
14801
|
+
if (!Number.isFinite(port) || port <= 0) continue;
|
|
14802
|
+
for (const pid of listUnixListenerPids(port, selfPid)) {
|
|
14803
|
+
const cwd = listenerCwd(pid);
|
|
14804
|
+
if (cwd && isOtherWorktreeListenerCwd(cwd, worktreePath)) continue;
|
|
14805
|
+
signalPid(pid, signal);
|
|
14806
|
+
}
|
|
14807
|
+
}
|
|
14808
|
+
}
|
|
14691
14809
|
function killScriptTree(child, ports = []) {
|
|
14692
14810
|
const pid = child.pid;
|
|
14693
14811
|
if (pid) {
|
|
@@ -14849,7 +14967,7 @@ function getRunMode(worktreePath, repoPath) {
|
|
|
14849
14967
|
return loadWorkspaceSettings(worktreePath, repoPath)?.runMode ?? "concurrent";
|
|
14850
14968
|
}
|
|
14851
14969
|
async function reservePort() {
|
|
14852
|
-
return new Promise((
|
|
14970
|
+
return new Promise((resolve2, reject) => {
|
|
14853
14971
|
const server = (0, import_node_net.createServer)();
|
|
14854
14972
|
let released = false;
|
|
14855
14973
|
const release = () => new Promise((res) => {
|
|
@@ -14866,13 +14984,14 @@ async function reservePort() {
|
|
|
14866
14984
|
void release().then(() => reject(new Error("Failed to allocate port")));
|
|
14867
14985
|
return;
|
|
14868
14986
|
}
|
|
14869
|
-
|
|
14987
|
+
resolve2({ port: addr.port, release });
|
|
14870
14988
|
});
|
|
14871
14989
|
server.on("error", reject);
|
|
14872
14990
|
});
|
|
14873
14991
|
}
|
|
14874
14992
|
async function tryReservePort(port) {
|
|
14875
|
-
|
|
14993
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) return null;
|
|
14994
|
+
return new Promise((resolve2) => {
|
|
14876
14995
|
const server = (0, import_node_net.createServer)();
|
|
14877
14996
|
let released = false;
|
|
14878
14997
|
const release = () => new Promise((res) => {
|
|
@@ -14883,24 +15002,54 @@ async function tryReservePort(port) {
|
|
|
14883
15002
|
released = true;
|
|
14884
15003
|
server.close(() => res());
|
|
14885
15004
|
});
|
|
14886
|
-
server.once("error", () =>
|
|
15005
|
+
server.once("error", () => {
|
|
15006
|
+
try {
|
|
15007
|
+
server.close();
|
|
15008
|
+
} catch {
|
|
15009
|
+
}
|
|
15010
|
+
resolve2(null);
|
|
15011
|
+
});
|
|
14887
15012
|
server.listen(port, "127.0.0.1", () => {
|
|
14888
|
-
|
|
15013
|
+
resolve2({ port, release });
|
|
14889
15014
|
});
|
|
14890
15015
|
});
|
|
14891
15016
|
}
|
|
14892
|
-
async function
|
|
14893
|
-
const held = [
|
|
14894
|
-
const
|
|
15017
|
+
async function tryReservePorts(ports) {
|
|
15018
|
+
const held = [];
|
|
15019
|
+
for (const port of ports) {
|
|
15020
|
+
const next = await tryReservePort(port);
|
|
15021
|
+
if (!next) {
|
|
15022
|
+
await Promise.all(held.map((h) => h.release()));
|
|
15023
|
+
return null;
|
|
15024
|
+
}
|
|
15025
|
+
held.push(next);
|
|
15026
|
+
}
|
|
15027
|
+
return held;
|
|
15028
|
+
}
|
|
15029
|
+
function normalizePreferredPorts(ports, size) {
|
|
15030
|
+
if (!ports?.length) return [];
|
|
15031
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15032
|
+
const out = [];
|
|
15033
|
+
for (const p of ports) {
|
|
15034
|
+
if (!Number.isInteger(p) || p <= 0 || p > 65535 || seen.has(p)) continue;
|
|
15035
|
+
seen.add(p);
|
|
15036
|
+
out.push(p);
|
|
15037
|
+
if (out.length >= size) break;
|
|
15038
|
+
}
|
|
15039
|
+
return out;
|
|
15040
|
+
}
|
|
15041
|
+
function delay(ms) {
|
|
15042
|
+
return new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
15043
|
+
}
|
|
15044
|
+
async function fillPortRange(held, size) {
|
|
15045
|
+
if (held.length >= size) return held;
|
|
15046
|
+
const base = held[0]?.port;
|
|
14895
15047
|
try {
|
|
14896
|
-
for (let i =
|
|
14897
|
-
const candidate = base + i;
|
|
14898
|
-
const next = await tryReservePort(candidate);
|
|
14899
|
-
if (next)
|
|
14900
|
-
|
|
14901
|
-
} else {
|
|
14902
|
-
held.push(await reservePort());
|
|
14903
|
-
}
|
|
15048
|
+
for (let i = held.length; i < size; i++) {
|
|
15049
|
+
const candidate = base != null ? base + i : null;
|
|
15050
|
+
const next = candidate != null ? await tryReservePort(candidate) : null;
|
|
15051
|
+
if (next) held.push(next);
|
|
15052
|
+
else held.push(await reservePort());
|
|
14904
15053
|
}
|
|
14905
15054
|
return held;
|
|
14906
15055
|
} catch (err) {
|
|
@@ -14908,11 +15057,43 @@ async function reservePortRange(size = PORT_RANGE_SIZE) {
|
|
|
14908
15057
|
throw err;
|
|
14909
15058
|
}
|
|
14910
15059
|
}
|
|
15060
|
+
async function reclaimPreferredPorts(ports, worktreePath) {
|
|
15061
|
+
let held = await tryReservePorts(ports);
|
|
15062
|
+
if (held) return held;
|
|
15063
|
+
if (worktreePath) {
|
|
15064
|
+
killStaleWorktreeListeners(ports, worktreePath, "SIGTERM");
|
|
15065
|
+
} else {
|
|
15066
|
+
killListenersOnPorts(ports);
|
|
15067
|
+
}
|
|
15068
|
+
for (let i = 0; i < RECLAIM_TRIES; i++) {
|
|
15069
|
+
await delay(RECLAIM_RETRY_DELAY_MS);
|
|
15070
|
+
held = await tryReservePorts(ports);
|
|
15071
|
+
if (held) return held;
|
|
15072
|
+
if (i === 2 && worktreePath) {
|
|
15073
|
+
killStaleWorktreeListeners(ports, worktreePath, "SIGKILL");
|
|
15074
|
+
}
|
|
15075
|
+
}
|
|
15076
|
+
return null;
|
|
15077
|
+
}
|
|
15078
|
+
async function reservePortRange(size = PORT_RANGE_SIZE, opts) {
|
|
15079
|
+
const preferred = normalizePreferredPorts(opts?.preferred, size);
|
|
15080
|
+
if (preferred.length) {
|
|
15081
|
+
const reused = await reclaimPreferredPorts(preferred, opts?.worktreePath);
|
|
15082
|
+
if (reused) return fillPortRange(reused, size);
|
|
15083
|
+
}
|
|
15084
|
+
const held = [await reservePort()];
|
|
15085
|
+
return fillPortRange(held, size);
|
|
15086
|
+
}
|
|
14911
15087
|
async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
14912
15088
|
const script = getRunScript(worktreePath, repoPath, opts?.scriptName);
|
|
14913
15089
|
if (!script) return null;
|
|
14914
|
-
const
|
|
15090
|
+
const preferred = loadWorktreeRunPorts(worktreePath, script.name) ?? opts?.preferredPorts;
|
|
15091
|
+
const held = await reservePortRange(PORT_RANGE_SIZE, {
|
|
15092
|
+
preferred: preferred ?? void 0,
|
|
15093
|
+
worktreePath
|
|
15094
|
+
});
|
|
14915
15095
|
const ports = held.map((h) => h.port);
|
|
15096
|
+
saveWorktreeRunPorts(worktreePath, script.name, ports);
|
|
14916
15097
|
try {
|
|
14917
15098
|
const handle = await spawnWorkspaceScript(script.command, {
|
|
14918
15099
|
worktreePath,
|
|
@@ -14935,14 +15116,14 @@ async function startDevServer(repoPath, worktreePath, onLine, opts) {
|
|
|
14935
15116
|
throw err;
|
|
14936
15117
|
}
|
|
14937
15118
|
}
|
|
14938
|
-
var
|
|
15119
|
+
var import_node_fs39, import_node_child_process4, import_node_net, import_node_path39, import_execa4, import_node_readline3, PORT_RANGE_SIZE, RECLAIM_RETRY_DELAY_MS, RECLAIM_TRIES, cachedLoginEnv;
|
|
14939
15120
|
var init_conductor = __esm({
|
|
14940
15121
|
"src/hook/conductor.ts"() {
|
|
14941
15122
|
"use strict";
|
|
14942
|
-
|
|
15123
|
+
import_node_fs39 = require("fs");
|
|
14943
15124
|
import_node_child_process4 = require("child_process");
|
|
14944
15125
|
import_node_net = require("net");
|
|
14945
|
-
|
|
15126
|
+
import_node_path39 = require("path");
|
|
14946
15127
|
import_execa4 = require("execa");
|
|
14947
15128
|
import_node_readline3 = require("readline");
|
|
14948
15129
|
init_settings();
|
|
@@ -14953,8 +15134,12 @@ var init_conductor = __esm({
|
|
|
14953
15134
|
init_git_auth_mode();
|
|
14954
15135
|
init_request_review();
|
|
14955
15136
|
init_worktree_exclude();
|
|
15137
|
+
init_worktree_run_ports();
|
|
15138
|
+
init_worktree_run_ports();
|
|
14956
15139
|
init_nested_electron_env();
|
|
14957
15140
|
PORT_RANGE_SIZE = 10;
|
|
15141
|
+
RECLAIM_RETRY_DELAY_MS = 40;
|
|
15142
|
+
RECLAIM_TRIES = 8;
|
|
14958
15143
|
cachedLoginEnv = null;
|
|
14959
15144
|
}
|
|
14960
15145
|
});
|
|
@@ -14992,7 +15177,7 @@ function materialize(mem) {
|
|
|
14992
15177
|
};
|
|
14993
15178
|
}
|
|
14994
15179
|
function setupLogPath(threadId) {
|
|
14995
|
-
return (0,
|
|
15180
|
+
return (0, import_node_path40.join)(threadsDir(), `${threadId}.setup.log.json`);
|
|
14996
15181
|
}
|
|
14997
15182
|
function setupLogKeyForWorktree(worktreePath) {
|
|
14998
15183
|
const norm = normalizeWorktreePath(worktreePath);
|
|
@@ -15010,7 +15195,7 @@ function persistNow(threadId) {
|
|
|
15010
15195
|
const mem = memory.get(threadId);
|
|
15011
15196
|
if (!mem) return;
|
|
15012
15197
|
try {
|
|
15013
|
-
(0,
|
|
15198
|
+
(0, import_node_fs40.writeFileSync)(
|
|
15014
15199
|
setupLogPath(threadId),
|
|
15015
15200
|
`${JSON.stringify(materialize(mem))}
|
|
15016
15201
|
`,
|
|
@@ -15031,9 +15216,9 @@ function schedulePersist(threadId) {
|
|
|
15031
15216
|
}
|
|
15032
15217
|
function loadFromDisk(threadId) {
|
|
15033
15218
|
const path = setupLogPath(threadId);
|
|
15034
|
-
if (!(0,
|
|
15219
|
+
if (!(0, import_node_fs40.existsSync)(path)) return null;
|
|
15035
15220
|
try {
|
|
15036
|
-
const raw = JSON.parse((0,
|
|
15221
|
+
const raw = JSON.parse((0, import_node_fs40.readFileSync)(path, "utf8"));
|
|
15037
15222
|
return {
|
|
15038
15223
|
output: typeof raw.output === "string" ? raw.output : "",
|
|
15039
15224
|
running: Boolean(raw.running),
|
|
@@ -15089,13 +15274,13 @@ function finishSetupLog(threadId, exitCode, source) {
|
|
|
15089
15274
|
persistNow(threadId);
|
|
15090
15275
|
return materialize(mem);
|
|
15091
15276
|
}
|
|
15092
|
-
var import_node_crypto8,
|
|
15277
|
+
var import_node_crypto8, import_node_fs40, import_node_path40, EMPTY, MAX_SETUP_LOG_CHARS, memory, persistTimers, PERSIST_DEBOUNCE_MS;
|
|
15093
15278
|
var init_setup_log = __esm({
|
|
15094
15279
|
"src/store/setup-log.ts"() {
|
|
15095
15280
|
"use strict";
|
|
15096
15281
|
import_node_crypto8 = require("crypto");
|
|
15097
|
-
|
|
15098
|
-
|
|
15282
|
+
import_node_fs40 = require("fs");
|
|
15283
|
+
import_node_path40 = require("path");
|
|
15099
15284
|
init_worktree_labels();
|
|
15100
15285
|
init_paths();
|
|
15101
15286
|
EMPTY = {
|
|
@@ -15140,7 +15325,7 @@ function safeScriptToken(scriptName) {
|
|
|
15140
15325
|
return token || "dev";
|
|
15141
15326
|
}
|
|
15142
15327
|
function runLogPath(key) {
|
|
15143
|
-
return (0,
|
|
15328
|
+
return (0, import_node_path41.join)(threadsDir(), `${key}.run.log.json`);
|
|
15144
15329
|
}
|
|
15145
15330
|
function runLogKeyForWorktree(worktreePath, scriptName) {
|
|
15146
15331
|
const norm = normalizeWorktreePath(worktreePath);
|
|
@@ -15168,7 +15353,7 @@ function persistNow2(key) {
|
|
|
15168
15353
|
const mem = memory2.get(key);
|
|
15169
15354
|
if (!mem) return;
|
|
15170
15355
|
try {
|
|
15171
|
-
(0,
|
|
15356
|
+
(0, import_node_fs41.writeFileSync)(runLogPath(key), `${JSON.stringify(materialize2(mem))}
|
|
15172
15357
|
`, "utf8");
|
|
15173
15358
|
} catch {
|
|
15174
15359
|
}
|
|
@@ -15185,9 +15370,9 @@ function schedulePersist2(key) {
|
|
|
15185
15370
|
}
|
|
15186
15371
|
function loadFromDisk2(key) {
|
|
15187
15372
|
const path = runLogPath(key);
|
|
15188
|
-
if (!(0,
|
|
15373
|
+
if (!(0, import_node_fs41.existsSync)(path)) return null;
|
|
15189
15374
|
try {
|
|
15190
|
-
const raw = JSON.parse((0,
|
|
15375
|
+
const raw = JSON.parse((0, import_node_fs41.readFileSync)(path, "utf8"));
|
|
15191
15376
|
return {
|
|
15192
15377
|
output: typeof raw.output === "string" ? raw.output : "",
|
|
15193
15378
|
running: Boolean(raw.running),
|
|
@@ -15245,13 +15430,13 @@ function finishRunLog(key, exitCode) {
|
|
|
15245
15430
|
function flushRunLog(key) {
|
|
15246
15431
|
persistNow2(key);
|
|
15247
15432
|
}
|
|
15248
|
-
var import_node_crypto9,
|
|
15433
|
+
var import_node_crypto9, import_node_fs41, import_node_path41, EMPTY2, MAX_RUN_LOG_CHARS, DEFAULT_RUN_LOG_TAIL_CHARS, memory2, persistTimers2, PERSIST_DEBOUNCE_MS2;
|
|
15249
15434
|
var init_run_log = __esm({
|
|
15250
15435
|
"src/store/run-log.ts"() {
|
|
15251
15436
|
"use strict";
|
|
15252
15437
|
import_node_crypto9 = require("crypto");
|
|
15253
|
-
|
|
15254
|
-
|
|
15438
|
+
import_node_fs41 = require("fs");
|
|
15439
|
+
import_node_path41 = require("path");
|
|
15255
15440
|
init_worktree_labels();
|
|
15256
15441
|
init_setup_log();
|
|
15257
15442
|
init_paths();
|
|
@@ -15280,9 +15465,9 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
15280
15465
|
repoPaths?.length ? repoPaths : threads.map((t) => t.repoPath).filter(Boolean)
|
|
15281
15466
|
);
|
|
15282
15467
|
const homeRoot = sideboardWorkspacesDir();
|
|
15283
|
-
if ((0,
|
|
15468
|
+
if ((0, import_node_fs42.existsSync)(homeRoot)) {
|
|
15284
15469
|
try {
|
|
15285
|
-
for (const entry of (0,
|
|
15470
|
+
for (const entry of (0, import_node_fs42.readdirSync)(homeRoot, { withFileTypes: true })) {
|
|
15286
15471
|
if (!entry.isDirectory()) continue;
|
|
15287
15472
|
void entry;
|
|
15288
15473
|
}
|
|
@@ -15292,7 +15477,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
15292
15477
|
const orphans = [];
|
|
15293
15478
|
const seen = /* @__PURE__ */ new Set();
|
|
15294
15479
|
for (const repoPath of repos) {
|
|
15295
|
-
if (!repoPath || !(0,
|
|
15480
|
+
if (!repoPath || !(0, import_node_fs42.existsSync)(repoPath)) continue;
|
|
15296
15481
|
try {
|
|
15297
15482
|
const wts = await listWorktrees(repoPath);
|
|
15298
15483
|
for (const wt of wts) {
|
|
@@ -15303,7 +15488,7 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
15303
15488
|
seen.add(path);
|
|
15304
15489
|
let mtimeMs = 0;
|
|
15305
15490
|
try {
|
|
15306
|
-
mtimeMs = (0,
|
|
15491
|
+
mtimeMs = (0, import_node_fs42.statSync)(path).mtimeMs;
|
|
15307
15492
|
} catch {
|
|
15308
15493
|
mtimeMs = 0;
|
|
15309
15494
|
}
|
|
@@ -15313,16 +15498,16 @@ async function findOrphanWorktrees(repoPaths) {
|
|
|
15313
15498
|
}
|
|
15314
15499
|
try {
|
|
15315
15500
|
const root = worktreesRoot(repoPath);
|
|
15316
|
-
if ((0,
|
|
15317
|
-
for (const entry of (0,
|
|
15501
|
+
if ((0, import_node_fs42.existsSync)(root)) {
|
|
15502
|
+
for (const entry of (0, import_node_fs42.readdirSync)(root, { withFileTypes: true })) {
|
|
15318
15503
|
if (!entry.isDirectory()) continue;
|
|
15319
|
-
const path = (0,
|
|
15504
|
+
const path = (0, import_node_path42.join)(root, entry.name).replace(/\/$/, "");
|
|
15320
15505
|
if (known.has(path) || seen.has(path)) continue;
|
|
15321
|
-
if (!(0,
|
|
15506
|
+
if (!(0, import_node_fs42.existsSync)((0, import_node_path42.join)(path, ".git"))) continue;
|
|
15322
15507
|
seen.add(path);
|
|
15323
15508
|
let mtimeMs = 0;
|
|
15324
15509
|
try {
|
|
15325
|
-
mtimeMs = (0,
|
|
15510
|
+
mtimeMs = (0, import_node_fs42.statSync)(path).mtimeMs;
|
|
15326
15511
|
} catch {
|
|
15327
15512
|
mtimeMs = Date.now();
|
|
15328
15513
|
}
|
|
@@ -15374,12 +15559,12 @@ function shouldRunWorktreeCleanup(settings = loadAppSettings()) {
|
|
|
15374
15559
|
const elapsed = Date.now() - Date.parse(last);
|
|
15375
15560
|
return elapsed >= intervalHours * 36e5;
|
|
15376
15561
|
}
|
|
15377
|
-
var
|
|
15562
|
+
var import_node_fs42, import_node_path42;
|
|
15378
15563
|
var init_orphan_cleanup = __esm({
|
|
15379
15564
|
"src/git/orphan-cleanup.ts"() {
|
|
15380
15565
|
"use strict";
|
|
15381
|
-
|
|
15382
|
-
|
|
15566
|
+
import_node_fs42 = require("fs");
|
|
15567
|
+
import_node_path42 = require("path");
|
|
15383
15568
|
init_worktree();
|
|
15384
15569
|
init_thread_store();
|
|
15385
15570
|
init_paths();
|
|
@@ -15554,12 +15739,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
15554
15739
|
if (!url) throw new Error("Clone URL is required");
|
|
15555
15740
|
let name = opts.name?.trim();
|
|
15556
15741
|
if (!name) {
|
|
15557
|
-
const leaf = (0,
|
|
15742
|
+
const leaf = (0, import_node_path43.basename)(url.replace(/\/$/, "").replace(/\.git$/, ""));
|
|
15558
15743
|
name = leaf || "repo";
|
|
15559
15744
|
}
|
|
15560
15745
|
name = name.replace(/[^a-zA-Z0-9._-]+/g, "-").replace(/^-+|-+$/g, "") || "repo";
|
|
15561
|
-
const dest = (0,
|
|
15562
|
-
if ((0,
|
|
15746
|
+
const dest = (0, import_node_path43.join)(sideboardReposDir(), name);
|
|
15747
|
+
if ((0, import_node_fs43.existsSync)(dest)) {
|
|
15563
15748
|
const repoPath2 = await resolveRepoRoot(dest);
|
|
15564
15749
|
const workspace2 = await ensureWorkspace(repoPath2);
|
|
15565
15750
|
return { repoPath: repoPath2, workspace: workspace2 };
|
|
@@ -15574,12 +15759,12 @@ async function cloneRepoIntoSideboard(opts) {
|
|
|
15574
15759
|
const workspace = await ensureWorkspace(repoPath);
|
|
15575
15760
|
return { repoPath, workspace };
|
|
15576
15761
|
}
|
|
15577
|
-
var
|
|
15762
|
+
var import_node_fs43, import_node_path43, import_execa6;
|
|
15578
15763
|
var init_clone_repo = __esm({
|
|
15579
15764
|
"src/git/clone-repo.ts"() {
|
|
15580
15765
|
"use strict";
|
|
15581
|
-
|
|
15582
|
-
|
|
15766
|
+
import_node_fs43 = require("fs");
|
|
15767
|
+
import_node_path43 = require("path");
|
|
15583
15768
|
import_execa6 = require("execa");
|
|
15584
15769
|
init_paths();
|
|
15585
15770
|
init_workspaces();
|
|
@@ -15599,11 +15784,11 @@ var init_thread = __esm({
|
|
|
15599
15784
|
|
|
15600
15785
|
// src/store/desktop-host.ts
|
|
15601
15786
|
function desktopHostPidPath() {
|
|
15602
|
-
return (0,
|
|
15787
|
+
return (0, import_node_path44.join)(appDataDir(), "desktop-host.pid");
|
|
15603
15788
|
}
|
|
15604
15789
|
function readDesktopHostPid() {
|
|
15605
15790
|
try {
|
|
15606
|
-
const pid = Number.parseInt((0,
|
|
15791
|
+
const pid = Number.parseInt((0, import_node_fs44.readFileSync)(desktopHostPidPath(), "utf8").trim(), 10);
|
|
15607
15792
|
if (!Number.isFinite(pid) || pid <= 0) return null;
|
|
15608
15793
|
return pid;
|
|
15609
15794
|
} catch {
|
|
@@ -15629,12 +15814,12 @@ function thisProcessShouldDrainAgentQueues() {
|
|
|
15629
15814
|
if (isThisProcessDesktopHost()) return true;
|
|
15630
15815
|
return !isDesktopHostAlive();
|
|
15631
15816
|
}
|
|
15632
|
-
var
|
|
15817
|
+
var import_node_fs44, import_node_path44;
|
|
15633
15818
|
var init_desktop_host = __esm({
|
|
15634
15819
|
"src/store/desktop-host.ts"() {
|
|
15635
15820
|
"use strict";
|
|
15636
|
-
|
|
15637
|
-
|
|
15821
|
+
import_node_fs44 = require("fs");
|
|
15822
|
+
import_node_path44 = require("path");
|
|
15638
15823
|
init_paths();
|
|
15639
15824
|
}
|
|
15640
15825
|
});
|
|
@@ -15760,24 +15945,24 @@ function jobTreeAlive(pid) {
|
|
|
15760
15945
|
return jobAlive(pid) || processGroupAlive(pid);
|
|
15761
15946
|
}
|
|
15762
15947
|
function readIntFile(file) {
|
|
15763
|
-
if (!(0,
|
|
15764
|
-
const n = Number.parseInt((0,
|
|
15948
|
+
if (!(0, import_node_fs45.existsSync)(file)) return null;
|
|
15949
|
+
const n = Number.parseInt((0, import_node_fs45.readFileSync)(file, "utf8").trim(), 10);
|
|
15765
15950
|
return Number.isInteger(n) ? n : null;
|
|
15766
15951
|
}
|
|
15767
15952
|
function jobDir(root, id, legacy = false) {
|
|
15768
|
-
return (0,
|
|
15953
|
+
return (0, import_node_path45.join)(root, legacy ? LEGACY_DETACHED_JOBS_DIR : DETACHED_JOBS_DIR, id);
|
|
15769
15954
|
}
|
|
15770
15955
|
function resolveJobDir(root, id) {
|
|
15771
15956
|
const modern = jobDir(root, id, false);
|
|
15772
|
-
if ((0,
|
|
15957
|
+
if ((0, import_node_fs45.existsSync)(modern)) return modern;
|
|
15773
15958
|
const legacy = jobDir(root, id, true);
|
|
15774
|
-
if ((0,
|
|
15959
|
+
if ((0, import_node_fs45.existsSync)(legacy)) return legacy;
|
|
15775
15960
|
return modern;
|
|
15776
15961
|
}
|
|
15777
15962
|
function listJobIdsIn(root, rel) {
|
|
15778
|
-
const dir = (0,
|
|
15779
|
-
if (!(0,
|
|
15780
|
-
return (0,
|
|
15963
|
+
const dir = (0, import_node_path45.join)(root, rel);
|
|
15964
|
+
if (!(0, import_node_fs45.existsSync)(dir)) return [];
|
|
15965
|
+
return (0, import_node_fs45.readdirSync)(dir, { withFileTypes: true }).filter((e) => e.isDirectory() && JOB_ID_RE.test(e.name)).map((e) => e.name);
|
|
15781
15966
|
}
|
|
15782
15967
|
function listRunningDetachedJobs(worktreePath) {
|
|
15783
15968
|
const root = worktreePath.trim();
|
|
@@ -15789,7 +15974,7 @@ function listRunningDetachedJobs(worktreePath) {
|
|
|
15789
15974
|
const running = [];
|
|
15790
15975
|
for (const id of ids) {
|
|
15791
15976
|
const dir = resolveJobDir(root, id);
|
|
15792
|
-
const pid = readIntFile((0,
|
|
15977
|
+
const pid = readIntFile((0, import_node_path45.join)(dir, "pid"));
|
|
15793
15978
|
if (jobTreeAlive(pid)) running.push(id);
|
|
15794
15979
|
}
|
|
15795
15980
|
return running.sort();
|
|
@@ -15872,8 +16057,8 @@ function planJobContinue(opts) {
|
|
|
15872
16057
|
return { action: "none" };
|
|
15873
16058
|
}
|
|
15874
16059
|
function tailProgress(logFile, maxLines = 12) {
|
|
15875
|
-
if (!(0,
|
|
15876
|
-
const lines = (0,
|
|
16060
|
+
if (!(0, import_node_fs45.existsSync)(logFile)) return "(no log yet)";
|
|
16061
|
+
const lines = (0, import_node_fs45.readFileSync)(logFile, "utf8").split("\n");
|
|
15877
16062
|
return lines.slice(-maxLines).join("\n");
|
|
15878
16063
|
}
|
|
15879
16064
|
function lastProgressLine(progress) {
|
|
@@ -15881,8 +16066,8 @@ function lastProgressLine(progress) {
|
|
|
15881
16066
|
return last ? last.slice(0, 72) : void 0;
|
|
15882
16067
|
}
|
|
15883
16068
|
function readLogLines(file) {
|
|
15884
|
-
if (!(0,
|
|
15885
|
-
const lines = (0,
|
|
16069
|
+
if (!(0, import_node_fs45.existsSync)(file)) return [];
|
|
16070
|
+
const lines = (0, import_node_fs45.readFileSync)(file, "utf8").split("\n");
|
|
15886
16071
|
if (lines.length && lines[lines.length - 1] === "") lines.pop();
|
|
15887
16072
|
return lines;
|
|
15888
16073
|
}
|
|
@@ -15893,15 +16078,15 @@ function takeDelta(logFile, cursorFile) {
|
|
|
15893
16078
|
return { delta: capJobLogDelta(lines.slice(start).join("\n")), nextCursor: lines.length };
|
|
15894
16079
|
}
|
|
15895
16080
|
function snapshotJob(dir) {
|
|
15896
|
-
const pid = readIntFile((0,
|
|
16081
|
+
const pid = readIntFile((0, import_node_path45.join)(dir, "pid"));
|
|
15897
16082
|
const running = jobTreeAlive(pid);
|
|
15898
16083
|
return {
|
|
15899
16084
|
pid,
|
|
15900
16085
|
running,
|
|
15901
|
-
exitCode: readIntFile((0,
|
|
15902
|
-
log: (0,
|
|
15903
|
-
cursor: (0,
|
|
15904
|
-
progress: tailProgress((0,
|
|
16086
|
+
exitCode: readIntFile((0, import_node_path45.join)(dir, "exit")),
|
|
16087
|
+
log: (0, import_node_path45.join)(dir, "log"),
|
|
16088
|
+
cursor: (0, import_node_path45.join)(dir, "present.cursor"),
|
|
16089
|
+
progress: tailProgress((0, import_node_path45.join)(dir, "log"))
|
|
15905
16090
|
};
|
|
15906
16091
|
}
|
|
15907
16092
|
function toResult(id, snap, extra) {
|
|
@@ -15910,8 +16095,8 @@ function toResult(id, snap, extra) {
|
|
|
15910
16095
|
const stillRunning = snap.running && !ok;
|
|
15911
16096
|
const { delta, nextCursor } = takeDelta(snap.log, snap.cursor);
|
|
15912
16097
|
try {
|
|
15913
|
-
(0,
|
|
15914
|
-
(0,
|
|
16098
|
+
(0, import_node_fs45.mkdirSync)((0, import_node_path45.dirname)(snap.cursor), { recursive: true });
|
|
16099
|
+
(0, import_node_fs45.writeFileSync)(snap.cursor, `${nextCursor}
|
|
15915
16100
|
`);
|
|
15916
16101
|
} catch {
|
|
15917
16102
|
}
|
|
@@ -15932,7 +16117,7 @@ function toResult(id, snap, extra) {
|
|
|
15932
16117
|
};
|
|
15933
16118
|
}
|
|
15934
16119
|
async function sleepMs(ms) {
|
|
15935
|
-
await new Promise((
|
|
16120
|
+
await new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
15936
16121
|
}
|
|
15937
16122
|
async function waitForDetachedJob(cwd, id, opts) {
|
|
15938
16123
|
const jobId = sanitizeDetachedJobId(id);
|
|
@@ -15940,7 +16125,7 @@ async function waitForDetachedJob(cwd, id, opts) {
|
|
|
15940
16125
|
const dir = resolveJobDir(root, jobId);
|
|
15941
16126
|
const timeoutMs = mcpWaitForJobTimeoutMs(opts?.timeoutMs);
|
|
15942
16127
|
const sleep = opts?.sleep ?? sleepMs;
|
|
15943
|
-
if (!(0,
|
|
16128
|
+
if (!(0, import_node_fs45.existsSync)(dir)) {
|
|
15944
16129
|
return {
|
|
15945
16130
|
stillRunning: false,
|
|
15946
16131
|
ok: false,
|
|
@@ -15986,10 +16171,10 @@ function killProcessTree(pid, signal) {
|
|
|
15986
16171
|
}
|
|
15987
16172
|
function appendJobLog(logFile, line) {
|
|
15988
16173
|
try {
|
|
15989
|
-
(0,
|
|
16174
|
+
(0, import_node_fs45.mkdirSync)((0, import_node_path45.dirname)(logFile), { recursive: true });
|
|
15990
16175
|
const body = line.endsWith("\n") ? line : `${line}
|
|
15991
16176
|
`;
|
|
15992
|
-
(0,
|
|
16177
|
+
(0, import_node_fs45.appendFileSync)(logFile, body);
|
|
15993
16178
|
} catch {
|
|
15994
16179
|
}
|
|
15995
16180
|
}
|
|
@@ -15999,7 +16184,7 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
15999
16184
|
const dir = resolveJobDir(root, jobId);
|
|
16000
16185
|
const sleep = opts?.sleep ?? sleepMs;
|
|
16001
16186
|
const why = opts?.reason?.trim() ?? "";
|
|
16002
|
-
if (!(0,
|
|
16187
|
+
if (!(0, import_node_fs45.existsSync)(dir)) {
|
|
16003
16188
|
return {
|
|
16004
16189
|
stillRunning: false,
|
|
16005
16190
|
ok: false,
|
|
@@ -16035,10 +16220,10 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
16035
16220
|
killProcessTree(targetPid, "SIGKILL");
|
|
16036
16221
|
await sleep(100);
|
|
16037
16222
|
}
|
|
16038
|
-
const exitFile = (0,
|
|
16039
|
-
if (!(0,
|
|
16223
|
+
const exitFile = (0, import_node_path45.join)(dir, "exit");
|
|
16224
|
+
if (!(0, import_node_fs45.existsSync)(exitFile)) {
|
|
16040
16225
|
try {
|
|
16041
|
-
(0,
|
|
16226
|
+
(0, import_node_fs45.writeFileSync)(exitFile, "1\n");
|
|
16042
16227
|
} catch {
|
|
16043
16228
|
}
|
|
16044
16229
|
}
|
|
@@ -16058,12 +16243,12 @@ async function stopDetachedJob(cwd, id, opts) {
|
|
|
16058
16243
|
hint: stopped ? MCP_STOP_JOB_HINT : MCP_WAIT_JOB_STILL_RUNNING_HINT
|
|
16059
16244
|
};
|
|
16060
16245
|
}
|
|
16061
|
-
var
|
|
16246
|
+
var import_node_fs45, import_node_path45, MAX_JOB_CONTINUES, MAX_JOB_DELTA_LINES, MAX_JOB_DELTA_CHARS, DEFERRED_DONE_MAX_CHARS, GH_WATCH_REFRESH, MCP_WAIT_JOB_STILL_RUNNING_HINT, MCP_STOP_JOB_HINT, JOB_ID_RE;
|
|
16062
16247
|
var init_wait_for_job = __esm({
|
|
16063
16248
|
"src/mcp/wait-for-job.ts"() {
|
|
16064
16249
|
"use strict";
|
|
16065
|
-
|
|
16066
|
-
|
|
16250
|
+
import_node_fs45 = require("fs");
|
|
16251
|
+
import_node_path45 = require("path");
|
|
16067
16252
|
init_workspace_scratch();
|
|
16068
16253
|
init_wait_for_turn();
|
|
16069
16254
|
MAX_JOB_CONTINUES = 8;
|
|
@@ -16798,14 +16983,14 @@ async function startAbleTimeOAuth(opts) {
|
|
|
16798
16983
|
const pkce = createAbleTimePkce();
|
|
16799
16984
|
const authorizeUrl = ableTimeOAuthAuthorizeUrl(clientId, state, pkce.challenge, host);
|
|
16800
16985
|
const timeoutMs = opts?.timeoutMs ?? 5 * 6e4;
|
|
16801
|
-
const code = await new Promise((
|
|
16986
|
+
const code = await new Promise((resolve2, reject) => {
|
|
16802
16987
|
let settled = false;
|
|
16803
16988
|
const finish = (err, value) => {
|
|
16804
16989
|
if (settled) return;
|
|
16805
16990
|
settled = true;
|
|
16806
16991
|
cleanup();
|
|
16807
16992
|
if (err) reject(err);
|
|
16808
|
-
else
|
|
16993
|
+
else resolve2(value);
|
|
16809
16994
|
};
|
|
16810
16995
|
const server = (0, import_node_http.createServer)((req, res) => {
|
|
16811
16996
|
try {
|
|
@@ -18098,7 +18283,7 @@ function reuseLiveThread(input, repoPath, match) {
|
|
|
18098
18283
|
}
|
|
18099
18284
|
async function createThread(input, _onSetupLine) {
|
|
18100
18285
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
18101
|
-
if (!(0,
|
|
18286
|
+
if (!(0, import_node_fs46.existsSync)(repoPath)) {
|
|
18102
18287
|
throw new Error(`Repo not found: ${repoPath}`);
|
|
18103
18288
|
}
|
|
18104
18289
|
const reused = reuseLiveThread(input, repoPath, {
|
|
@@ -18274,11 +18459,11 @@ async function createThread(input, _onSetupLine) {
|
|
|
18274
18459
|
await ensureWorkspace(repoPath);
|
|
18275
18460
|
return readThread(thread.id) ?? thread;
|
|
18276
18461
|
}
|
|
18277
|
-
var
|
|
18462
|
+
var import_node_fs46;
|
|
18278
18463
|
var init_create = __esm({
|
|
18279
18464
|
"src/threads/create.ts"() {
|
|
18280
18465
|
"use strict";
|
|
18281
|
-
|
|
18466
|
+
import_node_fs46 = require("fs");
|
|
18282
18467
|
init_detect();
|
|
18283
18468
|
init_worktree();
|
|
18284
18469
|
init_home_board();
|
|
@@ -18430,20 +18615,20 @@ function writeTurnLive(threadId, progress) {
|
|
|
18430
18615
|
const path = threadLivePath(threadId);
|
|
18431
18616
|
const tmp = `${path}.${process.pid}.tmp`;
|
|
18432
18617
|
try {
|
|
18433
|
-
(0,
|
|
18434
|
-
(0,
|
|
18618
|
+
(0, import_node_fs47.writeFileSync)(tmp, JSON.stringify(progress), "utf8");
|
|
18619
|
+
(0, import_node_fs47.renameSync)(tmp, path);
|
|
18435
18620
|
} catch {
|
|
18436
18621
|
try {
|
|
18437
|
-
(0,
|
|
18622
|
+
(0, import_node_fs47.unlinkSync)(tmp);
|
|
18438
18623
|
} catch {
|
|
18439
18624
|
}
|
|
18440
18625
|
}
|
|
18441
18626
|
}
|
|
18442
18627
|
function readTurnLive(threadId) {
|
|
18443
18628
|
const path = threadLivePath(threadId);
|
|
18444
|
-
if (!(0,
|
|
18629
|
+
if (!(0, import_node_fs47.existsSync)(path)) return null;
|
|
18445
18630
|
try {
|
|
18446
|
-
const raw = JSON.parse((0,
|
|
18631
|
+
const raw = JSON.parse((0, import_node_fs47.readFileSync)(path, "utf8"));
|
|
18447
18632
|
if (!raw || typeof raw.summary !== "string") return null;
|
|
18448
18633
|
return raw;
|
|
18449
18634
|
} catch {
|
|
@@ -18455,17 +18640,17 @@ function clearTurnLive(threadId) {
|
|
|
18455
18640
|
if (buf?.timer) clearTimeout(buf.timer);
|
|
18456
18641
|
buffers.delete(threadId);
|
|
18457
18642
|
const path = threadLivePath(threadId);
|
|
18458
|
-
if (!(0,
|
|
18643
|
+
if (!(0, import_node_fs47.existsSync)(path)) return;
|
|
18459
18644
|
try {
|
|
18460
|
-
(0,
|
|
18645
|
+
(0, import_node_fs47.unlinkSync)(path);
|
|
18461
18646
|
} catch {
|
|
18462
18647
|
}
|
|
18463
18648
|
}
|
|
18464
|
-
var
|
|
18649
|
+
var import_node_fs47, buffers, FLUSH_MS, MAX_PARTS;
|
|
18465
18650
|
var init_turn_live = __esm({
|
|
18466
18651
|
"src/store/turn-live.ts"() {
|
|
18467
18652
|
"use strict";
|
|
18468
|
-
|
|
18653
|
+
import_node_fs47 = require("fs");
|
|
18469
18654
|
init_message_parts();
|
|
18470
18655
|
init_paths();
|
|
18471
18656
|
buffers = /* @__PURE__ */ new Map();
|
|
@@ -18706,7 +18891,7 @@ var init_quota_failover = __esm({
|
|
|
18706
18891
|
// src/threads/adopt.ts
|
|
18707
18892
|
function thisModuleFile2() {
|
|
18708
18893
|
const cjsFile = typeof __filename !== "undefined" ? __filename : "";
|
|
18709
|
-
return cjsFile || process.argv[1] || (0,
|
|
18894
|
+
return cjsFile || process.argv[1] || (0, import_node_path46.join)(process.cwd(), "package.json");
|
|
18710
18895
|
}
|
|
18711
18896
|
function openReadonlySqlite(file) {
|
|
18712
18897
|
const req = (0, import_node_module5.createRequire)(thisModuleFile2());
|
|
@@ -18724,21 +18909,21 @@ function mapAgentType(raw) {
|
|
|
18724
18909
|
return null;
|
|
18725
18910
|
}
|
|
18726
18911
|
function resolveConductorCursorAgentId(workspacePath) {
|
|
18727
|
-
if (!workspacePath || !(0,
|
|
18912
|
+
if (!workspacePath || !(0, import_node_fs48.existsSync)(CURSOR_SDK_STORE)) return null;
|
|
18728
18913
|
const normalized = workspacePath.replace(/\/$/, "");
|
|
18729
18914
|
let best = null;
|
|
18730
18915
|
let hashes;
|
|
18731
18916
|
try {
|
|
18732
|
-
hashes = (0,
|
|
18917
|
+
hashes = (0, import_node_fs48.readdirSync)(CURSOR_SDK_STORE);
|
|
18733
18918
|
} catch {
|
|
18734
18919
|
return null;
|
|
18735
18920
|
}
|
|
18736
18921
|
for (const hash of hashes) {
|
|
18737
|
-
const agentsFile = (0,
|
|
18738
|
-
if (!(0,
|
|
18922
|
+
const agentsFile = (0, import_node_path46.join)(CURSOR_SDK_STORE, hash, "agents.ndjson");
|
|
18923
|
+
if (!(0, import_node_fs48.existsSync)(agentsFile)) continue;
|
|
18739
18924
|
let text7;
|
|
18740
18925
|
try {
|
|
18741
|
-
text7 = (0,
|
|
18926
|
+
text7 = (0, import_node_fs48.readFileSync)(agentsFile, "utf8");
|
|
18742
18927
|
} catch {
|
|
18743
18928
|
continue;
|
|
18744
18929
|
}
|
|
@@ -18762,7 +18947,7 @@ function resolveConductorCursorAgentId(workspacePath) {
|
|
|
18762
18947
|
return best?.agentId ?? null;
|
|
18763
18948
|
}
|
|
18764
18949
|
async function adoptThread(input) {
|
|
18765
|
-
if (!(0,
|
|
18950
|
+
if (!(0, import_node_fs48.existsSync)(input.worktreePath)) {
|
|
18766
18951
|
throw new Error(`Worktree not found: ${input.worktreePath}`);
|
|
18767
18952
|
}
|
|
18768
18953
|
const repoPath = await resolveRepoRoot(input.worktreePath);
|
|
@@ -18788,18 +18973,18 @@ async function adoptThread(input) {
|
|
|
18788
18973
|
return thread;
|
|
18789
18974
|
}
|
|
18790
18975
|
function listConductorWorkspaces() {
|
|
18791
|
-
if (!(0,
|
|
18976
|
+
if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
|
|
18792
18977
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
18793
18978
|
}
|
|
18794
|
-
const tmp = (0,
|
|
18795
|
-
const snapshot = (0,
|
|
18979
|
+
const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path46.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
|
|
18980
|
+
const snapshot = (0, import_node_path46.join)(tmp, "conductor.db");
|
|
18796
18981
|
try {
|
|
18797
|
-
(0,
|
|
18982
|
+
(0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
18798
18983
|
for (const suffix of ["-wal", "-shm"]) {
|
|
18799
18984
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
18800
|
-
if ((0,
|
|
18985
|
+
if ((0, import_node_fs48.existsSync)(src)) {
|
|
18801
18986
|
try {
|
|
18802
|
-
(0,
|
|
18987
|
+
(0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
18803
18988
|
} catch {
|
|
18804
18989
|
}
|
|
18805
18990
|
}
|
|
@@ -18875,22 +19060,22 @@ function listConductorWorkspaces() {
|
|
|
18875
19060
|
db.close();
|
|
18876
19061
|
}
|
|
18877
19062
|
} finally {
|
|
18878
|
-
(0,
|
|
19063
|
+
(0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
|
|
18879
19064
|
}
|
|
18880
19065
|
}
|
|
18881
19066
|
function importConductorWorkspace(workspaceId) {
|
|
18882
|
-
if (!(0,
|
|
19067
|
+
if (!(0, import_node_fs48.existsSync)(CONDUCTOR_DB)) {
|
|
18883
19068
|
throw new Error(`Conductor DB not found at ${CONDUCTOR_DB}`);
|
|
18884
19069
|
}
|
|
18885
|
-
const tmp = (0,
|
|
18886
|
-
const snapshot = (0,
|
|
19070
|
+
const tmp = (0, import_node_fs48.mkdtempSync)((0, import_node_path46.join)((0, import_node_os14.tmpdir)(), "sideboard-conductor-"));
|
|
19071
|
+
const snapshot = (0, import_node_path46.join)(tmp, "conductor.db");
|
|
18887
19072
|
try {
|
|
18888
|
-
(0,
|
|
19073
|
+
(0, import_node_fs48.copyFileSync)(CONDUCTOR_DB, snapshot);
|
|
18889
19074
|
for (const suffix of ["-wal", "-shm"]) {
|
|
18890
19075
|
const src = `${CONDUCTOR_DB}${suffix}`;
|
|
18891
|
-
if ((0,
|
|
19076
|
+
if ((0, import_node_fs48.existsSync)(src)) {
|
|
18892
19077
|
try {
|
|
18893
|
-
(0,
|
|
19078
|
+
(0, import_node_fs48.copyFileSync)(src, `${snapshot}${suffix}`);
|
|
18894
19079
|
} catch {
|
|
18895
19080
|
}
|
|
18896
19081
|
}
|
|
@@ -18908,7 +19093,7 @@ function importConductorWorkspace(workspaceId) {
|
|
|
18908
19093
|
).get(workspaceId);
|
|
18909
19094
|
if (!row) throw new Error(`Conductor workspace not found: ${workspaceId}`);
|
|
18910
19095
|
const worktreePath = String(row.workspacePath);
|
|
18911
|
-
if (!(0,
|
|
19096
|
+
if (!(0, import_node_fs48.existsSync)(worktreePath)) {
|
|
18912
19097
|
throw new Error(`Conductor worktree missing on disk: ${worktreePath}`);
|
|
18913
19098
|
}
|
|
18914
19099
|
let sessionId = null;
|
|
@@ -18971,31 +19156,31 @@ function importConductorWorkspace(workspaceId) {
|
|
|
18971
19156
|
db.close();
|
|
18972
19157
|
}
|
|
18973
19158
|
} finally {
|
|
18974
|
-
(0,
|
|
19159
|
+
(0, import_node_fs48.rmSync)(tmp, { recursive: true, force: true });
|
|
18975
19160
|
}
|
|
18976
19161
|
}
|
|
18977
19162
|
async function importConductorWorkspaceAsync(workspaceId) {
|
|
18978
19163
|
return importConductorWorkspace(workspaceId);
|
|
18979
19164
|
}
|
|
18980
|
-
var import_node_child_process5,
|
|
19165
|
+
var import_node_child_process5, import_node_fs48, import_node_os14, import_node_path46, import_node_module5, CONDUCTOR_APP_SUPPORT, CONDUCTOR_DB, CURSOR_SDK_STORE;
|
|
18981
19166
|
var init_adopt = __esm({
|
|
18982
19167
|
"src/threads/adopt.ts"() {
|
|
18983
19168
|
"use strict";
|
|
18984
19169
|
import_node_child_process5 = require("child_process");
|
|
18985
|
-
|
|
19170
|
+
import_node_fs48 = require("fs");
|
|
18986
19171
|
import_node_os14 = require("os");
|
|
18987
|
-
|
|
19172
|
+
import_node_path46 = require("path");
|
|
18988
19173
|
import_node_module5 = require("module");
|
|
18989
19174
|
init_worktree();
|
|
18990
19175
|
init_thread_store();
|
|
18991
|
-
CONDUCTOR_APP_SUPPORT = (0,
|
|
19176
|
+
CONDUCTOR_APP_SUPPORT = (0, import_node_path46.join)(
|
|
18992
19177
|
process.env.HOME ?? "",
|
|
18993
19178
|
"Library",
|
|
18994
19179
|
"Application Support",
|
|
18995
19180
|
"com.conductor.app"
|
|
18996
19181
|
);
|
|
18997
|
-
CONDUCTOR_DB = (0,
|
|
18998
|
-
CURSOR_SDK_STORE = (0,
|
|
19182
|
+
CONDUCTOR_DB = (0, import_node_path46.join)(CONDUCTOR_APP_SUPPORT, "conductor.db");
|
|
19183
|
+
CURSOR_SDK_STORE = (0, import_node_path46.join)(CONDUCTOR_APP_SUPPORT, "cursor-sdk-store");
|
|
18999
19184
|
}
|
|
19000
19185
|
});
|
|
19001
19186
|
|
|
@@ -19062,7 +19247,7 @@ async function openStackLayer(input, _onSetupLine) {
|
|
|
19062
19247
|
let createdWorktree = false;
|
|
19063
19248
|
const trees = await listWorktrees(repoPath);
|
|
19064
19249
|
const checkedOut = trees.find((w) => w.branch === branchName);
|
|
19065
|
-
if (checkedOut?.path && (0,
|
|
19250
|
+
if (checkedOut?.path && (0, import_node_fs49.existsSync)(checkedOut.path)) {
|
|
19066
19251
|
if (input.reuseExistingWorktree !== false) {
|
|
19067
19252
|
worktreePath = checkedOut.path;
|
|
19068
19253
|
} else {
|
|
@@ -19204,7 +19389,7 @@ async function initStackFromThread(input, onSetupLine) {
|
|
|
19204
19389
|
async function createPrStack(input, onSetupLine) {
|
|
19205
19390
|
await requireAgent(input.agent);
|
|
19206
19391
|
const repoPath = await resolveRepoRoot(input.repoPath);
|
|
19207
|
-
if (!(0,
|
|
19392
|
+
if (!(0, import_node_fs49.existsSync)(repoPath)) throw new Error(`Repo not found: ${repoPath}`);
|
|
19208
19393
|
if (!input.branches.length) throw new Error("At least one branch name required");
|
|
19209
19394
|
const status = await detectGhStack(repoPath);
|
|
19210
19395
|
if (!status.available) throw new Error(status.reason);
|
|
@@ -19271,7 +19456,7 @@ async function createPrStack(input, onSetupLine) {
|
|
|
19271
19456
|
}
|
|
19272
19457
|
}
|
|
19273
19458
|
const claimed = new Set(threads.map((t) => t.worktreePath));
|
|
19274
|
-
if (!claimed.has(bootstrap.worktreePath) && (0,
|
|
19459
|
+
if (!claimed.has(bootstrap.worktreePath) && (0, import_node_fs49.existsSync)(bootstrap.worktreePath)) {
|
|
19275
19460
|
try {
|
|
19276
19461
|
await removeWorktree(repoPath, bootstrap.worktreePath, {
|
|
19277
19462
|
deleteBranch: bootstrap.branchName
|
|
@@ -19281,11 +19466,11 @@ async function createPrStack(input, onSetupLine) {
|
|
|
19281
19466
|
}
|
|
19282
19467
|
return { stack, threads, createdThreadIds };
|
|
19283
19468
|
}
|
|
19284
|
-
var
|
|
19469
|
+
var import_node_fs49;
|
|
19285
19470
|
var init_stack_layers = __esm({
|
|
19286
19471
|
"src/threads/stack-layers.ts"() {
|
|
19287
19472
|
"use strict";
|
|
19288
|
-
|
|
19473
|
+
import_node_fs49 = require("fs");
|
|
19289
19474
|
init_detect();
|
|
19290
19475
|
init_run();
|
|
19291
19476
|
init_stack();
|
|
@@ -19298,7 +19483,7 @@ var init_stack_layers = __esm({
|
|
|
19298
19483
|
|
|
19299
19484
|
// src/diff/diff.ts
|
|
19300
19485
|
async function inspectGitWorktree(worktreePath) {
|
|
19301
|
-
if (!worktreePath || !(0,
|
|
19486
|
+
if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) return "missing_worktree";
|
|
19302
19487
|
const check = await git(["rev-parse", "--is-inside-work-tree"], worktreePath, {
|
|
19303
19488
|
reject: false
|
|
19304
19489
|
});
|
|
@@ -19306,7 +19491,7 @@ async function inspectGitWorktree(worktreePath) {
|
|
|
19306
19491
|
return "ok";
|
|
19307
19492
|
}
|
|
19308
19493
|
async function initializeGitRepository(worktreePath) {
|
|
19309
|
-
if (!worktreePath || !(0,
|
|
19494
|
+
if (!worktreePath || !(0, import_node_fs50.existsSync)(worktreePath)) {
|
|
19310
19495
|
throw new Error("Worktree not found");
|
|
19311
19496
|
}
|
|
19312
19497
|
const status = await inspectGitWorktree(worktreePath);
|
|
@@ -19440,11 +19625,11 @@ new file mode 100644
|
|
|
19440
19625
|
};
|
|
19441
19626
|
}
|
|
19442
19627
|
async function untrackedPatch(worktreePath, path, maxHunk) {
|
|
19443
|
-
const abs = (0,
|
|
19628
|
+
const abs = (0, import_node_path47.join)(worktreePath, path);
|
|
19444
19629
|
try {
|
|
19445
|
-
const st = (0,
|
|
19630
|
+
const st = (0, import_node_fs50.statSync)(abs);
|
|
19446
19631
|
if (st.isFile() && st.size > maxHunk) {
|
|
19447
|
-
const buf = (0,
|
|
19632
|
+
const buf = (0, import_node_fs50.readFileSync)(abs).subarray(0, maxHunk);
|
|
19448
19633
|
return syntheticAddPatch(path, buf.toString("utf8"), maxHunk);
|
|
19449
19634
|
}
|
|
19450
19635
|
} catch {
|
|
@@ -19911,9 +20096,9 @@ async function getDiff(worktreePath, repoPath, opts) {
|
|
|
19911
20096
|
}
|
|
19912
20097
|
function statWorktreePath(worktreePath, relativePath) {
|
|
19913
20098
|
assertSafeRelativePath(relativePath);
|
|
19914
|
-
const abs = (0,
|
|
19915
|
-
if (!(0,
|
|
19916
|
-
const st = (0,
|
|
20099
|
+
const abs = (0, import_node_path47.join)(worktreePath, relativePath);
|
|
20100
|
+
if (!(0, import_node_fs50.existsSync)(abs)) return "missing";
|
|
20101
|
+
const st = (0, import_node_fs50.statSync)(abs);
|
|
19917
20102
|
if (st.isDirectory()) return "dir";
|
|
19918
20103
|
if (st.isFile()) return "file";
|
|
19919
20104
|
return "missing";
|
|
@@ -19942,8 +20127,8 @@ function isImageRelativePath(relativePath) {
|
|
|
19942
20127
|
function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
19943
20128
|
assertSafeRelativePath(relativePath);
|
|
19944
20129
|
const maxBytes = opts?.maxBytes ?? DEFAULT_UPLOAD_MAX_BYTES;
|
|
19945
|
-
const abs = (0,
|
|
19946
|
-
const st = (0,
|
|
20130
|
+
const abs = (0, import_node_path47.join)(worktreePath, relativePath);
|
|
20131
|
+
const st = (0, import_node_fs50.statSync)(abs);
|
|
19947
20132
|
if (!st.isFile()) {
|
|
19948
20133
|
throw new Error(`Not a file: ${relativePath}`);
|
|
19949
20134
|
}
|
|
@@ -19952,7 +20137,7 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
19952
20137
|
`File too large to upload (${st.size} bytes; max ${maxBytes})`
|
|
19953
20138
|
);
|
|
19954
20139
|
}
|
|
19955
|
-
const buf = (0,
|
|
20140
|
+
const buf = (0, import_node_fs50.readFileSync)(abs);
|
|
19956
20141
|
return {
|
|
19957
20142
|
path: relativePath,
|
|
19958
20143
|
contentBase64: buf.toString("base64"),
|
|
@@ -19962,12 +20147,12 @@ function readWorktreeFileForUpload(worktreePath, relativePath, opts) {
|
|
|
19962
20147
|
function readWorktreeFile(worktreePath, relativePath, opts) {
|
|
19963
20148
|
assertSafeRelativePath(relativePath);
|
|
19964
20149
|
const maxBytes = opts?.maxBytes ?? 2e5;
|
|
19965
|
-
const abs = (0,
|
|
19966
|
-
const st = (0,
|
|
20150
|
+
const abs = (0, import_node_path47.join)(worktreePath, relativePath);
|
|
20151
|
+
const st = (0, import_node_fs50.statSync)(abs);
|
|
19967
20152
|
if (!st.isFile()) {
|
|
19968
20153
|
throw new Error(`Not a file: ${relativePath}`);
|
|
19969
20154
|
}
|
|
19970
|
-
const buf = (0,
|
|
20155
|
+
const buf = (0, import_node_fs50.readFileSync)(abs);
|
|
19971
20156
|
if (isImageRelativePath(relativePath)) {
|
|
19972
20157
|
const maxImageBytes = Math.max(maxBytes, 15e6);
|
|
19973
20158
|
const truncated2 = buf.length > maxImageBytes;
|
|
@@ -20010,9 +20195,9 @@ function assertSafeRelativePath(relativePath) {
|
|
|
20010
20195
|
}
|
|
20011
20196
|
function writeWorktreeFile(worktreePath, relativePath, content) {
|
|
20012
20197
|
assertSafeRelativePath(relativePath);
|
|
20013
|
-
const abs = (0,
|
|
20014
|
-
(0,
|
|
20015
|
-
(0,
|
|
20198
|
+
const abs = (0, import_node_path47.join)(worktreePath, relativePath);
|
|
20199
|
+
(0, import_node_fs50.mkdirSync)((0, import_node_path47.dirname)(abs), { recursive: true });
|
|
20200
|
+
(0, import_node_fs50.writeFileSync)(abs, content, "utf8");
|
|
20016
20201
|
return { path: relativePath };
|
|
20017
20202
|
}
|
|
20018
20203
|
async function getWorktreeDirtyStat(worktreePath) {
|
|
@@ -20052,12 +20237,12 @@ async function getDiffSummary(worktreePath, repoPath, opts) {
|
|
|
20052
20237
|
truncated: full.files.length > maxFiles
|
|
20053
20238
|
};
|
|
20054
20239
|
}
|
|
20055
|
-
var
|
|
20240
|
+
var import_node_fs50, import_node_path47, mergeBaseCache, MERGE_BASE_TTL_MS, SHA_RE, IMAGE_EXTENSIONS2, DEFAULT_UPLOAD_MAX_BYTES;
|
|
20056
20241
|
var init_diff = __esm({
|
|
20057
20242
|
"src/diff/diff.ts"() {
|
|
20058
20243
|
"use strict";
|
|
20059
|
-
|
|
20060
|
-
|
|
20244
|
+
import_node_fs50 = require("fs");
|
|
20245
|
+
import_node_path47 = require("path");
|
|
20061
20246
|
init_run();
|
|
20062
20247
|
init_worktree();
|
|
20063
20248
|
mergeBaseCache = /* @__PURE__ */ new Map();
|
|
@@ -20414,7 +20599,7 @@ function parseFrontmatter(content) {
|
|
|
20414
20599
|
}
|
|
20415
20600
|
function readSkill(skillMd, source) {
|
|
20416
20601
|
try {
|
|
20417
|
-
const content = (0,
|
|
20602
|
+
const content = (0, import_node_fs51.readFileSync)(skillMd, "utf8");
|
|
20418
20603
|
const { name: fmName, description } = parseFrontmatter(content);
|
|
20419
20604
|
const dirName = skillMd.split("/").slice(-2, -1)[0] || "skill";
|
|
20420
20605
|
const name = fmName || dirName;
|
|
@@ -20433,19 +20618,19 @@ function readSkill(skillMd, source) {
|
|
|
20433
20618
|
}
|
|
20434
20619
|
}
|
|
20435
20620
|
function scanSkillsDir(dir, source, out) {
|
|
20436
|
-
if (!(0,
|
|
20621
|
+
if (!(0, import_node_fs51.existsSync)(dir)) return;
|
|
20437
20622
|
let entries;
|
|
20438
20623
|
try {
|
|
20439
|
-
entries = (0,
|
|
20624
|
+
entries = (0, import_node_fs51.readdirSync)(dir);
|
|
20440
20625
|
} catch {
|
|
20441
20626
|
return;
|
|
20442
20627
|
}
|
|
20443
20628
|
for (const entry of entries) {
|
|
20444
20629
|
if (entry.startsWith(".")) continue;
|
|
20445
|
-
const skillMd = (0,
|
|
20446
|
-
if (!(0,
|
|
20630
|
+
const skillMd = (0, import_node_path48.join)(dir, entry, "SKILL.md");
|
|
20631
|
+
if (!(0, import_node_fs51.existsSync)(skillMd)) continue;
|
|
20447
20632
|
try {
|
|
20448
|
-
if (!(0,
|
|
20633
|
+
if (!(0, import_node_fs51.statSync)(skillMd).isFile()) continue;
|
|
20449
20634
|
} catch {
|
|
20450
20635
|
continue;
|
|
20451
20636
|
}
|
|
@@ -20454,24 +20639,24 @@ function scanSkillsDir(dir, source, out) {
|
|
|
20454
20639
|
}
|
|
20455
20640
|
}
|
|
20456
20641
|
function scanClaudePluginSkills(pluginsRoot, out) {
|
|
20457
|
-
if (!(0,
|
|
20642
|
+
if (!(0, import_node_fs51.existsSync)(pluginsRoot)) return;
|
|
20458
20643
|
const walk = (dir, depth, lookingForSkillsDir) => {
|
|
20459
20644
|
if (depth > 7) return;
|
|
20460
20645
|
let entries;
|
|
20461
20646
|
try {
|
|
20462
|
-
entries = (0,
|
|
20647
|
+
entries = (0, import_node_fs51.readdirSync)(dir);
|
|
20463
20648
|
} catch {
|
|
20464
20649
|
return;
|
|
20465
20650
|
}
|
|
20466
20651
|
if (lookingForSkillsDir && entries.includes("SKILL.md")) {
|
|
20467
|
-
const skill = readSkill((0,
|
|
20652
|
+
const skill = readSkill((0, import_node_path48.join)(dir, "SKILL.md"), "cli");
|
|
20468
20653
|
if (skill) out.push(skill);
|
|
20469
20654
|
}
|
|
20470
20655
|
for (const entry of entries) {
|
|
20471
20656
|
if (entry === "node_modules" || entry === ".git") continue;
|
|
20472
|
-
const full = (0,
|
|
20657
|
+
const full = (0, import_node_path48.join)(dir, entry);
|
|
20473
20658
|
try {
|
|
20474
|
-
if (!(0,
|
|
20659
|
+
if (!(0, import_node_fs51.statSync)(full).isDirectory()) continue;
|
|
20475
20660
|
} catch {
|
|
20476
20661
|
continue;
|
|
20477
20662
|
}
|
|
@@ -20489,17 +20674,17 @@ function discoverSkills(worktreePath) {
|
|
|
20489
20674
|
const home = (0, import_node_os15.homedir)();
|
|
20490
20675
|
const collected = [];
|
|
20491
20676
|
for (const rel of [".claude/skills", ".cursor/skills", ".sideboard/skills", ".brightsy/skills", "skills"]) {
|
|
20492
|
-
scanSkillsDir((0,
|
|
20677
|
+
scanSkillsDir((0, import_node_path48.join)(worktreePath, rel), "workspace", collected);
|
|
20493
20678
|
}
|
|
20494
20679
|
for (const abs of [
|
|
20495
|
-
(0,
|
|
20496
|
-
(0,
|
|
20497
|
-
(0,
|
|
20498
|
-
(0,
|
|
20680
|
+
(0, import_node_path48.join)(home, ".claude/skills"),
|
|
20681
|
+
(0, import_node_path48.join)(home, ".cursor/skills"),
|
|
20682
|
+
(0, import_node_path48.join)(home, ".sideboard/skills"),
|
|
20683
|
+
(0, import_node_path48.join)(home, ".brightsy/skills")
|
|
20499
20684
|
]) {
|
|
20500
20685
|
scanSkillsDir(abs, "user", collected);
|
|
20501
20686
|
}
|
|
20502
|
-
scanClaudePluginSkills((0,
|
|
20687
|
+
scanClaudePluginSkills((0, import_node_path48.join)(home, ".claude/plugins"), collected);
|
|
20503
20688
|
collected.push(...bundledSkills());
|
|
20504
20689
|
const rank = {
|
|
20505
20690
|
workspace: 0,
|
|
@@ -20525,7 +20710,7 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
20525
20710
|
\u2026(truncated)` : body;
|
|
20526
20711
|
}
|
|
20527
20712
|
}
|
|
20528
|
-
const raw = (0,
|
|
20713
|
+
const raw = (0, import_node_fs51.readFileSync)(skillPath, "utf8");
|
|
20529
20714
|
if (raw.startsWith("---")) {
|
|
20530
20715
|
const end = raw.indexOf("\n---", 3);
|
|
20531
20716
|
if (end >= 0) {
|
|
@@ -20539,13 +20724,13 @@ function readSkillBody(skillPath, maxChars = 12e3) {
|
|
|
20539
20724
|
|
|
20540
20725
|
\u2026(truncated)` : raw;
|
|
20541
20726
|
}
|
|
20542
|
-
var
|
|
20727
|
+
var import_node_fs51, import_node_os15, import_node_path48, BUNDLED_SKILL_PREFIX;
|
|
20543
20728
|
var init_discover = __esm({
|
|
20544
20729
|
"src/skills/discover.ts"() {
|
|
20545
20730
|
"use strict";
|
|
20546
|
-
|
|
20731
|
+
import_node_fs51 = require("fs");
|
|
20547
20732
|
import_node_os15 = require("os");
|
|
20548
|
-
|
|
20733
|
+
import_node_path48 = require("path");
|
|
20549
20734
|
init_long_running();
|
|
20550
20735
|
BUNDLED_SKILL_PREFIX = "bundled:";
|
|
20551
20736
|
}
|
|
@@ -20700,7 +20885,7 @@ function compiledModuleDir() {
|
|
|
20700
20885
|
try {
|
|
20701
20886
|
const url = import_meta4.url;
|
|
20702
20887
|
if (typeof url === "string" && url.length > 0) {
|
|
20703
|
-
return (0,
|
|
20888
|
+
return (0, import_node_path49.dirname)((0, import_node_url4.fileURLToPath)(url));
|
|
20704
20889
|
}
|
|
20705
20890
|
} catch {
|
|
20706
20891
|
}
|
|
@@ -20708,8 +20893,8 @@ function compiledModuleDir() {
|
|
|
20708
20893
|
}
|
|
20709
20894
|
function detachedJobScriptIn(dir) {
|
|
20710
20895
|
for (const name of DETACHED_JOB_FILENAMES) {
|
|
20711
|
-
const script = (0,
|
|
20712
|
-
if ((0,
|
|
20896
|
+
const script = (0, import_node_path49.join)(dir, "scripts", name);
|
|
20897
|
+
if ((0, import_node_fs52.existsSync)(script)) return script;
|
|
20713
20898
|
}
|
|
20714
20899
|
return null;
|
|
20715
20900
|
}
|
|
@@ -20726,7 +20911,7 @@ function resolveDetachedJobScript() {
|
|
|
20726
20911
|
for (let i = 0; i < 8; i++) {
|
|
20727
20912
|
const candidate = detachedJobScriptIn(dir);
|
|
20728
20913
|
if (candidate) return candidate;
|
|
20729
|
-
const parent = (0,
|
|
20914
|
+
const parent = (0, import_node_path49.dirname)(dir);
|
|
20730
20915
|
if (parent === dir) break;
|
|
20731
20916
|
dir = parent;
|
|
20732
20917
|
}
|
|
@@ -20737,12 +20922,12 @@ function formatDetachedJobInvoke(scriptPath) {
|
|
|
20737
20922
|
if (resolved) return `node ${JSON.stringify(resolved)}`;
|
|
20738
20923
|
return "node scripts/detached-job.cjs";
|
|
20739
20924
|
}
|
|
20740
|
-
var
|
|
20925
|
+
var import_node_fs52, import_node_path49, import_node_url4, import_meta4, DETACHED_JOB_FILENAMES;
|
|
20741
20926
|
var init_detached_job_path = __esm({
|
|
20742
20927
|
"src/skills/detached-job-path.ts"() {
|
|
20743
20928
|
"use strict";
|
|
20744
|
-
|
|
20745
|
-
|
|
20929
|
+
import_node_fs52 = require("fs");
|
|
20930
|
+
import_node_path49 = require("path");
|
|
20746
20931
|
import_node_url4 = require("url");
|
|
20747
20932
|
init_packaged_runtime();
|
|
20748
20933
|
import_meta4 = {};
|
|
@@ -20843,9 +21028,9 @@ function formatWorktreeDirective(thread, opts) {
|
|
|
20843
21028
|
);
|
|
20844
21029
|
} else {
|
|
20845
21030
|
const slug = opts?.githubSlug ?? "<origin-owner/name>";
|
|
20846
|
-
const
|
|
21031
|
+
const resolve2 = opts?.githubSlug ? "" : " Resolve `<origin-owner/name>` with `git remote get-url origin` in this worktree.";
|
|
20847
21032
|
lines.push(
|
|
20848
|
-
`- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${
|
|
21033
|
+
`- Prefer a draft PR first: \`gh pr create --draft -R ${slug}\` (update via \`gh pr edit -R ${slug}\`). Always pass \`-R\` \u2014 bare \`gh pr create\` may target upstream on dual-remote checkouts.${resolve2} Mark ready for review only when asked. If GitHub rejects the body as too long, retry with a short \`--body-file\` \u2014 do not paste a changelog or diff into \`--body\`.`
|
|
20849
21034
|
);
|
|
20850
21035
|
}
|
|
20851
21036
|
lines.push(
|
|
@@ -20932,9 +21117,9 @@ function formatPrGateDirective() {
|
|
|
20932
21117
|
}
|
|
20933
21118
|
function formatProcessGuideDirective(opts) {
|
|
20934
21119
|
const worktree = opts?.worktreePath?.trim();
|
|
20935
|
-
const hasGraphSkill = !!worktree && (0,
|
|
20936
|
-
const hasReviewSkill = !!worktree && (0,
|
|
20937
|
-
const hasInstallSkill = !!worktree && (0,
|
|
21120
|
+
const hasGraphSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/graph-engineering/SKILL.md"));
|
|
21121
|
+
const hasReviewSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/review/SKILL.md"));
|
|
21122
|
+
const hasInstallSkill = !!worktree && (0, import_node_fs53.existsSync)((0, import_node_path50.join)(worktree, ".claude/skills/worktree-install/SKILL.md"));
|
|
20938
21123
|
return [
|
|
20939
21124
|
"Process guides (recurring work only):",
|
|
20940
21125
|
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,
|
|
@@ -20973,12 +21158,12 @@ function formatArtifactDirective() {
|
|
|
20973
21158
|
function formatUiReminder() {
|
|
20974
21159
|
return "Sideboard UI: markdown table is enough to read data; present_schema if they ask to edit/filter (even after markdown); present_files for the file manager. html fence or present_artifact, not both for the same document. type=log appends (same artifact_id, new lines only). ask_user only for a real multiple-choice (not hellos, \u201Cwhat next?\u201D, or after a review) \u2014 reply in chat. ask_user wakes the parent orchestrator; notify_orchestrator if blocked without a picker. Do not say artifacts/CMS UI are unavailable. Dev / preview: run_dev_script (same as the Dev button) returns {url, port, preview} (SIDEBOARD_PORT \u2014 never guess :3000). preview=url \u2192 open url; preview=window \u2192 Electron window is the app, url is renderer/HMR only. list_run_scripts active[].url if already running; get_run_log for the Run-tab terminal; stop_dev_script to stop.";
|
|
20975
21160
|
}
|
|
20976
|
-
var
|
|
21161
|
+
var import_node_fs53, import_node_path50, PR_GOAL_RE, GITHUB_TICKET_REF, KEYED_TICKET_REF;
|
|
20977
21162
|
var init_instructions = __esm({
|
|
20978
21163
|
"src/agents/instructions.ts"() {
|
|
20979
21164
|
"use strict";
|
|
20980
|
-
|
|
20981
|
-
|
|
21165
|
+
import_node_fs53 = require("fs");
|
|
21166
|
+
import_node_path50 = require("path");
|
|
20982
21167
|
init_git_auth_mode();
|
|
20983
21168
|
init_branch_prefix();
|
|
20984
21169
|
init_worktree_labels();
|
|
@@ -21202,40 +21387,40 @@ __export(plan_file_exports, {
|
|
|
21202
21387
|
writePlanFile: () => writePlanFile
|
|
21203
21388
|
});
|
|
21204
21389
|
function ensureAttachmentsGitignore(worktreePath) {
|
|
21205
|
-
const gitignoreAbs = (0,
|
|
21206
|
-
if ((0,
|
|
21207
|
-
(0,
|
|
21208
|
-
(0,
|
|
21390
|
+
const gitignoreAbs = (0, import_node_path51.join)(worktreePath, ATTACHMENTS_DIR, ".gitignore");
|
|
21391
|
+
if ((0, import_node_fs54.existsSync)(gitignoreAbs)) return;
|
|
21392
|
+
(0, import_node_fs54.mkdirSync)((0, import_node_path51.dirname)(gitignoreAbs), { recursive: true });
|
|
21393
|
+
(0, import_node_fs54.writeFileSync)(gitignoreAbs, attachmentsGitignoreBody(), "utf8");
|
|
21209
21394
|
}
|
|
21210
21395
|
function planFileAbs(worktreePath) {
|
|
21211
|
-
return (0,
|
|
21396
|
+
return (0, import_node_path51.join)(worktreePath, PLAN_FILE_REL);
|
|
21212
21397
|
}
|
|
21213
21398
|
function readTextIfPresent2(abs) {
|
|
21214
|
-
if (!(0,
|
|
21399
|
+
if (!(0, import_node_fs54.existsSync)(abs)) return null;
|
|
21215
21400
|
try {
|
|
21216
|
-
const content = (0,
|
|
21401
|
+
const content = (0, import_node_fs54.readFileSync)(abs, "utf8");
|
|
21217
21402
|
return content.trim() ? content : null;
|
|
21218
21403
|
} catch {
|
|
21219
21404
|
return null;
|
|
21220
21405
|
}
|
|
21221
21406
|
}
|
|
21222
21407
|
function readPlanFile(worktreePath) {
|
|
21223
|
-
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0,
|
|
21408
|
+
return readTextIfPresent2(planFileAbs(worktreePath)) ?? readTextIfPresent2((0, import_node_path51.join)(worktreePath, `${LEGACY_ATTACHMENTS_DIR}/plan.md`)) ?? readTextIfPresent2((0, import_node_path51.join)(worktreePath, LEGACY_PLAN_FILE_REL));
|
|
21224
21409
|
}
|
|
21225
21410
|
function writePlanFile(worktreePath, content) {
|
|
21226
21411
|
ensureAttachmentsGitignore(worktreePath);
|
|
21227
21412
|
const abs = planFileAbs(worktreePath);
|
|
21228
|
-
(0,
|
|
21413
|
+
(0, import_node_fs54.mkdirSync)((0, import_node_path51.dirname)(abs), { recursive: true });
|
|
21229
21414
|
const body = content.trimEnd() + (content.endsWith("\n") ? "" : "\n");
|
|
21230
|
-
(0,
|
|
21415
|
+
(0, import_node_fs54.writeFileSync)(abs, body, "utf8");
|
|
21231
21416
|
return PLAN_FILE_REL;
|
|
21232
21417
|
}
|
|
21233
|
-
var
|
|
21418
|
+
var import_node_fs54, import_node_path51;
|
|
21234
21419
|
var init_plan_file = __esm({
|
|
21235
21420
|
"src/plan/plan-file.ts"() {
|
|
21236
21421
|
"use strict";
|
|
21237
|
-
|
|
21238
|
-
|
|
21422
|
+
import_node_fs54 = require("fs");
|
|
21423
|
+
import_node_path51 = require("path");
|
|
21239
21424
|
init_workspace_scratch();
|
|
21240
21425
|
init_plan_present();
|
|
21241
21426
|
init_plan_present();
|
|
@@ -21295,7 +21480,7 @@ function setCaffeinateHoldHooks(next) {
|
|
|
21295
21480
|
hooks = next;
|
|
21296
21481
|
}
|
|
21297
21482
|
function caffeinateHoldPath() {
|
|
21298
|
-
return (0,
|
|
21483
|
+
return (0, import_node_path52.join)(appDataDir(), "caffeinate-hold.json");
|
|
21299
21484
|
}
|
|
21300
21485
|
function processAlive(pid) {
|
|
21301
21486
|
if (hooks.processAlive) return hooks.processAlive(pid);
|
|
@@ -21329,9 +21514,9 @@ function uniqueIds(ids) {
|
|
|
21329
21514
|
}
|
|
21330
21515
|
function readHold() {
|
|
21331
21516
|
const path = caffeinateHoldPath();
|
|
21332
|
-
if (!(0,
|
|
21517
|
+
if (!(0, import_node_fs55.existsSync)(path)) return null;
|
|
21333
21518
|
try {
|
|
21334
|
-
const parsed = JSON.parse((0,
|
|
21519
|
+
const parsed = JSON.parse((0, import_node_fs55.readFileSync)(path, "utf8"));
|
|
21335
21520
|
if (typeof parsed?.pid === "number" && parsed.pid > 0) {
|
|
21336
21521
|
return {
|
|
21337
21522
|
pid: parsed.pid,
|
|
@@ -21353,7 +21538,7 @@ function writeHold(pid, threadIds) {
|
|
|
21353
21538
|
}
|
|
21354
21539
|
function clearHold() {
|
|
21355
21540
|
try {
|
|
21356
|
-
(0,
|
|
21541
|
+
(0, import_node_fs55.unlinkSync)(caffeinateHoldPath());
|
|
21357
21542
|
} catch {
|
|
21358
21543
|
}
|
|
21359
21544
|
}
|
|
@@ -21438,13 +21623,13 @@ function releaseCaffeinateHoldForThread(threadId) {
|
|
|
21438
21623
|
}
|
|
21439
21624
|
return setCaffeinateHold(false, { threadId: id });
|
|
21440
21625
|
}
|
|
21441
|
-
var import_node_child_process6,
|
|
21626
|
+
var import_node_child_process6, import_node_fs55, import_node_path52, hooks;
|
|
21442
21627
|
var init_caffeinate_hold = __esm({
|
|
21443
21628
|
"src/store/caffeinate-hold.ts"() {
|
|
21444
21629
|
"use strict";
|
|
21445
21630
|
import_node_child_process6 = require("child_process");
|
|
21446
|
-
|
|
21447
|
-
|
|
21631
|
+
import_node_fs55 = require("fs");
|
|
21632
|
+
import_node_path52 = require("path");
|
|
21448
21633
|
init_paths();
|
|
21449
21634
|
init_private_file();
|
|
21450
21635
|
hooks = {};
|
|
@@ -21453,7 +21638,7 @@ var init_caffeinate_hold = __esm({
|
|
|
21453
21638
|
|
|
21454
21639
|
// src/store/schedules.ts
|
|
21455
21640
|
function schedulesPath() {
|
|
21456
|
-
return (0,
|
|
21641
|
+
return (0, import_node_path53.join)(appDataDir(), "schedules.json");
|
|
21457
21642
|
}
|
|
21458
21643
|
function parseDurationMs(every) {
|
|
21459
21644
|
const m = every.trim().match(DURATION_RE);
|
|
@@ -21553,9 +21738,9 @@ function normalizeTask(raw) {
|
|
|
21553
21738
|
}
|
|
21554
21739
|
function readAll2() {
|
|
21555
21740
|
const path = schedulesPath();
|
|
21556
|
-
if (!(0,
|
|
21741
|
+
if (!(0, import_node_fs56.existsSync)(path)) return [];
|
|
21557
21742
|
try {
|
|
21558
|
-
const parsed = JSON.parse((0,
|
|
21743
|
+
const parsed = JSON.parse((0, import_node_fs56.readFileSync)(path, "utf8"));
|
|
21559
21744
|
if (!Array.isArray(parsed)) return [];
|
|
21560
21745
|
return parsed.map((row) => {
|
|
21561
21746
|
try {
|
|
@@ -21667,13 +21852,13 @@ function recordScheduleRun(id, result) {
|
|
|
21667
21852
|
writeAll2(rows);
|
|
21668
21853
|
return next;
|
|
21669
21854
|
}
|
|
21670
|
-
var import_node_crypto12,
|
|
21855
|
+
var import_node_crypto12, import_node_fs56, import_node_path53, import_croner, DURATION_RE, UNIT_MS;
|
|
21671
21856
|
var init_schedules = __esm({
|
|
21672
21857
|
"src/store/schedules.ts"() {
|
|
21673
21858
|
"use strict";
|
|
21674
21859
|
import_node_crypto12 = require("crypto");
|
|
21675
|
-
|
|
21676
|
-
|
|
21860
|
+
import_node_fs56 = require("fs");
|
|
21861
|
+
import_node_path53 = require("path");
|
|
21677
21862
|
import_croner = require("croner");
|
|
21678
21863
|
init_orchestrator_capable();
|
|
21679
21864
|
init_paths();
|
|
@@ -21759,14 +21944,14 @@ function armOne(schedule) {
|
|
|
21759
21944
|
if (!schedule.enabled) return;
|
|
21760
21945
|
const at = new Date(schedule.nextRunAt);
|
|
21761
21946
|
if (Number.isNaN(at.getTime())) return;
|
|
21762
|
-
const
|
|
21763
|
-
if (
|
|
21947
|
+
const delay2 = Math.max(0, at.getTime() - Date.now());
|
|
21948
|
+
if (delay2 <= 250) {
|
|
21764
21949
|
void fireSchedule(schedule.id).then(() => {
|
|
21765
21950
|
if (isThisProcessDesktopHost()) armSchedules();
|
|
21766
21951
|
});
|
|
21767
21952
|
return;
|
|
21768
21953
|
}
|
|
21769
|
-
const capped = Math.min(
|
|
21954
|
+
const capped = Math.min(delay2, SET_TIMEOUT_MAX);
|
|
21770
21955
|
const timer = setTimeout(() => {
|
|
21771
21956
|
timers.delete(schedule.id);
|
|
21772
21957
|
const live = getSchedule(schedule.id);
|
|
@@ -21829,9 +22014,9 @@ function recoverFinishedCursorRun(opts) {
|
|
|
21829
22014
|
return best;
|
|
21830
22015
|
}
|
|
21831
22016
|
function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
|
|
21832
|
-
if (!(0,
|
|
22017
|
+
if (!(0, import_node_fs57.existsSync)(runsPath)) return null;
|
|
21833
22018
|
try {
|
|
21834
|
-
const lines = (0,
|
|
22019
|
+
const lines = (0, import_node_fs57.readFileSync)(runsPath, "utf8").split("\n");
|
|
21835
22020
|
let best = null;
|
|
21836
22021
|
for (const line of lines) {
|
|
21837
22022
|
const trimmed = line.trim();
|
|
@@ -21857,11 +22042,11 @@ function scanFinishedCursorRuns(runsPath, agentId, startedAfterMs) {
|
|
|
21857
22042
|
return null;
|
|
21858
22043
|
}
|
|
21859
22044
|
}
|
|
21860
|
-
var
|
|
22045
|
+
var import_node_fs57;
|
|
21861
22046
|
var init_cursor_recover = __esm({
|
|
21862
22047
|
"src/agents/cursor-recover.ts"() {
|
|
21863
22048
|
"use strict";
|
|
21864
|
-
|
|
22049
|
+
import_node_fs57 = require("fs");
|
|
21865
22050
|
init_cursor_store();
|
|
21866
22051
|
}
|
|
21867
22052
|
});
|
|
@@ -22015,7 +22200,7 @@ async function startOrchestration(opts) {
|
|
|
22015
22200
|
}
|
|
22016
22201
|
return updated;
|
|
22017
22202
|
}
|
|
22018
|
-
var import_node_events, import_node_crypto13,
|
|
22203
|
+
var import_node_events, import_node_crypto13, import_node_fs58, LIVE_TURN_SPAWN_GRACE_MS, RUN_SCRIPT_DESKTOP_ADOPT_MS, STALE_AGENT_PID_WAIT_MS, LIGHT_RECONCILE_THROTTLE_MS, Orchestrator, singleton;
|
|
22019
22204
|
var init_orchestrator = __esm({
|
|
22020
22205
|
"src/orchestrator/orchestrator.ts"() {
|
|
22021
22206
|
"use strict";
|
|
@@ -22023,7 +22208,7 @@ var init_orchestrator = __esm({
|
|
|
22023
22208
|
init_injected_notices();
|
|
22024
22209
|
init_task_state();
|
|
22025
22210
|
import_node_crypto13 = require("crypto");
|
|
22026
|
-
|
|
22211
|
+
import_node_fs58 = require("fs");
|
|
22027
22212
|
init_error_detail();
|
|
22028
22213
|
init_run();
|
|
22029
22214
|
init_stale_lock();
|
|
@@ -22202,7 +22387,7 @@ var init_orchestrator = __esm({
|
|
|
22202
22387
|
this.lightReconcileAt.set(repoPath, Date.now());
|
|
22203
22388
|
for (const thread of listThreads()) {
|
|
22204
22389
|
if (isGlobalThread(thread) || thread.repoPath !== repoPath) continue;
|
|
22205
|
-
if (!(0,
|
|
22390
|
+
if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
|
|
22206
22391
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
22207
22392
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
22208
22393
|
}
|
|
@@ -22231,7 +22416,7 @@ var init_orchestrator = __esm({
|
|
|
22231
22416
|
}
|
|
22232
22417
|
continue;
|
|
22233
22418
|
}
|
|
22234
|
-
if (!(0,
|
|
22419
|
+
if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
|
|
22235
22420
|
setStatus(thread.id, "broken", "Worktree missing on disk");
|
|
22236
22421
|
this.emit({ type: "status_changed", threadId: thread.id, status: "broken" });
|
|
22237
22422
|
continue;
|
|
@@ -22399,8 +22584,8 @@ var init_orchestrator = __esm({
|
|
|
22399
22584
|
scheduleQuotaResume(threadId, resumeAt) {
|
|
22400
22585
|
this.clearQuotaResumeTimer(threadId);
|
|
22401
22586
|
updateThread(threadId, { quotaResumeAt: resumeAt.toISOString() });
|
|
22402
|
-
const
|
|
22403
|
-
const capped = Math.min(
|
|
22587
|
+
const delay2 = Math.max(5e3, resumeAt.getTime() - Date.now());
|
|
22588
|
+
const capped = Math.min(delay2, 2147483647);
|
|
22404
22589
|
const timer = setTimeout(() => {
|
|
22405
22590
|
this.quotaResumeTimers.delete(threadId);
|
|
22406
22591
|
void this.resumeAfterQuotaWait(threadId);
|
|
@@ -23455,6 +23640,7 @@ var init_orchestrator = __esm({
|
|
|
23455
23640
|
return { port: shared.devPort, scriptName: resolvedName, ports: [shared.devPort] };
|
|
23456
23641
|
}
|
|
23457
23642
|
}
|
|
23643
|
+
const preferredPorts = active?.ports?.length ? active.ports : active?.port != null ? [active.port] : void 0;
|
|
23458
23644
|
if (active && !existing) {
|
|
23459
23645
|
killListenersOnPorts(collectActiveRunPorts([active]));
|
|
23460
23646
|
this.syncWorktreeRuns(
|
|
@@ -23493,7 +23679,7 @@ var init_orchestrator = __esm({
|
|
|
23493
23679
|
thread.repoPath,
|
|
23494
23680
|
thread.worktreePath,
|
|
23495
23681
|
runOutput.push,
|
|
23496
|
-
{ scriptName: resolvedName }
|
|
23682
|
+
{ scriptName: resolvedName, preferredPorts }
|
|
23497
23683
|
);
|
|
23498
23684
|
} catch (err) {
|
|
23499
23685
|
runOutput.flush();
|
|
@@ -23942,7 +24128,7 @@ var init_orchestrator = __esm({
|
|
|
23942
24128
|
return thread;
|
|
23943
24129
|
}
|
|
23944
24130
|
const start = Date.now();
|
|
23945
|
-
return new Promise((
|
|
24131
|
+
return new Promise((resolve2, reject) => {
|
|
23946
24132
|
let settled = false;
|
|
23947
24133
|
let timer;
|
|
23948
24134
|
const finish = (fn) => {
|
|
@@ -23960,7 +24146,7 @@ var init_orchestrator = __esm({
|
|
|
23960
24146
|
finish(() => reject(new Error(`Thread not found: ${thread.id}`)));
|
|
23961
24147
|
return;
|
|
23962
24148
|
}
|
|
23963
|
-
finish(() =>
|
|
24149
|
+
finish(() => resolve2(latest));
|
|
23964
24150
|
return;
|
|
23965
24151
|
}
|
|
23966
24152
|
if (event.type === "status_changed") {
|
|
@@ -23970,7 +24156,7 @@ var init_orchestrator = __esm({
|
|
|
23970
24156
|
return;
|
|
23971
24157
|
}
|
|
23972
24158
|
if (!["running", "queued"].includes(latest.status)) {
|
|
23973
|
-
finish(() =>
|
|
24159
|
+
finish(() => resolve2(latest));
|
|
23974
24160
|
}
|
|
23975
24161
|
}
|
|
23976
24162
|
});
|
|
@@ -23982,12 +24168,12 @@ var init_orchestrator = __esm({
|
|
|
23982
24168
|
}
|
|
23983
24169
|
const current = this.healStaleReportedActivity(raw);
|
|
23984
24170
|
if (!this.threadLooksLive(current)) {
|
|
23985
|
-
finish(() =>
|
|
24171
|
+
finish(() => resolve2(current));
|
|
23986
24172
|
return;
|
|
23987
24173
|
}
|
|
23988
24174
|
if (Date.now() - start > timeoutMs) {
|
|
23989
24175
|
if (opts?.resolveIfStillRunning) {
|
|
23990
|
-
finish(() =>
|
|
24176
|
+
finish(() => resolve2(current));
|
|
23991
24177
|
} else {
|
|
23992
24178
|
finish(() => reject(new Error("wait_for_turn timed out")));
|
|
23993
24179
|
}
|
|
@@ -24579,7 +24765,7 @@ var init_orchestrator = __esm({
|
|
|
24579
24765
|
this.emit({ type: "status_changed", threadId: restored2.id, status: restored2.status });
|
|
24580
24766
|
return restored2;
|
|
24581
24767
|
}
|
|
24582
|
-
if (!(0,
|
|
24768
|
+
if (!(0, import_node_fs58.existsSync)(thread.worktreePath)) {
|
|
24583
24769
|
if (isCowboyThread(thread) || isPrimaryCheckoutThread(thread)) {
|
|
24584
24770
|
throw new Error(
|
|
24585
24771
|
`Cowboy checkout missing: ${thread.worktreePath}. Re-add the project folder, then restore.`
|
|
@@ -24663,7 +24849,7 @@ var import_mcp = require("@modelcontextprotocol/sdk/server/mcp.js");
|
|
|
24663
24849
|
var import_stdio = require("@modelcontextprotocol/sdk/server/stdio.js");
|
|
24664
24850
|
var import_zod9 = require("zod");
|
|
24665
24851
|
var import_node_crypto16 = require("crypto");
|
|
24666
|
-
var
|
|
24852
|
+
var import_node_path59 = require("path");
|
|
24667
24853
|
init_orchestrator();
|
|
24668
24854
|
init_task_state();
|
|
24669
24855
|
init_worktree();
|
|
@@ -26778,8 +26964,8 @@ ${link}` : link;
|
|
|
26778
26964
|
}
|
|
26779
26965
|
|
|
26780
26966
|
// src/slack/outbound-watch.ts
|
|
26781
|
-
var
|
|
26782
|
-
var
|
|
26967
|
+
var import_node_fs60 = require("fs");
|
|
26968
|
+
var import_node_path56 = require("path");
|
|
26783
26969
|
init_paths();
|
|
26784
26970
|
init_private_file();
|
|
26785
26971
|
init_secure_file();
|
|
@@ -26787,19 +26973,19 @@ init_thread_store();
|
|
|
26787
26973
|
init_injected_notices();
|
|
26788
26974
|
|
|
26789
26975
|
// src/slack/reply-target.ts
|
|
26790
|
-
var
|
|
26791
|
-
var
|
|
26976
|
+
var import_node_fs59 = require("fs");
|
|
26977
|
+
var import_node_path54 = require("path");
|
|
26792
26978
|
init_paths();
|
|
26793
26979
|
init_private_file();
|
|
26794
26980
|
init_secure_file();
|
|
26795
26981
|
function storePath2() {
|
|
26796
|
-
return (0,
|
|
26982
|
+
return (0, import_node_path54.join)(appDataDir(), "slack-reply-to.json");
|
|
26797
26983
|
}
|
|
26798
26984
|
function readStore2() {
|
|
26799
26985
|
const path = storePath2();
|
|
26800
|
-
if (!(0,
|
|
26986
|
+
if (!(0, import_node_fs59.existsSync)(path)) return {};
|
|
26801
26987
|
try {
|
|
26802
|
-
const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0,
|
|
26988
|
+
const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs59.readFileSync)(path, "utf8"));
|
|
26803
26989
|
return parsed?.targets && typeof parsed.targets === "object" ? parsed.targets : {};
|
|
26804
26990
|
} catch {
|
|
26805
26991
|
return {};
|
|
@@ -26810,11 +26996,11 @@ function getSlackReplyTarget(threadId) {
|
|
|
26810
26996
|
}
|
|
26811
26997
|
|
|
26812
26998
|
// src/slack/workspaces.ts
|
|
26813
|
-
var
|
|
26999
|
+
var import_node_path55 = require("path");
|
|
26814
27000
|
init_paths();
|
|
26815
27001
|
init_secure_file();
|
|
26816
27002
|
function storePath3() {
|
|
26817
|
-
return (0,
|
|
27003
|
+
return (0, import_node_path55.join)(appDataDir(), "slack-workspaces.json");
|
|
26818
27004
|
}
|
|
26819
27005
|
function readStore3() {
|
|
26820
27006
|
try {
|
|
@@ -26884,7 +27070,7 @@ var POLL_INTERVAL_MS = 12e3;
|
|
|
26884
27070
|
var lastPollMs = 0;
|
|
26885
27071
|
var nameCache = /* @__PURE__ */ new Map();
|
|
26886
27072
|
function storePath4() {
|
|
26887
|
-
return (0,
|
|
27073
|
+
return (0, import_node_path56.join)(appDataDir(), "slack-outbound-watch.json");
|
|
26888
27074
|
}
|
|
26889
27075
|
function watchId(teamId, channelId, ts) {
|
|
26890
27076
|
return `${teamId}:${channelId}:${ts}`;
|
|
@@ -26897,9 +27083,9 @@ function tsNewer(a, b) {
|
|
|
26897
27083
|
}
|
|
26898
27084
|
function readStore4() {
|
|
26899
27085
|
const path = storePath4();
|
|
26900
|
-
if (!(0,
|
|
27086
|
+
if (!(0, import_node_fs60.existsSync)(path)) return [];
|
|
26901
27087
|
try {
|
|
26902
|
-
const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0,
|
|
27088
|
+
const parsed = isSecureFileEncrypted(path) ? readSecureJson(path) : JSON.parse((0, import_node_fs60.readFileSync)(path, "utf8"));
|
|
26903
27089
|
return Array.isArray(parsed?.watches) ? parsed.watches : [];
|
|
26904
27090
|
} catch {
|
|
26905
27091
|
return [];
|
|
@@ -28641,27 +28827,27 @@ init_gh_errors();
|
|
|
28641
28827
|
init_git_auth_mode();
|
|
28642
28828
|
|
|
28643
28829
|
// src/board/load-home-board.ts
|
|
28644
|
-
var
|
|
28645
|
-
var
|
|
28830
|
+
var import_node_fs62 = require("fs");
|
|
28831
|
+
var import_node_path58 = require("path");
|
|
28646
28832
|
init_worktree();
|
|
28647
28833
|
init_paths();
|
|
28648
28834
|
|
|
28649
28835
|
// src/board/board-pins.ts
|
|
28650
28836
|
var import_node_crypto15 = require("crypto");
|
|
28651
|
-
var
|
|
28652
|
-
var
|
|
28837
|
+
var import_node_fs61 = require("fs");
|
|
28838
|
+
var import_node_path57 = require("path");
|
|
28653
28839
|
init_paths();
|
|
28654
28840
|
init_home_board();
|
|
28655
28841
|
var FILE = "home-board-pins.json";
|
|
28656
28842
|
var VERSION = 1;
|
|
28657
28843
|
function pinsFile() {
|
|
28658
|
-
return (0,
|
|
28844
|
+
return (0, import_node_path57.join)(appDataDir(), FILE);
|
|
28659
28845
|
}
|
|
28660
28846
|
function readDisk() {
|
|
28661
28847
|
const path = pinsFile();
|
|
28662
|
-
if (!(0,
|
|
28848
|
+
if (!(0, import_node_fs61.existsSync)(path)) return [];
|
|
28663
28849
|
try {
|
|
28664
|
-
const raw = JSON.parse((0,
|
|
28850
|
+
const raw = JSON.parse((0, import_node_fs61.readFileSync)(path, "utf8"));
|
|
28665
28851
|
if (raw?.version !== VERSION || !Array.isArray(raw.items)) return [];
|
|
28666
28852
|
return raw.items.filter((item) => item?.id && item.kind && item.ref);
|
|
28667
28853
|
} catch {
|
|
@@ -28669,8 +28855,8 @@ function readDisk() {
|
|
|
28669
28855
|
}
|
|
28670
28856
|
}
|
|
28671
28857
|
function writeDisk(items) {
|
|
28672
|
-
(0,
|
|
28673
|
-
(0,
|
|
28858
|
+
(0, import_node_fs61.mkdirSync)(appDataDir(), { recursive: true });
|
|
28859
|
+
(0, import_node_fs61.writeFileSync)(pinsFile(), JSON.stringify({ version: VERSION, items }, null, 2), "utf8");
|
|
28674
28860
|
}
|
|
28675
28861
|
function listBoardPins() {
|
|
28676
28862
|
return readDisk();
|
|
@@ -28691,7 +28877,7 @@ function homeBoardWorkspaceKey(workspaces) {
|
|
|
28691
28877
|
return workspaces.map((w) => w.path).filter(Boolean).sort().join("\n");
|
|
28692
28878
|
}
|
|
28693
28879
|
function cacheFile() {
|
|
28694
|
-
return (0,
|
|
28880
|
+
return (0, import_node_path58.join)(appDataDir(), "home-board-cache.json");
|
|
28695
28881
|
}
|
|
28696
28882
|
function emptyInputs() {
|
|
28697
28883
|
return {
|
|
@@ -28717,9 +28903,9 @@ function shouldCacheHomeBoardInputs(inputs) {
|
|
|
28717
28903
|
}
|
|
28718
28904
|
function readDiskCache() {
|
|
28719
28905
|
const path = cacheFile();
|
|
28720
|
-
if (!(0,
|
|
28906
|
+
if (!(0, import_node_fs62.existsSync)(path)) return null;
|
|
28721
28907
|
try {
|
|
28722
|
-
const raw = JSON.parse((0,
|
|
28908
|
+
const raw = JSON.parse((0, import_node_fs62.readFileSync)(path, "utf8"));
|
|
28723
28909
|
if (raw?.version !== CACHE_VERSION || typeof raw.fetchedAt !== "number") {
|
|
28724
28910
|
return null;
|
|
28725
28911
|
}
|
|
@@ -28733,8 +28919,8 @@ function readDiskCache() {
|
|
|
28733
28919
|
}
|
|
28734
28920
|
function writeDiskCache(entry) {
|
|
28735
28921
|
try {
|
|
28736
|
-
(0,
|
|
28737
|
-
(0,
|
|
28922
|
+
(0, import_node_fs62.mkdirSync)(appDataDir(), { recursive: true });
|
|
28923
|
+
(0, import_node_fs62.writeFileSync)(cacheFile(), JSON.stringify(entry), "utf8");
|
|
28738
28924
|
} catch {
|
|
28739
28925
|
}
|
|
28740
28926
|
}
|
|
@@ -28958,14 +29144,14 @@ function orchCreateThreadAgentNote(input) {
|
|
|
28958
29144
|
var MAX_ORCH_THREADS = 5;
|
|
28959
29145
|
var CREATE_THREAD_TIMEOUT_MS = 9e4;
|
|
28960
29146
|
function withTimeout2(promise, ms, label) {
|
|
28961
|
-
return new Promise((
|
|
29147
|
+
return new Promise((resolve2, reject) => {
|
|
28962
29148
|
const timer = setTimeout(() => {
|
|
28963
29149
|
reject(new Error(`${label} timed out after ${Math.round(ms / 1e3)}s`));
|
|
28964
29150
|
}, ms);
|
|
28965
29151
|
promise.then(
|
|
28966
29152
|
(value) => {
|
|
28967
29153
|
clearTimeout(timer);
|
|
28968
|
-
|
|
29154
|
+
resolve2(value);
|
|
28969
29155
|
},
|
|
28970
29156
|
(err) => {
|
|
28971
29157
|
clearTimeout(timer);
|
|
@@ -29137,7 +29323,7 @@ async function startMcpServer() {
|
|
|
29137
29323
|
async () => {
|
|
29138
29324
|
const threads = orch.getThreads(true);
|
|
29139
29325
|
const lines = threads.map((t) => {
|
|
29140
|
-
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0,
|
|
29326
|
+
const repo = t.repoPath === GLOBAL_WORKSPACE_ID ? "Orchestration" : (0, import_node_path59.basename)(t.repoPath) || t.repoPath;
|
|
29141
29327
|
const live = orch.threadLooksLive(t) ? readTurnLive(t.id) : null;
|
|
29142
29328
|
const parent = t.parentThreadId ? ` parent:${t.parentThreadId.slice(0, 8)}` : "";
|
|
29143
29329
|
const preview = lastMessagePreview(t.messages, 80);
|