sisyphi 1.1.14 → 1.1.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-4OVSSS2V.js → chunk-6TIO23U3.js} +1 -31
- package/dist/chunk-6TIO23U3.js.map +1 -0
- package/dist/chunk-IF55HPWX.js +44 -0
- package/dist/chunk-IF55HPWX.js.map +1 -0
- package/dist/chunk-UIVQXCWB.js +46 -0
- package/dist/chunk-UIVQXCWB.js.map +1 -0
- package/dist/cli.js +90 -42
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +41 -8
- package/dist/daemon.js.map +1 -1
- package/dist/templates/orchestrator-base.md +6 -1
- package/dist/templates/orchestrator-planning.md +1 -1
- package/dist/tui.js +11 -4
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
- package/templates/orchestrator-base.md +6 -1
- package/templates/orchestrator-planning.md +1 -1
- package/dist/chunk-4OVSSS2V.js.map +0 -1
- package/dist/chunk-6G226ZK7.js +0 -11
- package/dist/chunk-6G226ZK7.js.map +0 -1
|
@@ -1,33 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
globalConfigPath,
|
|
4
|
-
projectConfigPath
|
|
5
|
-
} from "./chunk-GSXF3TCZ.js";
|
|
6
|
-
|
|
7
|
-
// src/shared/config.ts
|
|
8
|
-
import { readFileSync } from "fs";
|
|
9
|
-
var DEFAULT_CONFIG = {
|
|
10
|
-
pollIntervalMs: 5e3,
|
|
11
|
-
orchestratorEffort: "high",
|
|
12
|
-
agentEffort: "medium",
|
|
13
|
-
notifications: {
|
|
14
|
-
enabled: true,
|
|
15
|
-
sound: "/System/Library/Sounds/Hero.aiff"
|
|
16
|
-
}
|
|
17
|
-
};
|
|
18
|
-
function readJsonFile(filePath) {
|
|
19
|
-
try {
|
|
20
|
-
const content = readFileSync(filePath, "utf-8");
|
|
21
|
-
return JSON.parse(content);
|
|
22
|
-
} catch {
|
|
23
|
-
return {};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
function loadConfig(cwd) {
|
|
27
|
-
const global = readJsonFile(globalConfigPath());
|
|
28
|
-
const project = readJsonFile(projectConfigPath(cwd));
|
|
29
|
-
return { ...DEFAULT_CONFIG, ...global, ...project };
|
|
30
|
-
}
|
|
31
2
|
|
|
32
3
|
// src/shared/env.ts
|
|
33
4
|
import { resolve } from "path";
|
|
@@ -87,11 +58,10 @@ function execSafe(cmd, cwd) {
|
|
|
87
58
|
}
|
|
88
59
|
|
|
89
60
|
export {
|
|
90
|
-
loadConfig,
|
|
91
61
|
augmentedPath,
|
|
92
62
|
execEnv,
|
|
93
63
|
EXEC_ENV,
|
|
94
64
|
exec,
|
|
95
65
|
execSafe
|
|
96
66
|
};
|
|
97
|
-
//# sourceMappingURL=chunk-
|
|
67
|
+
//# sourceMappingURL=chunk-6TIO23U3.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/env.ts","../src/shared/exec.ts"],"sourcesContent":["import { resolve } from 'node:path';\n\n/**\n * Build a PATH string that includes common binary directories\n * across package managers and platforms.\n *\n * Prepends known directories that exist on the system to the current PATH.\n * This ensures tmux commands can find binaries installed by Homebrew,\n * MacPorts, nix, and other package managers.\n */\nexport function augmentedPath(): string {\n const rawPath = process.env['PATH'];\n const basePath = rawPath !== undefined && rawPath.length > 0 ? rawPath : '/usr/bin:/bin';\n\n // Common binary directories across platforms/package managers.\n // Only prepend ones that aren't already in PATH.\n const home = process.env['HOME'];\n const candidates = [\n ...(home ? [`${home}/.local/bin`] : []), // Claude CLI, pipx, user-local installs\n resolve(process.execPath, '..'), // Node.js bin dir (ensures node/npm available)\n '/opt/homebrew/bin', // Homebrew (Apple Silicon macOS)\n '/opt/homebrew/sbin', // Homebrew sbin\n '/usr/local/bin', // Homebrew (Intel macOS), manual installs\n '/usr/local/sbin', // Manual installs\n '/opt/local/bin', // MacPorts\n '/opt/local/sbin', // MacPorts\n '/home/linuxbrew/.linuxbrew/bin', // Linuxbrew\n ];\n\n // Check for nix profile paths\n const nixProfile = process.env['NIX_PROFILES'];\n if (nixProfile) {\n for (const p of nixProfile.split(' ').reverse()) {\n candidates.push(`${p}/bin`);\n }\n }\n\n const existing = new Set(basePath.split(':'));\n const prepend = candidates.filter(dir => !existing.has(dir));\n\n return prepend.length > 0 ? `${prepend.join(':')}:${basePath}` : basePath;\n}\n\n/**\n * Environment variables for child processes that need access to\n * user-installed binaries (tmux, git, claude, etc.).\n */\nexport function execEnv(): Record<string, string | undefined> {\n return {\n ...process.env,\n PATH: augmentedPath(),\n };\n}\n","import { execSync } from 'node:child_process';\nimport { execEnv } from './env.js';\n\nexport const EXEC_ENV = execEnv();\n\nexport function exec(cmd: string, cwd?: string): string {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd }).trim();\n}\n\nexport function execSafe(cmd: string, cwd?: string): string | null {\n try {\n return execSync(cmd, { encoding: 'utf-8', env: EXEC_ENV, cwd, stdio: ['pipe', 'pipe', 'pipe'] }).trim();\n } catch { return null; }\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AAUjB,SAAS,gBAAwB;AACtC,QAAM,UAAU,QAAQ,IAAI,MAAM;AAClC,QAAM,WAAW,YAAY,UAAa,QAAQ,SAAS,IAAI,UAAU;AAIzE,QAAM,OAAO,QAAQ,IAAI,MAAM;AAC/B,QAAM,aAAa;AAAA,IACjB,GAAI,OAAO,CAAC,GAAG,IAAI,aAAa,IAAI,CAAC;AAAA;AAAA,IACrC,QAAQ,QAAQ,UAAU,IAAI;AAAA;AAAA,IAC9B;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,IACA;AAAA;AAAA,EACF;AAGA,QAAM,aAAa,QAAQ,IAAI,cAAc;AAC7C,MAAI,YAAY;AACd,eAAW,KAAK,WAAW,MAAM,GAAG,EAAE,QAAQ,GAAG;AAC/C,iBAAW,KAAK,GAAG,CAAC,MAAM;AAAA,IAC5B;AAAA,EACF;AAEA,QAAM,WAAW,IAAI,IAAI,SAAS,MAAM,GAAG,CAAC;AAC5C,QAAM,UAAU,WAAW,OAAO,SAAO,CAAC,SAAS,IAAI,GAAG,CAAC;AAE3D,SAAO,QAAQ,SAAS,IAAI,GAAG,QAAQ,KAAK,GAAG,CAAC,IAAI,QAAQ,KAAK;AACnE;AAMO,SAAS,UAA8C;AAC5D,SAAO;AAAA,IACL,GAAG,QAAQ;AAAA,IACX,MAAM,cAAc;AAAA,EACtB;AACF;;;ACpDA,SAAS,gBAAgB;AAGlB,IAAM,WAAW,QAAQ;AAEzB,SAAS,KAAK,KAAa,KAAsB;AACtD,SAAO,SAAS,KAAK,EAAE,UAAU,SAAS,KAAK,UAAU,IAAI,CAAC,EAAE,KAAK;AACvE;AAEO,SAAS,SAAS,KAAa,KAA6B;AACjE,MAAI;AACF,WAAO,SAAS,KAAK,EAAE,UAAU,SAAS,KAAK,UAAU,KAAK,OAAO,CAAC,QAAQ,QAAQ,MAAM,EAAE,CAAC,EAAE,KAAK;AAAA,EACxG,QAAQ;AAAE,WAAO;AAAA,EAAM;AACzB;","names":[]}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
globalConfigPath,
|
|
4
|
+
projectConfigPath
|
|
5
|
+
} from "./chunk-GSXF3TCZ.js";
|
|
6
|
+
|
|
7
|
+
// src/shared/config.ts
|
|
8
|
+
import { readFileSync } from "fs";
|
|
9
|
+
var DEFAULT_CONFIG = {
|
|
10
|
+
pollIntervalMs: 5e3,
|
|
11
|
+
orchestratorEffort: "high",
|
|
12
|
+
agentEffort: "medium",
|
|
13
|
+
notifications: {
|
|
14
|
+
enabled: true,
|
|
15
|
+
sound: "/System/Library/Sounds/Hero.aiff"
|
|
16
|
+
},
|
|
17
|
+
requiredPlugins: [
|
|
18
|
+
{ name: "devcore", marketplace: "crouton-kit" }
|
|
19
|
+
]
|
|
20
|
+
};
|
|
21
|
+
function readJsonFile(filePath) {
|
|
22
|
+
try {
|
|
23
|
+
const content = readFileSync(filePath, "utf-8");
|
|
24
|
+
return JSON.parse(content);
|
|
25
|
+
} catch {
|
|
26
|
+
return {};
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
function loadConfig(cwd) {
|
|
30
|
+
const global = readJsonFile(globalConfigPath());
|
|
31
|
+
const project = readJsonFile(projectConfigPath(cwd));
|
|
32
|
+
return { ...DEFAULT_CONFIG, ...global, ...project };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// src/shared/shell.ts
|
|
36
|
+
function shellQuote(s) {
|
|
37
|
+
return `'${s.replace(/'/g, "'\\''")}'`;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export {
|
|
41
|
+
loadConfig,
|
|
42
|
+
shellQuote
|
|
43
|
+
};
|
|
44
|
+
//# sourceMappingURL=chunk-IF55HPWX.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/config.ts","../src/shared/shell.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { globalConfigPath, projectConfigPath } from './paths.js';\n\nexport type EffortLevel = 'low' | 'medium' | 'high' | 'max';\n\nexport interface NotificationConfig {\n enabled?: boolean;\n sound?: string;\n}\n\nexport interface RequiredPlugin {\n name: string;\n marketplace: string;\n}\n\nexport interface Config {\n model?: string;\n tmuxSession?: string;\n orchestratorPrompt?: string;\n pollIntervalMs?: number;\n autoUpdate?: boolean;\n orchestratorEffort?: EffortLevel;\n agentEffort?: EffortLevel;\n editor?: string;\n repos?: string[];\n notifications?: NotificationConfig;\n requiredPlugins?: RequiredPlugin[];\n}\n\nconst DEFAULT_CONFIG: Config = {\n pollIntervalMs: 5000,\n orchestratorEffort: 'high',\n agentEffort: 'medium',\n notifications: {\n enabled: true,\n sound: '/System/Library/Sounds/Hero.aiff',\n },\n requiredPlugins: [\n { name: 'devcore', marketplace: 'crouton-kit' },\n ],\n};\n\nfunction readJsonFile(filePath: string): Partial<Config> {\n try {\n const content = readFileSync(filePath, 'utf-8');\n return JSON.parse(content) as Partial<Config>;\n } catch {\n return {};\n }\n}\n\nexport function loadConfig(cwd: string): Config {\n const global = readJsonFile(globalConfigPath());\n const project = readJsonFile(projectConfigPath(cwd));\n return { ...DEFAULT_CONFIG, ...global, ...project };\n}\n","export function shellQuote(s: string): string {\n return `'${s.replace(/'/g, \"'\\\\''\")}'`;\n}\n"],"mappings":";;;;;;;AAAA,SAAS,oBAAoB;AA6B7B,IAAM,iBAAyB;AAAA,EAC7B,gBAAgB;AAAA,EAChB,oBAAoB;AAAA,EACpB,aAAa;AAAA,EACb,eAAe;AAAA,IACb,SAAS;AAAA,IACT,OAAO;AAAA,EACT;AAAA,EACA,iBAAiB;AAAA,IACf,EAAE,MAAM,WAAW,aAAa,cAAc;AAAA,EAChD;AACF;AAEA,SAAS,aAAa,UAAmC;AACvD,MAAI;AACF,UAAM,UAAU,aAAa,UAAU,OAAO;AAC9C,WAAO,KAAK,MAAM,OAAO;AAAA,EAC3B,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;AAEO,SAAS,WAAW,KAAqB;AAC9C,QAAM,SAAS,aAAa,iBAAiB,CAAC;AAC9C,QAAM,UAAU,aAAa,kBAAkB,GAAG,CAAC;AACnD,SAAO,EAAE,GAAG,gBAAgB,GAAG,QAAQ,GAAG,QAAQ;AACpD;;;ACvDO,SAAS,WAAW,GAAmB;AAC5C,SAAO,IAAI,EAAE,QAAQ,MAAM,OAAO,CAAC;AACrC;","names":[]}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
loadConfig
|
|
4
|
+
} from "./chunk-IF55HPWX.js";
|
|
5
|
+
|
|
6
|
+
// src/daemon/plugins.ts
|
|
7
|
+
import { readFileSync } from "fs";
|
|
8
|
+
import { homedir } from "os";
|
|
9
|
+
import { join } from "path";
|
|
10
|
+
function installedPluginsPath() {
|
|
11
|
+
return join(homedir(), ".claude", "plugins", "installed_plugins.json");
|
|
12
|
+
}
|
|
13
|
+
function resolveInstalledPlugin(name) {
|
|
14
|
+
let data;
|
|
15
|
+
try {
|
|
16
|
+
data = JSON.parse(readFileSync(installedPluginsPath(), "utf-8"));
|
|
17
|
+
} catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
const entries = data.plugins?.[name];
|
|
21
|
+
if (!entries || entries.length === 0) return null;
|
|
22
|
+
const userEntry = entries.find((e) => e.scope === "user");
|
|
23
|
+
return (userEntry ?? entries[0]).installPath;
|
|
24
|
+
}
|
|
25
|
+
function resolveRequiredPluginDirs(cwd) {
|
|
26
|
+
const config = loadConfig(cwd);
|
|
27
|
+
const required = config.requiredPlugins;
|
|
28
|
+
if (!required || required.length === 0) return [];
|
|
29
|
+
const dirs = [];
|
|
30
|
+
for (const plugin of required) {
|
|
31
|
+
const key = `${plugin.name}@${plugin.marketplace}`;
|
|
32
|
+
const path = resolveInstalledPlugin(key);
|
|
33
|
+
if (path) {
|
|
34
|
+
dirs.push(path);
|
|
35
|
+
} else {
|
|
36
|
+
console.log(`[sisyphus] Warning: required plugin ${key} not installed \u2014 skipping`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return dirs;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export {
|
|
43
|
+
resolveInstalledPlugin,
|
|
44
|
+
resolveRequiredPluginDirs
|
|
45
|
+
};
|
|
46
|
+
//# sourceMappingURL=chunk-UIVQXCWB.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/daemon/plugins.ts"],"sourcesContent":["import { readFileSync } from 'node:fs';\nimport { homedir } from 'node:os';\nimport { join } from 'node:path';\nimport { loadConfig } from '../shared/config.js';\n\ninterface PluginEntry {\n scope: string;\n installPath: string;\n version: string;\n installedAt: string;\n lastUpdated: string;\n}\n\ninterface InstalledPlugins {\n version: number;\n plugins: Record<string, PluginEntry[]>;\n}\n\nfunction installedPluginsPath(): string {\n return join(homedir(), '.claude', 'plugins', 'installed_plugins.json');\n}\n\nexport function resolveInstalledPlugin(name: string): string | null {\n let data: InstalledPlugins;\n try {\n data = JSON.parse(readFileSync(installedPluginsPath(), 'utf-8'));\n } catch {\n return null;\n }\n\n const entries = data.plugins?.[name];\n if (!entries || entries.length === 0) return null;\n\n // Prefer user-scoped entry\n const userEntry = entries.find(e => e.scope === 'user');\n return (userEntry ?? entries[0])!.installPath;\n}\n\nexport function resolveRequiredPluginDirs(cwd: string): string[] {\n const config = loadConfig(cwd);\n const required = config.requiredPlugins;\n if (!required || required.length === 0) return [];\n\n const dirs: string[] = [];\n for (const plugin of required) {\n const key = `${plugin.name}@${plugin.marketplace}`;\n const path = resolveInstalledPlugin(key);\n if (path) {\n dirs.push(path);\n } else {\n console.log(`[sisyphus] Warning: required plugin ${key} not installed — skipping`);\n }\n }\n return dirs;\n}\n"],"mappings":";;;;;;AAAA,SAAS,oBAAoB;AAC7B,SAAS,eAAe;AACxB,SAAS,YAAY;AAgBrB,SAAS,uBAA+B;AACtC,SAAO,KAAK,QAAQ,GAAG,WAAW,WAAW,wBAAwB;AACvE;AAEO,SAAS,uBAAuB,MAA6B;AAClE,MAAI;AACJ,MAAI;AACF,WAAO,KAAK,MAAM,aAAa,qBAAqB,GAAG,OAAO,CAAC;AAAA,EACjE,QAAQ;AACN,WAAO;AAAA,EACT;AAEA,QAAM,UAAU,KAAK,UAAU,IAAI;AACnC,MAAI,CAAC,WAAW,QAAQ,WAAW,EAAG,QAAO;AAG7C,QAAM,YAAY,QAAQ,KAAK,OAAK,EAAE,UAAU,MAAM;AACtD,UAAQ,aAAa,QAAQ,CAAC,GAAI;AACpC;AAEO,SAAS,0BAA0B,KAAuB;AAC/D,QAAM,SAAS,WAAW,GAAG;AAC7B,QAAM,WAAW,OAAO;AACxB,MAAI,CAAC,YAAY,SAAS,WAAW,EAAG,QAAO,CAAC;AAEhD,QAAM,OAAiB,CAAC;AACxB,aAAW,UAAU,UAAU;AAC7B,UAAM,MAAM,GAAG,OAAO,IAAI,IAAI,OAAO,WAAW;AAChD,UAAM,OAAO,uBAAuB,GAAG;AACvC,QAAI,MAAM;AACR,WAAK,KAAK,IAAI;AAAA,IAChB,OAAO;AACL,cAAQ,IAAI,uCAAuC,GAAG,gCAA2B;AAAA,IACnF;AAAA,EACF;AACA,SAAO;AACT;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import {
|
|
3
|
+
resolveInstalledPlugin
|
|
4
|
+
} from "./chunk-UIVQXCWB.js";
|
|
2
5
|
import {
|
|
3
6
|
buildCompanionContext,
|
|
4
7
|
computeActiveTimeMs,
|
|
@@ -7,8 +10,9 @@ import {
|
|
|
7
10
|
statusColor
|
|
8
11
|
} from "./chunk-HQZOAX6D.js";
|
|
9
12
|
import {
|
|
13
|
+
loadConfig,
|
|
10
14
|
shellQuote
|
|
11
|
-
} from "./chunk-
|
|
15
|
+
} from "./chunk-IF55HPWX.js";
|
|
12
16
|
import {
|
|
13
17
|
cycleLogPath,
|
|
14
18
|
daemonLogPath,
|
|
@@ -26,10 +30,10 @@ import { dirname as dirname4, join as join8 } from "path";
|
|
|
26
30
|
import { fileURLToPath as fileURLToPath4 } from "url";
|
|
27
31
|
|
|
28
32
|
// src/cli/commands/start.ts
|
|
29
|
-
import { execSync as
|
|
33
|
+
import { execSync as execSync6 } from "child_process";
|
|
30
34
|
|
|
31
35
|
// src/cli/install.ts
|
|
32
|
-
import { execSync as
|
|
36
|
+
import { execSync as execSync3 } from "child_process";
|
|
33
37
|
import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmSync, unlinkSync as unlinkSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
34
38
|
import { connect } from "net";
|
|
35
39
|
import { homedir as homedir2 } from "os";
|
|
@@ -256,6 +260,49 @@ function removeTmuxKeybind() {
|
|
|
256
260
|
}
|
|
257
261
|
}
|
|
258
262
|
|
|
263
|
+
// src/cli/plugins.ts
|
|
264
|
+
import { execSync as execSync2 } from "child_process";
|
|
265
|
+
function exec(cmd) {
|
|
266
|
+
try {
|
|
267
|
+
return execSync2(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
268
|
+
} catch {
|
|
269
|
+
return "";
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function isMarketplaceInstalled(marketplace) {
|
|
273
|
+
const output = exec("claude plugins marketplace list");
|
|
274
|
+
return output.includes(marketplace);
|
|
275
|
+
}
|
|
276
|
+
function installMarketplace(marketplace) {
|
|
277
|
+
console.log(`Adding marketplace: ${marketplace}`);
|
|
278
|
+
execSync2(`claude plugins marketplace add CaptainCrouton89/${marketplace}`, { stdio: "inherit" });
|
|
279
|
+
}
|
|
280
|
+
function installPlugin(key) {
|
|
281
|
+
console.log(`Installing plugin: ${key}`);
|
|
282
|
+
execSync2(`claude plugins install ${key} --scope user`, { stdio: "inherit" });
|
|
283
|
+
}
|
|
284
|
+
async function ensureRequiredPlugins(cwd) {
|
|
285
|
+
const config = loadConfig(cwd);
|
|
286
|
+
const required = config.requiredPlugins;
|
|
287
|
+
if (!required || required.length === 0) return;
|
|
288
|
+
for (const plugin of required) {
|
|
289
|
+
const key = `${plugin.name}@${plugin.marketplace}`;
|
|
290
|
+
const existing = resolveInstalledPlugin(key);
|
|
291
|
+
if (existing) continue;
|
|
292
|
+
console.log(`Required plugin ${key} not found \u2014 installing...`);
|
|
293
|
+
if (!isMarketplaceInstalled(plugin.marketplace)) {
|
|
294
|
+
installMarketplace(plugin.marketplace);
|
|
295
|
+
}
|
|
296
|
+
installPlugin(key);
|
|
297
|
+
const verified = resolveInstalledPlugin(key);
|
|
298
|
+
if (verified) {
|
|
299
|
+
console.log(`Installed ${key} \u2192 ${verified}`);
|
|
300
|
+
} else {
|
|
301
|
+
console.warn(`Warning: failed to verify ${key} installation`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
259
306
|
// src/cli/install.ts
|
|
260
307
|
var PLIST_LABEL = "com.sisyphus.daemon";
|
|
261
308
|
var PLIST_FILENAME = `${PLIST_LABEL}.plist`;
|
|
@@ -306,8 +353,9 @@ async function ensureDaemonInstalled() {
|
|
|
306
353
|
mkdirSync2(launchAgentDir(), { recursive: true });
|
|
307
354
|
const plist = generatePlist(nodePath, daemonPath, logPath);
|
|
308
355
|
writeFileSync2(plistPath(), plist, "utf8");
|
|
309
|
-
|
|
356
|
+
execSync3(`launchctl load -w ${plistPath()}`);
|
|
310
357
|
const keybindResult = setupTmuxKeybind();
|
|
358
|
+
await ensureRequiredPlugins(process.cwd());
|
|
311
359
|
printGettingStarted(keybindResult);
|
|
312
360
|
}
|
|
313
361
|
await waitForDaemon();
|
|
@@ -320,7 +368,7 @@ async function uninstallDaemon(purge) {
|
|
|
320
368
|
const plist = plistPath();
|
|
321
369
|
if (existsSync2(plist)) {
|
|
322
370
|
try {
|
|
323
|
-
|
|
371
|
+
execSync3(`launchctl unload -w ${plist}`, { stdio: "pipe" });
|
|
324
372
|
} catch {
|
|
325
373
|
}
|
|
326
374
|
unlinkSync2(plist);
|
|
@@ -467,10 +515,10 @@ async function sendRequest(request) {
|
|
|
467
515
|
}
|
|
468
516
|
|
|
469
517
|
// src/cli/tmux.ts
|
|
470
|
-
import { execSync as
|
|
518
|
+
import { execSync as execSync4 } from "child_process";
|
|
471
519
|
function isTmuxInstalled() {
|
|
472
520
|
try {
|
|
473
|
-
|
|
521
|
+
execSync4("which tmux", { stdio: "pipe" });
|
|
474
522
|
return true;
|
|
475
523
|
} catch {
|
|
476
524
|
return false;
|
|
@@ -483,25 +531,25 @@ function assertTmux() {
|
|
|
483
531
|
}
|
|
484
532
|
function getTmuxSession() {
|
|
485
533
|
assertTmux();
|
|
486
|
-
return
|
|
534
|
+
return execSync4('tmux display-message -p "#{session_name}"', { encoding: "utf8" }).trim();
|
|
487
535
|
}
|
|
488
536
|
|
|
489
537
|
// src/cli/commands/dashboard.ts
|
|
490
538
|
import { join as join3 } from "path";
|
|
491
|
-
import { execSync as
|
|
539
|
+
import { execSync as execSync5 } from "child_process";
|
|
492
540
|
function openDashboardWindow(tmuxSession, cwd) {
|
|
493
541
|
try {
|
|
494
|
-
const storedId =
|
|
542
|
+
const storedId = execSync5(
|
|
495
543
|
`tmux show-option -t ${shellQuote(tmuxSession)} -v @sisyphus_dashboard`,
|
|
496
544
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
497
545
|
).trim();
|
|
498
546
|
if (storedId) {
|
|
499
547
|
try {
|
|
500
|
-
|
|
548
|
+
execSync5(
|
|
501
549
|
`tmux display-message -t ${shellQuote(storedId)} -p "#{window_id}"`,
|
|
502
550
|
{ stdio: "pipe" }
|
|
503
551
|
);
|
|
504
|
-
|
|
552
|
+
execSync5(`tmux select-window -t ${shellQuote(storedId)}`, { stdio: "pipe" });
|
|
505
553
|
return false;
|
|
506
554
|
} catch {
|
|
507
555
|
}
|
|
@@ -509,15 +557,15 @@ function openDashboardWindow(tmuxSession, cwd) {
|
|
|
509
557
|
} catch {
|
|
510
558
|
}
|
|
511
559
|
const tuiPath = join3(import.meta.dirname, "tui.js");
|
|
512
|
-
const windowId =
|
|
560
|
+
const windowId = execSync5(
|
|
513
561
|
`tmux new-window -n "sisyphus-dashboard" -c ${shellQuote(cwd)} -P -F "#{window_id}"`,
|
|
514
562
|
{ encoding: "utf-8" }
|
|
515
563
|
).trim();
|
|
516
564
|
const cmd = `node ${shellQuote(tuiPath)} --cwd ${shellQuote(cwd)}; exit`;
|
|
517
|
-
|
|
565
|
+
execSync5(
|
|
518
566
|
`tmux send-keys -t ${shellQuote(windowId)} ${shellQuote(cmd)} Enter`
|
|
519
567
|
);
|
|
520
|
-
|
|
568
|
+
execSync5(
|
|
521
569
|
`tmux set-option -t ${shellQuote(tmuxSession)} @sisyphus_dashboard ${shellQuote(windowId)}`,
|
|
522
570
|
{ stdio: "pipe" }
|
|
523
571
|
);
|
|
@@ -527,7 +575,7 @@ function registerDashboard(program2) {
|
|
|
527
575
|
program2.command("dashboard").description("Launch the TUI dashboard for monitoring and managing sessions").action(async () => {
|
|
528
576
|
assertTmux();
|
|
529
577
|
const tuiPath = join3(import.meta.dirname, "tui.js");
|
|
530
|
-
|
|
578
|
+
execSync5(`node ${shellQuote(tuiPath)} --cwd ${shellQuote(process.cwd())}`, {
|
|
531
579
|
stdio: "inherit"
|
|
532
580
|
});
|
|
533
581
|
});
|
|
@@ -558,7 +606,7 @@ function registerStart(program2) {
|
|
|
558
606
|
const tmuxSessionName = response.data?.tmuxSessionName;
|
|
559
607
|
if (process.env["TMUX"]) {
|
|
560
608
|
try {
|
|
561
|
-
|
|
609
|
+
execSync6(`tmux set-option @sisyphus_cwd ${shellQuote(cwd)}`, { stdio: "ignore" });
|
|
562
610
|
} catch {
|
|
563
611
|
}
|
|
564
612
|
try {
|
|
@@ -750,7 +798,7 @@ function registerContinue(program2) {
|
|
|
750
798
|
}
|
|
751
799
|
|
|
752
800
|
// src/cli/commands/status.ts
|
|
753
|
-
import { execSync as
|
|
801
|
+
import { execSync as execSync7 } from "child_process";
|
|
754
802
|
import { existsSync as existsSync4, readFileSync as readFileSync3 } from "fs";
|
|
755
803
|
var COLOR_CODES = {
|
|
756
804
|
green: "\x1B[32m",
|
|
@@ -857,7 +905,7 @@ function readCycleLog(cwd, sessionId, cycle) {
|
|
|
857
905
|
}
|
|
858
906
|
function capturePaneOutput(paneId, lines = 50) {
|
|
859
907
|
try {
|
|
860
|
-
return
|
|
908
|
+
return execSync7(
|
|
861
909
|
`tmux capture-pane -t "${paneId}" -p -S -${lines}`,
|
|
862
910
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
863
911
|
).trimEnd();
|
|
@@ -1246,11 +1294,11 @@ function registerSetupKeybind(program2) {
|
|
|
1246
1294
|
}
|
|
1247
1295
|
|
|
1248
1296
|
// src/cli/commands/doctor.ts
|
|
1249
|
-
import { execSync as
|
|
1297
|
+
import { execSync as execSync9 } from "child_process";
|
|
1250
1298
|
import { existsSync as existsSync6, statSync } from "fs";
|
|
1251
1299
|
|
|
1252
1300
|
// src/cli/onboard.ts
|
|
1253
|
-
import { execSync as
|
|
1301
|
+
import { execSync as execSync8 } from "child_process";
|
|
1254
1302
|
import { existsSync as existsSync5, mkdirSync as mkdirSync3, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
1255
1303
|
import { homedir as homedir3 } from "os";
|
|
1256
1304
|
import { dirname as dirname2, join as join5 } from "path";
|
|
@@ -1262,7 +1310,7 @@ function detectTerminal() {
|
|
|
1262
1310
|
}
|
|
1263
1311
|
function isTmuxAvailable() {
|
|
1264
1312
|
try {
|
|
1265
|
-
|
|
1313
|
+
execSync8("which tmux", { stdio: "pipe" });
|
|
1266
1314
|
return true;
|
|
1267
1315
|
} catch {
|
|
1268
1316
|
return false;
|
|
@@ -1270,7 +1318,7 @@ function isTmuxAvailable() {
|
|
|
1270
1318
|
}
|
|
1271
1319
|
function isBrewAvailable() {
|
|
1272
1320
|
try {
|
|
1273
|
-
|
|
1321
|
+
execSync8("which brew", { stdio: "pipe" });
|
|
1274
1322
|
return true;
|
|
1275
1323
|
} catch {
|
|
1276
1324
|
return false;
|
|
@@ -1280,7 +1328,7 @@ function tryAutoInstallTmux() {
|
|
|
1280
1328
|
if (!isBrewAvailable()) return false;
|
|
1281
1329
|
try {
|
|
1282
1330
|
console.log(" Installing tmux via Homebrew...");
|
|
1283
|
-
|
|
1331
|
+
execSync8("brew install tmux", { stdio: "inherit" });
|
|
1284
1332
|
return isTmuxAvailable();
|
|
1285
1333
|
} catch {
|
|
1286
1334
|
return false;
|
|
@@ -1295,7 +1343,7 @@ function checkItermOptionKey() {
|
|
|
1295
1343
|
return { checked: false, allCorrect: false, incorrectProfiles: [] };
|
|
1296
1344
|
}
|
|
1297
1345
|
try {
|
|
1298
|
-
const json =
|
|
1346
|
+
const json = execSync8(
|
|
1299
1347
|
`plutil -extract "New Bookmarks" json -o - "${plistPath2}"`,
|
|
1300
1348
|
{ encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
|
|
1301
1349
|
);
|
|
@@ -1386,7 +1434,7 @@ function writeTmuxDefaults() {
|
|
|
1386
1434
|
}
|
|
1387
1435
|
function isNvimAvailable() {
|
|
1388
1436
|
try {
|
|
1389
|
-
|
|
1437
|
+
execSync8("which nvim", { stdio: "pipe" });
|
|
1390
1438
|
return true;
|
|
1391
1439
|
} catch {
|
|
1392
1440
|
return false;
|
|
@@ -1394,7 +1442,7 @@ function isNvimAvailable() {
|
|
|
1394
1442
|
}
|
|
1395
1443
|
function getNvimVersion() {
|
|
1396
1444
|
try {
|
|
1397
|
-
return
|
|
1445
|
+
return execSync8("nvim --version", { encoding: "utf-8", stdio: "pipe" }).split("\n")[0]?.replace("NVIM ", "") || "unknown";
|
|
1398
1446
|
} catch {
|
|
1399
1447
|
return "unknown";
|
|
1400
1448
|
}
|
|
@@ -1411,7 +1459,7 @@ function tryAutoInstallNvim() {
|
|
|
1411
1459
|
}
|
|
1412
1460
|
try {
|
|
1413
1461
|
console.log(" Installing neovim via Homebrew...");
|
|
1414
|
-
|
|
1462
|
+
execSync8("brew install neovim", { stdio: "inherit" });
|
|
1415
1463
|
} catch {
|
|
1416
1464
|
return { installed: false, autoInstalled: false, version: "", lazyVimInstalled: false };
|
|
1417
1465
|
}
|
|
@@ -1423,10 +1471,10 @@ function tryAutoInstallNvim() {
|
|
|
1423
1471
|
if (!existsSync5(nvimConfigDir)) {
|
|
1424
1472
|
try {
|
|
1425
1473
|
console.log(" Cloning LazyVim starter config...");
|
|
1426
|
-
|
|
1474
|
+
execSync8(`git clone https://github.com/LazyVim/starter ${nvimConfigDir}`, { stdio: "inherit" });
|
|
1427
1475
|
const gitDir = join5(nvimConfigDir, ".git");
|
|
1428
1476
|
if (existsSync5(gitDir)) {
|
|
1429
|
-
|
|
1477
|
+
execSync8(`rm -rf "${gitDir}"`, { stdio: "pipe" });
|
|
1430
1478
|
}
|
|
1431
1479
|
lazyVimInstalled = true;
|
|
1432
1480
|
} catch {
|
|
@@ -1494,7 +1542,7 @@ function checkNodeVersion() {
|
|
|
1494
1542
|
}
|
|
1495
1543
|
function checkClaudeCli() {
|
|
1496
1544
|
try {
|
|
1497
|
-
|
|
1545
|
+
execSync9("which claude", { stdio: "pipe" });
|
|
1498
1546
|
return { name: "Claude CLI", status: "ok", detail: "Found on PATH" };
|
|
1499
1547
|
} catch {
|
|
1500
1548
|
return {
|
|
@@ -1507,7 +1555,7 @@ function checkClaudeCli() {
|
|
|
1507
1555
|
}
|
|
1508
1556
|
function checkGit() {
|
|
1509
1557
|
try {
|
|
1510
|
-
const version =
|
|
1558
|
+
const version = execSync9("git --version", { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
1511
1559
|
return { name: "git", status: "ok", detail: version };
|
|
1512
1560
|
} catch {
|
|
1513
1561
|
return { name: "git", status: "fail", detail: "Not found on PATH", fix: "Install git: https://git-scm.com/downloads" };
|
|
@@ -1515,7 +1563,7 @@ function checkGit() {
|
|
|
1515
1563
|
}
|
|
1516
1564
|
function checkTmuxVersion() {
|
|
1517
1565
|
try {
|
|
1518
|
-
const version =
|
|
1566
|
+
const version = execSync9("tmux -V", { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
1519
1567
|
const match = version.match(/(\d+\.\d+)/);
|
|
1520
1568
|
if (!match) return { name: "tmux version", status: "warn", detail: `Could not parse version: ${version}` };
|
|
1521
1569
|
const ver = parseFloat(match[1]);
|
|
@@ -1564,7 +1612,7 @@ function checkDaemonRunning() {
|
|
|
1564
1612
|
}
|
|
1565
1613
|
try {
|
|
1566
1614
|
const sock = socketPath();
|
|
1567
|
-
|
|
1615
|
+
execSync9(`test -S "${sock}"`, { stdio: "pipe" });
|
|
1568
1616
|
return { name: "Daemon process", status: "ok", detail: `Socket at ${sock}` };
|
|
1569
1617
|
} catch {
|
|
1570
1618
|
return {
|
|
@@ -1577,13 +1625,13 @@ function checkDaemonRunning() {
|
|
|
1577
1625
|
}
|
|
1578
1626
|
function checkTmux() {
|
|
1579
1627
|
try {
|
|
1580
|
-
|
|
1628
|
+
execSync9("which tmux", { stdio: "pipe" });
|
|
1581
1629
|
} catch {
|
|
1582
1630
|
const installHint = process.platform === "darwin" ? "brew install tmux" : "apt install tmux (Debian/Ubuntu) or your package manager";
|
|
1583
1631
|
return { name: "tmux", status: "fail", detail: "Not found on PATH", fix: installHint };
|
|
1584
1632
|
}
|
|
1585
1633
|
try {
|
|
1586
|
-
|
|
1634
|
+
execSync9("tmux list-sessions", { stdio: "pipe" });
|
|
1587
1635
|
return { name: "tmux", status: "ok", detail: "Running" };
|
|
1588
1636
|
} catch {
|
|
1589
1637
|
return { name: "tmux", status: "warn", detail: "Installed but no server running" };
|
|
@@ -1696,7 +1744,7 @@ function checkNvim() {
|
|
|
1696
1744
|
return { name: "nvim", status: "warn", detail: "Not installed", fix };
|
|
1697
1745
|
}
|
|
1698
1746
|
try {
|
|
1699
|
-
const version =
|
|
1747
|
+
const version = execSync9("nvim --version", { encoding: "utf-8", stdio: "pipe" }).split("\n")[0]?.replace("NVIM ", "");
|
|
1700
1748
|
return { name: "nvim", status: "ok", detail: version ?? "installed" };
|
|
1701
1749
|
} catch {
|
|
1702
1750
|
return { name: "nvim", status: "ok", detail: "installed" };
|
|
@@ -1750,7 +1798,7 @@ function registerCompanionContext(program2) {
|
|
|
1750
1798
|
}
|
|
1751
1799
|
|
|
1752
1800
|
// src/cli/commands/getting-started.ts
|
|
1753
|
-
import { execSync as
|
|
1801
|
+
import { execSync as execSync10 } from "child_process";
|
|
1754
1802
|
import { dirname as dirname3, join as join6 } from "path";
|
|
1755
1803
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
1756
1804
|
function templatePath(name) {
|
|
@@ -2240,11 +2288,11 @@ function printStep5() {
|
|
|
2240
2288
|
let recentCommits = "";
|
|
2241
2289
|
let topLevelFiles = "";
|
|
2242
2290
|
try {
|
|
2243
|
-
recentCommits =
|
|
2291
|
+
recentCommits = execSync10("git log --oneline -15 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
2244
2292
|
} catch {
|
|
2245
2293
|
}
|
|
2246
2294
|
try {
|
|
2247
|
-
topLevelFiles =
|
|
2295
|
+
topLevelFiles = execSync10("ls -1 2>/dev/null", { encoding: "utf-8" }).trim();
|
|
2248
2296
|
} catch {
|
|
2249
2297
|
}
|
|
2250
2298
|
console.log(`
|
|
@@ -2740,10 +2788,10 @@ function registerInit(program2) {
|
|
|
2740
2788
|
}
|
|
2741
2789
|
|
|
2742
2790
|
// src/cli/commands/setup.ts
|
|
2743
|
-
import { execSync as
|
|
2791
|
+
import { execSync as execSync11 } from "child_process";
|
|
2744
2792
|
function getTmuxVersion() {
|
|
2745
2793
|
try {
|
|
2746
|
-
return
|
|
2794
|
+
return execSync11("tmux -V", { encoding: "utf-8", stdio: "pipe" }).trim();
|
|
2747
2795
|
} catch {
|
|
2748
2796
|
return "installed";
|
|
2749
2797
|
}
|