sisyphi 1.1.38 → 1.1.40
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/README.md +10 -0
- package/dist/cli.js +847 -468
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +251 -173
- package/dist/daemon.js.map +1 -1
- package/dist/tui.js +307 -160
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -336,7 +336,7 @@ var init_config = __esm({
|
|
|
336
336
|
},
|
|
337
337
|
companionPopup: true,
|
|
338
338
|
requiredPlugins: [
|
|
339
|
-
{ name: "devcore", marketplace: "crouton-kit" }
|
|
339
|
+
{ name: "devcore", marketplace: "crouton-kit", owner: "crouton-labs" }
|
|
340
340
|
]
|
|
341
341
|
};
|
|
342
342
|
}
|
|
@@ -2254,9 +2254,56 @@ var init_history = __esm({
|
|
|
2254
2254
|
}
|
|
2255
2255
|
});
|
|
2256
2256
|
|
|
2257
|
+
// src/shared/platform.ts
|
|
2258
|
+
import { execSync as execSync3 } from "child_process";
|
|
2259
|
+
import { existsSync as existsSync8, readFileSync as readFileSync10 } from "fs";
|
|
2260
|
+
function detectPlatform() {
|
|
2261
|
+
if (cachedPlatform) return cachedPlatform;
|
|
2262
|
+
if (process.platform === "darwin") {
|
|
2263
|
+
cachedPlatform = "darwin";
|
|
2264
|
+
} else if (process.platform === "win32") {
|
|
2265
|
+
cachedPlatform = "win32";
|
|
2266
|
+
} else if (process.platform === "linux") {
|
|
2267
|
+
cachedPlatform = isWsl() ? "wsl" : "linux";
|
|
2268
|
+
} else {
|
|
2269
|
+
cachedPlatform = "unknown";
|
|
2270
|
+
}
|
|
2271
|
+
return cachedPlatform;
|
|
2272
|
+
}
|
|
2273
|
+
function isWsl() {
|
|
2274
|
+
if (process.env["WSL_DISTRO_NAME"] || process.env["WSL_INTEROP"]) return true;
|
|
2275
|
+
try {
|
|
2276
|
+
if (existsSync8("/proc/version")) {
|
|
2277
|
+
const v = readFileSync10("/proc/version", "utf-8").toLowerCase();
|
|
2278
|
+
if (v.includes("microsoft") || v.includes("wsl")) return true;
|
|
2279
|
+
}
|
|
2280
|
+
} catch {
|
|
2281
|
+
}
|
|
2282
|
+
return false;
|
|
2283
|
+
}
|
|
2284
|
+
function hasCommand(cmd) {
|
|
2285
|
+
const cached = cmdCache.get(cmd);
|
|
2286
|
+
if (cached !== void 0) return cached;
|
|
2287
|
+
try {
|
|
2288
|
+
execSync3(`command -v ${cmd}`, { stdio: "pipe", shell: "/bin/sh" });
|
|
2289
|
+
cmdCache.set(cmd, true);
|
|
2290
|
+
return true;
|
|
2291
|
+
} catch {
|
|
2292
|
+
cmdCache.set(cmd, false);
|
|
2293
|
+
return false;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
var cachedPlatform, cmdCache;
|
|
2297
|
+
var init_platform = __esm({
|
|
2298
|
+
"src/shared/platform.ts"() {
|
|
2299
|
+
"use strict";
|
|
2300
|
+
cmdCache = /* @__PURE__ */ new Map();
|
|
2301
|
+
}
|
|
2302
|
+
});
|
|
2303
|
+
|
|
2257
2304
|
// src/daemon/notify.ts
|
|
2258
2305
|
import { spawn, execFile } from "child_process";
|
|
2259
|
-
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync5, existsSync as
|
|
2306
|
+
import { writeFileSync as writeFileSync8, mkdirSync as mkdirSync5, existsSync as existsSync9 } from "fs";
|
|
2260
2307
|
import { join as join11 } from "path";
|
|
2261
2308
|
import { homedir as homedir5 } from "os";
|
|
2262
2309
|
function ensureSwitchScript() {
|
|
@@ -2276,7 +2323,7 @@ function ensureNotifyProcess() {
|
|
|
2276
2323
|
return notifyProcess;
|
|
2277
2324
|
}
|
|
2278
2325
|
const binary = getNotifyBinary();
|
|
2279
|
-
if (!
|
|
2326
|
+
if (!existsSync9(binary)) {
|
|
2280
2327
|
return null;
|
|
2281
2328
|
}
|
|
2282
2329
|
notifyProcess = spawn(binary, [], {
|
|
@@ -2294,6 +2341,13 @@ function ensureNotifyProcess() {
|
|
|
2294
2341
|
notifyProcess.stderr?.unref();
|
|
2295
2342
|
return notifyProcess;
|
|
2296
2343
|
}
|
|
2344
|
+
function sendLinuxNotification(title, msg, level) {
|
|
2345
|
+
if (!hasCommand("notify-send")) return false;
|
|
2346
|
+
const urgency = level === "urgent" ? "critical" : "normal";
|
|
2347
|
+
execFile("notify-send", ["--app-name=Sisyphus", `--urgency=${urgency}`, title, msg], () => {
|
|
2348
|
+
});
|
|
2349
|
+
return true;
|
|
2350
|
+
}
|
|
2297
2351
|
function sendTerminalNotification(titleOrOpts, message, tmuxSession, level) {
|
|
2298
2352
|
let title;
|
|
2299
2353
|
let msg;
|
|
@@ -2303,77 +2357,87 @@ function sendTerminalNotification(titleOrOpts, message, tmuxSession, level) {
|
|
|
2303
2357
|
title = titleOrOpts.title;
|
|
2304
2358
|
msg = titleOrOpts.message;
|
|
2305
2359
|
tmuxSess = titleOrOpts.tmuxSession;
|
|
2306
|
-
lvl = titleOrOpts.level
|
|
2360
|
+
lvl = titleOrOpts.level === void 0 ? "urgent" : titleOrOpts.level;
|
|
2307
2361
|
} else {
|
|
2308
2362
|
title = titleOrOpts;
|
|
2309
2363
|
msg = message;
|
|
2310
2364
|
tmuxSess = tmuxSession;
|
|
2311
|
-
lvl = level
|
|
2365
|
+
lvl = level === void 0 ? "urgent" : level;
|
|
2312
2366
|
}
|
|
2313
2367
|
if (tmuxSess) ensureSwitchScript();
|
|
2314
|
-
const
|
|
2315
|
-
if (
|
|
2316
|
-
const
|
|
2317
|
-
if (
|
|
2318
|
-
|
|
2368
|
+
const platform = detectPlatform();
|
|
2369
|
+
if (platform === "darwin") {
|
|
2370
|
+
const proc = ensureNotifyProcess();
|
|
2371
|
+
if (proc?.stdin?.writable) {
|
|
2372
|
+
const payload = { title, message: msg, level: lvl };
|
|
2373
|
+
if (tmuxSess) payload.tmuxSession = tmuxSess;
|
|
2374
|
+
proc.stdin.write(JSON.stringify(payload) + "\n");
|
|
2375
|
+
return;
|
|
2376
|
+
}
|
|
2377
|
+
const tnArgs = ["-title", title, "-message", msg];
|
|
2378
|
+
if (lvl === "urgent") tnArgs.push("-sound", "default");
|
|
2379
|
+
execFile("terminal-notifier", tnArgs, (err) => {
|
|
2380
|
+
if (err) {
|
|
2381
|
+
const soundClause = lvl === "urgent" ? ' sound name "default"' : "";
|
|
2382
|
+
execFile("osascript", [
|
|
2383
|
+
"-e",
|
|
2384
|
+
`display notification "${escapeAppleScript(msg)}" with title "${escapeAppleScript(title)}"${soundClause}`
|
|
2385
|
+
], () => {
|
|
2386
|
+
});
|
|
2387
|
+
}
|
|
2388
|
+
});
|
|
2389
|
+
return;
|
|
2390
|
+
}
|
|
2391
|
+
if (platform === "linux" || platform === "wsl") {
|
|
2392
|
+
sendLinuxNotification(title, msg, lvl);
|
|
2319
2393
|
return;
|
|
2320
2394
|
}
|
|
2321
|
-
const tnArgs = ["-title", title, "-message", msg];
|
|
2322
|
-
if (lvl === "urgent") tnArgs.push("-sound", "default");
|
|
2323
|
-
execFile("terminal-notifier", tnArgs, (err) => {
|
|
2324
|
-
if (err) {
|
|
2325
|
-
const soundClause = lvl === "urgent" ? ' sound name "default"' : "";
|
|
2326
|
-
execFile("osascript", [
|
|
2327
|
-
"-e",
|
|
2328
|
-
`display notification "${escapeAppleScript(msg)}" with title "${escapeAppleScript(title)}"${soundClause}`
|
|
2329
|
-
], () => {
|
|
2330
|
-
});
|
|
2331
|
-
}
|
|
2332
|
-
});
|
|
2333
2395
|
}
|
|
2334
2396
|
var TMUX_SOCKET, SWITCH_SCRIPT, notifyProcess;
|
|
2335
2397
|
var init_notify = __esm({
|
|
2336
2398
|
"src/daemon/notify.ts"() {
|
|
2337
2399
|
"use strict";
|
|
2338
2400
|
init_shell();
|
|
2401
|
+
init_platform();
|
|
2339
2402
|
TMUX_SOCKET = `/tmp/tmux-${process.getuid?.() ?? 0}/default`;
|
|
2340
2403
|
SWITCH_SCRIPT = [
|
|
2341
2404
|
"#!/bin/bash",
|
|
2342
2405
|
'SESSION="$1"',
|
|
2343
2406
|
`TMUX_SOCKET="${TMUX_SOCKET}"`,
|
|
2344
|
-
"TMUX=/opt/homebrew/bin/tmux",
|
|
2345
2407
|
"",
|
|
2346
2408
|
"# Find any attached client (user is likely on a different session)",
|
|
2347
|
-
`CLIENT_TTY=$(
|
|
2409
|
+
`CLIENT_TTY=$(tmux -S "$TMUX_SOCKET" list-clients -F '#{client_tty}' 2>/dev/null | head -1)`,
|
|
2348
2410
|
'[ -z "$CLIENT_TTY" ] && exit 0',
|
|
2349
2411
|
"",
|
|
2350
2412
|
"# Switch that client to the target session",
|
|
2351
|
-
'
|
|
2352
|
-
'
|
|
2413
|
+
'tmux -S "$TMUX_SOCKET" switch-client -c "$CLIENT_TTY" -t "$SESSION" 2>/dev/null',
|
|
2414
|
+
'tmux -S "$TMUX_SOCKET" select-window -t "$SESSION" 2>/dev/null',
|
|
2353
2415
|
"",
|
|
2354
|
-
"#
|
|
2355
|
-
|
|
2356
|
-
|
|
2357
|
-
'
|
|
2358
|
-
|
|
2359
|
-
"
|
|
2360
|
-
"
|
|
2361
|
-
"
|
|
2362
|
-
"
|
|
2363
|
-
"
|
|
2364
|
-
"
|
|
2365
|
-
|
|
2366
|
-
|
|
2367
|
-
"
|
|
2368
|
-
"
|
|
2369
|
-
"
|
|
2370
|
-
"
|
|
2371
|
-
"
|
|
2372
|
-
"
|
|
2373
|
-
"
|
|
2374
|
-
"
|
|
2375
|
-
"
|
|
2376
|
-
|
|
2416
|
+
"# macOS-only: bring iTerm2 to front and select the tab with this client",
|
|
2417
|
+
'if [ "$(uname -s)" = "Darwin" ] && command -v osascript >/dev/null 2>&1; then',
|
|
2418
|
+
` TTY_SHORT=$(echo "$CLIENT_TTY" | sed 's|/dev/||')`,
|
|
2419
|
+
' osascript -e "',
|
|
2420
|
+
' tell application \\"iTerm2\\"',
|
|
2421
|
+
" activate",
|
|
2422
|
+
" repeat with w in windows",
|
|
2423
|
+
" tell w",
|
|
2424
|
+
" repeat with t in tabs",
|
|
2425
|
+
" tell t",
|
|
2426
|
+
" repeat with s in sessions",
|
|
2427
|
+
" tell s",
|
|
2428
|
+
' if tty contains \\"$TTY_SHORT\\" then',
|
|
2429
|
+
" select t",
|
|
2430
|
+
" return",
|
|
2431
|
+
" end if",
|
|
2432
|
+
" end tell",
|
|
2433
|
+
" end repeat",
|
|
2434
|
+
" end tell",
|
|
2435
|
+
" end repeat",
|
|
2436
|
+
" end tell",
|
|
2437
|
+
" end repeat",
|
|
2438
|
+
" end tell",
|
|
2439
|
+
` " 2>/dev/null || osascript -e 'tell application "iTerm2" to activate' 2>/dev/null`,
|
|
2440
|
+
"fi",
|
|
2377
2441
|
""
|
|
2378
2442
|
].join("\n");
|
|
2379
2443
|
notifyProcess = null;
|
|
@@ -2381,7 +2445,7 @@ var init_notify = __esm({
|
|
|
2381
2445
|
});
|
|
2382
2446
|
|
|
2383
2447
|
// src/daemon/ask-store.ts
|
|
2384
|
-
import { existsSync as
|
|
2448
|
+
import { existsSync as existsSync10, mkdirSync as mkdirSync6, readFileSync as readFileSync11, readdirSync as readdirSync7 } from "fs";
|
|
2385
2449
|
function maybeNotifyOnAskCreated(cwd, sessionId, meta) {
|
|
2386
2450
|
if (process.env.NODE_ENV === "test" || process.env.SISYPHUS_DISABLE_NOTIFY === "1") return;
|
|
2387
2451
|
const isActionable = meta.kind !== void 0 && ACTIONABLE_KINDS.has(meta.kind);
|
|
@@ -2432,7 +2496,7 @@ function writeDecisions(cwd, sessionId, askId, deck) {
|
|
|
2432
2496
|
function readDecisions(cwd, sessionId, askId) {
|
|
2433
2497
|
const p = askDecisionsPath(cwd, sessionId, askId);
|
|
2434
2498
|
try {
|
|
2435
|
-
return JSON.parse(
|
|
2499
|
+
return JSON.parse(readFileSync11(p, { encoding: "utf-8" }));
|
|
2436
2500
|
} catch (_e) {
|
|
2437
2501
|
return null;
|
|
2438
2502
|
}
|
|
@@ -2445,10 +2509,10 @@ function writeOutput(cwd, sessionId, askId, responses, completedAt) {
|
|
|
2445
2509
|
}
|
|
2446
2510
|
function readMeta(cwd, sessionId, askId) {
|
|
2447
2511
|
const p = askMetaPath(cwd, sessionId, askId);
|
|
2448
|
-
if (!
|
|
2512
|
+
if (!existsSync10(p)) {
|
|
2449
2513
|
return null;
|
|
2450
2514
|
}
|
|
2451
|
-
return JSON.parse(
|
|
2515
|
+
return JSON.parse(readFileSync11(p, "utf-8"));
|
|
2452
2516
|
}
|
|
2453
2517
|
async function updateMeta(cwd, sessionId, askId, patch) {
|
|
2454
2518
|
return withLock(askId, () => {
|
|
@@ -2463,7 +2527,7 @@ async function updateMeta(cwd, sessionId, askId, patch) {
|
|
|
2463
2527
|
}
|
|
2464
2528
|
function listAsks(cwd, sessionId) {
|
|
2465
2529
|
const dir = askDir(cwd, sessionId);
|
|
2466
|
-
if (!
|
|
2530
|
+
if (!existsSync10(dir)) {
|
|
2467
2531
|
return [];
|
|
2468
2532
|
}
|
|
2469
2533
|
return readdirSync7(dir, { withFileTypes: true }).filter((e) => e.isDirectory()).map((e) => e.name);
|
|
@@ -2479,7 +2543,7 @@ function buildAutoResponses(deck) {
|
|
|
2479
2543
|
}
|
|
2480
2544
|
async function autoResolveAsk(cwd, sessionId, askId, deck) {
|
|
2481
2545
|
try {
|
|
2482
|
-
if (
|
|
2546
|
+
if (existsSync10(askOutputPath(cwd, sessionId, askId))) return false;
|
|
2483
2547
|
const d = deck ?? readDecisions(cwd, sessionId, askId);
|
|
2484
2548
|
if (!d) return false;
|
|
2485
2549
|
const responses = buildAutoResponses(d);
|
|
@@ -2512,7 +2576,7 @@ function listOpenAsksFor(cwd, sessionId, askedBy) {
|
|
|
2512
2576
|
if (meta.orphaned) continue;
|
|
2513
2577
|
if (!meta.blocking) continue;
|
|
2514
2578
|
if (meta.status !== "pending" && meta.status !== "in-progress") continue;
|
|
2515
|
-
if (
|
|
2579
|
+
if (existsSync10(askOutputPath(cwd, sessionId, askId))) continue;
|
|
2516
2580
|
out.push({ askId, status: meta.status, ...meta.title !== void 0 ? { title: meta.title } : {} });
|
|
2517
2581
|
}
|
|
2518
2582
|
return out;
|
|
@@ -2781,8 +2845,8 @@ var init_process = __esm({
|
|
|
2781
2845
|
});
|
|
2782
2846
|
|
|
2783
2847
|
// src/daemon/orphan-sweep.ts
|
|
2784
|
-
import { existsSync as
|
|
2785
|
-
import { execSync as
|
|
2848
|
+
import { existsSync as existsSync11 } from "fs";
|
|
2849
|
+
import { execSync as execSync4 } from "child_process";
|
|
2786
2850
|
function probePidLstart(pid, expectedLstart, psRunner = defaultPsRunner) {
|
|
2787
2851
|
try {
|
|
2788
2852
|
const lstart = psRunner(pid, execEnv());
|
|
@@ -2816,7 +2880,7 @@ async function capturePanePidLstart(paneId) {
|
|
|
2816
2880
|
async function sweepOrphans(registry) {
|
|
2817
2881
|
const reg = registry ?? loadSessionRegistry();
|
|
2818
2882
|
for (const [sessionId, cwd] of Object.entries(reg)) {
|
|
2819
|
-
if (!
|
|
2883
|
+
if (!existsSync11(statePath(cwd, sessionId))) continue;
|
|
2820
2884
|
try {
|
|
2821
2885
|
await sweepSessionAgents(cwd, sessionId);
|
|
2822
2886
|
await sweepSessionAsks(cwd, sessionId);
|
|
@@ -2879,13 +2943,13 @@ var init_orphan_sweep = __esm({
|
|
|
2879
2943
|
init_paths();
|
|
2880
2944
|
init_orphan_asks();
|
|
2881
2945
|
init_process();
|
|
2882
|
-
defaultPsRunner = (pid, env) =>
|
|
2946
|
+
defaultPsRunner = (pid, env) => execSync4(`ps -o lstart= -p ${pid}`, { encoding: "utf-8", env, stdio: ["ignore", "pipe", "ignore"] }).trim();
|
|
2883
2947
|
}
|
|
2884
2948
|
});
|
|
2885
2949
|
|
|
2886
2950
|
// src/daemon/agent.ts
|
|
2887
|
-
import { readFileSync as
|
|
2888
|
-
import { execSync as
|
|
2951
|
+
import { readFileSync as readFileSync12, writeFileSync as writeFileSync9, mkdirSync as mkdirSync7, readdirSync as readdirSync8, existsSync as existsSync12, unlinkSync } from "fs";
|
|
2952
|
+
import { execSync as execSync5 } from "child_process";
|
|
2889
2953
|
import { randomUUID as randomUUID3 } from "crypto";
|
|
2890
2954
|
import { resolve as resolve5, relative as relative2, dirname as dirname3, join as join12 } from "path";
|
|
2891
2955
|
function resetAgentCounterFromState(sessionId, agents) {
|
|
@@ -2906,7 +2970,7 @@ function renderAgentSuffix(sessionId, instruction, contextDirRel) {
|
|
|
2906
2970
|
const templatePath = resolve5(import.meta.dirname, "../templates/agent-suffix.md");
|
|
2907
2971
|
let template;
|
|
2908
2972
|
try {
|
|
2909
|
-
template =
|
|
2973
|
+
template = readFileSync12(templatePath, "utf-8");
|
|
2910
2974
|
} catch {
|
|
2911
2975
|
template = `# Sisyphus Agent
|
|
2912
2976
|
Session: {{SESSION_ID}}
|
|
@@ -2930,10 +2994,10 @@ function createAgentPlugin(cwd, sessionId, agentId, agentType, agentConfig) {
|
|
|
2930
2994
|
if (agentConfig?.filePath && agentType && agentType !== "worker") {
|
|
2931
2995
|
const shortName = agentType.replace(/^sisyphus:/, "");
|
|
2932
2996
|
const subAgentDir = join12(dirname3(agentConfig.filePath), shortName);
|
|
2933
|
-
if (
|
|
2997
|
+
if (existsSync12(subAgentDir)) {
|
|
2934
2998
|
for (const f of readdirSync8(subAgentDir)) {
|
|
2935
2999
|
if (f.endsWith(".md") && f !== "CLAUDE.md") {
|
|
2936
|
-
writeFileSync9(`${base}/agents/${f}`, substituteEnvVars(
|
|
3000
|
+
writeFileSync9(`${base}/agents/${f}`, substituteEnvVars(readFileSync12(join12(subAgentDir, f), "utf-8")), "utf-8");
|
|
2937
3001
|
}
|
|
2938
3002
|
}
|
|
2939
3003
|
}
|
|
@@ -3030,7 +3094,7 @@ ${instruction}`);
|
|
|
3030
3094
|
const sessionIdFlag = claudeSessionId ? ` --session-id "${claudeSessionId}"` : "";
|
|
3031
3095
|
const promptFlag = agentConfig?.frontmatter.systemPrompt === "replace" ? "--system-prompt" : "--append-system-prompt";
|
|
3032
3096
|
const siblingSettingsPath = agentConfig?.filePath ? agentConfig.filePath.replace(/\.md$/, ".settings.json") : null;
|
|
3033
|
-
const settingsFlag = siblingSettingsPath &&
|
|
3097
|
+
const settingsFlag = siblingSettingsPath && existsSync12(siblingSettingsPath) ? ` --settings "${siblingSettingsPath}"` : "";
|
|
3034
3098
|
mainCmd = `claude${permFlag} --effort ${effort}${modelFlag} --plugin-dir "${pluginPath}"${sessionIdFlag}${extraPluginFlags ? ` ${extraPluginFlags}` : ""}${settingsFlag} --name ${shellQuote(agentTitle)} ${promptFlag} "$(cat '${suffixFilePath}')" ${shellQuote(instruction)}`;
|
|
3035
3099
|
resumeArgs = `${permFlag.trimStart()} --effort ${effort}${modelFlag} --plugin-dir "${pluginPath}"${extraPluginFlags ? ` ${extraPluginFlags}` : ""}${settingsFlag}`;
|
|
3036
3100
|
}
|
|
@@ -3055,14 +3119,14 @@ async function spawnAgent(opts) {
|
|
|
3055
3119
|
const color = (agentConfig?.frontmatter.color ? normalizeTmuxColor(agentConfig.frontmatter.color) : null) ?? getNextColor(sessionId);
|
|
3056
3120
|
let cliToCheck = provider === "openai" ? "codex" : "claude";
|
|
3057
3121
|
try {
|
|
3058
|
-
|
|
3122
|
+
execSync5(`which ${cliToCheck}`, { stdio: "pipe", env: execEnv() });
|
|
3059
3123
|
} catch {
|
|
3060
3124
|
const fallback = agentConfig?.frontmatter.fallbackModel;
|
|
3061
3125
|
if (fallback) {
|
|
3062
3126
|
const fallbackProvider = detectProvider(fallback);
|
|
3063
3127
|
const fallbackCli = fallbackProvider === "openai" ? "codex" : "claude";
|
|
3064
3128
|
try {
|
|
3065
|
-
|
|
3129
|
+
execSync5(`which ${fallbackCli}`, { stdio: "pipe", env: execEnv() });
|
|
3066
3130
|
} catch {
|
|
3067
3131
|
throw new Error(`Neither ${cliToCheck} (model: ${agentConfig?.frontmatter.model}) nor ${fallbackCli} (fallback: ${fallback}) CLI found on PATH. Run \`sis admin doctor\` to diagnose.`);
|
|
3068
3132
|
}
|
|
@@ -3219,9 +3283,9 @@ async function handleAgentReport(cwd, sessionId, agentId, content) {
|
|
|
3219
3283
|
}
|
|
3220
3284
|
function gcBgTasks(cwd, sessionId, agentId) {
|
|
3221
3285
|
const file = `${sessionDir(cwd, sessionId)}/runtime/bg-tasks/${agentId}.txt`;
|
|
3222
|
-
if (!
|
|
3286
|
+
if (!existsSync12(file)) return;
|
|
3223
3287
|
try {
|
|
3224
|
-
const leftover =
|
|
3288
|
+
const leftover = readFileSync12(file, "utf-8").split("\n").map((s) => s.trim()).filter(Boolean);
|
|
3225
3289
|
if (leftover.length > 0) {
|
|
3226
3290
|
console.warn(`[bg-tasks] ${agentId} exited with ${leftover.length} untracked background task(s): ${leftover.join(", ")}`);
|
|
3227
3291
|
emitHistoryEvent(sessionId, "bg-tasks-leftover", { agentId, leftover });
|
|
@@ -3494,7 +3558,7 @@ var init_companion_types = __esm({
|
|
|
3494
3558
|
});
|
|
3495
3559
|
|
|
3496
3560
|
// src/daemon/companion-memory.ts
|
|
3497
|
-
import { existsSync as
|
|
3561
|
+
import { existsSync as existsSync13, mkdirSync as mkdirSync8, readFileSync as readFileSync13, renameSync as renameSync3, writeFileSync as writeFileSync10 } from "fs";
|
|
3498
3562
|
import { dirname as dirname4, join as join13 } from "path";
|
|
3499
3563
|
import { randomUUID as randomUUID4 } from "crypto";
|
|
3500
3564
|
import { z } from "zod";
|
|
@@ -3527,10 +3591,10 @@ function fillDefaults(state) {
|
|
|
3527
3591
|
}
|
|
3528
3592
|
function loadMemoryStrict() {
|
|
3529
3593
|
const path = resolvedMemoryPath();
|
|
3530
|
-
if (!
|
|
3594
|
+
if (!existsSync13(path)) return defaultMemoryState();
|
|
3531
3595
|
let raw;
|
|
3532
3596
|
try {
|
|
3533
|
-
raw =
|
|
3597
|
+
raw = readFileSync13(path, "utf-8");
|
|
3534
3598
|
} catch (err) {
|
|
3535
3599
|
throw new MemoryStoreParseError(err);
|
|
3536
3600
|
}
|
|
@@ -3971,7 +4035,7 @@ var init_companion_memory = __esm({
|
|
|
3971
4035
|
});
|
|
3972
4036
|
|
|
3973
4037
|
// src/daemon/companion.ts
|
|
3974
|
-
import { existsSync as
|
|
4038
|
+
import { existsSync as existsSync14, mkdirSync as mkdirSync9, readFileSync as readFileSync14, renameSync as renameSync4, writeFileSync as writeFileSync11 } from "fs";
|
|
3975
4039
|
import { randomUUID as randomUUID5 } from "crypto";
|
|
3976
4040
|
import { dirname as dirname5, join as join14 } from "path";
|
|
3977
4041
|
function welfordUpdate(stats, value) {
|
|
@@ -3995,12 +4059,12 @@ function zScore(value, stats, metric) {
|
|
|
3995
4059
|
}
|
|
3996
4060
|
function loadCompanion() {
|
|
3997
4061
|
const path = companionPath();
|
|
3998
|
-
if (!
|
|
4062
|
+
if (!existsSync14(path)) {
|
|
3999
4063
|
const state2 = createDefaultCompanion();
|
|
4000
4064
|
saveCompanion(state2);
|
|
4001
4065
|
return state2;
|
|
4002
4066
|
}
|
|
4003
|
-
const raw =
|
|
4067
|
+
const raw = readFileSync14(path, "utf-8");
|
|
4004
4068
|
const state = JSON.parse(raw);
|
|
4005
4069
|
return normalizeCompanion(state);
|
|
4006
4070
|
}
|
|
@@ -5739,7 +5803,7 @@ var init_companion_render = __esm({
|
|
|
5739
5803
|
});
|
|
5740
5804
|
|
|
5741
5805
|
// src/daemon/companion-popup.ts
|
|
5742
|
-
import { writeFileSync as writeFileSync12, readFileSync as
|
|
5806
|
+
import { writeFileSync as writeFileSync12, readFileSync as readFileSync15, unlinkSync as unlinkSync2, existsSync as existsSync15 } from "fs";
|
|
5743
5807
|
import { tmpdir } from "os";
|
|
5744
5808
|
import { join as join15, resolve as resolve6 } from "path";
|
|
5745
5809
|
function wrapText(text, width) {
|
|
@@ -5783,7 +5847,7 @@ function showCommentaryPopupQueue(pages) {
|
|
|
5783
5847
|
if (contentHeight > maxContentHeight) maxContentHeight = contentHeight;
|
|
5784
5848
|
writeFileSync12(`${POPUP_TMP_PREFIX}-${i}.txt`, content);
|
|
5785
5849
|
}
|
|
5786
|
-
const whipAvailable =
|
|
5850
|
+
const whipAvailable = existsSync15(WHIP_ANIMATION_PATH);
|
|
5787
5851
|
if (whipAvailable && maxContentHeight < WHIP_ANIMATION_ROWS + 2) {
|
|
5788
5852
|
maxContentHeight = WHIP_ANIMATION_ROWS + 2;
|
|
5789
5853
|
}
|
|
@@ -5857,7 +5921,7 @@ fi
|
|
|
5857
5921
|
}
|
|
5858
5922
|
let raw;
|
|
5859
5923
|
try {
|
|
5860
|
-
raw =
|
|
5924
|
+
raw = readFileSync15(POPUP_RESULT_PREFIX, "utf8").trim();
|
|
5861
5925
|
} catch {
|
|
5862
5926
|
return null;
|
|
5863
5927
|
} finally {
|
|
@@ -6328,7 +6392,7 @@ var init_pane_monitor = __esm({
|
|
|
6328
6392
|
});
|
|
6329
6393
|
|
|
6330
6394
|
// src/daemon/mode-notify.ts
|
|
6331
|
-
import { existsSync as
|
|
6395
|
+
import { existsSync as existsSync16 } from "fs";
|
|
6332
6396
|
import { ulid as ulid2 } from "ulid";
|
|
6333
6397
|
function capitalize(s) {
|
|
6334
6398
|
return s.length === 0 ? s : s[0].toUpperCase() + s.slice(1);
|
|
@@ -6350,7 +6414,7 @@ function findOpenModeTransitionAsk(cwd, sessionId) {
|
|
|
6350
6414
|
if (meta.modeTransition !== true) continue;
|
|
6351
6415
|
if (meta.status === "answered") continue;
|
|
6352
6416
|
if (meta.orphaned === true) continue;
|
|
6353
|
-
if (
|
|
6417
|
+
if (existsSync16(askOutputPath(cwd, sessionId, askId))) continue;
|
|
6354
6418
|
return askId;
|
|
6355
6419
|
}
|
|
6356
6420
|
return null;
|
|
@@ -6464,14 +6528,14 @@ var init_mode_notify = __esm({
|
|
|
6464
6528
|
});
|
|
6465
6529
|
|
|
6466
6530
|
// src/daemon/orchestrator.ts
|
|
6467
|
-
import { existsSync as
|
|
6468
|
-
import { execSync as
|
|
6531
|
+
import { existsSync as existsSync17, readdirSync as readdirSync10, readFileSync as readFileSync16, writeFileSync as writeFileSync13 } from "fs";
|
|
6532
|
+
import { execSync as execSync6 } from "child_process";
|
|
6469
6533
|
import { randomUUID as randomUUID6 } from "crypto";
|
|
6470
6534
|
import { resolve as resolve7, join as join16, relative as relative3 } from "path";
|
|
6471
6535
|
function detectRepos(cwd) {
|
|
6472
6536
|
const config = loadConfig(cwd);
|
|
6473
6537
|
const repos = [];
|
|
6474
|
-
if (
|
|
6538
|
+
if (existsSync17(join16(cwd, ".git"))) {
|
|
6475
6539
|
try {
|
|
6476
6540
|
repos.push(getRepoInfo(cwd, "."));
|
|
6477
6541
|
} catch {
|
|
@@ -6483,7 +6547,7 @@ function detectRepos(cwd) {
|
|
|
6483
6547
|
if (!entry.isDirectory()) continue;
|
|
6484
6548
|
if (entry.name.startsWith(".")) continue;
|
|
6485
6549
|
const childPath = join16(cwd, entry.name);
|
|
6486
|
-
if (
|
|
6550
|
+
if (existsSync17(join16(childPath, ".git"))) {
|
|
6487
6551
|
try {
|
|
6488
6552
|
repos.push(getRepoInfo(childPath, entry.name));
|
|
6489
6553
|
} catch {
|
|
@@ -6521,14 +6585,14 @@ function resolveOrchestratorSettings(cwd, sessionId) {
|
|
|
6521
6585
|
const bundled = resolve7(import.meta.dirname, "../templates/orchestrator-settings.json");
|
|
6522
6586
|
const projectSettings = projectOrchestratorSettingsPath(cwd);
|
|
6523
6587
|
const userSettings = userOrchestratorSettingsPath();
|
|
6524
|
-
const hasProject =
|
|
6525
|
-
const hasUser =
|
|
6588
|
+
const hasProject = existsSync17(projectSettings);
|
|
6589
|
+
const hasUser = existsSync17(userSettings);
|
|
6526
6590
|
if (!hasProject && !hasUser) return bundled;
|
|
6527
6591
|
let merged = {};
|
|
6528
6592
|
for (const path of [bundled, hasUser ? userSettings : null, hasProject ? projectSettings : null]) {
|
|
6529
|
-
if (!path || !
|
|
6593
|
+
if (!path || !existsSync17(path)) continue;
|
|
6530
6594
|
try {
|
|
6531
|
-
const parsed = JSON.parse(
|
|
6595
|
+
const parsed = JSON.parse(readFileSync16(path, "utf-8"));
|
|
6532
6596
|
merged = { ...merged, ...parsed };
|
|
6533
6597
|
} catch (err) {
|
|
6534
6598
|
console.warn(`[sisyphus] Failed to parse settings layer ${path}: ${err instanceof Error ? err.message : err}`);
|
|
@@ -6540,21 +6604,21 @@ function resolveOrchestratorSettings(cwd, sessionId) {
|
|
|
6540
6604
|
}
|
|
6541
6605
|
function loadOrchestratorPrompt(cwd, sessionId, mode) {
|
|
6542
6606
|
const projectPath = projectOrchestratorPromptPath(cwd);
|
|
6543
|
-
if (
|
|
6544
|
-
return
|
|
6607
|
+
if (existsSync17(projectPath)) {
|
|
6608
|
+
return readFileSync16(projectPath, "utf-8");
|
|
6545
6609
|
}
|
|
6546
6610
|
const userPath = userOrchestratorPromptPath();
|
|
6547
|
-
if (
|
|
6548
|
-
return
|
|
6611
|
+
if (existsSync17(userPath)) {
|
|
6612
|
+
return readFileSync16(userPath, "utf-8");
|
|
6549
6613
|
}
|
|
6550
6614
|
const basePath = resolve7(import.meta.dirname, "../templates/orchestrator-base.md");
|
|
6551
|
-
const base =
|
|
6615
|
+
const base = readFileSync16(basePath, "utf-8");
|
|
6552
6616
|
const modes = discoverOrchestratorModes(cwd);
|
|
6553
6617
|
const selected = modes.find((m) => m.name === mode) ?? modes.find((m) => m.name === "discovery");
|
|
6554
6618
|
if (!selected) {
|
|
6555
6619
|
throw new Error(`Unknown orchestrator mode '${mode}' and no fallback found. Available: ${modes.map((m) => m.name).join(", ")}`);
|
|
6556
6620
|
}
|
|
6557
|
-
const modeContent =
|
|
6621
|
+
const modeContent = readFileSync16(selected.filePath, "utf-8");
|
|
6558
6622
|
const modeBody = extractAgentBody(modeContent);
|
|
6559
6623
|
return base + "\n\n" + modeBody;
|
|
6560
6624
|
}
|
|
@@ -6572,7 +6636,7 @@ function buildCompletionContent(session) {
|
|
|
6572
6636
|
lines.push("");
|
|
6573
6637
|
}
|
|
6574
6638
|
const logsDirPath = logsDir(session.cwd, session.id);
|
|
6575
|
-
if (
|
|
6639
|
+
if (existsSync17(logsDirPath)) {
|
|
6576
6640
|
const logFiles = readdirSync10(logsDirPath).filter((f) => f.startsWith("cycle-") && f.endsWith(".md")).sort();
|
|
6577
6641
|
if (logFiles.length > 0) {
|
|
6578
6642
|
lines.push("### Cycle Logs\n");
|
|
@@ -6597,7 +6661,7 @@ function buildCompletionContent(session) {
|
|
|
6597
6661
|
while (j < entries.length && entries[j].idle && entries[j].mode === e.mode) j++;
|
|
6598
6662
|
const runEntries = entries.slice(i, j);
|
|
6599
6663
|
if (runEntries.length === 1) {
|
|
6600
|
-
const content =
|
|
6664
|
+
const content = readFileSync16(join16(logsDirPath, e.file), "utf-8").trim();
|
|
6601
6665
|
if (content) {
|
|
6602
6666
|
lines.push(content);
|
|
6603
6667
|
lines.push("");
|
|
@@ -6613,7 +6677,7 @@ function buildCompletionContent(session) {
|
|
|
6613
6677
|
}
|
|
6614
6678
|
i = j;
|
|
6615
6679
|
} else {
|
|
6616
|
-
const content =
|
|
6680
|
+
const content = readFileSync16(join16(logsDirPath, e.file), "utf-8").trim();
|
|
6617
6681
|
if (content) {
|
|
6618
6682
|
lines.push(content);
|
|
6619
6683
|
lines.push("");
|
|
@@ -6624,7 +6688,7 @@ function buildCompletionContent(session) {
|
|
|
6624
6688
|
}
|
|
6625
6689
|
}
|
|
6626
6690
|
const reportsDirPath = reportsDir(session.cwd, session.id);
|
|
6627
|
-
if (
|
|
6691
|
+
if (existsSync17(reportsDirPath)) {
|
|
6628
6692
|
const reportFiles = readdirSync10(reportsDirPath).filter((f) => f.endsWith(".md"));
|
|
6629
6693
|
if (reportFiles.length > 0) {
|
|
6630
6694
|
lines.push("### Detailed Reports\n");
|
|
@@ -6650,7 +6714,7 @@ ${session.context}
|
|
|
6650
6714
|
}
|
|
6651
6715
|
} else {
|
|
6652
6716
|
let ctxFiles = [];
|
|
6653
|
-
if (
|
|
6717
|
+
if (existsSync17(ctxDir)) {
|
|
6654
6718
|
ctxFiles = readdirSync10(ctxDir).filter((f) => f !== "CLAUDE.md");
|
|
6655
6719
|
}
|
|
6656
6720
|
if (ctxFiles.length > 0) {
|
|
@@ -6692,10 +6756,10 @@ ${agentLines}
|
|
|
6692
6756
|
}
|
|
6693
6757
|
}
|
|
6694
6758
|
const strategyFile = strategyPath(session.cwd, session.id);
|
|
6695
|
-
const strategyRef =
|
|
6696
|
-
const roadmapRef =
|
|
6759
|
+
const strategyRef = existsSync17(strategyFile) ? `@${relative3(session.cwd, strategyFile)}` : "(empty)";
|
|
6760
|
+
const roadmapRef = existsSync17(roadmapFile) ? `@${relative3(session.cwd, roadmapFile)}` : "(empty)";
|
|
6697
6761
|
const digestFile = digestPath(session.cwd, session.id);
|
|
6698
|
-
const digestRef =
|
|
6762
|
+
const digestRef = existsSync17(digestFile) ? `@${relative3(session.cwd, digestFile)}` : "(not yet created)";
|
|
6699
6763
|
const repos = detectRepos(session.cwd);
|
|
6700
6764
|
let repositoriesSection = "\n\n## Repositories\n";
|
|
6701
6765
|
if (repos.length === 0) {
|
|
@@ -6722,7 +6786,7 @@ ${agentLines}
|
|
|
6722
6786
|
}
|
|
6723
6787
|
}
|
|
6724
6788
|
const goalFile = goalPath(session.cwd, session.id);
|
|
6725
|
-
const goalContent =
|
|
6789
|
+
const goalContent = existsSync17(goalFile) ? readFileSync16(goalFile, "utf-8").trim() : session.task;
|
|
6726
6790
|
const modeContent = modeContentBuilders[mode]?.(session) ?? "";
|
|
6727
6791
|
return `## Goal
|
|
6728
6792
|
|
|
@@ -6747,7 +6811,7 @@ ${digestRef}
|
|
|
6747
6811
|
}
|
|
6748
6812
|
async function spawnOrchestrator(sessionId, cwd, windowId, message, forceMode) {
|
|
6749
6813
|
try {
|
|
6750
|
-
|
|
6814
|
+
execSync6("which claude", { stdio: "pipe", env: EXEC_ENV });
|
|
6751
6815
|
} catch {
|
|
6752
6816
|
throw new Error("Claude CLI not found on PATH. Run `sis admin doctor` to diagnose.");
|
|
6753
6817
|
}
|
|
@@ -6965,7 +7029,7 @@ var init_orchestrator = __esm({
|
|
|
6965
7029
|
});
|
|
6966
7030
|
|
|
6967
7031
|
// src/daemon/status-dots.ts
|
|
6968
|
-
import { readFileSync as
|
|
7032
|
+
import { readFileSync as readFileSync17 } from "fs";
|
|
6969
7033
|
function renderDots(dots) {
|
|
6970
7034
|
const sorted = [...dots].sort((a, b) => a.createdAt.localeCompare(b.createdAt));
|
|
6971
7035
|
return sorted.map((d) => {
|
|
@@ -6976,7 +7040,7 @@ function renderDots(dots) {
|
|
|
6976
7040
|
function readClaudeState(paneId) {
|
|
6977
7041
|
const numericId = paneId.replace("%", "");
|
|
6978
7042
|
try {
|
|
6979
|
-
const content =
|
|
7043
|
+
const content = readFileSync17(`${CLAUDE_STATE_DIR}/${numericId}`, "utf-8").trim();
|
|
6980
7044
|
if (content === "idle" || content === "processing" || content === "stopped") {
|
|
6981
7045
|
return content;
|
|
6982
7046
|
}
|
|
@@ -7158,7 +7222,7 @@ var init_manifest = __esm({
|
|
|
7158
7222
|
// src/shared/session-export.ts
|
|
7159
7223
|
import { execFile as execFile2 } from "child_process";
|
|
7160
7224
|
import { promisify } from "util";
|
|
7161
|
-
import { existsSync as
|
|
7225
|
+
import { existsSync as existsSync18, readFileSync as readFileSync18, mkdirSync as mkdirSync10, symlinkSync, rmSync as rmSync5, writeFileSync as writeFileSync14 } from "fs";
|
|
7162
7226
|
import { homedir as homedir6 } from "os";
|
|
7163
7227
|
import { join as join17 } from "path";
|
|
7164
7228
|
function sanitizeName(name) {
|
|
@@ -7170,7 +7234,7 @@ function buildOutputPath(label, dir) {
|
|
|
7170
7234
|
const base = `sisyphus-${label}-${date}`;
|
|
7171
7235
|
let candidate = join17(dir, `${base}.zip`);
|
|
7172
7236
|
let counter = 1;
|
|
7173
|
-
while (
|
|
7237
|
+
while (existsSync18(candidate)) {
|
|
7174
7238
|
counter++;
|
|
7175
7239
|
candidate = join17(dir, `${base}-${counter}.zip`);
|
|
7176
7240
|
}
|
|
@@ -7233,16 +7297,16 @@ async function exportSessionToZip(sessionId, cwd, options) {
|
|
|
7233
7297
|
const reveal = options?.reveal ?? true;
|
|
7234
7298
|
const sessDir = sessionDir(cwd, sessionId);
|
|
7235
7299
|
const histDir = historySessionDir(sessionId);
|
|
7236
|
-
const sessExists =
|
|
7237
|
-
const histExists =
|
|
7300
|
+
const sessExists = existsSync18(sessDir);
|
|
7301
|
+
const histExists = existsSync18(histDir);
|
|
7238
7302
|
if (!sessExists && !histExists) {
|
|
7239
7303
|
throw new Error(`No data found for session ${sessionId}`);
|
|
7240
7304
|
}
|
|
7241
7305
|
let label = sessionId.slice(0, 8);
|
|
7242
7306
|
const stPath = statePath(cwd, sessionId);
|
|
7243
|
-
if (
|
|
7307
|
+
if (existsSync18(stPath)) {
|
|
7244
7308
|
try {
|
|
7245
|
-
const state = JSON.parse(
|
|
7309
|
+
const state = JSON.parse(readFileSync18(stPath, "utf-8"));
|
|
7246
7310
|
if (state.name) {
|
|
7247
7311
|
label = sanitizeName(state.name);
|
|
7248
7312
|
}
|
|
@@ -7363,12 +7427,12 @@ var init_uploader = __esm({
|
|
|
7363
7427
|
});
|
|
7364
7428
|
|
|
7365
7429
|
// src/shared/version.ts
|
|
7366
|
-
import { readFileSync as
|
|
7430
|
+
import { readFileSync as readFileSync19 } from "fs";
|
|
7367
7431
|
import { resolve as resolve8 } from "path";
|
|
7368
7432
|
function readSisyphusVersion() {
|
|
7369
7433
|
for (const rel of ["../package.json", "../../package.json"]) {
|
|
7370
7434
|
try {
|
|
7371
|
-
const raw =
|
|
7435
|
+
const raw = readFileSync19(resolve8(import.meta.dirname, rel), "utf-8");
|
|
7372
7436
|
const pkg = JSON.parse(raw);
|
|
7373
7437
|
if (pkg.name === "sisyphi" && pkg.version) return pkg.version;
|
|
7374
7438
|
} catch {
|
|
@@ -7406,14 +7470,28 @@ function formatDuration2(startOrMs, endIso) {
|
|
|
7406
7470
|
if (minutes > 0) return `${minutes}m${seconds}s`;
|
|
7407
7471
|
return `${seconds}s`;
|
|
7408
7472
|
}
|
|
7473
|
+
function wrap(open, close = "\x1B[0m") {
|
|
7474
|
+
return (s) => COLOR_ENABLED ? `${open}${s}${close}` : s;
|
|
7475
|
+
}
|
|
7476
|
+
var COLOR_ENABLED, bold, dim, red, green, yellow, cyan, gray, magenta, white;
|
|
7409
7477
|
var init_format = __esm({
|
|
7410
7478
|
"src/shared/format.ts"() {
|
|
7411
7479
|
"use strict";
|
|
7480
|
+
COLOR_ENABLED = process.env["FORCE_COLOR"] === "1" || process.stdout.isTTY === true && process.env["NO_COLOR"] === void 0 && process.env["TERM"] !== "dumb";
|
|
7481
|
+
bold = wrap("\x1B[1m");
|
|
7482
|
+
dim = wrap("\x1B[2m");
|
|
7483
|
+
red = wrap("\x1B[31m");
|
|
7484
|
+
green = wrap("\x1B[32m");
|
|
7485
|
+
yellow = wrap("\x1B[33m");
|
|
7486
|
+
cyan = wrap("\x1B[36m");
|
|
7487
|
+
gray = wrap("\x1B[90m");
|
|
7488
|
+
magenta = wrap("\x1B[35m");
|
|
7489
|
+
white = wrap("\x1B[37m");
|
|
7412
7490
|
}
|
|
7413
7491
|
});
|
|
7414
7492
|
|
|
7415
7493
|
// src/cli/deploy/creds.ts
|
|
7416
|
-
import { chmodSync, existsSync as
|
|
7494
|
+
import { chmodSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync20 } from "fs";
|
|
7417
7495
|
import { createInterface } from "readline";
|
|
7418
7496
|
function isValidProvider(value) {
|
|
7419
7497
|
return PROVIDERS.includes(value);
|
|
@@ -7454,12 +7532,12 @@ var init_pricing = __esm({
|
|
|
7454
7532
|
});
|
|
7455
7533
|
|
|
7456
7534
|
// src/cli/deploy/runtime.ts
|
|
7457
|
-
import { existsSync as
|
|
7535
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21, unlinkSync as unlinkSync3 } from "fs";
|
|
7458
7536
|
function readRuntimeState(provider) {
|
|
7459
7537
|
const path = deployRuntimePath(provider);
|
|
7460
|
-
if (!
|
|
7538
|
+
if (!existsSync20(path)) return null;
|
|
7461
7539
|
try {
|
|
7462
|
-
return JSON.parse(
|
|
7540
|
+
return JSON.parse(readFileSync21(path, "utf-8"));
|
|
7463
7541
|
} catch {
|
|
7464
7542
|
return null;
|
|
7465
7543
|
}
|
|
@@ -7481,15 +7559,15 @@ var init_tailnet = __esm({
|
|
|
7481
7559
|
});
|
|
7482
7560
|
|
|
7483
7561
|
// src/cli/deploy/templates.ts
|
|
7484
|
-
import { existsSync as
|
|
7562
|
+
import { existsSync as existsSync21 } from "fs";
|
|
7485
7563
|
import { dirname as dirname6, resolve as resolve9 } from "path";
|
|
7486
7564
|
import { fileURLToPath } from "url";
|
|
7487
7565
|
function deployRoot() {
|
|
7488
7566
|
const here = dirname6(fileURLToPath(import.meta.url));
|
|
7489
7567
|
const bundled = resolve9(here, "..", "deploy");
|
|
7490
|
-
if (
|
|
7568
|
+
if (existsSync21(bundled)) return bundled;
|
|
7491
7569
|
const sourceRoot = resolve9(here, "..", "..", "..", "deploy");
|
|
7492
|
-
if (
|
|
7570
|
+
if (existsSync21(sourceRoot)) return sourceRoot;
|
|
7493
7571
|
throw new Error(
|
|
7494
7572
|
`Could not locate deploy/ templates. Looked at:
|
|
7495
7573
|
${bundled}
|
|
@@ -7518,7 +7596,7 @@ var init_tailscale = __esm({
|
|
|
7518
7596
|
|
|
7519
7597
|
// src/cli/deploy/runner.ts
|
|
7520
7598
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
7521
|
-
import { copyFileSync as copyFileSync5, existsSync as
|
|
7599
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync22 } from "fs";
|
|
7522
7600
|
function readOutputs(provider) {
|
|
7523
7601
|
const result = spawnSync("terraform", ["output", "-json", `-state=${deployStatePath(provider)}`], {
|
|
7524
7602
|
cwd: providerModuleDir(provider),
|
|
@@ -7544,7 +7622,7 @@ function readOutputs(provider) {
|
|
|
7544
7622
|
}
|
|
7545
7623
|
}
|
|
7546
7624
|
function isProvisioned(provider) {
|
|
7547
|
-
if (!
|
|
7625
|
+
if (!existsSync22(deployStatePath(provider))) return false;
|
|
7548
7626
|
return readOutputs(provider) !== null;
|
|
7549
7627
|
}
|
|
7550
7628
|
function effectiveSshTarget(provider) {
|
|
@@ -7663,7 +7741,7 @@ var init_grove = __esm({
|
|
|
7663
7741
|
|
|
7664
7742
|
// src/cli/cloud/repo.ts
|
|
7665
7743
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
7666
|
-
import { existsSync as
|
|
7744
|
+
import { existsSync as existsSync23 } from "fs";
|
|
7667
7745
|
import { basename as basename5, join as join18 } from "path";
|
|
7668
7746
|
function captureGit(args, cwd) {
|
|
7669
7747
|
const result = spawnSync3("git", args, {
|
|
@@ -7704,10 +7782,10 @@ function buildRsyncArgs(localDir, remoteTarget) {
|
|
|
7704
7782
|
];
|
|
7705
7783
|
}
|
|
7706
7784
|
function detectPackageManager(toplevel) {
|
|
7707
|
-
if (
|
|
7708
|
-
if (
|
|
7709
|
-
if (
|
|
7710
|
-
if (
|
|
7785
|
+
if (existsSync23(join18(toplevel, "pnpm-lock.yaml"))) return "pnpm";
|
|
7786
|
+
if (existsSync23(join18(toplevel, "bun.lockb"))) return "bun";
|
|
7787
|
+
if (existsSync23(join18(toplevel, "yarn.lock"))) return "yarn";
|
|
7788
|
+
if (existsSync23(join18(toplevel, "package-lock.json"))) return "npm";
|
|
7711
7789
|
return null;
|
|
7712
7790
|
}
|
|
7713
7791
|
function packageManagerInstallCmd(pm) {
|
|
@@ -7908,7 +7986,7 @@ __export(cloud_handoff_exports, {
|
|
|
7908
7986
|
triggerForceHandoff: () => triggerForceHandoff
|
|
7909
7987
|
});
|
|
7910
7988
|
import { spawn as spawn5 } from "child_process";
|
|
7911
|
-
import { existsSync as
|
|
7989
|
+
import { existsSync as existsSync24 } from "fs";
|
|
7912
7990
|
import { join as join19 } from "path";
|
|
7913
7991
|
function runRsync2(args) {
|
|
7914
7992
|
return new Promise((resolve13) => {
|
|
@@ -7948,7 +8026,7 @@ async function syncSessionState(cwd, sessionId, repo, target, provider) {
|
|
|
7948
8026
|
const candidates = ["config.json", "orchestrator.md", "orchestrator-settings.json"];
|
|
7949
8027
|
for (const name of candidates) {
|
|
7950
8028
|
const localPath = join19(localProject, name);
|
|
7951
|
-
if (!
|
|
8029
|
+
if (!existsSync24(localPath)) continue;
|
|
7952
8030
|
const remotePath = `${boxRepoPath(repo)}/.sisyphus/${name}`;
|
|
7953
8031
|
const args = [
|
|
7954
8032
|
"-avz",
|
|
@@ -8115,14 +8193,14 @@ var init_cloud_handoff = __esm({
|
|
|
8115
8193
|
|
|
8116
8194
|
// src/daemon/session-manager.ts
|
|
8117
8195
|
import { v4 as uuidv4 } from "uuid";
|
|
8118
|
-
import { existsSync as
|
|
8196
|
+
import { existsSync as existsSync25, readFileSync as readFileSync23, readdirSync as readdirSync11, rmSync as rmSync6 } from "fs";
|
|
8119
8197
|
function truncate(s, max) {
|
|
8120
8198
|
return s.length <= max ? s : s.slice(0, max) + "...";
|
|
8121
8199
|
}
|
|
8122
8200
|
function readGoal(cwd, sessionId, fallback) {
|
|
8123
8201
|
try {
|
|
8124
8202
|
const p = goalPath(cwd, sessionId);
|
|
8125
|
-
if (
|
|
8203
|
+
if (existsSync25(p)) return readFileSync23(p, "utf-8").trim();
|
|
8126
8204
|
} catch {
|
|
8127
8205
|
}
|
|
8128
8206
|
return fallback;
|
|
@@ -8361,7 +8439,7 @@ It is the other session's responsibility. You do not need to monitor it.
|
|
|
8361
8439
|
function pruneOldSessions(cwd) {
|
|
8362
8440
|
try {
|
|
8363
8441
|
const dir = sessionsDir(cwd);
|
|
8364
|
-
if (!
|
|
8442
|
+
if (!existsSync25(dir)) return;
|
|
8365
8443
|
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
8366
8444
|
const candidates = [];
|
|
8367
8445
|
for (const entry of entries) {
|
|
@@ -8499,7 +8577,7 @@ function getSessionStatus(cwd, sessionId) {
|
|
|
8499
8577
|
}
|
|
8500
8578
|
function listSessions(cwd) {
|
|
8501
8579
|
const dir = sessionsDir(cwd);
|
|
8502
|
-
if (!
|
|
8580
|
+
if (!existsSync25(dir)) return [];
|
|
8503
8581
|
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
8504
8582
|
const sessions = [];
|
|
8505
8583
|
for (const entry of entries) {
|
|
@@ -8572,8 +8650,8 @@ function onAllAgentsDone2(sessionId, cwd, windowId) {
|
|
|
8572
8650
|
Agents: ${truncate(spawnedThisCycle, 200)}`;
|
|
8573
8651
|
try {
|
|
8574
8652
|
const logPath2 = cycleLogPath(cwd, sessionId, cycleNumber);
|
|
8575
|
-
if (
|
|
8576
|
-
const log =
|
|
8653
|
+
if (existsSync25(logPath2)) {
|
|
8654
|
+
const log = readFileSync23(logPath2, "utf-8").trim();
|
|
8577
8655
|
if (log) cycleCtx += `
|
|
8578
8656
|
Cycle log: ${truncate(log, 200)}`;
|
|
8579
8657
|
}
|
|
@@ -9205,7 +9283,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
9205
9283
|
import {
|
|
9206
9284
|
closeSync as closeSync2,
|
|
9207
9285
|
constants,
|
|
9208
|
-
existsSync as
|
|
9286
|
+
existsSync as existsSync26,
|
|
9209
9287
|
fstatSync as fstatSync2,
|
|
9210
9288
|
lstatSync,
|
|
9211
9289
|
openSync as openSync2,
|
|
@@ -9226,7 +9304,7 @@ async function generateVisualForQuestion(opts) {
|
|
|
9226
9304
|
if (!question) return { ok: false, error: `qid ${opts.qid} not found in decisions` };
|
|
9227
9305
|
const mdPath = askVisualMarkdownPath(opts.cwd, opts.sessionId, opts.askId, opts.qid);
|
|
9228
9306
|
const ansiPath = askVisualAnsiPath(opts.cwd, opts.sessionId, opts.askId, opts.qid);
|
|
9229
|
-
if (!opts.force &&
|
|
9307
|
+
if (!opts.force && existsSync26(mdPath) && existsSync26(ansiPath)) {
|
|
9230
9308
|
return { ok: true, markdownPath: mdPath, ansiPath, turns: 0 };
|
|
9231
9309
|
}
|
|
9232
9310
|
if (opts.force) {
|
|
@@ -9300,7 +9378,7 @@ function buildUserPrompt(q, askedBy, ctx) {
|
|
|
9300
9378
|
}
|
|
9301
9379
|
function readSystemPrompt() {
|
|
9302
9380
|
if (cachedSystemPrompt !== void 0) return cachedSystemPrompt;
|
|
9303
|
-
const found = SYSTEM_PROMPT_CANDIDATES.find((p) =>
|
|
9381
|
+
const found = SYSTEM_PROMPT_CANDIDATES.find((p) => existsSync26(p));
|
|
9304
9382
|
if (found === void 0) {
|
|
9305
9383
|
throw new Error(
|
|
9306
9384
|
`termrender-haiku-system.md not found in any candidate location: ${SYSTEM_PROMPT_CANDIDATES.join(", ")}`
|
|
@@ -9476,7 +9554,7 @@ var init_ask_visual = __esm({
|
|
|
9476
9554
|
|
|
9477
9555
|
// src/daemon/server.ts
|
|
9478
9556
|
import { createServer } from "net";
|
|
9479
|
-
import { unlinkSync as unlinkSync4, existsSync as
|
|
9557
|
+
import { unlinkSync as unlinkSync4, existsSync as existsSync27, writeFileSync as writeFileSync15, readFileSync as readFileSync25, mkdirSync as mkdirSync13, readdirSync as readdirSync12, rmSync as rmSync8, chmodSync as chmodSync2 } from "fs";
|
|
9480
9558
|
import { join as join21 } from "path";
|
|
9481
9559
|
function setCompositor(c) {
|
|
9482
9560
|
compositor = c;
|
|
@@ -9495,9 +9573,9 @@ function persistSessionRegistry() {
|
|
|
9495
9573
|
}
|
|
9496
9574
|
function loadSessionRegistry() {
|
|
9497
9575
|
const p = registryPath();
|
|
9498
|
-
if (!
|
|
9576
|
+
if (!existsSync27(p)) return {};
|
|
9499
9577
|
try {
|
|
9500
|
-
return JSON.parse(
|
|
9578
|
+
return JSON.parse(readFileSync25(p, "utf-8"));
|
|
9501
9579
|
} catch (err) {
|
|
9502
9580
|
console.warn("[sisyphus] Failed to parse session registry:", err instanceof Error ? err.message : err);
|
|
9503
9581
|
return {};
|
|
@@ -9544,7 +9622,7 @@ function collectAllSessionIds() {
|
|
|
9544
9622
|
scannedCwds.add(cwd);
|
|
9545
9623
|
try {
|
|
9546
9624
|
const dir = sessionsDir(cwd);
|
|
9547
|
-
if (!
|
|
9625
|
+
if (!existsSync27(dir)) continue;
|
|
9548
9626
|
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
9549
9627
|
if (entry.isDirectory() && !idToCwd.has(entry.name)) {
|
|
9550
9628
|
idToCwd.set(entry.name, cwd);
|
|
@@ -9745,7 +9823,7 @@ async function handleRequest(req) {
|
|
|
9745
9823
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9746
9824
|
if (!tracking) {
|
|
9747
9825
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9748
|
-
if (
|
|
9826
|
+
if (existsSync27(stateFile)) {
|
|
9749
9827
|
tracking = { cwd: req.cwd, messageCounter: 0 };
|
|
9750
9828
|
sessionTrackingMap.set(req.sessionId, tracking);
|
|
9751
9829
|
persistSessionRegistry();
|
|
@@ -9760,7 +9838,7 @@ async function handleRequest(req) {
|
|
|
9760
9838
|
}
|
|
9761
9839
|
case "clear-orphan": {
|
|
9762
9840
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9763
|
-
if (!
|
|
9841
|
+
if (!existsSync27(stateFile)) {
|
|
9764
9842
|
return { ok: false, error: `Unknown session: ${req.sessionId}. No state.json at ${stateFile}.` };
|
|
9765
9843
|
}
|
|
9766
9844
|
await Promise.all([
|
|
@@ -9811,7 +9889,7 @@ async function handleRequest(req) {
|
|
|
9811
9889
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9812
9890
|
if (!tracking) {
|
|
9813
9891
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9814
|
-
if (
|
|
9892
|
+
if (existsSync27(stateFile)) {
|
|
9815
9893
|
registerSessionCwd(req.sessionId, req.cwd);
|
|
9816
9894
|
tracking = sessionTrackingMap.get(req.sessionId);
|
|
9817
9895
|
} else {
|
|
@@ -9825,7 +9903,7 @@ async function handleRequest(req) {
|
|
|
9825
9903
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9826
9904
|
if (!tracking) {
|
|
9827
9905
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9828
|
-
if (
|
|
9906
|
+
if (existsSync27(stateFile)) {
|
|
9829
9907
|
registerSessionCwd(req.sessionId, req.cwd);
|
|
9830
9908
|
tracking = sessionTrackingMap.get(req.sessionId);
|
|
9831
9909
|
} else {
|
|
@@ -9842,7 +9920,7 @@ async function handleRequest(req) {
|
|
|
9842
9920
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9843
9921
|
if (!tracking) {
|
|
9844
9922
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9845
|
-
if (
|
|
9923
|
+
if (existsSync27(stateFile)) {
|
|
9846
9924
|
tracking = { cwd: req.cwd, messageCounter: 0 };
|
|
9847
9925
|
sessionTrackingMap.set(req.sessionId, tracking);
|
|
9848
9926
|
persistSessionRegistry();
|
|
@@ -9912,7 +9990,7 @@ async function handleRequest(req) {
|
|
|
9912
9990
|
}
|
|
9913
9991
|
case "set-upload-status": {
|
|
9914
9992
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9915
|
-
if (!
|
|
9993
|
+
if (!existsSync27(stateFile)) {
|
|
9916
9994
|
return unknownSessionError(req.sessionId);
|
|
9917
9995
|
}
|
|
9918
9996
|
try {
|
|
@@ -10207,7 +10285,7 @@ async function handleRequest(req) {
|
|
|
10207
10285
|
function startServer() {
|
|
10208
10286
|
return new Promise((resolve13, reject) => {
|
|
10209
10287
|
const sock = socketPath();
|
|
10210
|
-
if (
|
|
10288
|
+
if (existsSync27(sock)) {
|
|
10211
10289
|
unlinkSync4(sock);
|
|
10212
10290
|
}
|
|
10213
10291
|
server = createServer((conn) => {
|
|
@@ -10262,7 +10340,7 @@ function stopServer() {
|
|
|
10262
10340
|
}
|
|
10263
10341
|
server.close(() => {
|
|
10264
10342
|
const sock = socketPath();
|
|
10265
|
-
if (
|
|
10343
|
+
if (existsSync27(sock)) {
|
|
10266
10344
|
unlinkSync4(sock);
|
|
10267
10345
|
}
|
|
10268
10346
|
server = null;
|
|
@@ -10300,8 +10378,8 @@ init_paths();
|
|
|
10300
10378
|
init_config();
|
|
10301
10379
|
init_server();
|
|
10302
10380
|
init_orphan_sweep();
|
|
10303
|
-
import { mkdirSync as mkdirSync15, readFileSync as
|
|
10304
|
-
import { execSync as
|
|
10381
|
+
import { mkdirSync as mkdirSync15, readFileSync as readFileSync28, writeFileSync as writeFileSync17, unlinkSync as unlinkSync6, existsSync as existsSync31 } from "fs";
|
|
10382
|
+
import { execSync as execSync8 } from "child_process";
|
|
10305
10383
|
import { setTimeout as sleep } from "timers/promises";
|
|
10306
10384
|
|
|
10307
10385
|
// src/daemon/heartbeat-asks.ts
|
|
@@ -10310,7 +10388,7 @@ init_state();
|
|
|
10310
10388
|
init_server();
|
|
10311
10389
|
init_paths();
|
|
10312
10390
|
import { ulid as ulid3 } from "ulid";
|
|
10313
|
-
import { existsSync as
|
|
10391
|
+
import { existsSync as existsSync28 } from "fs";
|
|
10314
10392
|
var HEARTBEAT_ASKED_BY2 = "system:heartbeat";
|
|
10315
10393
|
var HEARTBEAT_THRESHOLD_MS = 60 * 60 * 1e3;
|
|
10316
10394
|
var HEARTBEAT_SCAN_INTERVAL_MS = 15 * 60 * 1e3;
|
|
@@ -10393,7 +10471,7 @@ async function scanSessionForStaleAsks(cwd, sessionId) {
|
|
|
10393
10471
|
async function scanAllSessionsForStaleAsks() {
|
|
10394
10472
|
const reg = loadSessionRegistry();
|
|
10395
10473
|
for (const [sessionId, cwd] of Object.entries(reg)) {
|
|
10396
|
-
if (!
|
|
10474
|
+
if (!existsSync28(statePath(cwd, sessionId))) continue;
|
|
10397
10475
|
try {
|
|
10398
10476
|
await scanSessionForStaleAsks(cwd, sessionId);
|
|
10399
10477
|
} catch (err) {
|
|
@@ -10458,15 +10536,15 @@ init_status_dots();
|
|
|
10458
10536
|
init_companion();
|
|
10459
10537
|
init_exec();
|
|
10460
10538
|
init_shell();
|
|
10461
|
-
import { readFileSync as
|
|
10539
|
+
import { readFileSync as readFileSync26, existsSync as existsSync29 } from "fs";
|
|
10462
10540
|
import { homedir as homedir8 } from "os";
|
|
10463
10541
|
import { join as join22 } from "path";
|
|
10464
10542
|
var STATUS_BAR_BG = "#1d1e21";
|
|
10465
10543
|
var SESSION_ORDER_PATH = join22(homedir8(), ".config", "tmux", "session-order");
|
|
10466
10544
|
function getSessionOrder() {
|
|
10467
10545
|
try {
|
|
10468
|
-
if (!
|
|
10469
|
-
return
|
|
10546
|
+
if (!existsSync29(SESSION_ORDER_PATH)) return [];
|
|
10547
|
+
return readFileSync26(SESSION_ORDER_PATH, "utf-8").split("\n").filter(Boolean);
|
|
10470
10548
|
} catch {
|
|
10471
10549
|
return [];
|
|
10472
10550
|
}
|
|
@@ -11020,7 +11098,7 @@ init_state();
|
|
|
11020
11098
|
// src/daemon/updater.ts
|
|
11021
11099
|
init_paths();
|
|
11022
11100
|
init_version();
|
|
11023
|
-
import { execSync as
|
|
11101
|
+
import { execSync as execSync7 } from "child_process";
|
|
11024
11102
|
import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync5, lstatSync as lstatSync2 } from "fs";
|
|
11025
11103
|
import { resolve as resolve11 } from "path";
|
|
11026
11104
|
import { get } from "https";
|
|
@@ -11072,8 +11150,8 @@ function applyUpdate(expectedVersion) {
|
|
|
11072
11150
|
try {
|
|
11073
11151
|
const nodeDir = resolve11(process.execPath, "..");
|
|
11074
11152
|
const env = { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` };
|
|
11075
|
-
|
|
11076
|
-
const result =
|
|
11153
|
+
execSync7("npm install -g sisyphi", { timeout: 15e3, stdio: "pipe", env });
|
|
11154
|
+
const result = execSync7("npm ls -g sisyphi --json --depth=0", {
|
|
11077
11155
|
timeout: 5e3,
|
|
11078
11156
|
encoding: "utf-8",
|
|
11079
11157
|
env
|
|
@@ -11105,7 +11183,7 @@ function clearUpdating() {
|
|
|
11105
11183
|
function isLinkedInstall() {
|
|
11106
11184
|
try {
|
|
11107
11185
|
const nodeDir = resolve11(process.execPath, "..");
|
|
11108
|
-
const globalPrefix =
|
|
11186
|
+
const globalPrefix = execSync7("npm prefix -g", { timeout: 5e3, encoding: "utf-8", env: { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` } }).trim();
|
|
11109
11187
|
const globalPkgDir = resolve11(globalPrefix, "lib", "node_modules", "sisyphi");
|
|
11110
11188
|
return lstatSync2(globalPkgDir).isSymbolicLink();
|
|
11111
11189
|
} catch {
|
|
@@ -11148,7 +11226,7 @@ function stopPeriodicUpdateCheck() {
|
|
|
11148
11226
|
}
|
|
11149
11227
|
|
|
11150
11228
|
// src/daemon/plugin-install.ts
|
|
11151
|
-
import { copyFileSync as copyFileSync6, mkdirSync as mkdirSync14, readdirSync as readdirSync13, statSync as statSync4, existsSync as
|
|
11229
|
+
import { copyFileSync as copyFileSync6, mkdirSync as mkdirSync14, readdirSync as readdirSync13, statSync as statSync4, existsSync as existsSync30, readFileSync as readFileSync27, chmodSync as chmodSync3 } from "fs";
|
|
11152
11230
|
import { join as join23, resolve as resolve12 } from "path";
|
|
11153
11231
|
import { homedir as homedir9 } from "os";
|
|
11154
11232
|
var PLUGIN_NAME = "sisyphus-tmux";
|
|
@@ -11162,7 +11240,7 @@ function copyDir(src, dest) {
|
|
|
11162
11240
|
copyDir(srcPath, destPath);
|
|
11163
11241
|
} else {
|
|
11164
11242
|
const srcMtime = statSync4(srcPath).mtimeMs;
|
|
11165
|
-
const destMtime =
|
|
11243
|
+
const destMtime = existsSync30(destPath) ? statSync4(destPath).mtimeMs : 0;
|
|
11166
11244
|
if (srcMtime > destMtime) {
|
|
11167
11245
|
copyFileSync6(srcPath, destPath);
|
|
11168
11246
|
}
|
|
@@ -11172,16 +11250,16 @@ function copyDir(src, dest) {
|
|
|
11172
11250
|
function pluginNeedsUpdate(sourceDir) {
|
|
11173
11251
|
const srcHooks = join23(sourceDir, "hooks", "hooks.json");
|
|
11174
11252
|
const destHooks = join23(INSTALL_DIR, "hooks", "hooks.json");
|
|
11175
|
-
if (!
|
|
11253
|
+
if (!existsSync30(destHooks)) return true;
|
|
11176
11254
|
try {
|
|
11177
|
-
return
|
|
11255
|
+
return readFileSync27(srcHooks, "utf-8") !== readFileSync27(destHooks, "utf-8");
|
|
11178
11256
|
} catch {
|
|
11179
11257
|
return true;
|
|
11180
11258
|
}
|
|
11181
11259
|
}
|
|
11182
11260
|
function installPlugin() {
|
|
11183
11261
|
const sourceDir = resolve12(import.meta.dirname, "../templates/sisyphus-tmux-plugin");
|
|
11184
|
-
if (!
|
|
11262
|
+
if (!existsSync30(sourceDir)) {
|
|
11185
11263
|
console.error(`[plugin-install] Source dir not found: ${sourceDir}`);
|
|
11186
11264
|
return;
|
|
11187
11265
|
}
|
|
@@ -11189,7 +11267,7 @@ function installPlugin() {
|
|
|
11189
11267
|
try {
|
|
11190
11268
|
copyDir(sourceDir, INSTALL_DIR);
|
|
11191
11269
|
const hookScript = join23(INSTALL_DIR, "hooks", "tmux-state.sh");
|
|
11192
|
-
if (
|
|
11270
|
+
if (existsSync30(hookScript)) {
|
|
11193
11271
|
try {
|
|
11194
11272
|
chmodSync3(hookScript, 493);
|
|
11195
11273
|
} catch {
|
|
@@ -11255,7 +11333,7 @@ function ensureDirs() {
|
|
|
11255
11333
|
function readPid() {
|
|
11256
11334
|
const pidFile = daemonPidPath();
|
|
11257
11335
|
try {
|
|
11258
|
-
const pid = parseInt(
|
|
11336
|
+
const pid = parseInt(readFileSync28(pidFile, "utf-8").trim(), 10);
|
|
11259
11337
|
return pid && isProcessAlive(pid) ? pid : null;
|
|
11260
11338
|
} catch {
|
|
11261
11339
|
return null;
|
|
@@ -11271,7 +11349,7 @@ function acquirePidLock() {
|
|
|
11271
11349
|
}
|
|
11272
11350
|
function isLaunchdManaged() {
|
|
11273
11351
|
try {
|
|
11274
|
-
|
|
11352
|
+
execSync8("launchctl list com.sisyphus.daemon", { stdio: "pipe" });
|
|
11275
11353
|
return true;
|
|
11276
11354
|
} catch {
|
|
11277
11355
|
return false;
|
|
@@ -11326,11 +11404,11 @@ async function recoverSessions() {
|
|
|
11326
11404
|
let recovered = 0;
|
|
11327
11405
|
for (const [sessionId, cwd] of entries) {
|
|
11328
11406
|
const stateFile = statePath(cwd, sessionId);
|
|
11329
|
-
if (!
|
|
11407
|
+
if (!existsSync31(stateFile)) {
|
|
11330
11408
|
continue;
|
|
11331
11409
|
}
|
|
11332
11410
|
try {
|
|
11333
|
-
const session = JSON.parse(
|
|
11411
|
+
const session = JSON.parse(readFileSync28(stateFile, "utf-8"));
|
|
11334
11412
|
if (session.status === "active" || session.status === "paused") {
|
|
11335
11413
|
registerSessionCwd(sessionId, cwd);
|
|
11336
11414
|
resetAgentCounterFromState(sessionId, session.agents ?? []);
|