sisyphi 1.0.14 → 1.1.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/{chunk-Q6VQOUN3.js → chunk-M7LZ2ZHD.js} +3 -27
- package/dist/chunk-M7LZ2ZHD.js.map +1 -0
- package/dist/{chunk-YGBGKMTF.js → chunk-REUQ4B45.js} +7 -11
- package/dist/chunk-REUQ4B45.js.map +1 -0
- package/dist/{chunk-MMA43N67.js → chunk-Z32YVDMY.js} +2 -2
- package/dist/chunk-Z32YVDMY.js.map +1 -0
- package/dist/cli.js +46 -49
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +795 -796
- package/dist/daemon.js.map +1 -1
- package/dist/{paths-FYYSBD27.js → paths-IJXOAN4E.js} +4 -6
- package/dist/templates/CLAUDE.md +16 -14
- package/dist/templates/agent-plugin/agents/CLAUDE.md +17 -6
- package/dist/templates/agent-plugin/agents/design.md +134 -0
- package/dist/templates/agent-plugin/agents/explore.md +39 -0
- package/dist/templates/agent-plugin/agents/operator.md +24 -0
- package/dist/templates/agent-plugin/agents/plan.md +15 -20
- package/dist/templates/agent-plugin/agents/problem.md +119 -0
- package/dist/templates/agent-plugin/agents/requirements.md +138 -0
- package/dist/templates/agent-plugin/agents/review/CLAUDE.md +29 -0
- package/dist/templates/agent-plugin/agents/review/compliance.md +6 -6
- package/dist/templates/agent-plugin/agents/review-plan/code-smells.md +4 -4
- package/dist/templates/agent-plugin/agents/review-plan/requirements-coverage.md +62 -0
- package/dist/templates/agent-plugin/agents/review-plan/security.md +1 -1
- package/dist/templates/agent-plugin/agents/review-plan.md +9 -8
- package/dist/templates/agent-plugin/agents/review.md +1 -1
- package/dist/templates/agent-plugin/agents/test-spec.md +2 -2
- package/dist/templates/agent-plugin/hooks/CLAUDE.md +2 -2
- package/dist/templates/agent-plugin/hooks/explore-user-prompt.sh +13 -0
- package/dist/templates/agent-plugin/hooks/plan-user-prompt.sh +1 -1
- package/dist/templates/agent-plugin/hooks/require-submit.sh +69 -2
- package/dist/templates/agent-plugin/hooks/review-plan-user-prompt.sh +4 -4
- package/dist/templates/agent-plugin/hooks/review-user-prompt.sh +1 -1
- package/dist/templates/agent-suffix.md +0 -2
- package/dist/templates/orchestrator-base.md +167 -145
- package/dist/templates/orchestrator-impl.md +92 -57
- package/dist/templates/orchestrator-planning.md +46 -56
- package/dist/templates/orchestrator-plugin/commands/sisyphus/design.md +13 -0
- package/dist/templates/orchestrator-plugin/commands/sisyphus/problem.md +13 -0
- package/dist/templates/orchestrator-plugin/commands/sisyphus/requirements.md +13 -0
- package/dist/templates/orchestrator-plugin/commands/sisyphus/strategize.md +19 -0
- package/dist/templates/orchestrator-plugin/hooks/explore-gate.sh +15 -0
- package/dist/templates/orchestrator-plugin/hooks/hooks.json +14 -1
- package/dist/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +34 -27
- package/dist/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +56 -24
- package/dist/templates/orchestrator-strategy.md +233 -0
- package/dist/templates/orchestrator-validation.md +94 -0
- package/dist/tui.js +193 -120
- package/dist/tui.js.map +1 -1
- package/package.json +2 -2
- package/templates/CLAUDE.md +16 -14
- package/templates/agent-plugin/agents/CLAUDE.md +17 -6
- package/templates/agent-plugin/agents/design.md +134 -0
- package/templates/agent-plugin/agents/explore.md +39 -0
- package/templates/agent-plugin/agents/operator.md +24 -0
- package/templates/agent-plugin/agents/plan.md +15 -20
- package/templates/agent-plugin/agents/problem.md +119 -0
- package/templates/agent-plugin/agents/requirements.md +138 -0
- package/templates/agent-plugin/agents/review/CLAUDE.md +29 -0
- package/templates/agent-plugin/agents/review/compliance.md +6 -6
- package/templates/agent-plugin/agents/review-plan/code-smells.md +4 -4
- package/templates/agent-plugin/agents/review-plan/requirements-coverage.md +62 -0
- package/templates/agent-plugin/agents/review-plan/security.md +1 -1
- package/templates/agent-plugin/agents/review-plan.md +9 -8
- package/templates/agent-plugin/agents/review.md +1 -1
- package/templates/agent-plugin/agents/test-spec.md +2 -2
- package/templates/agent-plugin/hooks/CLAUDE.md +2 -2
- package/templates/agent-plugin/hooks/explore-user-prompt.sh +13 -0
- package/templates/agent-plugin/hooks/plan-user-prompt.sh +1 -1
- package/templates/agent-plugin/hooks/require-submit.sh +69 -2
- package/templates/agent-plugin/hooks/review-plan-user-prompt.sh +4 -4
- package/templates/agent-plugin/hooks/review-user-prompt.sh +1 -1
- package/templates/agent-suffix.md +0 -2
- package/templates/orchestrator-base.md +167 -145
- package/templates/orchestrator-impl.md +92 -57
- package/templates/orchestrator-planning.md +46 -56
- package/templates/orchestrator-plugin/commands/sisyphus/design.md +13 -0
- package/templates/orchestrator-plugin/commands/sisyphus/problem.md +13 -0
- package/templates/orchestrator-plugin/commands/sisyphus/requirements.md +13 -0
- package/templates/orchestrator-plugin/commands/sisyphus/strategize.md +19 -0
- package/templates/orchestrator-plugin/hooks/explore-gate.sh +15 -0
- package/templates/orchestrator-plugin/hooks/hooks.json +14 -1
- package/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +34 -27
- package/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +56 -24
- package/templates/orchestrator-strategy.md +233 -0
- package/templates/orchestrator-validation.md +94 -0
- package/dist/chunk-MMA43N67.js.map +0 -1
- package/dist/chunk-Q6VQOUN3.js.map +0 -1
- package/dist/chunk-YGBGKMTF.js.map +0 -1
- package/dist/templates/agent-plugin/agents/review-plan/spec-coverage.md +0 -44
- package/dist/templates/agent-plugin/agents/spec-draft.md +0 -78
- package/dist/templates/agent-plugin/hooks/hooks.json +0 -25
- package/dist/templates/agent-plugin/hooks/spec-user-prompt.sh +0 -19
- package/dist/templates/orchestrator-plugin/skills/git-management/SKILL.md +0 -111
- package/templates/agent-plugin/agents/review-plan/spec-coverage.md +0 -44
- package/templates/agent-plugin/agents/spec-draft.md +0 -78
- package/templates/agent-plugin/hooks/hooks.json +0 -25
- package/templates/agent-plugin/hooks/spec-user-prompt.sh +0 -19
- package/templates/orchestrator-plugin/skills/git-management/SKILL.md +0 -111
- /package/dist/{paths-FYYSBD27.js.map → paths-IJXOAN4E.js.map} +0 -0
package/dist/tui.js
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
exec,
|
|
6
6
|
execSafe,
|
|
7
7
|
loadConfig
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-Z32YVDMY.js";
|
|
9
9
|
import {
|
|
10
10
|
buildSessionContext,
|
|
11
11
|
computeActiveTimeMs,
|
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
rawSend,
|
|
14
14
|
resolveReports,
|
|
15
15
|
statusColor
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-M7LZ2ZHD.js";
|
|
17
17
|
import {
|
|
18
18
|
shellQuote
|
|
19
19
|
} from "./chunk-6G226ZK7.js";
|
|
@@ -23,8 +23,9 @@ import {
|
|
|
23
23
|
goalPath,
|
|
24
24
|
logsDir,
|
|
25
25
|
roadmapPath,
|
|
26
|
-
sessionDir
|
|
27
|
-
|
|
26
|
+
sessionDir,
|
|
27
|
+
strategyPath
|
|
28
|
+
} from "./chunk-REUQ4B45.js";
|
|
28
29
|
|
|
29
30
|
// src/tui/terminal.ts
|
|
30
31
|
function emptyKey() {
|
|
@@ -311,6 +312,7 @@ function createAppState(cwd2) {
|
|
|
311
312
|
notification: null,
|
|
312
313
|
notificationTimer: null,
|
|
313
314
|
showLogs: false,
|
|
315
|
+
showStrategy: false,
|
|
314
316
|
inputText: "",
|
|
315
317
|
inputCursorPos: 0,
|
|
316
318
|
detailScroll,
|
|
@@ -318,6 +320,7 @@ function createAppState(cwd2) {
|
|
|
318
320
|
sessions: [],
|
|
319
321
|
selectedSession: null,
|
|
320
322
|
planContent: "",
|
|
323
|
+
strategyContent: "",
|
|
321
324
|
goalContent: "",
|
|
322
325
|
logsContent: "",
|
|
323
326
|
logsCycles: [],
|
|
@@ -393,7 +396,7 @@ function autoExpandCycle(state2) {
|
|
|
393
396
|
}
|
|
394
397
|
|
|
395
398
|
// src/tui/app.ts
|
|
396
|
-
import { readFileSync as readFileSync2, existsSync as existsSync2, readdirSync } from "fs";
|
|
399
|
+
import { readFileSync as readFileSync2, existsSync as existsSync2, readdirSync, statSync } from "fs";
|
|
397
400
|
import { join as join3 } from "path";
|
|
398
401
|
|
|
399
402
|
// src/tui/lib/tree.ts
|
|
@@ -544,6 +547,8 @@ function abbreviateMode(mode) {
|
|
|
544
547
|
if (!mode) return "";
|
|
545
548
|
if (mode === "implementation") return "impl";
|
|
546
549
|
if (mode === "planning") return "plan";
|
|
550
|
+
if (mode === "strategy") return "strat";
|
|
551
|
+
if (mode === "validation") return "valid";
|
|
547
552
|
return mode;
|
|
548
553
|
}
|
|
549
554
|
function ansiBold(text) {
|
|
@@ -564,22 +569,10 @@ function ansiColor(text, color, bold = false) {
|
|
|
564
569
|
function modeColor(mode) {
|
|
565
570
|
if (mode === "planning") return "blue";
|
|
566
571
|
if (mode === "implementation") return "green";
|
|
572
|
+
if (mode === "strategy") return "yellow";
|
|
573
|
+
if (mode === "validation") return "magenta";
|
|
567
574
|
return "cyan";
|
|
568
575
|
}
|
|
569
|
-
function mergeStatusDisplay(status) {
|
|
570
|
-
switch (status) {
|
|
571
|
-
case "merged":
|
|
572
|
-
return { icon: "\u2295", label: "merged", color: "green" };
|
|
573
|
-
case "pending":
|
|
574
|
-
return { icon: "\u25CC", label: "pending", color: "yellow" };
|
|
575
|
-
case "no-changes":
|
|
576
|
-
return { icon: "\u2205", label: "no changes", color: "gray" };
|
|
577
|
-
case "conflict":
|
|
578
|
-
return { icon: "\u26A0", label: "conflict", color: "red" };
|
|
579
|
-
default:
|
|
580
|
-
return null;
|
|
581
|
-
}
|
|
582
|
-
}
|
|
583
576
|
function wrapText(text, width) {
|
|
584
577
|
const cleaned = cleanMarkdown(text);
|
|
585
578
|
if (width <= 0) return cleaned.split("\n");
|
|
@@ -589,30 +582,32 @@ function wrapText(text, width) {
|
|
|
589
582
|
result.push(rawLine);
|
|
590
583
|
continue;
|
|
591
584
|
}
|
|
592
|
-
let
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
585
|
+
let lineStart = 0;
|
|
586
|
+
let lastSpace = -1;
|
|
587
|
+
let displayWidth = 0;
|
|
588
|
+
for (let i = 0; i < rawLine.length; i++) {
|
|
589
|
+
const charWidth = stringWidth(rawLine[i]);
|
|
590
|
+
displayWidth += charWidth;
|
|
591
|
+
if (rawLine[i] === " ") lastSpace = i;
|
|
592
|
+
if (displayWidth > width) {
|
|
593
|
+
let breakAt;
|
|
594
|
+
if (lastSpace > lineStart) {
|
|
595
|
+
breakAt = lastSpace;
|
|
596
|
+
result.push(rawLine.slice(lineStart, breakAt));
|
|
597
|
+
lineStart = breakAt + 1;
|
|
598
|
+
while (lineStart < rawLine.length && rawLine[lineStart] === " ") lineStart++;
|
|
599
|
+
} else {
|
|
600
|
+
breakAt = Math.max(lineStart + 1, i);
|
|
601
|
+
result.push(rawLine.slice(lineStart, breakAt));
|
|
602
|
+
lineStart = breakAt;
|
|
609
603
|
}
|
|
610
|
-
|
|
604
|
+
displayWidth = stringWidth(rawLine.slice(lineStart, i + 1));
|
|
605
|
+
lastSpace = -1;
|
|
611
606
|
}
|
|
612
|
-
result.push(remaining.slice(0, breakAt));
|
|
613
|
-
remaining = remaining.slice(breakAt).trimStart();
|
|
614
607
|
}
|
|
615
|
-
if (
|
|
608
|
+
if (lineStart < rawLine.length) {
|
|
609
|
+
result.push(rawLine.slice(lineStart));
|
|
610
|
+
}
|
|
616
611
|
}
|
|
617
612
|
return result;
|
|
618
613
|
}
|
|
@@ -674,6 +669,7 @@ function buildTree(sessions, selectedSession, expanded, cwd2, polledContextFiles
|
|
|
674
669
|
cycleNumber: cycle.cycle,
|
|
675
670
|
timestamp: cycle.timestamp,
|
|
676
671
|
completedAt: cycle.completedAt,
|
|
672
|
+
activeMs: cycle.activeMs,
|
|
677
673
|
agentCount: allCycleAgents.length,
|
|
678
674
|
mode: cycle.mode
|
|
679
675
|
});
|
|
@@ -695,8 +691,8 @@ function buildTree(sessions, selectedSession, expanded, cwd2, polledContextFiles
|
|
|
695
691
|
status: agent.status,
|
|
696
692
|
spawnedAt: agent.spawnedAt,
|
|
697
693
|
completedAt: agent.completedAt,
|
|
698
|
-
|
|
699
|
-
|
|
694
|
+
activeMs: agent.activeMs,
|
|
695
|
+
reportCount: agent.reports.length
|
|
700
696
|
});
|
|
701
697
|
if (!agentExpanded || !hasReports) continue;
|
|
702
698
|
for (let ri = 0; ri < agent.reports.length; ri++) {
|
|
@@ -1410,6 +1406,30 @@ function handleNavigateKey(input, key, state2, actions) {
|
|
|
1410
1406
|
})();
|
|
1411
1407
|
return;
|
|
1412
1408
|
}
|
|
1409
|
+
if (input === "o") {
|
|
1410
|
+
if (!cursorNode) {
|
|
1411
|
+
notify(state2, "No node selected");
|
|
1412
|
+
return;
|
|
1413
|
+
}
|
|
1414
|
+
let claudeSessionId;
|
|
1415
|
+
if (cursorNode.type === "agent" || cursorNode.type === "report") {
|
|
1416
|
+
const agent = actions.getAgentForNode(cursorNode);
|
|
1417
|
+
claudeSessionId = agent?.claudeSessionId ?? void 0;
|
|
1418
|
+
} else if (cursorNode.type === "cycle" && session) {
|
|
1419
|
+
const cycle = session.orchestratorCycles.find((c) => c.cycle === cursorNode.cycleNumber);
|
|
1420
|
+
claudeSessionId = cycle?.claudeSessionId;
|
|
1421
|
+
}
|
|
1422
|
+
if (!claudeSessionId) {
|
|
1423
|
+
notify(state2, "No Claude session ID available");
|
|
1424
|
+
return;
|
|
1425
|
+
}
|
|
1426
|
+
try {
|
|
1427
|
+
actions.openClaudeResumePopup(state2.cwd, claudeSessionId);
|
|
1428
|
+
} catch {
|
|
1429
|
+
notify(state2, "Failed to open Claude session");
|
|
1430
|
+
}
|
|
1431
|
+
return;
|
|
1432
|
+
}
|
|
1413
1433
|
if (input === "g") {
|
|
1414
1434
|
if (!state2.selectedSessionId) {
|
|
1415
1435
|
notify(state2, "No session selected");
|
|
@@ -1551,6 +1571,29 @@ function handleNavigateKey(input, key, state2, actions) {
|
|
|
1551
1571
|
}
|
|
1552
1572
|
return;
|
|
1553
1573
|
}
|
|
1574
|
+
if (input === "s") {
|
|
1575
|
+
if (!state2.strategyContent) {
|
|
1576
|
+
notify(state2, "No strategy for this session");
|
|
1577
|
+
return;
|
|
1578
|
+
}
|
|
1579
|
+
state2.showStrategy = !state2.showStrategy;
|
|
1580
|
+
requestRender();
|
|
1581
|
+
return;
|
|
1582
|
+
}
|
|
1583
|
+
if (input === "S") {
|
|
1584
|
+
if (!state2.selectedSessionId) {
|
|
1585
|
+
notify(state2, "No session selected");
|
|
1586
|
+
return;
|
|
1587
|
+
}
|
|
1588
|
+
const sp = strategyPath(state2.cwd, state2.selectedSessionId);
|
|
1589
|
+
const editor = actions.resolveEditor();
|
|
1590
|
+
try {
|
|
1591
|
+
actions.openEditorPopup(state2.cwd, editor, sp);
|
|
1592
|
+
} catch {
|
|
1593
|
+
notify(state2, `Failed to open strategy in ${editor}`);
|
|
1594
|
+
}
|
|
1595
|
+
return;
|
|
1596
|
+
}
|
|
1554
1597
|
if (input === "t") {
|
|
1555
1598
|
if (state2.showLogs) {
|
|
1556
1599
|
if (state2.focusPane === "logs") state2.focusPane = "detail";
|
|
@@ -1831,6 +1874,14 @@ function openShellPopup(cwd2, command) {
|
|
|
1831
1874
|
function openInFileManager(path) {
|
|
1832
1875
|
execSync(`open ${shellQuote(path)}`, { stdio: "inherit", env: EXEC_ENV });
|
|
1833
1876
|
}
|
|
1877
|
+
function openClaudeResumePopup(cwd2, claudeSessionId) {
|
|
1878
|
+
const pathEnv = augmentedPath();
|
|
1879
|
+
const cmd = `PATH=${shellQuote(pathEnv)} claude --resume ${shellQuote(claudeSessionId)}`;
|
|
1880
|
+
execSync(
|
|
1881
|
+
`tmux display-popup -E -w 90% -h 80% -d ${shellQuote(cwd2)} ${shellQuote(cmd)}`,
|
|
1882
|
+
{ stdio: "inherit", env: EXEC_ENV }
|
|
1883
|
+
);
|
|
1884
|
+
}
|
|
1834
1885
|
function openEditorPopup(cwd2, editor, filePath, size) {
|
|
1835
1886
|
const { w = "90%", h = "90%" } = size ?? {};
|
|
1836
1887
|
const editorBin = editor.split(/\s+/)[0].split("/").pop();
|
|
@@ -1902,7 +1953,7 @@ function renderNodeContent(node, maxWidth) {
|
|
|
1902
1953
|
}
|
|
1903
1954
|
case "cycle": {
|
|
1904
1955
|
const isRunning = !node.completedAt;
|
|
1905
|
-
const dur =
|
|
1956
|
+
const dur = isRunning ? "running" : formatDuration(node.activeMs);
|
|
1906
1957
|
const agents = `${node.agentCount} agent${node.agentCount !== 1 ? "s" : ""}`;
|
|
1907
1958
|
const modeShort = abbreviateMode(node.mode);
|
|
1908
1959
|
const mode = modeShort ? ` \xB7 ${modeShort}` : "";
|
|
@@ -1917,34 +1968,22 @@ function renderNodeContent(node, maxWidth) {
|
|
|
1917
1968
|
case "agent": {
|
|
1918
1969
|
const icon = agentStatusIcon(node.status);
|
|
1919
1970
|
const color = statusColor(node.status);
|
|
1920
|
-
const dur = formatDuration(node.
|
|
1921
|
-
const durClr = durationColor(node.
|
|
1971
|
+
const dur = formatDuration(node.activeMs);
|
|
1972
|
+
const durClr = durationColor(node.activeMs) || void 0;
|
|
1922
1973
|
const dim = node.status === "completed";
|
|
1923
1974
|
const displayName = agentDisplayName({
|
|
1924
1975
|
name: node.name,
|
|
1925
1976
|
id: node.agentId,
|
|
1926
1977
|
agentType: node.agentType
|
|
1927
1978
|
});
|
|
1928
|
-
|
|
1929
|
-
let suffixColor;
|
|
1930
|
-
if (node.mergeStatus) {
|
|
1931
|
-
const ms = node.mergeStatus === "pending" ? { icon: "\u2387", color: "yellow" } : mergeStatusDisplay(node.mergeStatus);
|
|
1932
|
-
if (ms) {
|
|
1933
|
-
suffix = ms.icon;
|
|
1934
|
-
suffixColor = ms.color;
|
|
1935
|
-
}
|
|
1936
|
-
}
|
|
1937
|
-
const suffixLen = suffix ? 2 : 0;
|
|
1938
|
-
const maxLabel = Math.max(8, maxWidth - dur.length - suffixLen - 4);
|
|
1979
|
+
const maxLabel = Math.max(8, maxWidth - dur.length - 4);
|
|
1939
1980
|
return {
|
|
1940
1981
|
icon,
|
|
1941
1982
|
label: truncate(displayName, maxLabel),
|
|
1942
1983
|
meta: dur,
|
|
1943
1984
|
color,
|
|
1944
1985
|
dim,
|
|
1945
|
-
metaColor: durClr
|
|
1946
|
-
suffix,
|
|
1947
|
-
suffixColor
|
|
1986
|
+
metaColor: durClr
|
|
1948
1987
|
};
|
|
1949
1988
|
}
|
|
1950
1989
|
case "report": {
|
|
@@ -2148,14 +2187,13 @@ function buildPlanLines(content, maxLines, width) {
|
|
|
2148
2187
|
}
|
|
2149
2188
|
return lines;
|
|
2150
2189
|
}
|
|
2151
|
-
function buildSessionLines(session, planContent, goalContent, width, paneAlive) {
|
|
2190
|
+
function buildSessionLines(session, planContent, goalContent, width, paneAlive, strategyContent = "", showStrategy = false) {
|
|
2152
2191
|
const lines = [];
|
|
2153
2192
|
const contentWidth = width - 4;
|
|
2154
2193
|
const agents = session.agents;
|
|
2155
2194
|
const cycles = session.orchestratorCycles;
|
|
2156
2195
|
const messages = session.messages;
|
|
2157
2196
|
const isDead = session.status === "active" && !paneAlive;
|
|
2158
|
-
const conflicts = agents.filter((a) => a.mergeStatus === "conflict");
|
|
2159
2197
|
const goalText = goalContent ? cleanMarkdown(stripFrontmatter(goalContent).trim()) : session.task;
|
|
2160
2198
|
goalText.split("\n").flatMap((l) => wrapText(l, contentWidth - 2)).forEach((line, i) => {
|
|
2161
2199
|
lines.push(singleLine(`${i === 0 ? " " : " "}${line}`, { bold: true }));
|
|
@@ -2189,28 +2227,34 @@ function buildSessionLines(session, planContent, goalContent, width, paneAlive)
|
|
|
2189
2227
|
seg(" tmux window closed \u2014 [w] reopen [R] resume", { color: "red" })
|
|
2190
2228
|
]);
|
|
2191
2229
|
}
|
|
2192
|
-
if (conflicts.length > 0) {
|
|
2193
|
-
lines.push(
|
|
2194
|
-
singleLine(
|
|
2195
|
-
` \u26A0 ${conflicts.length} merge conflict${conflicts.length > 1 ? "s" : ""}`,
|
|
2196
|
-
{ color: "red", bold: true }
|
|
2197
|
-
)
|
|
2198
|
-
);
|
|
2199
|
-
lines.push(
|
|
2200
|
-
singleLine(
|
|
2201
|
-
" resolve in worktree, then [x] restart agent",
|
|
2202
|
-
{ color: "red", dim: true }
|
|
2203
|
-
)
|
|
2204
|
-
);
|
|
2205
|
-
}
|
|
2206
2230
|
lines.push(singleLine(" "));
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2231
|
+
if (showStrategy && strategyContent) {
|
|
2232
|
+
const stratHint = strategyContent ? " [s] toggle plan" : "";
|
|
2233
|
+
lines.push([
|
|
2234
|
+
seg(" \u258E \u25C8 STRATEGY", { color: "yellow", bold: true }),
|
|
2235
|
+
seg(stratHint, { dim: true })
|
|
2236
|
+
]);
|
|
2237
|
+
const stratLines = buildPlanLines(strategyContent, 99999, width);
|
|
2238
|
+
if (stratLines.length === 0) {
|
|
2239
|
+
lines.push(singleLine(" (empty)", { dim: true, italic: true }));
|
|
2240
|
+
} else {
|
|
2241
|
+
for (const pl of stratLines) {
|
|
2242
|
+
lines.push(singleLine(pl.text, { bold: pl.bold, dim: pl.dim, color: pl.color }));
|
|
2243
|
+
}
|
|
2244
|
+
}
|
|
2211
2245
|
} else {
|
|
2212
|
-
|
|
2213
|
-
|
|
2246
|
+
const toggleHint = strategyContent ? " [s] toggle strategy" : "";
|
|
2247
|
+
lines.push([
|
|
2248
|
+
seg(" \u258E \u25C8 PLAN", { color: "yellow", bold: true }),
|
|
2249
|
+
seg(toggleHint, { dim: true })
|
|
2250
|
+
]);
|
|
2251
|
+
const planLines = buildPlanLines(planContent, 99999, width);
|
|
2252
|
+
if (planLines.length === 0) {
|
|
2253
|
+
lines.push(singleLine(" orchestrator will create one", { dim: true, italic: true }));
|
|
2254
|
+
} else {
|
|
2255
|
+
for (const pl of planLines) {
|
|
2256
|
+
lines.push(singleLine(pl.text, { bold: pl.bold, dim: pl.dim, color: pl.color }));
|
|
2257
|
+
}
|
|
2214
2258
|
}
|
|
2215
2259
|
}
|
|
2216
2260
|
if (session.status === "completed" && session.completionReport) {
|
|
@@ -2258,7 +2302,7 @@ function buildSessionLines(session, planContent, goalContent, width, paneAlive)
|
|
|
2258
2302
|
const dot = isRunning ? "\u25CF" : "\u25CB";
|
|
2259
2303
|
const dotColor = isRunning ? "green" : isNewest ? "white" : "gray";
|
|
2260
2304
|
const rowDim = !isRunning && !isNewest && !isSecond;
|
|
2261
|
-
const duration = isRunning ? "running" : formatDuration(cycle.
|
|
2305
|
+
const duration = isRunning ? "running" : formatDuration(cycle.activeMs);
|
|
2262
2306
|
const n = cycle.agentsSpawned.length;
|
|
2263
2307
|
const startTime = formatTime(cycle.timestamp);
|
|
2264
2308
|
const modeLabel = abbreviateMode(cycle.mode);
|
|
@@ -2314,7 +2358,7 @@ function buildCycleLines(cycle, agents, width) {
|
|
|
2314
2358
|
const lines = [];
|
|
2315
2359
|
const contentWidth = width - 4;
|
|
2316
2360
|
const isRunning = !cycle.completedAt;
|
|
2317
|
-
const dur =
|
|
2361
|
+
const dur = isRunning ? "running" : formatDuration(cycle.activeMs);
|
|
2318
2362
|
const cycleAgents = agents.filter((a) => cycle.agentsSpawned.includes(a.id));
|
|
2319
2363
|
lines.push(singleLine(` Cycle ${cycle.cycle}`, { bold: true }));
|
|
2320
2364
|
lines.push([
|
|
@@ -2327,6 +2371,9 @@ function buildCycleLines(cycle, agents, width) {
|
|
|
2327
2371
|
` ${formatTime(cycle.timestamp)}${cycle.completedAt ? ` \u2192 ${formatTime(cycle.completedAt)}` : ""}`,
|
|
2328
2372
|
{ dim: true }
|
|
2329
2373
|
));
|
|
2374
|
+
if (cycle.claudeSessionId) {
|
|
2375
|
+
lines.push(singleLine(` Session: ${cycle.claudeSessionId}`, { dim: true }));
|
|
2376
|
+
}
|
|
2330
2377
|
lines.push(singleLine(" "));
|
|
2331
2378
|
lines.push([seg(" \u258E \u229E AGENTS", { color: "green", bold: true })]);
|
|
2332
2379
|
if (cycleAgents.length === 0) {
|
|
@@ -2337,8 +2384,8 @@ function buildCycleLines(cycle, agents, width) {
|
|
|
2337
2384
|
const instrPreview = agent.instruction.split("\n")[0];
|
|
2338
2385
|
const latestReport = agent.reports.length > 0 ? agent.reports[agent.reports.length - 1] : null;
|
|
2339
2386
|
const reportSummary = latestReport !== null && agent.status === "completed" ? extractFirstSentence(latestReport.summary, contentWidth - 14) : null;
|
|
2340
|
-
const agentDur = formatDuration(agent.
|
|
2341
|
-
const durClrRaw = durationColor(agent.
|
|
2387
|
+
const agentDur = formatDuration(agent.activeMs);
|
|
2388
|
+
const durClrRaw = durationColor(agent.activeMs);
|
|
2342
2389
|
const durClr = durClrRaw !== "" ? durClrRaw : void 0;
|
|
2343
2390
|
const typeClrRaw = agentTypeColor(agent.agentType);
|
|
2344
2391
|
const typeClr = typeClrRaw !== void 0 ? typeClrRaw : void 0;
|
|
@@ -2377,34 +2424,23 @@ function buildCycleLines(cycle, agents, width) {
|
|
|
2377
2424
|
function buildAgentLines(agent, reportBlocks, width) {
|
|
2378
2425
|
const lines = [];
|
|
2379
2426
|
const contentWidth = width - 4;
|
|
2380
|
-
const dur = formatDuration(agent.
|
|
2427
|
+
const dur = formatDuration(agent.activeMs);
|
|
2381
2428
|
const icon = agentStatusIcon(agent.status);
|
|
2382
2429
|
const color = statusColor(agent.status);
|
|
2383
2430
|
const nameLabel = agentDisplayName(agent);
|
|
2384
|
-
const maxMergeLines = 3;
|
|
2385
2431
|
lines.push([
|
|
2386
2432
|
seg(" "),
|
|
2387
2433
|
seg(icon, { color }),
|
|
2388
2434
|
seg(` ${agent.id} \xB7 ${nameLabel}`, { bold: true })
|
|
2389
2435
|
]);
|
|
2390
|
-
const merge = agent.mergeStatus ? mergeStatusDisplay(agent.mergeStatus) : null;
|
|
2391
2436
|
lines.push([
|
|
2392
2437
|
seg(" "),
|
|
2393
2438
|
seg(agent.status, { color }),
|
|
2394
|
-
seg(` \xB7 ${dur} \xB7 ${agent.agentType}`, { dim: true })
|
|
2395
|
-
...merge ? [seg(" \xB7 ", { dim: true }), seg(`${merge.icon} ${merge.label}`, { color: merge.color })] : agent.mergeStatus ? [seg(" \xB7 ", { dim: true }), seg(agent.mergeStatus, { dim: true })] : []
|
|
2439
|
+
seg(` \xB7 ${dur} \xB7 ${agent.agentType}`, { dim: true })
|
|
2396
2440
|
]);
|
|
2397
2441
|
if (agent.killedReason) {
|
|
2398
2442
|
lines.push(singleLine(` \u26A0 ${agent.killedReason}`, { color: "red" }));
|
|
2399
2443
|
}
|
|
2400
|
-
if (agent.mergeStatus === "conflict" && agent.mergeDetails) {
|
|
2401
|
-
for (const ml of wrapText(agent.mergeDetails, contentWidth - 6).slice(0, maxMergeLines)) {
|
|
2402
|
-
lines.push(singleLine(` \u26A0 ${ml}`, { color: "red" }));
|
|
2403
|
-
}
|
|
2404
|
-
}
|
|
2405
|
-
if (agent.mergeStatus === "conflict") {
|
|
2406
|
-
lines.push(singleLine(" resolve conflicts in worktree dir, then restart", { color: "red", dim: true }));
|
|
2407
|
-
}
|
|
2408
2444
|
lines.push(singleLine(" "));
|
|
2409
2445
|
lines.push(singleLine(" \u258E \u25B7 INSTRUCTION", { color: "white", bold: true }));
|
|
2410
2446
|
for (const wl of wrapText(agent.instruction, contentWidth - 6)) {
|
|
@@ -2445,21 +2481,18 @@ function buildAgentLines(agent, reportBlocks, width) {
|
|
|
2445
2481
|
if (agent.completedAt) {
|
|
2446
2482
|
lines.push(singleLine(` Completed: ${formatTime(agent.completedAt)}`, { dim: true }));
|
|
2447
2483
|
}
|
|
2484
|
+
if (agent.claudeSessionId) {
|
|
2485
|
+
lines.push(singleLine(` Session: ${agent.claudeSessionId}`, { dim: true }));
|
|
2486
|
+
}
|
|
2448
2487
|
if (agent.paneId) {
|
|
2449
2488
|
lines.push(singleLine(` Pane: ${agent.paneId}`, { dim: true }));
|
|
2450
2489
|
}
|
|
2451
|
-
if (agent.worktreePath) {
|
|
2452
|
-
lines.push(singleLine(` Worktree: ${agent.worktreePath}`, { dim: true }));
|
|
2453
|
-
}
|
|
2454
|
-
if (agent.branchName) {
|
|
2455
|
-
lines.push(singleLine(` Branch: ${agent.branchName}`, { dim: true }));
|
|
2456
|
-
}
|
|
2457
2490
|
return lines;
|
|
2458
2491
|
}
|
|
2459
2492
|
function buildReportViewLines(agent, reportBlocks, width) {
|
|
2460
2493
|
const lines = [];
|
|
2461
2494
|
const contentWidth = width - 6;
|
|
2462
|
-
const dur = formatDuration(agent.
|
|
2495
|
+
const dur = formatDuration(agent.activeMs);
|
|
2463
2496
|
const icon = agentStatusIcon(agent.status);
|
|
2464
2497
|
const color = statusColor(agent.status);
|
|
2465
2498
|
const totalReports = agent.reports.length;
|
|
@@ -2552,14 +2585,14 @@ function renderDetailContent(buf, rect, state2, detailCtx) {
|
|
|
2552
2585
|
let borderColor = "gray";
|
|
2553
2586
|
switch (cursorNode.type) {
|
|
2554
2587
|
case "session": {
|
|
2555
|
-
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive);
|
|
2588
|
+
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive, state2.strategyContent, state2.showStrategy);
|
|
2556
2589
|
break;
|
|
2557
2590
|
}
|
|
2558
2591
|
case "cycle": {
|
|
2559
2592
|
const cycleNode = cursorNode;
|
|
2560
2593
|
const cycle = session.orchestratorCycles.find((c) => c.cycle === cycleNode.cycleNumber);
|
|
2561
2594
|
if (!cycle) {
|
|
2562
|
-
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive);
|
|
2595
|
+
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive, state2.strategyContent, state2.showStrategy);
|
|
2563
2596
|
} else {
|
|
2564
2597
|
lines = buildCycleLines(cycle, session.agents, rect.w);
|
|
2565
2598
|
}
|
|
@@ -2569,7 +2602,7 @@ function renderDetailContent(buf, rect, state2, detailCtx) {
|
|
|
2569
2602
|
const agentNode = cursorNode;
|
|
2570
2603
|
const agent = agents.find((a) => a.id === agentNode.agentId);
|
|
2571
2604
|
if (!agent) {
|
|
2572
|
-
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive);
|
|
2605
|
+
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive, state2.strategyContent, state2.showStrategy);
|
|
2573
2606
|
} else {
|
|
2574
2607
|
lines = buildAgentLines(agent, detailReportBlocks, rect.w);
|
|
2575
2608
|
}
|
|
@@ -2579,7 +2612,7 @@ function renderDetailContent(buf, rect, state2, detailCtx) {
|
|
|
2579
2612
|
const reportNode = cursorNode;
|
|
2580
2613
|
const agent = agents.find((a) => a.id === reportNode.agentId);
|
|
2581
2614
|
if (!agent) {
|
|
2582
|
-
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive);
|
|
2615
|
+
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive, state2.strategyContent, state2.showStrategy);
|
|
2583
2616
|
break;
|
|
2584
2617
|
}
|
|
2585
2618
|
const reportIdx = reportNode.reportIndex;
|
|
@@ -2671,7 +2704,7 @@ function renderDetailContent(buf, rect, state2, detailCtx) {
|
|
|
2671
2704
|
break;
|
|
2672
2705
|
}
|
|
2673
2706
|
default: {
|
|
2674
|
-
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive);
|
|
2707
|
+
lines = buildSessionLines(session, state2.planContent, state2.goalContent, rect.w, state2.paneAlive, state2.strategyContent, state2.showStrategy);
|
|
2675
2708
|
break;
|
|
2676
2709
|
}
|
|
2677
2710
|
}
|
|
@@ -2744,7 +2777,7 @@ function renderStatusLine(buf, y, state2, cursorNodeType) {
|
|
|
2744
2777
|
} else if (mode !== "navigate") {
|
|
2745
2778
|
content = D("[enter] send [esc] cancel");
|
|
2746
2779
|
} else if (focusPane === "logs" || focusPane === "detail") {
|
|
2747
|
-
content = B("[jk/\u2191\u2193]") + D(" scroll ") + B("[h/\u2190/tab]") + D(" back ") + B("[t]") + D("oggle logs ") + SEP + B("[m]") + D("sg ") + B("[g]") + D("oal ") + B("[n]") + D("ew ") + B("[p]") + D("lan ") + B("[w]") + D("indow ") + B("[R]") + D("esume ") + B("[q]") + D("uit");
|
|
2780
|
+
content = B("[jk/\u2191\u2193]") + D(" scroll ") + B("[h/\u2190/tab]") + D(" back ") + B("[t]") + D("oggle logs ") + SEP + B("[m]") + D("sg ") + B("[g]") + D("oal ") + B("[n]") + D("ew ") + B("[p]") + D("lan ") + B("[s]") + D("trat ") + B("[w]") + D("indow ") + B("[R]") + D("esume ") + B("[q]") + D("uit");
|
|
2748
2781
|
} else {
|
|
2749
2782
|
let contextFilePart = "";
|
|
2750
2783
|
if (cursorNodeType === "context-file") {
|
|
@@ -2821,8 +2854,10 @@ function renderHelpOverlay(buf, rows, cols) {
|
|
|
2821
2854
|
helpRow(" R resume session", " C continue session", innerWidth),
|
|
2822
2855
|
helpRow(" b rollback cycle", " x restart agent", innerWidth),
|
|
2823
2856
|
helpRow(" r re-run agent", " g edit goal", innerWidth),
|
|
2824
|
-
helpRow(" p open roadmap", "
|
|
2825
|
-
helpRow("
|
|
2857
|
+
helpRow(" p open roadmap", " s toggle strategy", innerWidth),
|
|
2858
|
+
helpRow(" S edit strategy", " w go to window", innerWidth),
|
|
2859
|
+
helpRow(" o resume claude session", " c claude companion", innerWidth),
|
|
2860
|
+
helpRow(" q quit", "", innerWidth),
|
|
2826
2861
|
" ".padEnd(innerWidth),
|
|
2827
2862
|
helpRow(" space \u2192 y copy submenu", " space \u2192 d delete session", innerWidth),
|
|
2828
2863
|
helpRow(" space \u2192 j jump to pane", " space \u2192 k kill", innerWidth),
|
|
@@ -2854,6 +2889,8 @@ var latestNodes = [];
|
|
|
2854
2889
|
var cachedContextFilePath = null;
|
|
2855
2890
|
var cachedContextFileContent = null;
|
|
2856
2891
|
var prevFrame = [];
|
|
2892
|
+
var cachedLogSessionId = null;
|
|
2893
|
+
var cachedLogFiles = /* @__PURE__ */ new Map();
|
|
2857
2894
|
function getAgentForNode(node, agents) {
|
|
2858
2895
|
if (!node) return null;
|
|
2859
2896
|
if (node.type === "agent" || node.type === "report") {
|
|
@@ -2868,6 +2905,7 @@ function startApp(state2, cleanup2) {
|
|
|
2868
2905
|
try {
|
|
2869
2906
|
let selectedSession = null;
|
|
2870
2907
|
let planContent = "";
|
|
2908
|
+
let strategyContent = "";
|
|
2871
2909
|
let goalContent = "";
|
|
2872
2910
|
let logsContent = "";
|
|
2873
2911
|
let logsCycles = [];
|
|
@@ -2911,15 +2949,39 @@ function startApp(state2, cleanup2) {
|
|
|
2911
2949
|
}
|
|
2912
2950
|
} catch {
|
|
2913
2951
|
}
|
|
2952
|
+
try {
|
|
2953
|
+
const sp = strategyPath(state2.cwd, state2.selectedSessionId);
|
|
2954
|
+
if (existsSync2(sp)) {
|
|
2955
|
+
strategyContent = readFileSync2(sp, "utf-8");
|
|
2956
|
+
}
|
|
2957
|
+
} catch {
|
|
2958
|
+
}
|
|
2914
2959
|
try {
|
|
2915
2960
|
const ld = logsDir(state2.cwd, state2.selectedSessionId);
|
|
2916
2961
|
if (existsSync2(ld)) {
|
|
2962
|
+
if (state2.selectedSessionId !== cachedLogSessionId) {
|
|
2963
|
+
cachedLogFiles = /* @__PURE__ */ new Map();
|
|
2964
|
+
cachedLogSessionId = state2.selectedSessionId;
|
|
2965
|
+
}
|
|
2917
2966
|
const files = readdirSync(ld).filter((f) => f.startsWith("cycle-")).sort();
|
|
2967
|
+
const fileSet = new Set(files);
|
|
2968
|
+
for (const key of cachedLogFiles.keys()) {
|
|
2969
|
+
if (!fileSet.has(key)) cachedLogFiles.delete(key);
|
|
2970
|
+
}
|
|
2971
|
+
for (const f of files) {
|
|
2972
|
+
const filePath = join3(ld, f);
|
|
2973
|
+
const mtime = statSync(filePath).mtimeMs;
|
|
2974
|
+
const cached = cachedLogFiles.get(f);
|
|
2975
|
+
if (!cached || cached.mtime !== mtime) {
|
|
2976
|
+
const match = f.match(/cycle-(\d+)\.md$/);
|
|
2977
|
+
const cycle = match ? parseInt(match[1], 10) : 0;
|
|
2978
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
2979
|
+
cachedLogFiles.set(f, { mtime, cycle, content });
|
|
2980
|
+
}
|
|
2981
|
+
}
|
|
2918
2982
|
logsCycles = files.map((f) => {
|
|
2919
|
-
const
|
|
2920
|
-
|
|
2921
|
-
const content = readFileSync2(join3(ld, f), "utf-8");
|
|
2922
|
-
return { cycle, content };
|
|
2983
|
+
const entry = cachedLogFiles.get(f);
|
|
2984
|
+
return { cycle: entry.cycle, content: entry.content };
|
|
2923
2985
|
});
|
|
2924
2986
|
logsContent = logsCycles.map((c) => c.content).join("\n");
|
|
2925
2987
|
}
|
|
@@ -2942,6 +3004,7 @@ function startApp(state2, cleanup2) {
|
|
|
2942
3004
|
state2.sessions = sessions;
|
|
2943
3005
|
state2.selectedSession = selectedSession;
|
|
2944
3006
|
state2.planContent = planContent;
|
|
3007
|
+
state2.strategyContent = strategyContent;
|
|
2945
3008
|
state2.goalContent = goalContent;
|
|
2946
3009
|
state2.logsContent = logsContent;
|
|
2947
3010
|
state2.logsCycles = logsCycles;
|
|
@@ -3088,6 +3151,7 @@ function startApp(state2, cleanup2) {
|
|
|
3088
3151
|
openEditorPopup,
|
|
3089
3152
|
editInPopup,
|
|
3090
3153
|
openCompanionPane,
|
|
3154
|
+
openClaudeResumePopup,
|
|
3091
3155
|
selectWindow,
|
|
3092
3156
|
selectPane,
|
|
3093
3157
|
switchToSession,
|
|
@@ -3107,10 +3171,10 @@ function startApp(state2, cleanup2) {
|
|
|
3107
3171
|
}
|
|
3108
3172
|
};
|
|
3109
3173
|
setRenderFunction(render);
|
|
3110
|
-
startKeypressListener((input, key) => {
|
|
3174
|
+
const stopKeypress = startKeypressListener((input, key) => {
|
|
3111
3175
|
handleKeypress(input, key, state2, inputActions);
|
|
3112
3176
|
});
|
|
3113
|
-
onResize(() => {
|
|
3177
|
+
const stopResize = onResize(() => {
|
|
3114
3178
|
const stdoutRows = process.stdout.rows;
|
|
3115
3179
|
const stdoutCols = process.stdout.columns;
|
|
3116
3180
|
state2.rows = typeof stdoutRows === "number" && stdoutRows > 0 ? stdoutRows : 24;
|
|
@@ -3119,7 +3183,16 @@ function startApp(state2, cleanup2) {
|
|
|
3119
3183
|
requestRender();
|
|
3120
3184
|
});
|
|
3121
3185
|
void poll();
|
|
3122
|
-
setInterval(() => void poll(), 2500);
|
|
3186
|
+
const pollInterval = setInterval(() => void poll(), 2500);
|
|
3187
|
+
const origCleanup = inputActions.cleanup;
|
|
3188
|
+
inputActions.cleanup = () => {
|
|
3189
|
+
clearInterval(pollInterval);
|
|
3190
|
+
stopKeypress();
|
|
3191
|
+
stopResize();
|
|
3192
|
+
state2.detailScroll.destroy();
|
|
3193
|
+
state2.logsScroll.destroy();
|
|
3194
|
+
origCleanup();
|
|
3195
|
+
};
|
|
3123
3196
|
requestRender();
|
|
3124
3197
|
}
|
|
3125
3198
|
|