sisyphi 1.0.6 → 1.0.7
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/daemon.js +77 -21
- package/dist/daemon.js.map +1 -1
- package/dist/templates/agent-plugin/hooks/plan-user-prompt.sh +19 -0
- package/dist/templates/agent-plugin/hooks/spec-user-prompt.sh +22 -0
- package/dist/templates/orchestrator-planning.md +8 -0
- package/dist/tui.js +22 -5
- package/dist/tui.js.map +1 -1
- package/package.json +1 -1
- package/templates/agent-plugin/hooks/plan-user-prompt.sh +19 -0
- package/templates/agent-plugin/hooks/spec-user-prompt.sh +22 -0
- package/templates/orchestrator-planning.md +8 -0
package/dist/daemon.js
CHANGED
|
@@ -509,6 +509,7 @@ function createSession2(sessionName, windowName, cwd) {
|
|
|
509
509
|
exec(`tmux new-session -d -s "${sessionName}" -n "${windowName}" -c ${shellQuote(cwd)}`);
|
|
510
510
|
const windowId = exec(`tmux display-message -t "${sessionName}:${windowName}" -p "#{window_id}"`);
|
|
511
511
|
const initialPaneId = exec(`tmux display-message -t "${sessionName}:${windowName}" -p "#{pane_id}"`);
|
|
512
|
+
configureSessionDefaults(sessionName, windowId);
|
|
512
513
|
return { windowId, initialPaneId };
|
|
513
514
|
}
|
|
514
515
|
function paneExists(paneTarget) {
|
|
@@ -535,7 +536,8 @@ function setPaneTitle(paneTarget, title) {
|
|
|
535
536
|
execSafe(`tmux select-pane -t "${paneTarget}" -T ${shellQuote(title)}`);
|
|
536
537
|
}
|
|
537
538
|
function setPaneStyle(paneTarget, color) {
|
|
538
|
-
const
|
|
539
|
+
const gitBranch = `#(cd #{pane_current_path} && git branch --show-current 2>/dev/null || echo 'n/a')`;
|
|
540
|
+
const fmt = `#[fg=${color},bold] #{pane_title} #[fg=${color}]#{pane_current_path} | ${gitBranch} #[default]`;
|
|
539
541
|
execSafe(`tmux set -p -t "${paneTarget}" pane-border-format ${shellQuote(fmt)}`);
|
|
540
542
|
execSafe(`tmux set -p -t "${paneTarget}" @pane_color "${color}"`);
|
|
541
543
|
execSafe(`tmux set -w -t "${paneTarget}" pane-border-style "fg=#{?#{@pane_color},#{@pane_color},default}"`);
|
|
@@ -544,6 +546,13 @@ function setPaneStyle(paneTarget, color) {
|
|
|
544
546
|
function selectLayout(windowTarget, layout = "even-horizontal") {
|
|
545
547
|
execSafe(`tmux select-layout -t "${windowTarget}" ${layout}`);
|
|
546
548
|
}
|
|
549
|
+
function configureSessionDefaults(sessionName, windowId) {
|
|
550
|
+
execSafe(`tmux set -w -t "${windowId}" pane-border-status top`);
|
|
551
|
+
execSafe(`tmux set -w -t "${windowId}" allow-rename off`);
|
|
552
|
+
execSafe(`tmux set -w -t "${windowId}" automatic-rename off`);
|
|
553
|
+
execSafe(`tmux set-hook -t "${sessionName}" after-kill-pane "select-layout even-horizontal"`);
|
|
554
|
+
execSafe(`tmux set-hook -t "${sessionName}" pane-exited "select-layout even-horizontal"`);
|
|
555
|
+
}
|
|
547
556
|
|
|
548
557
|
// src/daemon/pane-registry.ts
|
|
549
558
|
var paneMap = /* @__PURE__ */ new Map();
|
|
@@ -656,31 +665,18 @@ ${lines.join("\n")}
|
|
|
656
665
|
const lastCycle = session.orchestratorCycles[session.orchestratorCycles.length - 1];
|
|
657
666
|
if (lastCycle && lastCycle.agentsSpawned.length > 0) {
|
|
658
667
|
const agentMap = new Map(session.agents.map((a) => [a.id, a]));
|
|
659
|
-
const
|
|
668
|
+
const agentLines = lastCycle.agentsSpawned.map((id) => {
|
|
660
669
|
const agent = agentMap.get(id);
|
|
661
|
-
if (!agent) return
|
|
662
|
-
(no agent data)
|
|
663
|
-
</agent-${id}>`;
|
|
670
|
+
if (!agent) return `- **${id}**: unknown (no agent data)`;
|
|
664
671
|
const finalReport = agent.reports.find((r) => r.type === "final");
|
|
665
672
|
const reportToUse = finalReport ?? agent.reports[agent.reports.length - 1];
|
|
666
|
-
|
|
667
|
-
|
|
668
|
-
try {
|
|
669
|
-
reportContent = readFileSync3(reportToUse.filePath, "utf-8");
|
|
670
|
-
} catch {
|
|
671
|
-
reportContent = `(could not read report: ${reportToUse.filePath})`;
|
|
672
|
-
}
|
|
673
|
-
}
|
|
674
|
-
return `<agent-${id} name="${agent.name}" status="${agent.status}">
|
|
675
|
-
${reportContent}
|
|
676
|
-
</agent-${id}>`;
|
|
673
|
+
const reportRef = reportToUse ? `@${reportToUse.filePath}` : "(no reports)";
|
|
674
|
+
return `- **${id}** (${agent.name}) [${agent.status}]: ${reportRef}`;
|
|
677
675
|
}).join("\n");
|
|
678
676
|
mostRecentCycleSection = `
|
|
679
677
|
### Most Recent Cycle
|
|
680
678
|
|
|
681
|
-
|
|
682
|
-
${agentBlocks}
|
|
683
|
-
</last-cycle>
|
|
679
|
+
${agentLines}
|
|
684
680
|
`;
|
|
685
681
|
}
|
|
686
682
|
const roadmapRef = existsSync4(roadmapFile) ? `@${roadmapFile}` : "(empty)";
|
|
@@ -1057,9 +1053,30 @@ function createAgentPlugin(cwd, sessionId, agentId, agentType, agentConfig) {
|
|
|
1057
1053
|
copyFileSync2(agentConfig.filePath, `${base}/agents/${shortName}.md`);
|
|
1058
1054
|
}
|
|
1059
1055
|
const srcHooks = resolve3(import.meta.dirname, "../templates/agent-plugin/hooks");
|
|
1060
|
-
for (const f of ["
|
|
1056
|
+
for (const f of ["require-submit.sh", "intercept-send-message.sh"]) {
|
|
1061
1057
|
copyFileSync2(`${srcHooks}/${f}`, `${base}/hooks/${f}`);
|
|
1062
1058
|
}
|
|
1059
|
+
const hooksConfig = {
|
|
1060
|
+
PreToolUse: [
|
|
1061
|
+
{ matcher: "SendMessage", hook: { type: "command", command: "bash hooks/intercept-send-message.sh" } }
|
|
1062
|
+
],
|
|
1063
|
+
Stop: [
|
|
1064
|
+
{ hook: { type: "command", command: "bash hooks/require-submit.sh" } }
|
|
1065
|
+
]
|
|
1066
|
+
};
|
|
1067
|
+
const normalizedType = agentType?.replace(/^sisyphus:/, "") ?? "";
|
|
1068
|
+
if (normalizedType === "plan") {
|
|
1069
|
+
hooksConfig.UserPromptSubmit = [
|
|
1070
|
+
{ hook: { type: "command", command: "bash hooks/plan-user-prompt.sh" } }
|
|
1071
|
+
];
|
|
1072
|
+
copyFileSync2(`${srcHooks}/plan-user-prompt.sh`, `${base}/hooks/plan-user-prompt.sh`);
|
|
1073
|
+
} else if (normalizedType === "spec-draft") {
|
|
1074
|
+
hooksConfig.UserPromptSubmit = [
|
|
1075
|
+
{ hook: { type: "command", command: "bash hooks/spec-user-prompt.sh" } }
|
|
1076
|
+
];
|
|
1077
|
+
copyFileSync2(`${srcHooks}/spec-user-prompt.sh`, `${base}/hooks/spec-user-prompt.sh`);
|
|
1078
|
+
}
|
|
1079
|
+
writeFileSync4(`${base}/hooks/hooks.json`, JSON.stringify({ hooks: hooksConfig }, null, 2), "utf-8");
|
|
1063
1080
|
return base;
|
|
1064
1081
|
}
|
|
1065
1082
|
function setupAgentPane(opts) {
|
|
@@ -1500,6 +1517,17 @@ function pruneOldSessions(cwd) {
|
|
|
1500
1517
|
console.error("[sisyphus] Session pruning failed:", err);
|
|
1501
1518
|
}
|
|
1502
1519
|
}
|
|
1520
|
+
async function reopenWindow(sessionId, cwd) {
|
|
1521
|
+
const session = getSession(cwd, sessionId);
|
|
1522
|
+
const tmuxName = session.tmuxSessionName ?? `sisyphus-${session.name ?? sessionId.slice(0, 8)}`;
|
|
1523
|
+
if (sessionExists(tmuxName) && session.tmuxWindowId) {
|
|
1524
|
+
return { tmuxSessionName: tmuxName, tmuxWindowId: session.tmuxWindowId };
|
|
1525
|
+
}
|
|
1526
|
+
const created = createSession2(tmuxName, "main", cwd);
|
|
1527
|
+
setSessionOption(tmuxName, "@sisyphus_cwd", cwd.replace(/\/+$/, ""));
|
|
1528
|
+
await updateSessionTmux(cwd, sessionId, tmuxName, created.windowId);
|
|
1529
|
+
return { tmuxSessionName: tmuxName, tmuxWindowId: created.windowId };
|
|
1530
|
+
}
|
|
1503
1531
|
async function resumeSession(sessionId, cwd, message) {
|
|
1504
1532
|
const session = getSession(cwd, sessionId);
|
|
1505
1533
|
const tmuxName = session.tmuxSessionName ?? `sisyphus-${sessionId.slice(0, 8)}`;
|
|
@@ -2018,6 +2046,23 @@ async function handleRequest(req) {
|
|
|
2018
2046
|
const result = await handleRollback(req.sessionId, tracking.cwd, req.toCycle);
|
|
2019
2047
|
return { ok: true, data: result };
|
|
2020
2048
|
}
|
|
2049
|
+
case "reopen-window": {
|
|
2050
|
+
let tracking = sessionTrackingMap.get(req.sessionId);
|
|
2051
|
+
if (!tracking) {
|
|
2052
|
+
const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
|
|
2053
|
+
if (existsSync8(stateFile)) {
|
|
2054
|
+
tracking = { cwd: req.cwd, messageCounter: 0 };
|
|
2055
|
+
sessionTrackingMap.set(req.sessionId, tracking);
|
|
2056
|
+
persistSessionRegistry();
|
|
2057
|
+
} else {
|
|
2058
|
+
return unknownSessionError(req.sessionId);
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
const result = await reopenWindow(req.sessionId, tracking.cwd);
|
|
2062
|
+
tracking.tmuxSession = result.tmuxSessionName;
|
|
2063
|
+
tracking.windowId = result.tmuxWindowId;
|
|
2064
|
+
return { ok: true, data: result };
|
|
2065
|
+
}
|
|
2021
2066
|
case "delete": {
|
|
2022
2067
|
const activeTracking = sessionTrackingMap.get(req.sessionId);
|
|
2023
2068
|
if (activeTracking) {
|
|
@@ -2138,7 +2183,7 @@ function stopServer() {
|
|
|
2138
2183
|
|
|
2139
2184
|
// src/daemon/updater.ts
|
|
2140
2185
|
import { execSync as execSync3 } from "child_process";
|
|
2141
|
-
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, unlinkSync as unlinkSync2 } from "fs";
|
|
2186
|
+
import { readFileSync as readFileSync7, writeFileSync as writeFileSync6, unlinkSync as unlinkSync2, lstatSync } from "fs";
|
|
2142
2187
|
import { resolve as resolve4 } from "path";
|
|
2143
2188
|
import { get } from "https";
|
|
2144
2189
|
function isNewer(latest, current) {
|
|
@@ -2228,8 +2273,19 @@ function clearUpdating() {
|
|
|
2228
2273
|
} catch {
|
|
2229
2274
|
}
|
|
2230
2275
|
}
|
|
2276
|
+
function isLinkedInstall() {
|
|
2277
|
+
try {
|
|
2278
|
+
const nodeDir = resolve4(process.execPath, "..");
|
|
2279
|
+
const globalPrefix = execSync3("npm prefix -g", { timeout: 5e3, encoding: "utf-8", env: { ...process.env, PATH: `${nodeDir}:${process.env.PATH ?? ""}` } }).trim();
|
|
2280
|
+
const globalPkgDir = resolve4(globalPrefix, "lib", "node_modules", "sisyphi");
|
|
2281
|
+
return lstatSync(globalPkgDir).isSymbolicLink();
|
|
2282
|
+
} catch {
|
|
2283
|
+
return false;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2231
2286
|
async function checkAndApply() {
|
|
2232
2287
|
clearUpdating();
|
|
2288
|
+
if (isLinkedInstall()) return;
|
|
2233
2289
|
try {
|
|
2234
2290
|
const update = await checkForUpdate();
|
|
2235
2291
|
if (!update) return;
|