sisyphi 1.1.11 → 1.1.13

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 CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  execEnv,
6
6
  execSafe,
7
7
  loadConfig
8
- } from "./chunk-ZSIYQB45.js";
8
+ } from "./chunk-CAJEBTUE.js";
9
9
  import {
10
10
  shellQuote
11
11
  } from "./chunk-6G226ZK7.js";
@@ -339,7 +339,7 @@ function deleteSnapshotsAfter(cwd, sessionId, afterCycle) {
339
339
  import { existsSync as existsSync5, readdirSync as readdirSync4, readFileSync as readFileSync4, writeFileSync as writeFileSync4 } from "fs";
340
340
  import { execSync as execSync2 } from "child_process";
341
341
  import { randomUUID as randomUUID3 } from "crypto";
342
- import { resolve as resolve3, join as join4 } from "path";
342
+ import { resolve as resolve3, join as join4, relative } from "path";
343
343
 
344
344
  // src/daemon/spawn-helpers.ts
345
345
  import { writeFileSync as writeFileSync2, existsSync as existsSync2 } from "fs";
@@ -603,9 +603,14 @@ function setPaneStyle(paneTarget, color, meta) {
603
603
  execSafe(`tmux set -p -t "${paneTarget}" @pane_role ${shellQuote(meta.role)}`);
604
604
  execSafe(`tmux set -p -t "${paneTarget}" @pane_session ${shellQuote(meta.session)}`);
605
605
  execSafe(`tmux set -p -t "${paneTarget}" @pane_cycle ${shellQuote(meta.cycle)}`);
606
+ if (meta.mode) {
607
+ execSafe(`tmux set -p -t "${paneTarget}" @pane_mode ${shellQuote(meta.mode)}`);
608
+ }
609
+ const modeSegment = `#{?#{@pane_mode}, #[fg=${color}\\,italics]#{@pane_mode}#[default],}`;
606
610
  const fmt = [
607
611
  `#[bg=${color},fg=black,bold] #{@pane_role} #[default]`,
608
612
  ` #[fg=${color},bold]#{@pane_session}`,
613
+ modeSegment,
609
614
  ` #[default,dim]#{@pane_cycle}`,
610
615
  ` ${homePath}${branchSuffix}`,
611
616
  `#[default]`
@@ -619,6 +624,7 @@ function updatePaneMeta(paneTarget, updates) {
619
624
  if (updates.role !== void 0) execSafe(`tmux set -p -t "${paneTarget}" @pane_role ${shellQuote(updates.role)}`);
620
625
  if (updates.session !== void 0) execSafe(`tmux set -p -t "${paneTarget}" @pane_session ${shellQuote(updates.session)}`);
621
626
  if (updates.cycle !== void 0) execSafe(`tmux set -p -t "${paneTarget}" @pane_cycle ${shellQuote(updates.cycle)}`);
627
+ if (updates.mode !== void 0) execSafe(`tmux set -p -t "${paneTarget}" @pane_mode ${shellQuote(updates.mode)}`);
622
628
  }
623
629
  function selectLayout(windowTarget, layout = "even-horizontal") {
624
630
  execSafe(`tmux select-layout -t "${windowTarget}" ${layout}`);
@@ -1328,6 +1334,18 @@ function getOrchestratorPaneId(sessionId) {
1328
1334
  function setOrchestratorPaneId(sessionId, paneId) {
1329
1335
  sessionOrchestratorPane.set(sessionId, paneId);
1330
1336
  }
1337
+ function discoverOrchestratorModes() {
1338
+ const templatesDir = resolve3(import.meta.dirname, "../templates");
1339
+ const files = readdirSync4(templatesDir).filter(
1340
+ (f) => f.startsWith("orchestrator-") && f.endsWith(".md") && f !== "orchestrator-base.md"
1341
+ );
1342
+ return files.map((file) => {
1343
+ const content = readFileSync4(join4(templatesDir, file), "utf-8");
1344
+ const fm = parseAgentFrontmatter(content);
1345
+ const name = fm.name ?? file.replace(/^orchestrator-/, "").replace(/\.md$/, "");
1346
+ return { name, description: fm.description, filePath: join4(templatesDir, file) };
1347
+ });
1348
+ }
1331
1349
  function loadOrchestratorPrompt(cwd, sessionId, mode) {
1332
1350
  const projectPath = projectOrchestratorPromptPath(cwd);
1333
1351
  if (existsSync5(projectPath)) {
@@ -1335,24 +1353,14 @@ function loadOrchestratorPrompt(cwd, sessionId, mode) {
1335
1353
  }
1336
1354
  const basePath = resolve3(import.meta.dirname, "../templates/orchestrator-base.md");
1337
1355
  const base = readFileSync4(basePath, "utf-8");
1338
- let modePrompt;
1339
- if (mode === "strategy") {
1340
- const strategyTemplatePath = resolve3(import.meta.dirname, "../templates/orchestrator-strategy.md");
1341
- modePrompt = readFileSync4(strategyTemplatePath, "utf-8");
1342
- } else if (mode === "implementation") {
1343
- const implPath = resolve3(import.meta.dirname, "../templates/orchestrator-impl.md");
1344
- modePrompt = readFileSync4(implPath, "utf-8");
1345
- } else if (mode === "validation") {
1346
- const validationPath = resolve3(import.meta.dirname, "../templates/orchestrator-validation.md");
1347
- modePrompt = readFileSync4(validationPath, "utf-8");
1348
- } else if (mode === "completion") {
1349
- const completionPath = resolve3(import.meta.dirname, "../templates/orchestrator-completion.md");
1350
- modePrompt = readFileSync4(completionPath, "utf-8");
1351
- } else {
1352
- const planningPath = resolve3(import.meta.dirname, "../templates/orchestrator-planning.md");
1353
- modePrompt = readFileSync4(planningPath, "utf-8");
1356
+ const modes = discoverOrchestratorModes();
1357
+ const selected = modes.find((m) => m.name === mode) ?? modes.find((m) => m.name === "strategy");
1358
+ if (!selected) {
1359
+ throw new Error(`Unknown orchestrator mode '${mode}' and no fallback found. Available: ${modes.map((m) => m.name).join(", ")}`);
1354
1360
  }
1355
- return base + "\n\n" + modePrompt;
1361
+ const modeContent = readFileSync4(selected.filePath, "utf-8");
1362
+ const modeBody = extractAgentBody(modeContent);
1363
+ return base + "\n\n" + modeBody;
1356
1364
  }
1357
1365
  function formatStateForOrchestrator(session) {
1358
1366
  const cycleNum = session.orchestratorCycles.length;
@@ -1374,37 +1382,19 @@ ${session.context}
1374
1382
  ctxFiles = readdirSync4(ctxDir).filter((f) => f !== "CLAUDE.md");
1375
1383
  }
1376
1384
  if (ctxFiles.length > 0) {
1377
- const ctxLines = ctxFiles.map((f) => `- ${join4(ctxDir, f)}`).join("\n");
1378
1385
  contextSection = `
1379
1386
  ## Context
1380
1387
 
1381
- ${ctxLines}
1388
+ @${relative(session.cwd, ctxDir)}
1382
1389
  `;
1383
1390
  }
1384
1391
  }
1385
1392
  const messages = session.messages ?? [];
1386
1393
  const messagesSection = messages.length > 0 ? "\n### Messages\n\n" + messages.map((m) => {
1387
1394
  const sourceLabel = m.source.type === "agent" ? `agent:${m.source.agentId}` : m.source.type === "system" && m.source.detail ? `system:${m.source.detail}` : m.source.type;
1388
- const fileRef = m.filePath ? ` \u2192 ${m.filePath}` : "";
1395
+ const fileRef = m.filePath ? ` \u2192 ${relative(session.cwd, m.filePath)}` : "";
1389
1396
  return `- [${sourceLabel} @ ${m.timestamp}] "${m.summary}"${fileRef}`;
1390
1397
  }).join("\n") + "\n" : "";
1391
- let previousCyclesSection = "";
1392
- if (session.orchestratorCycles.length > 1) {
1393
- const previousCycles = session.orchestratorCycles.slice(0, -1);
1394
- const agentMap = new Map(session.agents.map((a) => [a.id, a]));
1395
- const lines = previousCycles.map((c) => {
1396
- const agentDescs = c.agentsSpawned.map((id) => {
1397
- const agent = agentMap.get(id);
1398
- return agent ? `${id} (${agent.name})` : id;
1399
- }).join(", ");
1400
- return `Cycle ${c.cycle}: ${agentDescs || "(none)"}`;
1401
- });
1402
- previousCyclesSection = `
1403
- ### Previous Cycles
1404
-
1405
- ${lines.join("\n")}
1406
- `;
1407
- }
1408
1398
  let mostRecentCycleSection = "";
1409
1399
  const lastCycle = session.orchestratorCycles[session.orchestratorCycles.length - 1];
1410
1400
  if (lastCycle && lastCycle.agentsSpawned.length > 0) {
@@ -1414,7 +1404,7 @@ ${lines.join("\n")}
1414
1404
  if (!agent) return `- **${id}**: unknown (no agent data)`;
1415
1405
  const finalReport = agent.reports.find((r) => r.type === "final");
1416
1406
  const reportToUse = finalReport ?? agent.reports[agent.reports.length - 1];
1417
- const reportRef = reportToUse ? `@${reportToUse.filePath}` : "(no reports)";
1407
+ const reportRef = reportToUse ? `@${relative(session.cwd, reportToUse.filePath)}` : "(no reports)";
1418
1408
  return `- **${id}** (${agent.name}) [${agent.status}]: ${reportRef}`;
1419
1409
  }).join("\n");
1420
1410
  mostRecentCycleSection = `
@@ -1424,8 +1414,8 @@ ${agentLines}
1424
1414
  `;
1425
1415
  }
1426
1416
  const strategyFile = strategyPath(session.cwd, session.id);
1427
- const strategyRef = existsSync5(strategyFile) ? `@${strategyFile}` : "(empty)";
1428
- const roadmapRef = existsSync5(roadmapFile) ? `@${roadmapFile}` : "(empty)";
1417
+ const strategyRef = existsSync5(strategyFile) ? `@${relative(session.cwd, strategyFile)}` : "(empty)";
1418
+ const roadmapRef = existsSync5(roadmapFile) ? `@${relative(session.cwd, roadmapFile)}` : "(empty)";
1429
1419
  const repos = detectRepos(session.cwd);
1430
1420
  let repositoriesSection = "\n\n## Repositories\n";
1431
1421
  if (repos.length === 0) {
@@ -1459,8 +1449,8 @@ ${goalContent}
1459
1449
  ${contextSection}${messagesSection}
1460
1450
  ### Cycle Log
1461
1451
 
1462
- Write your cycle summary to: ${logFile}
1463
- ${previousCyclesSection}${mostRecentCycleSection}
1452
+ Write your cycle summary to: ${relative(session.cwd, logFile)}
1453
+ ${mostRecentCycleSection}
1464
1454
  ## Strategy
1465
1455
 
1466
1456
  ${strategyRef}
@@ -1490,7 +1480,14 @@ async function spawnOrchestrator(sessionId, cwd, windowId, message) {
1490
1480
  }).join("\n") : " (none)";
1491
1481
  const sesDir = sessionDir(cwd, sessionId);
1492
1482
  const substituteEnvVars = (text) => text.replace(/\$SISYPHUS_SESSION_DIR/g, sesDir).replace(/\$SISYPHUS_SESSION_ID/g, sessionId);
1493
- const systemPrompt = substituteEnvVars(basePrompt.replace("{{AGENT_TYPES}}", agentTypeLines));
1483
+ const modes = discoverOrchestratorModes();
1484
+ const modeLines = modes.map((m) => {
1485
+ const desc = m.description ? ` \u2014 ${m.description}` : "";
1486
+ return `- \`${m.name}\`${desc}`;
1487
+ }).join("\n");
1488
+ const systemPrompt = substituteEnvVars(
1489
+ basePrompt.replace("{{AGENT_TYPES}}", agentTypeLines).replace("{{ORCHESTRATOR_MODES}}", modeLines)
1490
+ );
1494
1491
  const cycleNum = session.orchestratorCycles.length + 1;
1495
1492
  const promptFilePath = `${promptsDir(cwd, sessionId)}/orchestrator-system-${cycleNum}.md`;
1496
1493
  writeFileSync4(promptFilePath, systemPrompt, "utf-8");
@@ -1535,13 +1532,21 @@ ${continuationText}`;
1535
1532
  registerPane(paneId, sessionId, "orchestrator");
1536
1533
  const sessionLabel = session.name ?? sessionId.slice(0, 8);
1537
1534
  setPaneTitle(paneId, `ssph:orch ${sessionLabel} c${cycleNum}`);
1538
- setPaneStyle(paneId, ORCHESTRATOR_COLOR, { role: "orch", session: sessionLabel, cycle: `c${cycleNum}` });
1535
+ setPaneStyle(paneId, ORCHESTRATOR_COLOR, { role: "orch", session: sessionLabel, cycle: `c${cycleNum}`, mode });
1536
+ const notifyEnabled = config.notifications?.enabled !== false ? "1" : "0";
1537
+ const notifySound = config.notifications?.sound ?? "/System/Library/Sounds/Hero.aiff";
1538
+ const notifyEnvExports = buildEnvExports([
1539
+ `export SISYPHUS_NOTIFY_ENABLED='${notifyEnabled}'`,
1540
+ `export SISYPHUS_NOTIFY_SOUND='${notifySound}'`,
1541
+ `export SISYPHUS_SESSION_NAME='${sessionLabel}'`
1542
+ ]);
1539
1543
  const bannerCmd = resolveBannerCmd();
1540
1544
  const notifyCmd = buildNotifyCmd(paneId);
1541
1545
  const scriptPath = writeRunScript(promptsDir(cwd, sessionId), `orchestrator-run-${cycleNum}`, [
1542
1546
  "#!/usr/bin/env bash",
1543
1547
  ...bannerCmd ? [bannerCmd] : [],
1544
1548
  envExports,
1549
+ notifyEnvExports,
1545
1550
  claudeCmd,
1546
1551
  notifyCmd
1547
1552
  ]);
@@ -1552,7 +1557,8 @@ ${continuationText}`;
1552
1557
  activeMs: 0,
1553
1558
  agentsSpawned: [],
1554
1559
  paneId,
1555
- claudeSessionId
1560
+ claudeSessionId,
1561
+ mode
1556
1562
  });
1557
1563
  }
1558
1564
  function resolveOrchestratorPane(sessionId, cwd) {