sisyphi 1.1.38 → 1.1.39
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/cli.js +620 -311
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +236 -172
- package/dist/daemon.js.map +1 -1
- package/dist/tui.js +235 -102
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -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 {
|
|
@@ -7413,7 +7477,7 @@ var init_format = __esm({
|
|
|
7413
7477
|
});
|
|
7414
7478
|
|
|
7415
7479
|
// src/cli/deploy/creds.ts
|
|
7416
|
-
import { chmodSync, existsSync as
|
|
7480
|
+
import { chmodSync, existsSync as existsSync19, mkdirSync as mkdirSync11, readFileSync as readFileSync20 } from "fs";
|
|
7417
7481
|
import { createInterface } from "readline";
|
|
7418
7482
|
function isValidProvider(value) {
|
|
7419
7483
|
return PROVIDERS.includes(value);
|
|
@@ -7454,12 +7518,12 @@ var init_pricing = __esm({
|
|
|
7454
7518
|
});
|
|
7455
7519
|
|
|
7456
7520
|
// src/cli/deploy/runtime.ts
|
|
7457
|
-
import { existsSync as
|
|
7521
|
+
import { existsSync as existsSync20, readFileSync as readFileSync21, unlinkSync as unlinkSync3 } from "fs";
|
|
7458
7522
|
function readRuntimeState(provider) {
|
|
7459
7523
|
const path = deployRuntimePath(provider);
|
|
7460
|
-
if (!
|
|
7524
|
+
if (!existsSync20(path)) return null;
|
|
7461
7525
|
try {
|
|
7462
|
-
return JSON.parse(
|
|
7526
|
+
return JSON.parse(readFileSync21(path, "utf-8"));
|
|
7463
7527
|
} catch {
|
|
7464
7528
|
return null;
|
|
7465
7529
|
}
|
|
@@ -7481,15 +7545,15 @@ var init_tailnet = __esm({
|
|
|
7481
7545
|
});
|
|
7482
7546
|
|
|
7483
7547
|
// src/cli/deploy/templates.ts
|
|
7484
|
-
import { existsSync as
|
|
7548
|
+
import { existsSync as existsSync21 } from "fs";
|
|
7485
7549
|
import { dirname as dirname6, resolve as resolve9 } from "path";
|
|
7486
7550
|
import { fileURLToPath } from "url";
|
|
7487
7551
|
function deployRoot() {
|
|
7488
7552
|
const here = dirname6(fileURLToPath(import.meta.url));
|
|
7489
7553
|
const bundled = resolve9(here, "..", "deploy");
|
|
7490
|
-
if (
|
|
7554
|
+
if (existsSync21(bundled)) return bundled;
|
|
7491
7555
|
const sourceRoot = resolve9(here, "..", "..", "..", "deploy");
|
|
7492
|
-
if (
|
|
7556
|
+
if (existsSync21(sourceRoot)) return sourceRoot;
|
|
7493
7557
|
throw new Error(
|
|
7494
7558
|
`Could not locate deploy/ templates. Looked at:
|
|
7495
7559
|
${bundled}
|
|
@@ -7518,7 +7582,7 @@ var init_tailscale = __esm({
|
|
|
7518
7582
|
|
|
7519
7583
|
// src/cli/deploy/runner.ts
|
|
7520
7584
|
import { spawn as spawn2, spawnSync } from "child_process";
|
|
7521
|
-
import { copyFileSync as copyFileSync5, existsSync as
|
|
7585
|
+
import { copyFileSync as copyFileSync5, existsSync as existsSync22, mkdirSync as mkdirSync12, readFileSync as readFileSync22 } from "fs";
|
|
7522
7586
|
function readOutputs(provider) {
|
|
7523
7587
|
const result = spawnSync("terraform", ["output", "-json", `-state=${deployStatePath(provider)}`], {
|
|
7524
7588
|
cwd: providerModuleDir(provider),
|
|
@@ -7544,7 +7608,7 @@ function readOutputs(provider) {
|
|
|
7544
7608
|
}
|
|
7545
7609
|
}
|
|
7546
7610
|
function isProvisioned(provider) {
|
|
7547
|
-
if (!
|
|
7611
|
+
if (!existsSync22(deployStatePath(provider))) return false;
|
|
7548
7612
|
return readOutputs(provider) !== null;
|
|
7549
7613
|
}
|
|
7550
7614
|
function effectiveSshTarget(provider) {
|
|
@@ -7663,7 +7727,7 @@ var init_grove = __esm({
|
|
|
7663
7727
|
|
|
7664
7728
|
// src/cli/cloud/repo.ts
|
|
7665
7729
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
7666
|
-
import { existsSync as
|
|
7730
|
+
import { existsSync as existsSync23 } from "fs";
|
|
7667
7731
|
import { basename as basename5, join as join18 } from "path";
|
|
7668
7732
|
function captureGit(args, cwd) {
|
|
7669
7733
|
const result = spawnSync3("git", args, {
|
|
@@ -7704,10 +7768,10 @@ function buildRsyncArgs(localDir, remoteTarget) {
|
|
|
7704
7768
|
];
|
|
7705
7769
|
}
|
|
7706
7770
|
function detectPackageManager(toplevel) {
|
|
7707
|
-
if (
|
|
7708
|
-
if (
|
|
7709
|
-
if (
|
|
7710
|
-
if (
|
|
7771
|
+
if (existsSync23(join18(toplevel, "pnpm-lock.yaml"))) return "pnpm";
|
|
7772
|
+
if (existsSync23(join18(toplevel, "bun.lockb"))) return "bun";
|
|
7773
|
+
if (existsSync23(join18(toplevel, "yarn.lock"))) return "yarn";
|
|
7774
|
+
if (existsSync23(join18(toplevel, "package-lock.json"))) return "npm";
|
|
7711
7775
|
return null;
|
|
7712
7776
|
}
|
|
7713
7777
|
function packageManagerInstallCmd(pm) {
|
|
@@ -7908,7 +7972,7 @@ __export(cloud_handoff_exports, {
|
|
|
7908
7972
|
triggerForceHandoff: () => triggerForceHandoff
|
|
7909
7973
|
});
|
|
7910
7974
|
import { spawn as spawn5 } from "child_process";
|
|
7911
|
-
import { existsSync as
|
|
7975
|
+
import { existsSync as existsSync24 } from "fs";
|
|
7912
7976
|
import { join as join19 } from "path";
|
|
7913
7977
|
function runRsync2(args) {
|
|
7914
7978
|
return new Promise((resolve13) => {
|
|
@@ -7948,7 +8012,7 @@ async function syncSessionState(cwd, sessionId, repo, target, provider) {
|
|
|
7948
8012
|
const candidates = ["config.json", "orchestrator.md", "orchestrator-settings.json"];
|
|
7949
8013
|
for (const name of candidates) {
|
|
7950
8014
|
const localPath = join19(localProject, name);
|
|
7951
|
-
if (!
|
|
8015
|
+
if (!existsSync24(localPath)) continue;
|
|
7952
8016
|
const remotePath = `${boxRepoPath(repo)}/.sisyphus/${name}`;
|
|
7953
8017
|
const args = [
|
|
7954
8018
|
"-avz",
|
|
@@ -8115,14 +8179,14 @@ var init_cloud_handoff = __esm({
|
|
|
8115
8179
|
|
|
8116
8180
|
// src/daemon/session-manager.ts
|
|
8117
8181
|
import { v4 as uuidv4 } from "uuid";
|
|
8118
|
-
import { existsSync as
|
|
8182
|
+
import { existsSync as existsSync25, readFileSync as readFileSync23, readdirSync as readdirSync11, rmSync as rmSync6 } from "fs";
|
|
8119
8183
|
function truncate(s, max) {
|
|
8120
8184
|
return s.length <= max ? s : s.slice(0, max) + "...";
|
|
8121
8185
|
}
|
|
8122
8186
|
function readGoal(cwd, sessionId, fallback) {
|
|
8123
8187
|
try {
|
|
8124
8188
|
const p = goalPath(cwd, sessionId);
|
|
8125
|
-
if (
|
|
8189
|
+
if (existsSync25(p)) return readFileSync23(p, "utf-8").trim();
|
|
8126
8190
|
} catch {
|
|
8127
8191
|
}
|
|
8128
8192
|
return fallback;
|
|
@@ -8361,7 +8425,7 @@ It is the other session's responsibility. You do not need to monitor it.
|
|
|
8361
8425
|
function pruneOldSessions(cwd) {
|
|
8362
8426
|
try {
|
|
8363
8427
|
const dir = sessionsDir(cwd);
|
|
8364
|
-
if (!
|
|
8428
|
+
if (!existsSync25(dir)) return;
|
|
8365
8429
|
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
8366
8430
|
const candidates = [];
|
|
8367
8431
|
for (const entry of entries) {
|
|
@@ -8499,7 +8563,7 @@ function getSessionStatus(cwd, sessionId) {
|
|
|
8499
8563
|
}
|
|
8500
8564
|
function listSessions(cwd) {
|
|
8501
8565
|
const dir = sessionsDir(cwd);
|
|
8502
|
-
if (!
|
|
8566
|
+
if (!existsSync25(dir)) return [];
|
|
8503
8567
|
const entries = readdirSync11(dir, { withFileTypes: true });
|
|
8504
8568
|
const sessions = [];
|
|
8505
8569
|
for (const entry of entries) {
|
|
@@ -8572,8 +8636,8 @@ function onAllAgentsDone2(sessionId, cwd, windowId) {
|
|
|
8572
8636
|
Agents: ${truncate(spawnedThisCycle, 200)}`;
|
|
8573
8637
|
try {
|
|
8574
8638
|
const logPath2 = cycleLogPath(cwd, sessionId, cycleNumber);
|
|
8575
|
-
if (
|
|
8576
|
-
const log =
|
|
8639
|
+
if (existsSync25(logPath2)) {
|
|
8640
|
+
const log = readFileSync23(logPath2, "utf-8").trim();
|
|
8577
8641
|
if (log) cycleCtx += `
|
|
8578
8642
|
Cycle log: ${truncate(log, 200)}`;
|
|
8579
8643
|
}
|
|
@@ -9205,7 +9269,7 @@ import { spawn as spawn6 } from "child_process";
|
|
|
9205
9269
|
import {
|
|
9206
9270
|
closeSync as closeSync2,
|
|
9207
9271
|
constants,
|
|
9208
|
-
existsSync as
|
|
9272
|
+
existsSync as existsSync26,
|
|
9209
9273
|
fstatSync as fstatSync2,
|
|
9210
9274
|
lstatSync,
|
|
9211
9275
|
openSync as openSync2,
|
|
@@ -9226,7 +9290,7 @@ async function generateVisualForQuestion(opts) {
|
|
|
9226
9290
|
if (!question) return { ok: false, error: `qid ${opts.qid} not found in decisions` };
|
|
9227
9291
|
const mdPath = askVisualMarkdownPath(opts.cwd, opts.sessionId, opts.askId, opts.qid);
|
|
9228
9292
|
const ansiPath = askVisualAnsiPath(opts.cwd, opts.sessionId, opts.askId, opts.qid);
|
|
9229
|
-
if (!opts.force &&
|
|
9293
|
+
if (!opts.force && existsSync26(mdPath) && existsSync26(ansiPath)) {
|
|
9230
9294
|
return { ok: true, markdownPath: mdPath, ansiPath, turns: 0 };
|
|
9231
9295
|
}
|
|
9232
9296
|
if (opts.force) {
|
|
@@ -9300,7 +9364,7 @@ function buildUserPrompt(q, askedBy, ctx) {
|
|
|
9300
9364
|
}
|
|
9301
9365
|
function readSystemPrompt() {
|
|
9302
9366
|
if (cachedSystemPrompt !== void 0) return cachedSystemPrompt;
|
|
9303
|
-
const found = SYSTEM_PROMPT_CANDIDATES.find((p) =>
|
|
9367
|
+
const found = SYSTEM_PROMPT_CANDIDATES.find((p) => existsSync26(p));
|
|
9304
9368
|
if (found === void 0) {
|
|
9305
9369
|
throw new Error(
|
|
9306
9370
|
`termrender-haiku-system.md not found in any candidate location: ${SYSTEM_PROMPT_CANDIDATES.join(", ")}`
|
|
@@ -9476,7 +9540,7 @@ var init_ask_visual = __esm({
|
|
|
9476
9540
|
|
|
9477
9541
|
// src/daemon/server.ts
|
|
9478
9542
|
import { createServer } from "net";
|
|
9479
|
-
import { unlinkSync as unlinkSync4, existsSync as
|
|
9543
|
+
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
9544
|
import { join as join21 } from "path";
|
|
9481
9545
|
function setCompositor(c) {
|
|
9482
9546
|
compositor = c;
|
|
@@ -9495,9 +9559,9 @@ function persistSessionRegistry() {
|
|
|
9495
9559
|
}
|
|
9496
9560
|
function loadSessionRegistry() {
|
|
9497
9561
|
const p = registryPath();
|
|
9498
|
-
if (!
|
|
9562
|
+
if (!existsSync27(p)) return {};
|
|
9499
9563
|
try {
|
|
9500
|
-
return JSON.parse(
|
|
9564
|
+
return JSON.parse(readFileSync25(p, "utf-8"));
|
|
9501
9565
|
} catch (err) {
|
|
9502
9566
|
console.warn("[sisyphus] Failed to parse session registry:", err instanceof Error ? err.message : err);
|
|
9503
9567
|
return {};
|
|
@@ -9544,7 +9608,7 @@ function collectAllSessionIds() {
|
|
|
9544
9608
|
scannedCwds.add(cwd);
|
|
9545
9609
|
try {
|
|
9546
9610
|
const dir = sessionsDir(cwd);
|
|
9547
|
-
if (!
|
|
9611
|
+
if (!existsSync27(dir)) continue;
|
|
9548
9612
|
for (const entry of readdirSync12(dir, { withFileTypes: true })) {
|
|
9549
9613
|
if (entry.isDirectory() && !idToCwd.has(entry.name)) {
|
|
9550
9614
|
idToCwd.set(entry.name, cwd);
|
|
@@ -9745,7 +9809,7 @@ async function handleRequest(req) {
|
|
|
9745
9809
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9746
9810
|
if (!tracking) {
|
|
9747
9811
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9748
|
-
if (
|
|
9812
|
+
if (existsSync27(stateFile)) {
|
|
9749
9813
|
tracking = { cwd: req.cwd, messageCounter: 0 };
|
|
9750
9814
|
sessionTrackingMap.set(req.sessionId, tracking);
|
|
9751
9815
|
persistSessionRegistry();
|
|
@@ -9760,7 +9824,7 @@ async function handleRequest(req) {
|
|
|
9760
9824
|
}
|
|
9761
9825
|
case "clear-orphan": {
|
|
9762
9826
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9763
|
-
if (!
|
|
9827
|
+
if (!existsSync27(stateFile)) {
|
|
9764
9828
|
return { ok: false, error: `Unknown session: ${req.sessionId}. No state.json at ${stateFile}.` };
|
|
9765
9829
|
}
|
|
9766
9830
|
await Promise.all([
|
|
@@ -9811,7 +9875,7 @@ async function handleRequest(req) {
|
|
|
9811
9875
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9812
9876
|
if (!tracking) {
|
|
9813
9877
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9814
|
-
if (
|
|
9878
|
+
if (existsSync27(stateFile)) {
|
|
9815
9879
|
registerSessionCwd(req.sessionId, req.cwd);
|
|
9816
9880
|
tracking = sessionTrackingMap.get(req.sessionId);
|
|
9817
9881
|
} else {
|
|
@@ -9825,7 +9889,7 @@ async function handleRequest(req) {
|
|
|
9825
9889
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9826
9890
|
if (!tracking) {
|
|
9827
9891
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9828
|
-
if (
|
|
9892
|
+
if (existsSync27(stateFile)) {
|
|
9829
9893
|
registerSessionCwd(req.sessionId, req.cwd);
|
|
9830
9894
|
tracking = sessionTrackingMap.get(req.sessionId);
|
|
9831
9895
|
} else {
|
|
@@ -9842,7 +9906,7 @@ async function handleRequest(req) {
|
|
|
9842
9906
|
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
9843
9907
|
if (!tracking) {
|
|
9844
9908
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9845
|
-
if (
|
|
9909
|
+
if (existsSync27(stateFile)) {
|
|
9846
9910
|
tracking = { cwd: req.cwd, messageCounter: 0 };
|
|
9847
9911
|
sessionTrackingMap.set(req.sessionId, tracking);
|
|
9848
9912
|
persistSessionRegistry();
|
|
@@ -9912,7 +9976,7 @@ async function handleRequest(req) {
|
|
|
9912
9976
|
}
|
|
9913
9977
|
case "set-upload-status": {
|
|
9914
9978
|
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
9915
|
-
if (!
|
|
9979
|
+
if (!existsSync27(stateFile)) {
|
|
9916
9980
|
return unknownSessionError(req.sessionId);
|
|
9917
9981
|
}
|
|
9918
9982
|
try {
|
|
@@ -10207,7 +10271,7 @@ async function handleRequest(req) {
|
|
|
10207
10271
|
function startServer() {
|
|
10208
10272
|
return new Promise((resolve13, reject) => {
|
|
10209
10273
|
const sock = socketPath();
|
|
10210
|
-
if (
|
|
10274
|
+
if (existsSync27(sock)) {
|
|
10211
10275
|
unlinkSync4(sock);
|
|
10212
10276
|
}
|
|
10213
10277
|
server = createServer((conn) => {
|
|
@@ -10262,7 +10326,7 @@ function stopServer() {
|
|
|
10262
10326
|
}
|
|
10263
10327
|
server.close(() => {
|
|
10264
10328
|
const sock = socketPath();
|
|
10265
|
-
if (
|
|
10329
|
+
if (existsSync27(sock)) {
|
|
10266
10330
|
unlinkSync4(sock);
|
|
10267
10331
|
}
|
|
10268
10332
|
server = null;
|
|
@@ -10300,8 +10364,8 @@ init_paths();
|
|
|
10300
10364
|
init_config();
|
|
10301
10365
|
init_server();
|
|
10302
10366
|
init_orphan_sweep();
|
|
10303
|
-
import { mkdirSync as mkdirSync15, readFileSync as
|
|
10304
|
-
import { execSync as
|
|
10367
|
+
import { mkdirSync as mkdirSync15, readFileSync as readFileSync28, writeFileSync as writeFileSync17, unlinkSync as unlinkSync6, existsSync as existsSync31 } from "fs";
|
|
10368
|
+
import { execSync as execSync8 } from "child_process";
|
|
10305
10369
|
import { setTimeout as sleep } from "timers/promises";
|
|
10306
10370
|
|
|
10307
10371
|
// src/daemon/heartbeat-asks.ts
|
|
@@ -10310,7 +10374,7 @@ init_state();
|
|
|
10310
10374
|
init_server();
|
|
10311
10375
|
init_paths();
|
|
10312
10376
|
import { ulid as ulid3 } from "ulid";
|
|
10313
|
-
import { existsSync as
|
|
10377
|
+
import { existsSync as existsSync28 } from "fs";
|
|
10314
10378
|
var HEARTBEAT_ASKED_BY2 = "system:heartbeat";
|
|
10315
10379
|
var HEARTBEAT_THRESHOLD_MS = 60 * 60 * 1e3;
|
|
10316
10380
|
var HEARTBEAT_SCAN_INTERVAL_MS = 15 * 60 * 1e3;
|
|
@@ -10393,7 +10457,7 @@ async function scanSessionForStaleAsks(cwd, sessionId) {
|
|
|
10393
10457
|
async function scanAllSessionsForStaleAsks() {
|
|
10394
10458
|
const reg = loadSessionRegistry();
|
|
10395
10459
|
for (const [sessionId, cwd] of Object.entries(reg)) {
|
|
10396
|
-
if (!
|
|
10460
|
+
if (!existsSync28(statePath(cwd, sessionId))) continue;
|
|
10397
10461
|
try {
|
|
10398
10462
|
await scanSessionForStaleAsks(cwd, sessionId);
|
|
10399
10463
|
} catch (err) {
|
|
@@ -10458,15 +10522,15 @@ init_status_dots();
|
|
|
10458
10522
|
init_companion();
|
|
10459
10523
|
init_exec();
|
|
10460
10524
|
init_shell();
|
|
10461
|
-
import { readFileSync as
|
|
10525
|
+
import { readFileSync as readFileSync26, existsSync as existsSync29 } from "fs";
|
|
10462
10526
|
import { homedir as homedir8 } from "os";
|
|
10463
10527
|
import { join as join22 } from "path";
|
|
10464
10528
|
var STATUS_BAR_BG = "#1d1e21";
|
|
10465
10529
|
var SESSION_ORDER_PATH = join22(homedir8(), ".config", "tmux", "session-order");
|
|
10466
10530
|
function getSessionOrder() {
|
|
10467
10531
|
try {
|
|
10468
|
-
if (!
|
|
10469
|
-
return
|
|
10532
|
+
if (!existsSync29(SESSION_ORDER_PATH)) return [];
|
|
10533
|
+
return readFileSync26(SESSION_ORDER_PATH, "utf-8").split("\n").filter(Boolean);
|
|
10470
10534
|
} catch {
|
|
10471
10535
|
return [];
|
|
10472
10536
|
}
|
|
@@ -11020,7 +11084,7 @@ init_state();
|
|
|
11020
11084
|
// src/daemon/updater.ts
|
|
11021
11085
|
init_paths();
|
|
11022
11086
|
init_version();
|
|
11023
|
-
import { execSync as
|
|
11087
|
+
import { execSync as execSync7 } from "child_process";
|
|
11024
11088
|
import { writeFileSync as writeFileSync16, unlinkSync as unlinkSync5, lstatSync as lstatSync2 } from "fs";
|
|
11025
11089
|
import { resolve as resolve11 } from "path";
|
|
11026
11090
|
import { get } from "https";
|
|
@@ -11072,8 +11136,8 @@ function applyUpdate(expectedVersion) {
|
|
|
11072
11136
|
try {
|
|
11073
11137
|
const nodeDir = resolve11(process.execPath, "..");
|
|
11074
11138
|
const env = { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` };
|
|
11075
|
-
|
|
11076
|
-
const result =
|
|
11139
|
+
execSync7("npm install -g sisyphi", { timeout: 15e3, stdio: "pipe", env });
|
|
11140
|
+
const result = execSync7("npm ls -g sisyphi --json --depth=0", {
|
|
11077
11141
|
timeout: 5e3,
|
|
11078
11142
|
encoding: "utf-8",
|
|
11079
11143
|
env
|
|
@@ -11105,7 +11169,7 @@ function clearUpdating() {
|
|
|
11105
11169
|
function isLinkedInstall() {
|
|
11106
11170
|
try {
|
|
11107
11171
|
const nodeDir = resolve11(process.execPath, "..");
|
|
11108
|
-
const globalPrefix =
|
|
11172
|
+
const globalPrefix = execSync7("npm prefix -g", { timeout: 5e3, encoding: "utf-8", env: { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` } }).trim();
|
|
11109
11173
|
const globalPkgDir = resolve11(globalPrefix, "lib", "node_modules", "sisyphi");
|
|
11110
11174
|
return lstatSync2(globalPkgDir).isSymbolicLink();
|
|
11111
11175
|
} catch {
|
|
@@ -11148,7 +11212,7 @@ function stopPeriodicUpdateCheck() {
|
|
|
11148
11212
|
}
|
|
11149
11213
|
|
|
11150
11214
|
// src/daemon/plugin-install.ts
|
|
11151
|
-
import { copyFileSync as copyFileSync6, mkdirSync as mkdirSync14, readdirSync as readdirSync13, statSync as statSync4, existsSync as
|
|
11215
|
+
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
11216
|
import { join as join23, resolve as resolve12 } from "path";
|
|
11153
11217
|
import { homedir as homedir9 } from "os";
|
|
11154
11218
|
var PLUGIN_NAME = "sisyphus-tmux";
|
|
@@ -11162,7 +11226,7 @@ function copyDir(src, dest) {
|
|
|
11162
11226
|
copyDir(srcPath, destPath);
|
|
11163
11227
|
} else {
|
|
11164
11228
|
const srcMtime = statSync4(srcPath).mtimeMs;
|
|
11165
|
-
const destMtime =
|
|
11229
|
+
const destMtime = existsSync30(destPath) ? statSync4(destPath).mtimeMs : 0;
|
|
11166
11230
|
if (srcMtime > destMtime) {
|
|
11167
11231
|
copyFileSync6(srcPath, destPath);
|
|
11168
11232
|
}
|
|
@@ -11172,16 +11236,16 @@ function copyDir(src, dest) {
|
|
|
11172
11236
|
function pluginNeedsUpdate(sourceDir) {
|
|
11173
11237
|
const srcHooks = join23(sourceDir, "hooks", "hooks.json");
|
|
11174
11238
|
const destHooks = join23(INSTALL_DIR, "hooks", "hooks.json");
|
|
11175
|
-
if (!
|
|
11239
|
+
if (!existsSync30(destHooks)) return true;
|
|
11176
11240
|
try {
|
|
11177
|
-
return
|
|
11241
|
+
return readFileSync27(srcHooks, "utf-8") !== readFileSync27(destHooks, "utf-8");
|
|
11178
11242
|
} catch {
|
|
11179
11243
|
return true;
|
|
11180
11244
|
}
|
|
11181
11245
|
}
|
|
11182
11246
|
function installPlugin() {
|
|
11183
11247
|
const sourceDir = resolve12(import.meta.dirname, "../templates/sisyphus-tmux-plugin");
|
|
11184
|
-
if (!
|
|
11248
|
+
if (!existsSync30(sourceDir)) {
|
|
11185
11249
|
console.error(`[plugin-install] Source dir not found: ${sourceDir}`);
|
|
11186
11250
|
return;
|
|
11187
11251
|
}
|
|
@@ -11189,7 +11253,7 @@ function installPlugin() {
|
|
|
11189
11253
|
try {
|
|
11190
11254
|
copyDir(sourceDir, INSTALL_DIR);
|
|
11191
11255
|
const hookScript = join23(INSTALL_DIR, "hooks", "tmux-state.sh");
|
|
11192
|
-
if (
|
|
11256
|
+
if (existsSync30(hookScript)) {
|
|
11193
11257
|
try {
|
|
11194
11258
|
chmodSync3(hookScript, 493);
|
|
11195
11259
|
} catch {
|
|
@@ -11255,7 +11319,7 @@ function ensureDirs() {
|
|
|
11255
11319
|
function readPid() {
|
|
11256
11320
|
const pidFile = daemonPidPath();
|
|
11257
11321
|
try {
|
|
11258
|
-
const pid = parseInt(
|
|
11322
|
+
const pid = parseInt(readFileSync28(pidFile, "utf-8").trim(), 10);
|
|
11259
11323
|
return pid && isProcessAlive(pid) ? pid : null;
|
|
11260
11324
|
} catch {
|
|
11261
11325
|
return null;
|
|
@@ -11271,7 +11335,7 @@ function acquirePidLock() {
|
|
|
11271
11335
|
}
|
|
11272
11336
|
function isLaunchdManaged() {
|
|
11273
11337
|
try {
|
|
11274
|
-
|
|
11338
|
+
execSync8("launchctl list com.sisyphus.daemon", { stdio: "pipe" });
|
|
11275
11339
|
return true;
|
|
11276
11340
|
} catch {
|
|
11277
11341
|
return false;
|
|
@@ -11326,11 +11390,11 @@ async function recoverSessions() {
|
|
|
11326
11390
|
let recovered = 0;
|
|
11327
11391
|
for (const [sessionId, cwd] of entries) {
|
|
11328
11392
|
const stateFile = statePath(cwd, sessionId);
|
|
11329
|
-
if (!
|
|
11393
|
+
if (!existsSync31(stateFile)) {
|
|
11330
11394
|
continue;
|
|
11331
11395
|
}
|
|
11332
11396
|
try {
|
|
11333
|
-
const session = JSON.parse(
|
|
11397
|
+
const session = JSON.parse(readFileSync28(stateFile, "utf-8"));
|
|
11334
11398
|
if (session.status === "active" || session.status === "paused") {
|
|
11335
11399
|
registerSessionCwd(sessionId, cwd);
|
|
11336
11400
|
resetAgentCounterFromState(sessionId, session.agents ?? []);
|