sisyphi 0.1.2 → 0.1.3
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-FWHTKXN5.js → chunk-N2BPQOO2.js} +23 -3
- package/dist/chunk-N2BPQOO2.js.map +1 -0
- package/dist/cli.js +85 -162
- package/dist/cli.js.map +1 -1
- package/dist/daemon.js +603 -186
- package/dist/daemon.js.map +1 -1
- package/dist/templates/CLAUDE.md +50 -0
- package/dist/templates/agent-plugin/.claude/agents/debug.md +39 -0
- package/dist/templates/agent-plugin/.claude/agents/plan.md +101 -0
- package/dist/templates/agent-plugin/.claude/agents/review-plan.md +81 -0
- package/dist/templates/agent-plugin/.claude/agents/review.md +56 -0
- package/dist/templates/agent-plugin/.claude/agents/spec-draft.md +73 -0
- package/dist/templates/agent-plugin/.claude/agents/test-spec.md +56 -0
- package/dist/templates/agent-plugin/.claude-plugin/plugin.json +5 -0
- package/dist/templates/agent-plugin/agents/CLAUDE.md +52 -0
- package/dist/templates/agent-plugin/agents/debug.md +39 -0
- package/dist/templates/agent-plugin/agents/operator.md +56 -0
- package/dist/templates/agent-plugin/agents/plan.md +101 -0
- package/dist/templates/agent-plugin/agents/review-plan.md +81 -0
- package/dist/templates/agent-plugin/agents/review.md +56 -0
- package/dist/templates/agent-plugin/agents/spec-draft.md +73 -0
- package/dist/templates/agent-plugin/agents/test-spec.md +56 -0
- package/dist/templates/agent-suffix.md +3 -1
- package/dist/templates/banner.txt +24 -6
- package/dist/templates/orchestrator-plugin/.claude/commands/begin.md +62 -0
- package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/SKILL.md +40 -0
- package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/task-patterns.md +222 -0
- package/dist/templates/orchestrator-plugin/.claude/skills/orchestration/workflow-examples.md +208 -0
- package/dist/templates/orchestrator-plugin/.claude-plugin/plugin.json +5 -0
- package/dist/templates/orchestrator-plugin/hooks/hooks.json +25 -0
- package/dist/templates/orchestrator-plugin/scripts/block-task.sh +4 -0
- package/dist/templates/orchestrator-plugin/scripts/stop-suggest.sh +4 -0
- package/dist/templates/orchestrator-plugin/skills/git-management/SKILL.md +111 -0
- package/dist/templates/orchestrator-plugin/skills/orchestration/SKILL.md +40 -0
- package/dist/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +248 -0
- package/dist/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +237 -0
- package/dist/templates/orchestrator-settings.json +2 -0
- package/dist/templates/orchestrator.md +56 -49
- package/dist/templates/resources/.claude/agents/debug.md +39 -0
- package/dist/templates/resources/.claude/agents/plan.md +101 -0
- package/dist/templates/resources/.claude/agents/review-plan.md +81 -0
- package/dist/templates/resources/.claude/agents/review.md +56 -0
- package/dist/templates/resources/.claude/agents/spec-draft.md +73 -0
- package/dist/templates/resources/.claude/agents/test-spec.md +56 -0
- package/dist/templates/resources/.claude/commands/begin.md +62 -0
- package/dist/templates/resources/.claude/skills/orchestration/SKILL.md +40 -0
- package/dist/templates/resources/.claude/skills/orchestration/task-patterns.md +222 -0
- package/dist/templates/resources/.claude/skills/orchestration/workflow-examples.md +208 -0
- package/dist/templates/resources/.claude-plugin/plugin.json +8 -0
- package/package.json +2 -2
- package/templates/CLAUDE.md +50 -0
- package/templates/agent-plugin/.claude-plugin/plugin.json +5 -0
- package/templates/agent-plugin/agents/CLAUDE.md +52 -0
- package/templates/agent-plugin/agents/debug.md +39 -0
- package/templates/agent-plugin/agents/operator.md +56 -0
- package/templates/agent-plugin/agents/plan.md +101 -0
- package/templates/agent-plugin/agents/review-plan.md +81 -0
- package/templates/agent-plugin/agents/review.md +56 -0
- package/templates/agent-plugin/agents/spec-draft.md +73 -0
- package/templates/agent-plugin/agents/test-spec.md +56 -0
- package/templates/agent-suffix.md +3 -1
- package/templates/banner.txt +24 -6
- package/templates/orchestrator-plugin/.claude-plugin/plugin.json +5 -0
- package/templates/orchestrator-plugin/hooks/hooks.json +25 -0
- package/templates/orchestrator-plugin/scripts/block-task.sh +4 -0
- package/templates/orchestrator-plugin/scripts/stop-suggest.sh +4 -0
- package/templates/orchestrator-plugin/skills/git-management/SKILL.md +111 -0
- package/templates/orchestrator-plugin/skills/orchestration/SKILL.md +40 -0
- package/templates/orchestrator-plugin/skills/orchestration/task-patterns.md +248 -0
- package/templates/orchestrator-plugin/skills/orchestration/workflow-examples.md +237 -0
- package/templates/orchestrator-settings.json +2 -0
- package/templates/orchestrator.md +56 -49
- package/dist/chunk-FWHTKXN5.js.map +0 -1
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
// src/shared/paths.ts
|
|
4
4
|
import { homedir } from "os";
|
|
5
|
-
import { join } from "path";
|
|
5
|
+
import { basename, join } from "path";
|
|
6
6
|
function globalDir() {
|
|
7
7
|
return join(homedir(), ".sisyphus");
|
|
8
8
|
}
|
|
@@ -42,9 +42,24 @@ function reportsDir(cwd, sessionId) {
|
|
|
42
42
|
function reportFilePath(cwd, sessionId, agentId, suffix) {
|
|
43
43
|
return join(reportsDir(cwd, sessionId), `${agentId}-${suffix}.md`);
|
|
44
44
|
}
|
|
45
|
+
function promptsDir(cwd, sessionId) {
|
|
46
|
+
return join(sessionDir(cwd, sessionId), "prompts");
|
|
47
|
+
}
|
|
45
48
|
function contextDir(cwd, sessionId) {
|
|
46
49
|
return join(sessionDir(cwd, sessionId), "context");
|
|
47
50
|
}
|
|
51
|
+
function planPath(cwd, sessionId) {
|
|
52
|
+
return join(sessionDir(cwd, sessionId), "plan.md");
|
|
53
|
+
}
|
|
54
|
+
function logsPath(cwd, sessionId) {
|
|
55
|
+
return join(sessionDir(cwd, sessionId), "logs.md");
|
|
56
|
+
}
|
|
57
|
+
function worktreeConfigPath(cwd) {
|
|
58
|
+
return join(projectDir(cwd), "worktree.json");
|
|
59
|
+
}
|
|
60
|
+
function worktreeBaseDir(cwd) {
|
|
61
|
+
return join(cwd, "..", `${basename(cwd)}-sisyphus-wt`);
|
|
62
|
+
}
|
|
48
63
|
|
|
49
64
|
export {
|
|
50
65
|
globalDir,
|
|
@@ -59,6 +74,11 @@ export {
|
|
|
59
74
|
statePath,
|
|
60
75
|
reportsDir,
|
|
61
76
|
reportFilePath,
|
|
62
|
-
|
|
77
|
+
promptsDir,
|
|
78
|
+
contextDir,
|
|
79
|
+
planPath,
|
|
80
|
+
logsPath,
|
|
81
|
+
worktreeConfigPath,
|
|
82
|
+
worktreeBaseDir
|
|
63
83
|
};
|
|
64
|
-
//# sourceMappingURL=chunk-
|
|
84
|
+
//# sourceMappingURL=chunk-N2BPQOO2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/shared/paths.ts"],"sourcesContent":["import { homedir } from 'node:os';\nimport { basename, join } from 'node:path';\n\nexport function globalDir(): string {\n return join(homedir(), '.sisyphus');\n}\n\nexport function socketPath(): string {\n return join(globalDir(), 'daemon.sock');\n}\n\nexport function globalConfigPath(): string {\n return join(globalDir(), 'config.json');\n}\n\nexport function daemonLogPath(): string {\n return join(globalDir(), 'daemon.log');\n}\n\nexport function daemonPidPath(): string {\n return join(globalDir(), 'daemon.pid');\n}\n\nexport function projectDir(cwd: string): string {\n return join(cwd, '.sisyphus');\n}\n\nexport function projectConfigPath(cwd: string): string {\n return join(projectDir(cwd), 'config.json');\n}\n\nexport function projectOrchestratorPromptPath(cwd: string): string {\n return join(projectDir(cwd), 'orchestrator.md');\n}\n\nexport function sessionsDir(cwd: string): string {\n return join(projectDir(cwd), 'sessions');\n}\n\nexport function sessionDir(cwd: string, sessionId: string): string {\n return join(sessionsDir(cwd), sessionId);\n}\n\nexport function statePath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'state.json');\n}\n\nexport function reportsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'reports');\n}\n\nexport function reportFilePath(cwd: string, sessionId: string, agentId: string, suffix: string): string {\n return join(reportsDir(cwd, sessionId), `${agentId}-${suffix}.md`);\n}\n\nexport function promptsDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'prompts');\n}\n\nexport function contextDir(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'context');\n}\n\nexport function planPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'plan.md');\n}\n\nexport function logsPath(cwd: string, sessionId: string): string {\n return join(sessionDir(cwd, sessionId), 'logs.md');\n}\n\nexport function worktreeConfigPath(cwd: string): string {\n return join(projectDir(cwd), 'worktree.json');\n}\n\nexport function worktreeBaseDir(cwd: string): string {\n return join(cwd, '..', `${basename(cwd)}-sisyphus-wt`);\n}\n"],"mappings":";;;AAAA,SAAS,eAAe;AACxB,SAAS,UAAU,YAAY;AAExB,SAAS,YAAoB;AAClC,SAAO,KAAK,QAAQ,GAAG,WAAW;AACpC;AAEO,SAAS,aAAqB;AACnC,SAAO,KAAK,UAAU,GAAG,aAAa;AACxC;AAEO,SAAS,mBAA2B;AACzC,SAAO,KAAK,UAAU,GAAG,aAAa;AACxC;AAEO,SAAS,gBAAwB;AACtC,SAAO,KAAK,UAAU,GAAG,YAAY;AACvC;AAEO,SAAS,gBAAwB;AACtC,SAAO,KAAK,UAAU,GAAG,YAAY;AACvC;AAEO,SAAS,WAAW,KAAqB;AAC9C,SAAO,KAAK,KAAK,WAAW;AAC9B;AAEO,SAAS,kBAAkB,KAAqB;AACrD,SAAO,KAAK,WAAW,GAAG,GAAG,aAAa;AAC5C;AAEO,SAAS,8BAA8B,KAAqB;AACjE,SAAO,KAAK,WAAW,GAAG,GAAG,iBAAiB;AAChD;AAEO,SAAS,YAAY,KAAqB;AAC/C,SAAO,KAAK,WAAW,GAAG,GAAG,UAAU;AACzC;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,YAAY,GAAG,GAAG,SAAS;AACzC;AAEO,SAAS,UAAU,KAAa,WAA2B;AAChE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,YAAY;AACtD;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,eAAe,KAAa,WAAmB,SAAiB,QAAwB;AACtG,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,GAAG,OAAO,IAAI,MAAM,KAAK;AACnE;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,WAAW,KAAa,WAA2B;AACjE,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,SAAS,KAAa,WAA2B;AAC/D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,SAAS,KAAa,WAA2B;AAC/D,SAAO,KAAK,WAAW,KAAK,SAAS,GAAG,SAAS;AACnD;AAEO,SAAS,mBAAmB,KAAqB;AACtD,SAAO,KAAK,WAAW,GAAG,GAAG,eAAe;AAC9C;AAEO,SAAS,gBAAgB,KAAqB;AACnD,SAAO,KAAK,KAAK,MAAM,GAAG,SAAS,GAAG,CAAC,cAAc;AACvD;","names":[]}
|
package/dist/cli.js
CHANGED
|
@@ -3,14 +3,11 @@ import {
|
|
|
3
3
|
daemonLogPath,
|
|
4
4
|
globalDir,
|
|
5
5
|
socketPath
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-N2BPQOO2.js";
|
|
7
7
|
|
|
8
8
|
// src/cli/index.ts
|
|
9
9
|
import { Command } from "commander";
|
|
10
10
|
|
|
11
|
-
// src/cli/commands/start.ts
|
|
12
|
-
import { execSync as execSync2 } from "child_process";
|
|
13
|
-
|
|
14
11
|
// src/cli/client.ts
|
|
15
12
|
import { connect as connect2 } from "net";
|
|
16
13
|
|
|
@@ -163,41 +160,59 @@ function rawSend(request) {
|
|
|
163
160
|
});
|
|
164
161
|
}
|
|
165
162
|
async function sendRequest(request) {
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
163
|
+
const sleep2 = (ms) => new Promise((resolve2) => setTimeout(resolve2, ms));
|
|
164
|
+
const MAX_ATTEMPTS = 5;
|
|
165
|
+
const RETRY_DELAY_MS = 2e3;
|
|
166
|
+
let installedDaemon = false;
|
|
167
|
+
let lastErr;
|
|
168
|
+
for (let attempt = 1; attempt <= MAX_ATTEMPTS; attempt++) {
|
|
169
|
+
try {
|
|
170
|
+
return await rawSend(request);
|
|
171
|
+
} catch (err) {
|
|
172
|
+
lastErr = err;
|
|
173
|
+
const code = err.code;
|
|
174
|
+
if (code !== "ENOENT" && code !== "ECONNREFUSED") {
|
|
175
|
+
throw err;
|
|
176
|
+
}
|
|
177
|
+
if (attempt === MAX_ATTEMPTS) break;
|
|
178
|
+
if (process.platform === "darwin" && !installedDaemon) {
|
|
179
|
+
installedDaemon = true;
|
|
180
|
+
await ensureDaemonInstalled();
|
|
181
|
+
await waitForDaemon(5e3);
|
|
182
|
+
} else {
|
|
183
|
+
process.stderr.write(`Daemon not ready, retrying (${attempt}/${MAX_ATTEMPTS - 1})...
|
|
184
|
+
`);
|
|
185
|
+
await sleep2(RETRY_DELAY_MS);
|
|
177
186
|
}
|
|
178
|
-
await ensureDaemonInstalled();
|
|
179
|
-
await waitForDaemon(5e3);
|
|
180
|
-
return rawSend(request);
|
|
181
187
|
}
|
|
182
|
-
throw err;
|
|
183
188
|
}
|
|
189
|
+
if (process.platform !== "darwin") {
|
|
190
|
+
throw new Error(
|
|
191
|
+
`Sisyphus daemon is not running.
|
|
192
|
+
Start it manually: sisyphusd &
|
|
193
|
+
Or check logs at: ~/.sisyphus/daemon.log`
|
|
194
|
+
);
|
|
195
|
+
}
|
|
196
|
+
throw lastErr;
|
|
184
197
|
}
|
|
185
198
|
|
|
186
|
-
// src/cli/
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
throw new Error("Not running inside tmux");
|
|
199
|
+
// src/cli/tmux.ts
|
|
200
|
+
import { execSync as execSync2 } from "child_process";
|
|
201
|
+
function assertTmux() {
|
|
202
|
+
if (!process.env.TMUX) {
|
|
203
|
+
throw new Error("Not running inside a tmux pane. Sisyphus requires tmux.");
|
|
192
204
|
}
|
|
193
205
|
}
|
|
206
|
+
function getTmuxSession() {
|
|
207
|
+
assertTmux();
|
|
208
|
+
return execSync2('tmux display-message -p "#{session_name}"', { encoding: "utf8" }).trim();
|
|
209
|
+
}
|
|
194
210
|
function getTmuxWindow() {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
} catch {
|
|
198
|
-
throw new Error("Not running inside tmux");
|
|
199
|
-
}
|
|
211
|
+
assertTmux();
|
|
212
|
+
return execSync2('tmux display-message -p "#{window_id}"', { encoding: "utf8" }).trim();
|
|
200
213
|
}
|
|
214
|
+
|
|
215
|
+
// src/cli/commands/start.ts
|
|
201
216
|
function registerStart(program2) {
|
|
202
217
|
program2.command("start").description("Start a new sisyphus session").argument("<task>", "Task description for the orchestrator").action(async (task) => {
|
|
203
218
|
const tmuxSession = getTmuxSession();
|
|
@@ -219,7 +234,8 @@ function registerStart(program2) {
|
|
|
219
234
|
|
|
220
235
|
// src/cli/commands/spawn.ts
|
|
221
236
|
function registerSpawn(program2) {
|
|
222
|
-
program2.command("spawn").description("Spawn a new agent (orchestrator only)").option("--agent-type <type>", "Agent role label (default: worker)", "worker").requiredOption("--name <name>", "Agent name").requiredOption("--instruction <instruction>", "Task instruction for the agent").action(async (opts) => {
|
|
237
|
+
program2.command("spawn").description("Spawn a new agent (orchestrator only)").option("--agent-type <type>", "Agent role label (default: worker)", "worker").requiredOption("--name <name>", "Agent name").requiredOption("--instruction <instruction>", "Task instruction for the agent").option("--worktree", "Spawn agent in an isolated git worktree").action(async (opts) => {
|
|
238
|
+
assertTmux();
|
|
223
239
|
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
224
240
|
if (!sessionId) {
|
|
225
241
|
console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
|
|
@@ -230,7 +246,8 @@ function registerSpawn(program2) {
|
|
|
230
246
|
sessionId,
|
|
231
247
|
agentType: opts.agentType,
|
|
232
248
|
name: opts.name,
|
|
233
|
-
instruction: opts.instruction
|
|
249
|
+
instruction: opts.instruction,
|
|
250
|
+
...opts.worktree ? { worktree: true } : {}
|
|
234
251
|
};
|
|
235
252
|
const response = await sendRequest(request);
|
|
236
253
|
if (response.ok) {
|
|
@@ -262,6 +279,7 @@ function readStdin() {
|
|
|
262
279
|
// src/cli/commands/submit.ts
|
|
263
280
|
function registerSubmit(program2) {
|
|
264
281
|
program2.command("submit").description("Submit work report and exit (agent only)").option("--report <report>", "Work report (or pipe via stdin)").action(async (opts) => {
|
|
282
|
+
assertTmux();
|
|
265
283
|
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
266
284
|
const agentId = process.env.SISYPHUS_AGENT_ID;
|
|
267
285
|
if (!sessionId || !agentId) {
|
|
@@ -288,6 +306,7 @@ function registerSubmit(program2) {
|
|
|
288
306
|
// src/cli/commands/yield.ts
|
|
289
307
|
function registerYield(program2) {
|
|
290
308
|
program2.command("yield").description("Yield control back to daemon (orchestrator only)").option("--prompt <text>", "Instructions for the next orchestrator cycle (or pipe via stdin)").action(async (opts) => {
|
|
309
|
+
assertTmux();
|
|
291
310
|
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
292
311
|
if (!sessionId) {
|
|
293
312
|
console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
|
|
@@ -308,6 +327,7 @@ function registerYield(program2) {
|
|
|
308
327
|
// src/cli/commands/complete.ts
|
|
309
328
|
function registerComplete(program2) {
|
|
310
329
|
program2.command("complete").description("Mark session as completed (orchestrator only)").requiredOption("--report <report>", "Final completion report").action(async (opts) => {
|
|
330
|
+
assertTmux();
|
|
311
331
|
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
312
332
|
if (!sessionId) {
|
|
313
333
|
console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
|
|
@@ -317,7 +337,6 @@ function registerComplete(program2) {
|
|
|
317
337
|
const response = await sendRequest(request);
|
|
318
338
|
if (response.ok) {
|
|
319
339
|
console.log("Session completed.");
|
|
320
|
-
console.log("All panes will close.");
|
|
321
340
|
} else {
|
|
322
341
|
console.error(`Error: ${response.error}`);
|
|
323
342
|
process.exit(1);
|
|
@@ -339,16 +358,8 @@ var STATUS_COLORS = {
|
|
|
339
358
|
// red
|
|
340
359
|
crashed: "\x1B[31m",
|
|
341
360
|
// red
|
|
342
|
-
lost: "\x1B[90m"
|
|
361
|
+
lost: "\x1B[90m"
|
|
343
362
|
// gray
|
|
344
|
-
draft: "\x1B[2m",
|
|
345
|
-
// dim
|
|
346
|
-
pending: "\x1B[90m",
|
|
347
|
-
// gray
|
|
348
|
-
in_progress: "\x1B[33m",
|
|
349
|
-
// yellow
|
|
350
|
-
done: "\x1B[32m"
|
|
351
|
-
// green
|
|
352
363
|
};
|
|
353
364
|
var RESET = "\x1B[0m";
|
|
354
365
|
var BOLD = "\x1B[1m";
|
|
@@ -390,10 +401,6 @@ function formatAgent(agent) {
|
|
|
390
401
|
}
|
|
391
402
|
return line;
|
|
392
403
|
}
|
|
393
|
-
function formatTask(task) {
|
|
394
|
-
const status = colorize(task.status, task.status);
|
|
395
|
-
return ` ${task.id}: ${task.description} [${status}]`;
|
|
396
|
-
}
|
|
397
404
|
function formatCycle(cycle) {
|
|
398
405
|
const duration = cycle.completedAt ? ` ${DIM}(${formatDuration(cycle.timestamp, cycle.completedAt)})${RESET}` : ` ${DIM}(running)${RESET}`;
|
|
399
406
|
const agents = cycle.agentsSpawned.length > 0 ? ` \u2014 agents: ${cycle.agentsSpawned.join(", ")}` : "";
|
|
@@ -417,13 +424,6 @@ ${BOLD}Session: ${session.id}${RESET}`);
|
|
|
417
424
|
console.log(formatCycle(cycle));
|
|
418
425
|
}
|
|
419
426
|
}
|
|
420
|
-
if (session.tasks.length > 0) {
|
|
421
|
-
console.log(`
|
|
422
|
-
${BOLD}Tasks:${RESET}`);
|
|
423
|
-
for (const task of session.tasks) {
|
|
424
|
-
console.log(formatTask(task));
|
|
425
|
-
}
|
|
426
|
-
}
|
|
427
427
|
if (session.agents.length > 0) {
|
|
428
428
|
console.log(`
|
|
429
429
|
${BOLD}Agents:${RESET}`);
|
|
@@ -451,112 +451,50 @@ function registerStatus(program2) {
|
|
|
451
451
|
});
|
|
452
452
|
}
|
|
453
453
|
|
|
454
|
-
// src/cli/commands/tasks.ts
|
|
455
|
-
function getSessionId() {
|
|
456
|
-
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
457
|
-
if (!sessionId) {
|
|
458
|
-
console.error("Error: SISYPHUS_SESSION_ID environment variable not set");
|
|
459
|
-
process.exit(1);
|
|
460
|
-
}
|
|
461
|
-
return sessionId;
|
|
462
|
-
}
|
|
463
|
-
var STATUS_COLORS2 = {
|
|
464
|
-
draft: "\x1B[2m",
|
|
465
|
-
// dim
|
|
466
|
-
pending: "\x1B[90m",
|
|
467
|
-
// gray
|
|
468
|
-
in_progress: "\x1B[33m",
|
|
469
|
-
// yellow
|
|
470
|
-
done: "\x1B[32m"
|
|
471
|
-
// green
|
|
472
|
-
};
|
|
473
|
-
var RESET2 = "\x1B[0m";
|
|
474
|
-
function registerTasks(program2) {
|
|
475
|
-
const tasks = program2.command("tasks").description("Manage session tasks");
|
|
476
|
-
tasks.command("add").description("Add a new task").argument("[description]", "Task description (or pipe via stdin)").option("--status <status>", "Initial status (draft|pending)", "pending").action(async (descriptionArg, opts) => {
|
|
477
|
-
const description = descriptionArg ?? await readStdin();
|
|
478
|
-
if (!description) {
|
|
479
|
-
console.error("Error: provide a description argument or pipe via stdin");
|
|
480
|
-
process.exit(1);
|
|
481
|
-
}
|
|
482
|
-
const sessionId = getSessionId();
|
|
483
|
-
const request = { type: "tasks_add", sessionId, description, status: opts.status !== "pending" ? opts.status : void 0 };
|
|
484
|
-
const response = await sendRequest(request);
|
|
485
|
-
if (response.ok) {
|
|
486
|
-
const taskId = response.data?.taskId;
|
|
487
|
-
console.log(`Task added: ${taskId} [${opts.status}]`);
|
|
488
|
-
} else {
|
|
489
|
-
console.error(`Error: ${response.error}`);
|
|
490
|
-
if (response.error?.includes("Unknown session")) console.error("Hint: run `sisyphus list` to see active sessions.");
|
|
491
|
-
process.exit(1);
|
|
492
|
-
}
|
|
493
|
-
});
|
|
494
|
-
tasks.command("update").description("Update a task").argument("<task-id>", "Task ID (e.g. t1)").option("--status <status>", "New status (draft|pending|in_progress|done)").option("--description <description>", "New description").action(async (taskId, opts) => {
|
|
495
|
-
if (!opts.status && !opts.description) {
|
|
496
|
-
console.error("Error: provide --status and/or --description");
|
|
497
|
-
process.exit(1);
|
|
498
|
-
}
|
|
499
|
-
const sessionId = getSessionId();
|
|
500
|
-
const request = { type: "tasks_update", sessionId, taskId, status: opts.status, description: opts.description };
|
|
501
|
-
const response = await sendRequest(request);
|
|
502
|
-
if (response.ok) {
|
|
503
|
-
const parts = [];
|
|
504
|
-
if (opts.status) parts.push(`status \u2192 ${opts.status}`);
|
|
505
|
-
if (opts.description) parts.push(`description updated`);
|
|
506
|
-
console.log(`Task ${taskId}: ${parts.join(", ")}`);
|
|
507
|
-
} else {
|
|
508
|
-
console.error(`Error: ${response.error}`);
|
|
509
|
-
if (response.error?.includes("not found")) console.error("Hint: run `sisyphus tasks list` to see current tasks.");
|
|
510
|
-
if (response.error?.includes("Unknown session")) console.error("Hint: run `sisyphus list` to see active sessions.");
|
|
511
|
-
process.exit(1);
|
|
512
|
-
}
|
|
513
|
-
});
|
|
514
|
-
tasks.command("list").description("List all tasks").action(async () => {
|
|
515
|
-
const sessionId = getSessionId();
|
|
516
|
-
const request = { type: "tasks_list", sessionId };
|
|
517
|
-
const response = await sendRequest(request);
|
|
518
|
-
if (response.ok) {
|
|
519
|
-
const taskList = response.data?.tasks ?? [];
|
|
520
|
-
if (taskList.length === 0) {
|
|
521
|
-
console.log("No tasks");
|
|
522
|
-
return;
|
|
523
|
-
}
|
|
524
|
-
for (const task of taskList) {
|
|
525
|
-
const color = STATUS_COLORS2[task.status] ?? "";
|
|
526
|
-
console.log(` ${task.id}: ${task.description} [${color}${task.status}${RESET2}]`);
|
|
527
|
-
}
|
|
528
|
-
} else {
|
|
529
|
-
console.error(`Error: ${response.error}`);
|
|
530
|
-
if (response.error?.includes("Unknown session")) console.error("Hint: run `sisyphus list` to see active sessions.");
|
|
531
|
-
process.exit(1);
|
|
532
|
-
}
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
|
|
536
454
|
// src/cli/commands/list.ts
|
|
537
|
-
|
|
455
|
+
import { basename } from "path";
|
|
456
|
+
var STATUS_COLORS2 = {
|
|
538
457
|
active: "\x1B[32m",
|
|
539
458
|
paused: "\x1B[33m",
|
|
540
459
|
completed: "\x1B[36m"
|
|
541
460
|
};
|
|
542
|
-
var
|
|
461
|
+
var RESET2 = "\x1B[0m";
|
|
543
462
|
var BOLD2 = "\x1B[1m";
|
|
544
463
|
var DIM2 = "\x1B[2m";
|
|
464
|
+
function truncateTask(task, max) {
|
|
465
|
+
if (task.length <= max) return task;
|
|
466
|
+
return task.slice(0, max - 1) + "\u2026";
|
|
467
|
+
}
|
|
545
468
|
function registerList(program2) {
|
|
546
|
-
program2.command("list").description("List all sessions").action(async () => {
|
|
547
|
-
const
|
|
469
|
+
program2.command("list").description("List sessions (defaults to current project)").option("-a, --all", "Show sessions from all projects").action(async (opts) => {
|
|
470
|
+
const cwd = process.cwd();
|
|
471
|
+
const request = { type: "list", cwd, all: opts.all };
|
|
548
472
|
const response = await sendRequest(request);
|
|
549
473
|
if (response.ok) {
|
|
550
474
|
const sessions = response.data?.sessions ?? [];
|
|
475
|
+
const totalCount = response.data?.totalCount;
|
|
476
|
+
const filtered = response.data?.filtered;
|
|
551
477
|
if (sessions.length === 0) {
|
|
552
|
-
|
|
478
|
+
if (filtered && totalCount && totalCount > 0) {
|
|
479
|
+
console.log(`No sessions in this project. ${totalCount} session(s) in other projects.`);
|
|
480
|
+
console.log(`${DIM2}Run ${RESET2}sisyphus list --all${DIM2} to show all.${RESET2}`);
|
|
481
|
+
} else {
|
|
482
|
+
console.log("No sessions");
|
|
483
|
+
}
|
|
553
484
|
return;
|
|
554
485
|
}
|
|
555
486
|
for (const s of sessions) {
|
|
556
|
-
const color =
|
|
557
|
-
const status = `${color}${s.status}${
|
|
558
|
-
const agents = `${DIM2}${s.agentCount} agent(s)${
|
|
559
|
-
|
|
487
|
+
const color = STATUS_COLORS2[s.status] ?? "";
|
|
488
|
+
const status = `${color}${s.status}${RESET2}`;
|
|
489
|
+
const agents = `${DIM2}${s.agentCount} agent(s)${RESET2}`;
|
|
490
|
+
const task = truncateTask(s.task, 60);
|
|
491
|
+
const cwdLabel = opts.all && s.cwd ? ` ${DIM2}${basename(s.cwd)}${RESET2}` : "";
|
|
492
|
+
console.log(` ${BOLD2}${s.id}${RESET2} ${status} ${agents} ${task}${cwdLabel}`);
|
|
493
|
+
}
|
|
494
|
+
if (filtered && totalCount && totalCount > sessions.length) {
|
|
495
|
+
const otherCount = totalCount - sessions.length;
|
|
496
|
+
console.log(`
|
|
497
|
+
${DIM2}${otherCount} more session(s) in other projects. Run ${RESET2}sisyphus list --all${DIM2} to show all.${RESET2}`);
|
|
560
498
|
}
|
|
561
499
|
} else {
|
|
562
500
|
console.error(`Error: ${response.error}`);
|
|
@@ -568,6 +506,7 @@ function registerList(program2) {
|
|
|
568
506
|
// src/cli/commands/report.ts
|
|
569
507
|
function registerReport(program2) {
|
|
570
508
|
program2.command("report").description("Send a progress report without exiting (agent only)").option("--message <message>", "Progress report content").action(async (opts) => {
|
|
509
|
+
assertTmux();
|
|
571
510
|
const sessionId = process.env.SISYPHUS_SESSION_ID;
|
|
572
511
|
const agentId = process.env.SISYPHUS_AGENT_ID;
|
|
573
512
|
if (!sessionId || !agentId) {
|
|
@@ -591,25 +530,10 @@ function registerReport(program2) {
|
|
|
591
530
|
}
|
|
592
531
|
|
|
593
532
|
// src/cli/commands/resume.ts
|
|
594
|
-
import { execSync as execSync3 } from "child_process";
|
|
595
|
-
function getTmuxSession2() {
|
|
596
|
-
try {
|
|
597
|
-
return execSync3('tmux display-message -p "#{session_name}"', { encoding: "utf8" }).trim();
|
|
598
|
-
} catch {
|
|
599
|
-
throw new Error("Not running inside tmux");
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
function getTmuxWindow2() {
|
|
603
|
-
try {
|
|
604
|
-
return execSync3('tmux display-message -p "#{window_id}"', { encoding: "utf8" }).trim();
|
|
605
|
-
} catch {
|
|
606
|
-
throw new Error("Not running inside tmux");
|
|
607
|
-
}
|
|
608
|
-
}
|
|
609
533
|
function registerResume(program2) {
|
|
610
534
|
program2.command("resume").description("Resume a paused session").argument("<session-id>", "Session ID to resume").argument("[message]", "Additional instructions for the orchestrator").action(async (sessionId, message) => {
|
|
611
|
-
const tmuxSession =
|
|
612
|
-
const tmuxWindow =
|
|
535
|
+
const tmuxSession = getTmuxSession();
|
|
536
|
+
const tmuxWindow = getTmuxWindow();
|
|
613
537
|
const cwd = process.cwd();
|
|
614
538
|
const request = { type: "resume", sessionId, cwd, tmuxSession, tmuxWindow, message };
|
|
615
539
|
const response = await sendRequest(request);
|
|
@@ -678,7 +602,6 @@ registerReport(program);
|
|
|
678
602
|
registerYield(program);
|
|
679
603
|
registerComplete(program);
|
|
680
604
|
registerStatus(program);
|
|
681
|
-
registerTasks(program);
|
|
682
605
|
registerList(program);
|
|
683
606
|
registerResume(program);
|
|
684
607
|
registerKill(program);
|