sisyphi 1.1.32 → 1.1.33

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/README.md CHANGED
@@ -160,6 +160,7 @@ Key bindings — navigate mode:
160
160
  | `e` | Edit context file |
161
161
  | `S` | Session info |
162
162
  | `F` | Filter / search |
163
+ | `D` | Toggle DANGEROUS mode for the selected session (auto-accepts the default for every ask) |
163
164
  | `c` | Open companion overlay |
164
165
  | `/` | Search sessions |
165
166
  | `q` | Quit |
package/dist/cli.js CHANGED
@@ -36,6 +36,12 @@ function projectDir(cwd) {
36
36
  function projectConfigPath(cwd) {
37
37
  return join(projectDir(cwd), "config.json");
38
38
  }
39
+ function projectAgentPluginDir(cwd) {
40
+ return join(projectDir(cwd), "agent-plugin");
41
+ }
42
+ function userAgentPluginDir() {
43
+ return join(globalDir(), "agent-plugin");
44
+ }
39
45
  function sessionsDir(cwd) {
40
46
  return join(projectDir(cwd), "sessions");
41
47
  }
@@ -3282,13 +3288,79 @@ function emitHistoryEvent(sessionId, event, data) {
3282
3288
  }
3283
3289
  }
3284
3290
 
3291
+ // src/daemon/state.ts
3292
+ init_atomic();
3293
+ init_paths();
3294
+ import { copyFileSync, cpSync, existsSync as existsSync7, mkdirSync as mkdirSync4, readFileSync as readFileSync11, readdirSync as readdirSync2, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync6 } from "fs";
3295
+ import { join as join10 } from "path";
3296
+
3297
+ // src/shared/gitignore.ts
3298
+ import { existsSync as existsSync6, readFileSync as readFileSync10, writeFileSync as writeFileSync5 } from "fs";
3299
+ import { join as join9 } from "path";
3300
+
3301
+ // src/shared/types.ts
3302
+ var ORCHESTRATOR_ASKED_BY = "orchestrator";
3303
+
3304
+ // src/daemon/state.ts
3305
+ function withSessionLock(sessionId, fn) {
3306
+ return withLock(sessionId, fn);
3307
+ }
3308
+ function getSession(cwd, sessionId) {
3309
+ const content = readFileSync11(statePath(cwd, sessionId), "utf-8");
3310
+ const session2 = JSON.parse(content);
3311
+ if (session2.activeMs == null) session2.activeMs = 0;
3312
+ if (session2.userBlockedMs == null) session2.userBlockedMs = 0;
3313
+ for (const agent2 of session2.agents) {
3314
+ if (!agent2.repo) agent2.repo = ".";
3315
+ if (agent2.activeMs == null) agent2.activeMs = 0;
3316
+ if (agent2.orphaned == null) agent2.orphaned = false;
3317
+ }
3318
+ if (session2.orphaned == null) session2.orphaned = false;
3319
+ for (const cycle of session2.orchestratorCycles) {
3320
+ if (cycle.activeMs == null) cycle.activeMs = 0;
3321
+ if (cycle.userBlockedMs == null) cycle.userBlockedMs = 0;
3322
+ }
3323
+ return session2;
3324
+ }
3325
+ function saveSession(session2) {
3326
+ atomicWrite(statePath(session2.cwd, session2.id), JSON.stringify(session2, null, 2));
3327
+ }
3328
+ function isSessionDangerous(cwd, sessionId) {
3329
+ try {
3330
+ return getSession(cwd, sessionId).dangerousMode === true;
3331
+ } catch {
3332
+ return false;
3333
+ }
3334
+ }
3335
+ async function incrementUserBlockedMs(cwd, sessionId, deltaMs, askedAt, askedBy) {
3336
+ if (deltaMs <= 0) return;
3337
+ return withSessionLock(sessionId, () => {
3338
+ const session2 = getSession(cwd, sessionId);
3339
+ session2.userBlockedMs = (session2.userBlockedMs ?? 0) + deltaMs;
3340
+ if (askedAt) {
3341
+ const askedAtMs = new Date(askedAt).getTime();
3342
+ const cycle = session2.orchestratorCycles.find((c2) => {
3343
+ const startMs = new Date(c2.timestamp).getTime();
3344
+ const endMs = c2.completedAt ? new Date(c2.completedAt).getTime() : Infinity;
3345
+ return startMs <= askedAtMs && askedAtMs < endMs;
3346
+ });
3347
+ if (cycle) cycle.userBlockedMs = (cycle.userBlockedMs ?? 0) + deltaMs;
3348
+ }
3349
+ if (askedBy && askedBy !== ORCHESTRATOR_ASKED_BY) {
3350
+ const agent2 = session2.agents.slice().reverse().find((a) => a.id === askedBy);
3351
+ if (agent2) agent2.userBlockedMs = (agent2.userBlockedMs ?? 0) + deltaMs;
3352
+ }
3353
+ saveSession(session2);
3354
+ });
3355
+ }
3356
+
3285
3357
  // src/daemon/ask-store.ts
3286
3358
  init_atomic();
3287
3359
 
3288
3360
  // src/daemon/notify.ts
3289
3361
  import { spawn, execFile } from "child_process";
3290
- import { writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, existsSync as existsSync6 } from "fs";
3291
- import { join as join9 } from "path";
3362
+ import { writeFileSync as writeFileSync7, mkdirSync as mkdirSync5, existsSync as existsSync8 } from "fs";
3363
+ import { join as join11 } from "path";
3292
3364
  import { homedir as homedir6 } from "os";
3293
3365
  var TMUX_SOCKET = `/tmp/tmux-${process.getuid?.() ?? 0}/default`;
3294
3366
  var SWITCH_SCRIPT = [
@@ -3331,24 +3403,24 @@ var SWITCH_SCRIPT = [
3331
3403
  ""
3332
3404
  ].join("\n");
3333
3405
  function ensureSwitchScript() {
3334
- const dir = join9(homedir6(), ".sisyphus");
3335
- const scriptPath2 = join9(dir, "notify-switch.sh");
3406
+ const dir = join11(homedir6(), ".sisyphus");
3407
+ const scriptPath2 = join11(dir, "notify-switch.sh");
3336
3408
  try {
3337
- mkdirSync4(dir, { recursive: true });
3338
- writeFileSync5(scriptPath2, SWITCH_SCRIPT, { mode: 493 });
3409
+ mkdirSync5(dir, { recursive: true });
3410
+ writeFileSync7(scriptPath2, SWITCH_SCRIPT, { mode: 493 });
3339
3411
  } catch {
3340
3412
  }
3341
3413
  }
3342
3414
  var notifyProcess = null;
3343
3415
  function getNotifyBinary() {
3344
- return join9(homedir6(), ".sisyphus", "SisyphusNotify.app", "Contents", "MacOS", "sisyphus-notify");
3416
+ return join11(homedir6(), ".sisyphus", "SisyphusNotify.app", "Contents", "MacOS", "sisyphus-notify");
3345
3417
  }
3346
3418
  function ensureNotifyProcess() {
3347
3419
  if (notifyProcess && !notifyProcess.killed && notifyProcess.stdin?.writable) {
3348
3420
  return notifyProcess;
3349
3421
  }
3350
3422
  const binary = getNotifyBinary();
3351
- if (!existsSync6(binary)) {
3423
+ if (!existsSync8(binary)) {
3352
3424
  return null;
3353
3425
  }
3354
3426
  notifyProcess = spawn(binary, [], {
@@ -3404,65 +3476,6 @@ function sendTerminalNotification(titleOrOpts, message, tmuxSession, level) {
3404
3476
  });
3405
3477
  }
3406
3478
 
3407
- // src/daemon/state.ts
3408
- init_atomic();
3409
- init_paths();
3410
- import { copyFileSync, cpSync, existsSync as existsSync8, mkdirSync as mkdirSync5, readFileSync as readFileSync11, readdirSync as readdirSync2, rmSync as rmSync3, statSync as statSync2, writeFileSync as writeFileSync7 } from "fs";
3411
- import { join as join11 } from "path";
3412
-
3413
- // src/shared/gitignore.ts
3414
- import { existsSync as existsSync7, readFileSync as readFileSync10, writeFileSync as writeFileSync6 } from "fs";
3415
- import { join as join10 } from "path";
3416
-
3417
- // src/shared/types.ts
3418
- var ORCHESTRATOR_ASKED_BY = "orchestrator";
3419
-
3420
- // src/daemon/state.ts
3421
- function withSessionLock(sessionId, fn) {
3422
- return withLock(sessionId, fn);
3423
- }
3424
- function getSession(cwd, sessionId) {
3425
- const content = readFileSync11(statePath(cwd, sessionId), "utf-8");
3426
- const session2 = JSON.parse(content);
3427
- if (session2.activeMs == null) session2.activeMs = 0;
3428
- if (session2.userBlockedMs == null) session2.userBlockedMs = 0;
3429
- for (const agent2 of session2.agents) {
3430
- if (!agent2.repo) agent2.repo = ".";
3431
- if (agent2.activeMs == null) agent2.activeMs = 0;
3432
- if (agent2.orphaned == null) agent2.orphaned = false;
3433
- }
3434
- if (session2.orphaned == null) session2.orphaned = false;
3435
- for (const cycle of session2.orchestratorCycles) {
3436
- if (cycle.activeMs == null) cycle.activeMs = 0;
3437
- if (cycle.userBlockedMs == null) cycle.userBlockedMs = 0;
3438
- }
3439
- return session2;
3440
- }
3441
- function saveSession(session2) {
3442
- atomicWrite(statePath(session2.cwd, session2.id), JSON.stringify(session2, null, 2));
3443
- }
3444
- async function incrementUserBlockedMs(cwd, sessionId, deltaMs, askedAt, askedBy) {
3445
- if (deltaMs <= 0) return;
3446
- return withSessionLock(sessionId, () => {
3447
- const session2 = getSession(cwd, sessionId);
3448
- session2.userBlockedMs = (session2.userBlockedMs ?? 0) + deltaMs;
3449
- if (askedAt) {
3450
- const askedAtMs = new Date(askedAt).getTime();
3451
- const cycle = session2.orchestratorCycles.find((c2) => {
3452
- const startMs = new Date(c2.timestamp).getTime();
3453
- const endMs = c2.completedAt ? new Date(c2.completedAt).getTime() : Infinity;
3454
- return startMs <= askedAtMs && askedAtMs < endMs;
3455
- });
3456
- if (cycle) cycle.userBlockedMs = (cycle.userBlockedMs ?? 0) + deltaMs;
3457
- }
3458
- if (askedBy && askedBy !== ORCHESTRATOR_ASKED_BY) {
3459
- const agent2 = session2.agents.slice().reverse().find((a) => a.id === askedBy);
3460
- if (agent2) agent2.userBlockedMs = (agent2.userBlockedMs ?? 0) + deltaMs;
3461
- }
3462
- saveSession(session2);
3463
- });
3464
- }
3465
-
3466
3479
  // src/daemon/ask-store.ts
3467
3480
  var ACTIONABLE_KINDS = /* @__PURE__ */ new Set([
3468
3481
  "validation",
@@ -3516,6 +3529,21 @@ function createAsk(cwd, sessionId, params) {
3516
3529
  }
3517
3530
  function writeDecisions(cwd, sessionId, askId, deck) {
3518
3531
  atomicWrite(askDecisionsPath(cwd, sessionId, askId), JSON.stringify(deck, null, 2));
3532
+ void maybeAutoResolveAsk(cwd, sessionId, askId, deck);
3533
+ }
3534
+ function readDecisions(cwd, sessionId, askId) {
3535
+ const p = askDecisionsPath(cwd, sessionId, askId);
3536
+ try {
3537
+ return JSON.parse(readFileSync12(p, { encoding: "utf-8" }));
3538
+ } catch (_e) {
3539
+ return null;
3540
+ }
3541
+ }
3542
+ function writeOutput(cwd, sessionId, askId, responses, completedAt) {
3543
+ atomicWrite(askOutputPath(cwd, sessionId, askId), JSON.stringify({
3544
+ responses,
3545
+ completedAt: completedAt ?? (/* @__PURE__ */ new Date()).toISOString()
3546
+ }, null, 2));
3519
3547
  }
3520
3548
  function readMeta(cwd, sessionId, askId) {
3521
3549
  const p = askMetaPath(cwd, sessionId, askId);
@@ -3535,6 +3563,40 @@ async function updateMeta(cwd, sessionId, askId, patch) {
3535
3563
  return next;
3536
3564
  });
3537
3565
  }
3566
+ function buildAutoResponses(deck) {
3567
+ const out = [];
3568
+ for (const interaction of deck.interactions) {
3569
+ const first = interaction.options[0];
3570
+ if (!first) continue;
3571
+ out.push({ id: interaction.id, selectedOptionId: first.id });
3572
+ }
3573
+ return out;
3574
+ }
3575
+ async function autoResolveAsk(cwd, sessionId, askId, deck) {
3576
+ try {
3577
+ if (existsSync9(askOutputPath(cwd, sessionId, askId))) return false;
3578
+ const d = deck ?? readDecisions(cwd, sessionId, askId);
3579
+ if (!d) return false;
3580
+ const responses = buildAutoResponses(d);
3581
+ if (responses.length === 0) return false;
3582
+ writeOutput(cwd, sessionId, askId, responses);
3583
+ await updateMeta(cwd, sessionId, askId, {
3584
+ status: "answered",
3585
+ completedAt: (/* @__PURE__ */ new Date()).toISOString()
3586
+ });
3587
+ return true;
3588
+ } catch (err) {
3589
+ console.warn(`[sisyphus] dangerous-mode auto-resolve failed for ask ${askId}:`, err instanceof Error ? err.message : err);
3590
+ return false;
3591
+ }
3592
+ }
3593
+ async function maybeAutoResolveAsk(cwd, sessionId, askId, deck) {
3594
+ try {
3595
+ if (!isSessionDangerous(cwd, sessionId)) return;
3596
+ await autoResolveAsk(cwd, sessionId, askId, deck);
3597
+ } catch {
3598
+ }
3599
+ }
3538
3600
 
3539
3601
  // src/cli/commands/ask.ts
3540
3602
  init_paths();
@@ -4235,6 +4297,7 @@ import { existsSync as existsSync12 } from "fs";
4235
4297
  import { join as join14, resolve as resolve5 } from "path";
4236
4298
 
4237
4299
  // src/daemon/frontmatter.ts
4300
+ init_paths();
4238
4301
  import { readFileSync as readFileSync16, existsSync as existsSync11, readdirSync as readdirSync5 } from "fs";
4239
4302
  import { homedir as homedir7 } from "os";
4240
4303
  import { join as join13, basename as basename4 } from "path";
@@ -4295,6 +4358,8 @@ function discoverAgentTypes(pluginDir, cwd) {
4295
4358
  }
4296
4359
  }
4297
4360
  }
4361
+ scanDir(join13(projectAgentPluginDir(cwd), "agents"), null, "project-sis");
4362
+ scanDir(join13(userAgentPluginDir(), "agents"), null, "user-sis");
4298
4363
  scanDir(join13(cwd, ".claude", "agents"), null, "project");
4299
4364
  scanDir(join13(homedir7(), ".claude", "agents"), null, "user");
4300
4365
  scanDir(join13(pluginDir, "agents"), "sisyphus", "bundled");