sisyphi 0.1.18 → 0.1.22

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
@@ -21,7 +21,7 @@ import {
21
21
  } from "./chunk-LTAW6OWS.js";
22
22
 
23
23
  // src/daemon/index.ts
24
- import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3, existsSync as existsSync6 } from "fs";
24
+ import { mkdirSync as mkdirSync5, readFileSync as readFileSync9, writeFileSync as writeFileSync6, unlinkSync as unlinkSync3, existsSync as existsSync7 } from "fs";
25
25
  import { execSync as execSync4 } from "child_process";
26
26
  import { setTimeout as sleep } from "timers/promises";
27
27
 
@@ -46,12 +46,12 @@ function loadConfig(cwd) {
46
46
 
47
47
  // src/daemon/server.ts
48
48
  import { createServer } from "net";
49
- import { unlinkSync, existsSync as existsSync5, writeFileSync as writeFileSync4, readFileSync as readFileSync7, mkdirSync as mkdirSync4 } from "fs";
49
+ import { unlinkSync, existsSync as existsSync6, writeFileSync as writeFileSync4, readFileSync as readFileSync7, mkdirSync as mkdirSync4 } from "fs";
50
50
  import { join as join4 } from "path";
51
51
 
52
52
  // src/daemon/session-manager.ts
53
53
  import { v4 as uuidv4 } from "uuid";
54
- import { existsSync as existsSync4, readdirSync as readdirSync4, rmSync as rmSync2 } from "fs";
54
+ import { existsSync as existsSync5, readdirSync as readdirSync4, rmSync as rmSync2 } from "fs";
55
55
 
56
56
  // src/daemon/state.ts
57
57
  import { randomUUID } from "crypto";
@@ -95,7 +95,7 @@ function atomicWrite(filePath, data) {
95
95
  writeFileSync(tmpPath, data, "utf-8");
96
96
  renameSync(tmpPath, filePath);
97
97
  }
98
- function createSession(id, task, cwd) {
98
+ function createSession(id, task, cwd, context) {
99
99
  const dir = sessionDir(cwd, id);
100
100
  mkdirSync(dir, { recursive: true });
101
101
  mkdirSync(contextDir(cwd, id), { recursive: true });
@@ -106,6 +106,7 @@ function createSession(id, task, cwd) {
106
106
  const session = {
107
107
  id,
108
108
  task,
109
+ ...context ? { context } : {},
109
110
  cwd,
110
111
  status: "active",
111
112
  createdAt: (/* @__PURE__ */ new Date()).toISOString(),
@@ -203,13 +204,10 @@ async function completeOrchestratorCycle(cwd, sessionId, nextPrompt) {
203
204
  }
204
205
 
205
206
  // src/daemon/orchestrator.ts
206
- import { existsSync, readdirSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2 } from "fs";
207
+ import { existsSync, readdirSync, readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
207
208
  import { resolve } from "path";
208
209
 
209
210
  // src/daemon/colors.ts
210
- import { readFileSync as readFileSync3 } from "fs";
211
- import { homedir } from "os";
212
- import { join as join2 } from "path";
213
211
  var ORCHESTRATOR_COLOR = "yellow";
214
212
  var AGENT_PALETTE = ["blue", "green", "magenta", "cyan", "red", "white"];
215
213
  var TMUX_COLOR_MAP = {
@@ -229,56 +227,6 @@ function getNextColor(sessionId) {
229
227
  function resetColors(sessionId) {
230
228
  sessionColorIndex.delete(sessionId);
231
229
  }
232
- function extractFrontmatterColor(content) {
233
- const match = content.match(/^---\n([\s\S]*?)\n---/);
234
- if (!match) return null;
235
- const colorMatch = match[1].match(/^color:\s*(.+)$/m);
236
- return colorMatch ? colorMatch[1].trim() : null;
237
- }
238
- function findPluginInstallPath(namespace) {
239
- try {
240
- const registryPath2 = join2(homedir(), ".claude", "plugins", "installed_plugins.json");
241
- const registry = JSON.parse(readFileSync3(registryPath2, "utf-8"));
242
- for (const key of Object.keys(registry)) {
243
- if (key.startsWith(`${namespace}@`)) {
244
- return registry[key].installPath ?? null;
245
- }
246
- }
247
- } catch {
248
- }
249
- return null;
250
- }
251
- function resolveAgentTypeColor(agentType, pluginDir, cwd) {
252
- if (!agentType) return null;
253
- let namespace;
254
- let name;
255
- if (agentType.includes(":")) {
256
- [namespace, name] = agentType.split(":", 2);
257
- } else {
258
- name = agentType;
259
- }
260
- const searchPaths = [];
261
- if (namespace) {
262
- searchPaths.push(join2(pluginDir, "agents", `${name}.md`));
263
- const installPath = findPluginInstallPath(namespace);
264
- if (installPath) {
265
- searchPaths.push(join2(installPath, "agents", `${name}.md`));
266
- }
267
- } else {
268
- searchPaths.push(join2(cwd, ".claude", "agents", `${name}.md`));
269
- searchPaths.push(join2(homedir(), ".claude", "agents", `${name}.md`));
270
- searchPaths.push(join2(pluginDir, "agents", `${name}.md`));
271
- }
272
- for (const path of searchPaths) {
273
- try {
274
- const content = readFileSync3(path, "utf-8");
275
- const color = extractFrontmatterColor(content);
276
- if (color) return normalizeTmuxColor(color);
277
- } catch {
278
- }
279
- }
280
- return null;
281
- }
282
230
 
283
231
  // src/daemon/tmux.ts
284
232
  import { execSync } from "child_process";
@@ -296,9 +244,13 @@ function execSafe(cmd) {
296
244
  return null;
297
245
  }
298
246
  }
299
- function createPane(windowTarget, cwd) {
247
+ function createPane(windowTarget, cwd, position = "right") {
300
248
  const cwdFlag = cwd ? ` -c ${shellQuote(cwd)}` : "";
301
- const paneId = exec(`tmux split-window -h -t "${windowTarget}"${cwdFlag} -P -F "#{pane_id}"`);
249
+ const panes = listPanes(windowTarget);
250
+ const target = position === "left" ? panes[0]?.paneId : panes[panes.length - 1]?.paneId;
251
+ const targetFlag = target ? ` -t "${target}"` : ` -t "${windowTarget}"`;
252
+ const beforeFlag = position === "left" ? "b" : "";
253
+ const paneId = exec(`tmux split-window -h${beforeFlag}${targetFlag}${cwdFlag} -P -F "#{pane_id}"`);
302
254
  execSafe(`tmux select-layout -t "${windowTarget}" even-horizontal`);
303
255
  return paneId;
304
256
  }
@@ -381,10 +333,10 @@ function setOrchestratorPaneId(sessionId, paneId) {
381
333
  function loadOrchestratorPrompt(cwd) {
382
334
  const projectPath = projectOrchestratorPromptPath(cwd);
383
335
  if (existsSync(projectPath)) {
384
- return readFileSync4(projectPath, "utf-8");
336
+ return readFileSync3(projectPath, "utf-8");
385
337
  }
386
338
  const bundledPath = resolve(import.meta.dirname, "../templates/orchestrator.md");
387
- return readFileSync4(bundledPath, "utf-8");
339
+ return readFileSync3(bundledPath, "utf-8");
388
340
  }
389
341
  function formatStateForOrchestrator(session) {
390
342
  const shortId = session.id.slice(0, 8);
@@ -436,11 +388,15 @@ function formatStateForOrchestrator(session) {
436
388
  ${wtLines}`;
437
389
  }
438
390
  const worktreeHint = existsSync(worktreeConfigPath(session.cwd)) ? "Worktree config active (`.sisyphus/worktree.json`). Use `--worktree` flag with `sisyphus spawn` to isolate agents in their own worktrees. Recommended for feature work, especially with potential file overlap." : "No worktree configuration found. If this session involves parallel work where agents may edit overlapping files, use the `git-management` skill to set up `.sisyphus/worktree.json` and enable worktree isolation.";
391
+ const contextSection = session.context ? `
392
+ ## Background Context
393
+ ${session.context}
394
+ ` : "";
439
395
  return `<state>
440
396
  session: ${shortId} (cycle ${cycleNum})
441
397
  task: ${session.task}
442
398
  status: ${session.status}
443
-
399
+ ${contextSection}
444
400
  ## Plan
445
401
  ${planRef}
446
402
 
@@ -468,9 +424,12 @@ async function spawnOrchestrator(sessionId, cwd, windowId, message) {
468
424
  const promptFilePath = `${promptsDir(cwd, sessionId)}/orchestrator-system-${cycleNum}.md`;
469
425
  writeFileSync2(promptFilePath, basePrompt, "utf-8");
470
426
  sessionWindowMap.set(sessionId, windowId);
427
+ const cliBin = resolve(import.meta.dirname, "cli.js");
428
+ const npmBinDir = resolve(import.meta.dirname, "../../.bin");
471
429
  const envExports = [
472
430
  `export SISYPHUS_SESSION_ID='${sessionId}'`,
473
- `export SISYPHUS_AGENT_ID='orchestrator'`
431
+ `export SISYPHUS_AGENT_ID='orchestrator'`,
432
+ `export PATH="${npmBinDir}:$PATH"`
474
433
  ].join(" && ");
475
434
  let userPrompt;
476
435
  if (message) {
@@ -494,15 +453,15 @@ Review the current session and delegate the next cycle of work.`;
494
453
  writeFileSync2(userPromptFilePath, userPrompt, "utf-8");
495
454
  const pluginPath = resolve(import.meta.dirname, "../templates/orchestrator-plugin");
496
455
  const settingsPath = resolve(import.meta.dirname, "../templates/orchestrator-settings.json");
497
- const claudeCmd = `claude --dangerously-skip-permissions --agent-name Sisyphus --agent-id orchestrator --team-name sisyphus-${sessionId.slice(0, 8)} --settings "${settingsPath}" --plugin-dir "${pluginPath}" --append-system-prompt "$(cat '${promptFilePath}')" "$(cat '${userPromptFilePath}')"`;
498
- const paneId = createPane(windowId, cwd);
456
+ const claudeCmd = `claude --dangerously-skip-permissions --settings "${settingsPath}" --plugin-dir "${pluginPath}" --append-system-prompt "$(cat '${promptFilePath}')" "$(cat '${userPromptFilePath}')"`;
457
+ const paneId = createPane(windowId, cwd, "left");
499
458
  sessionOrchestratorPane.set(sessionId, paneId);
500
459
  registerPane(paneId, sessionId, "orchestrator");
501
460
  setPaneTitle(paneId, `Sisyphus`);
502
461
  setPaneStyle(paneId, ORCHESTRATOR_COLOR);
503
462
  const bannerPath = resolve(import.meta.dirname, "../templates/banner.txt");
504
463
  const bannerCmd = existsSync(bannerPath) ? `cat '${bannerPath}' &&` : "";
505
- const notifyCmd = `sisyphus notify pane-exited --pane-id ${paneId}`;
464
+ const notifyCmd = `node "${cliBin}" notify pane-exited --pane-id ${paneId}`;
506
465
  sendKeys(paneId, `${bannerCmd} ${envExports} && ${claudeCmd}; ${notifyCmd}`);
507
466
  await addOrchestratorCycle(cwd, sessionId, {
508
467
  cycle: cycleNum,
@@ -546,13 +505,13 @@ function cleanupSessionMaps(sessionId) {
546
505
  }
547
506
 
548
507
  // src/daemon/agent.ts
549
- import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync3, existsSync as existsSync3 } from "fs";
508
+ import { readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync3, readdirSync as readdirSync3, existsSync as existsSync4 } from "fs";
550
509
  import { resolve as resolve2 } from "path";
551
510
 
552
511
  // src/daemon/worktree.ts
553
512
  import { execSync as execSync2 } from "child_process";
554
- import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync5, readdirSync as readdirSync2, rmSync } from "fs";
555
- import { dirname as dirname2, join as join3 } from "path";
513
+ import { existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync4, readdirSync as readdirSync2, rmSync } from "fs";
514
+ import { dirname as dirname3, join as join2 } from "path";
556
515
  var EXEC_ENV2 = {
557
516
  ...process.env,
558
517
  PATH: `/opt/homebrew/bin:/usr/local/bin:${process.env["PATH"] ?? "/usr/bin:/bin"}`
@@ -572,7 +531,7 @@ function shellQuote2(s) {
572
531
  }
573
532
  function loadWorktreeConfig(cwd) {
574
533
  try {
575
- const content = readFileSync5(worktreeConfigPath(cwd), "utf-8");
534
+ const content = readFileSync4(worktreeConfigPath(cwd), "utf-8");
576
535
  return JSON.parse(content);
577
536
  } catch {
578
537
  return null;
@@ -580,8 +539,8 @@ function loadWorktreeConfig(cwd) {
580
539
  }
581
540
  function createWorktreeShell(cwd, sessionId, agentId) {
582
541
  const branchName = `sisyphus/${sessionId.slice(0, 8)}/${agentId}`;
583
- const worktreePath = join3(worktreeBaseDir(cwd), sessionId.slice(0, 8), agentId);
584
- mkdirSync2(dirname2(worktreePath), { recursive: true });
542
+ const worktreePath = join2(worktreeBaseDir(cwd), sessionId.slice(0, 8), agentId);
543
+ mkdirSync2(dirname3(worktreePath), { recursive: true });
585
544
  execSafe2(`git -C ${shellQuote2(cwd)} worktree prune`);
586
545
  if (existsSync2(worktreePath)) {
587
546
  execSafe2(`git -C ${shellQuote2(cwd)} worktree remove --force ${shellQuote2(worktreePath)}`);
@@ -594,16 +553,16 @@ function createWorktreeShell(cwd, sessionId, agentId) {
594
553
  function bootstrapWorktree(cwd, worktreePath, config) {
595
554
  if (config.copy) {
596
555
  for (const entry of config.copy) {
597
- const dest = join3(worktreePath, entry);
598
- mkdirSync2(dirname2(dest), { recursive: true });
599
- execSafe2(`cp -r ${shellQuote2(join3(cwd, entry))} ${shellQuote2(dest)}`);
556
+ const dest = join2(worktreePath, entry);
557
+ mkdirSync2(dirname3(dest), { recursive: true });
558
+ execSafe2(`cp -r ${shellQuote2(join2(cwd, entry))} ${shellQuote2(dest)}`);
600
559
  }
601
560
  }
602
561
  if (config.clone) {
603
562
  for (const entry of config.clone) {
604
- const dest = join3(worktreePath, entry);
605
- mkdirSync2(dirname2(dest), { recursive: true });
606
- const src = shellQuote2(join3(cwd, entry));
563
+ const dest = join2(worktreePath, entry);
564
+ mkdirSync2(dirname3(dest), { recursive: true });
565
+ const src = shellQuote2(join2(cwd, entry));
607
566
  const dstQ = shellQuote2(dest);
608
567
  if (execSafe2(`cp -Rc ${src} ${dstQ}`) === null) {
609
568
  execSafe2(`cp -r ${src} ${dstQ}`);
@@ -612,9 +571,9 @@ function bootstrapWorktree(cwd, worktreePath, config) {
612
571
  }
613
572
  if (config.symlink) {
614
573
  for (const entry of config.symlink) {
615
- const dest = join3(worktreePath, entry);
616
- mkdirSync2(dirname2(dest), { recursive: true });
617
- execSafe2(`ln -s ${shellQuote2(join3(cwd, entry))} ${shellQuote2(dest)}`);
574
+ const dest = join2(worktreePath, entry);
575
+ mkdirSync2(dirname3(dest), { recursive: true });
576
+ execSafe2(`ln -s ${shellQuote2(join2(cwd, entry))} ${shellQuote2(dest)}`);
618
577
  }
619
578
  }
620
579
  if (config.init) {
@@ -684,7 +643,7 @@ function mergeWorktrees(cwd, agents) {
684
643
  function cleanupWorktree(cwd, worktreePath, branchName) {
685
644
  execSafe2(`git -C ${shellQuote2(cwd)} worktree remove ${shellQuote2(worktreePath)} --force`);
686
645
  execSafe2(`git -C ${shellQuote2(cwd)} branch -D ${shellQuote2(branchName)}`);
687
- const baseDir = dirname2(worktreePath);
646
+ const baseDir = dirname3(worktreePath);
688
647
  try {
689
648
  const entries = readdirSync2(baseDir);
690
649
  if (entries.length === 0) {
@@ -697,6 +656,93 @@ function countWorktreeAgents(agents) {
697
656
  return agents.filter((a) => a.worktreePath && a.status === "running").length;
698
657
  }
699
658
 
659
+ // src/daemon/frontmatter.ts
660
+ import { readFileSync as readFileSync5, existsSync as existsSync3 } from "fs";
661
+ import { homedir } from "os";
662
+ import { join as join3 } from "path";
663
+ function detectProvider(model) {
664
+ if (!model) return "anthropic";
665
+ if (/^(gpt-|codex-)/.test(model)) return "openai";
666
+ return "anthropic";
667
+ }
668
+ function parseAgentFrontmatter(content) {
669
+ const match = content.match(/^---\n([\s\S]*?)\n---/);
670
+ if (!match) return {};
671
+ const block = match[1];
672
+ const fm = {};
673
+ const str = (key) => {
674
+ const m = block.match(new RegExp(`^${key}:\\s*(.+)$`, "m"));
675
+ return m ? m[1].trim() : void 0;
676
+ };
677
+ fm.name = str("name");
678
+ fm.model = str("model");
679
+ fm.color = str("color");
680
+ fm.description = str("description");
681
+ fm.permissionMode = str("permissionMode");
682
+ const skillsMatch = block.match(/^skills:\s*\n((?:\s+-\s+.+\n?)*)/m);
683
+ if (skillsMatch) {
684
+ fm.skills = skillsMatch[1].split("\n").map((line) => line.replace(/^\s+-\s+/, "").trim()).filter(Boolean);
685
+ }
686
+ return fm;
687
+ }
688
+ function extractAgentBody(content) {
689
+ const match = content.match(/^---\n[\s\S]*?\n---\n?([\s\S]*)$/);
690
+ return match ? match[1].trim() : content.trim();
691
+ }
692
+ function findPluginInstallPath(namespace) {
693
+ try {
694
+ const registryPath2 = join3(homedir(), ".claude", "plugins", "installed_plugins.json");
695
+ const registry = JSON.parse(readFileSync5(registryPath2, "utf-8"));
696
+ for (const key of Object.keys(registry)) {
697
+ if (key.startsWith(`${namespace}@`)) {
698
+ return registry[key].installPath ?? null;
699
+ }
700
+ }
701
+ } catch {
702
+ }
703
+ return null;
704
+ }
705
+ function resolveAgentTypePath(agentType, pluginDir, cwd) {
706
+ if (!agentType) return null;
707
+ let namespace;
708
+ let name;
709
+ if (agentType.includes(":")) {
710
+ [namespace, name] = agentType.split(":", 2);
711
+ } else {
712
+ name = agentType;
713
+ }
714
+ const searchPaths = [];
715
+ if (namespace) {
716
+ searchPaths.push(join3(pluginDir, "agents", `${name}.md`));
717
+ const installPath = findPluginInstallPath(namespace);
718
+ if (installPath) {
719
+ searchPaths.push(join3(installPath, "agents", `${name}.md`));
720
+ }
721
+ } else {
722
+ searchPaths.push(join3(cwd, ".claude", "agents", `${name}.md`));
723
+ searchPaths.push(join3(homedir(), ".claude", "agents", `${name}.md`));
724
+ searchPaths.push(join3(pluginDir, "agents", `${name}.md`));
725
+ }
726
+ for (const path of searchPaths) {
727
+ if (existsSync3(path)) return path;
728
+ }
729
+ return null;
730
+ }
731
+ function resolveAgentConfig(agentType, pluginDir, cwd) {
732
+ const filePath = resolveAgentTypePath(agentType, pluginDir, cwd);
733
+ if (!filePath) return null;
734
+ try {
735
+ const content = readFileSync5(filePath, "utf-8");
736
+ return {
737
+ frontmatter: parseAgentFrontmatter(content),
738
+ body: extractAgentBody(content),
739
+ filePath
740
+ };
741
+ } catch {
742
+ return null;
743
+ }
744
+ }
745
+
700
746
  // src/daemon/agent.ts
701
747
  var agentCounters = /* @__PURE__ */ new Map();
702
748
  function resetAgentCounterFromState(sessionId, agents) {
@@ -736,7 +782,9 @@ async function spawnAgent(opts) {
736
782
  agentCounters.set(sessionId, count);
737
783
  const agentId = `agent-${String(count).padStart(3, "0")}`;
738
784
  const pluginPath = resolve2(import.meta.dirname, "../templates/agent-plugin");
739
- const color = resolveAgentTypeColor(agentType, pluginPath, cwd) ?? getNextColor(sessionId);
785
+ const agentConfig = resolveAgentConfig(agentType, pluginPath, cwd);
786
+ const provider = detectProvider(agentConfig?.frontmatter.model);
787
+ const color = (agentConfig?.frontmatter.color ? normalizeTmuxColor(agentConfig.frontmatter.color) : null) ?? getNextColor(sessionId);
740
788
  let paneCwd = cwd;
741
789
  let worktreePath;
742
790
  let branchName;
@@ -760,22 +808,40 @@ async function spawnAgent(opts) {
760
808
  const suffixFilePath = `${promptsDir(cwd, sessionId)}/${agentId}-system.md`;
761
809
  writeFileSync3(suffixFilePath, suffix, "utf-8");
762
810
  const bannerPath = resolve2(import.meta.dirname, "../templates/banner.txt");
763
- const bannerCmd = existsSync3(bannerPath) ? `cat '${bannerPath}' &&` : "";
811
+ const bannerCmd = existsSync4(bannerPath) ? `cat '${bannerPath}' &&` : "";
812
+ const cliBin = resolve2(import.meta.dirname, "cli.js");
813
+ const npmBinDir = resolve2(import.meta.dirname, "../../.bin");
764
814
  const envExports = [
765
815
  `export SISYPHUS_SESSION_ID='${sessionId}'`,
766
816
  `export SISYPHUS_AGENT_ID='${agentId}'`,
767
- ...worktreeContext ? [`export SISYPHUS_PORT_OFFSET='${worktreeContext.offset}'`] : []
817
+ ...worktreeContext ? [`export SISYPHUS_PORT_OFFSET='${worktreeContext.offset}'`] : [],
818
+ `export PATH="${npmBinDir}:$PATH"`
768
819
  ].join(" && ");
769
- const agentFlag = agentType && agentType !== "worker" ? ` --agent ${shellQuote3(agentType)}` : "";
770
- const agentNameFlag = ` --agent-name ${shellQuote3(paneLabel)}`;
771
- const teamFlag = ` --agent-id ${shellQuote3(agentId)} --team-name sisyphus-${sessionId.slice(0, 8)}`;
772
- const claudeCmd = `claude --dangerously-skip-permissions --plugin-dir "${pluginPath}"${agentFlag}${agentNameFlag}${teamFlag} --append-system-prompt "$(cat '${suffixFilePath}')" ${shellQuote3(instruction)}`;
773
- const notifyCmd = `sisyphus notify pane-exited --pane-id ${paneId}`;
774
- const fullCmd = `${bannerCmd} ${envExports} && ${claudeCmd}; ${notifyCmd}`;
820
+ const notifyCmd = `node "${cliBin}" notify pane-exited --pane-id ${paneId}`;
821
+ let mainCmd;
822
+ if (provider === "openai") {
823
+ const codexPromptPath = `${promptsDir(cwd, sessionId)}/${agentId}-codex-prompt.md`;
824
+ const parts = [];
825
+ if (agentConfig?.body) {
826
+ parts.push(agentConfig.body);
827
+ }
828
+ parts.push(suffix);
829
+ parts.push(`## Task
830
+
831
+ ${instruction}`);
832
+ writeFileSync3(codexPromptPath, parts.join("\n\n"), "utf-8");
833
+ const model = agentConfig?.frontmatter.model ?? "codex-mini";
834
+ mainCmd = `codex -m ${shellQuote3(model)} --dangerously-bypass-approvals-and-sandbox "$(cat '${codexPromptPath}')"`;
835
+ } else {
836
+ const agentFlag = agentType && agentType !== "worker" ? ` --agent ${shellQuote3(agentType)}` : "";
837
+ mainCmd = `claude --dangerously-skip-permissions --plugin-dir "${pluginPath}"${agentFlag} --append-system-prompt "$(cat '${suffixFilePath}')" ${shellQuote3(instruction)}`;
838
+ }
839
+ const fullCmd = `${bannerCmd} ${envExports} && ${mainCmd}; ${notifyCmd}`;
775
840
  const agent = {
776
841
  id: agentId,
777
842
  name,
778
843
  agentType,
844
+ provider,
779
845
  color,
780
846
  instruction,
781
847
  status: "running",
@@ -970,9 +1036,9 @@ async function pollSession(sessionId, cwd, windowId) {
970
1036
  }
971
1037
 
972
1038
  // src/daemon/session-manager.ts
973
- async function startSession(task, cwd, tmuxSession, windowId) {
1039
+ async function startSession(task, cwd, tmuxSession, windowId, context) {
974
1040
  const sessionId = uuidv4();
975
- const session = createSession(sessionId, task, cwd);
1041
+ const session = createSession(sessionId, task, cwd, context);
976
1042
  await updateSessionTmux(cwd, sessionId, tmuxSession, windowId);
977
1043
  trackSession(sessionId, cwd, tmuxSession);
978
1044
  await spawnOrchestrator(sessionId, cwd, windowId);
@@ -985,7 +1051,7 @@ var PRUNE_KEEP_DAYS = 7;
985
1051
  function pruneOldSessions(cwd) {
986
1052
  try {
987
1053
  const dir = sessionsDir(cwd);
988
- if (!existsSync4(dir)) return;
1054
+ if (!existsSync5(dir)) return;
989
1055
  const entries = readdirSync4(dir, { withFileTypes: true });
990
1056
  const candidates = [];
991
1057
  for (const entry of entries) {
@@ -1052,7 +1118,7 @@ function getSessionStatus(cwd, sessionId) {
1052
1118
  }
1053
1119
  function listSessions(cwd) {
1054
1120
  const dir = sessionsDir(cwd);
1055
- if (!existsSync4(dir)) return [];
1121
+ if (!existsSync5(dir)) return [];
1056
1122
  const entries = readdirSync4(dir, { withFileTypes: true });
1057
1123
  const sessions = [];
1058
1124
  for (const entry of entries) {
@@ -1223,7 +1289,7 @@ function persistSessionRegistry() {
1223
1289
  }
1224
1290
  function loadSessionRegistry() {
1225
1291
  const p = registryPath();
1226
- if (!existsSync5(p)) return {};
1292
+ if (!existsSync6(p)) return {};
1227
1293
  try {
1228
1294
  return JSON.parse(readFileSync7(p, "utf-8"));
1229
1295
  } catch {
@@ -1242,7 +1308,7 @@ async function handleRequest(req) {
1242
1308
  try {
1243
1309
  switch (req.type) {
1244
1310
  case "start": {
1245
- const session = await startSession(req.task, req.cwd, req.tmuxSession, req.tmuxWindow);
1311
+ const session = await startSession(req.task, req.cwd, req.tmuxSession, req.tmuxWindow, req.context);
1246
1312
  registerSessionCwd(session.id, req.cwd);
1247
1313
  sessionTmuxMap.set(session.id, req.tmuxSession);
1248
1314
  sessionWindowMap2.set(session.id, req.tmuxWindow);
@@ -1319,7 +1385,7 @@ async function handleRequest(req) {
1319
1385
  let cwd = sessionCwdMap.get(req.sessionId);
1320
1386
  if (!cwd) {
1321
1387
  const stateFile = `${req.cwd}/.sisyphus/sessions/${req.sessionId}/state.json`;
1322
- if (existsSync5(stateFile)) {
1388
+ if (existsSync6(stateFile)) {
1323
1389
  cwd = req.cwd;
1324
1390
  registerSessionCwd(req.sessionId, cwd);
1325
1391
  } else {
@@ -1370,7 +1436,7 @@ async function handleRequest(req) {
1370
1436
  function startServer() {
1371
1437
  return new Promise((resolve4, reject) => {
1372
1438
  const sock = socketPath();
1373
- if (existsSync5(sock)) {
1439
+ if (existsSync6(sock)) {
1374
1440
  unlinkSync(sock);
1375
1441
  }
1376
1442
  server = createServer((conn) => {
@@ -1412,7 +1478,7 @@ function stopServer() {
1412
1478
  }
1413
1479
  server.close(() => {
1414
1480
  const sock = socketPath();
1415
- if (existsSync5(sock)) {
1481
+ if (existsSync6(sock)) {
1416
1482
  unlinkSync(sock);
1417
1483
  }
1418
1484
  server = null;
@@ -1618,7 +1684,7 @@ async function recoverSessions() {
1618
1684
  let recovered = 0;
1619
1685
  for (const [sessionId, cwd] of entries) {
1620
1686
  const stateFile = statePath(cwd, sessionId);
1621
- if (!existsSync6(stateFile)) {
1687
+ if (!existsSync7(stateFile)) {
1622
1688
  continue;
1623
1689
  }
1624
1690
  try {