sisyphi 1.1.16 → 1.1.18

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/cli.js CHANGED
@@ -1,18 +1,22 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  resolveInstalledPlugin
4
- } from "./chunk-UIVQXCWB.js";
4
+ } from "./chunk-6PJVJEYQ.js";
5
5
  import {
6
6
  buildCompanionContext,
7
7
  computeActiveTimeMs,
8
+ createBadgeGallery,
8
9
  formatDuration,
9
10
  rawSend,
11
+ renderBadgeCard,
10
12
  statusColor
11
- } from "./chunk-HQZOAX6D.js";
13
+ } from "./chunk-C2XKXERJ.js";
12
14
  import {
15
+ ACHIEVEMENTS,
13
16
  loadConfig,
17
+ renderCompanion,
14
18
  shellQuote
15
- } from "./chunk-IF55HPWX.js";
19
+ } from "./chunk-V36NXMHP.js";
16
20
  import {
17
21
  cycleLogPath,
18
22
  daemonLogPath,
@@ -21,7 +25,7 @@ import {
21
25
  globalDir,
22
26
  roadmapPath,
23
27
  socketPath
24
- } from "./chunk-GSXF3TCZ.js";
28
+ } from "./chunk-TMBAVPHH.js";
25
29
 
26
30
  // src/cli/index.ts
27
31
  import { Command } from "commander";
@@ -92,7 +96,7 @@ cwd=$(tmux show-option -v @sisyphus_cwd 2>/dev/null)
92
96
  [ -z "$cwd" ] && exit 0
93
97
  while IFS= read -r name; do
94
98
  # Skip sisyphus agent/orchestrator sessions
95
- case "$name" in sisyphus-*) continue ;; esac
99
+ case "$name" in ssyph_*) continue ;; esac
96
100
  scwd=$(tmux show-option -t "$name" -v @sisyphus_cwd 2>/dev/null)
97
101
  if [ "$scwd" = "$cwd" ]; then
98
102
  tmux switch-client -t "$name"
@@ -114,7 +118,7 @@ if [ "$pane_count" -le 1 ]; then
114
118
  cwd=$(tmux show-option -t "$session" -v @sisyphus_cwd 2>/dev/null)
115
119
  if [ -n "$cwd" ]; then
116
120
  while IFS= read -r name; do
117
- case "$name" in sisyphus-*) continue ;; esac
121
+ case "$name" in ssyph_*) continue ;; esac
118
122
  scwd=$(tmux show-option -t "$name" -v @sisyphus_cwd 2>/dev/null)
119
123
  if [ "$scwd" = "$cwd" ]; then
120
124
  tmux switch-client -t "$name"
@@ -196,7 +200,7 @@ function setupTmuxKeybind(key = DEFAULT_KEY, homeKey = DEFAULT_HOME_KEY) {
196
200
  const confPath = sisyphusTmuxConfPath();
197
201
  const cycleBinding = `bind-key -T root ${key} run-shell ${cycleScriptPath()}`;
198
202
  const homeBinding = `bind-key -T root ${homeKey} run-shell ${homeScriptPath()}`;
199
- const killPaneOverride = `bind-key -T prefix x if-shell "tmux display-message -p '#{session_name}' | grep -q '^sisyphus-'" "run-shell ${killPaneScriptPath()}" "kill-pane \\; select-layout even-horizontal"`;
203
+ const killPaneOverride = `bind-key -T prefix x if-shell "tmux display-message -p '#{session_name}' | grep -q '^ssyph_'" "run-shell ${killPaneScriptPath()}" "kill-pane \\; select-layout even-horizontal"`;
200
204
  writeFileSync(confPath, `${SISYPHUS_CONF_MARKER}
201
205
  ${cycleBinding}
202
206
  ${homeBinding}
@@ -1018,7 +1022,8 @@ function registerStatus(program2) {
1018
1022
  program2.command("status").description("Show session status").argument("[session-id]", "Session ID (defaults to SISYPHUS_SESSION_ID env)").option("-v, --verbose", "Show detailed output (roadmap, pane output, agent instructions)").action(async (sessionIdArg, opts) => {
1019
1023
  const sessionId = sessionIdArg ?? process.env.SISYPHUS_SESSION_ID;
1020
1024
  const verbose = opts?.verbose ?? false;
1021
- const request = { type: "status", sessionId };
1025
+ const cwd = process.env["SISYPHUS_CWD"] ?? process.cwd();
1026
+ const request = { type: "status", sessionId, cwd };
1022
1027
  const response = await sendRequest(request);
1023
1028
  if (response.ok) {
1024
1029
  const session = response.data?.session;
@@ -1797,6 +1802,93 @@ function registerCompanionContext(program2) {
1797
1802
  });
1798
1803
  }
1799
1804
 
1805
+ // src/cli/commands/companion.ts
1806
+ var CATEGORY_LABELS = {
1807
+ milestone: "Milestone",
1808
+ session: "Session",
1809
+ time: "Time",
1810
+ behavioral: "Behavioral"
1811
+ };
1812
+ function registerCompanion(program2) {
1813
+ program2.command("companion").description("Show companion profile and stats").option("--name <name>", "Set companion name").option("--badges", "Show badge gallery").action(async (opts) => {
1814
+ const res = await sendRequest({ type: "companion", name: opts.name });
1815
+ if (!res.ok) {
1816
+ console.error(res.error);
1817
+ process.exit(1);
1818
+ }
1819
+ const companion = res.data;
1820
+ const face = renderCompanion(companion, ["face", "boulder"], { color: true });
1821
+ const displayName = companion.name !== null ? companion.name : "(unnamed)";
1822
+ console.log();
1823
+ console.log(` ${face}`);
1824
+ console.log();
1825
+ console.log(` ${displayName} \xB7 Level ${companion.level} ${companion.title}`);
1826
+ console.log(` Mood: ${companion.mood} \xB7 XP: ${companion.xp}`);
1827
+ console.log();
1828
+ const s = companion.stats;
1829
+ const endH = Math.floor(s.endurance / 36e5);
1830
+ console.log(" Stats");
1831
+ console.log(` Strength ${s.strength} sessions`);
1832
+ console.log(` Endurance ${endH}h total active`);
1833
+ console.log(` Wisdom ${s.wisdom} efficient sessions`);
1834
+ console.log(` Patience ${s.patience} persistence score`);
1835
+ console.log();
1836
+ if (opts.badges) {
1837
+ const gallery = createBadgeGallery(companion.achievements);
1838
+ console.log(` Badges ${companion.achievements.length}/${ACHIEVEMENTS.length} earned`);
1839
+ console.log();
1840
+ for (let i = 0; i < gallery.total; i++) {
1841
+ const def = gallery.achievements[i];
1842
+ const unlock = gallery.unlocked.get(def.id) ?? null;
1843
+ const card = renderBadgeCard(def, unlock);
1844
+ for (const line of card.lines) {
1845
+ console.log(` ${line}`);
1846
+ }
1847
+ console.log();
1848
+ }
1849
+ } else {
1850
+ const unlocked = new Set(companion.achievements.map((a) => a.id));
1851
+ const byCategory = /* @__PURE__ */ new Map();
1852
+ for (const def of ACHIEVEMENTS) {
1853
+ const group = byCategory.get(def.category) ?? [];
1854
+ group.push(def);
1855
+ byCategory.set(def.category, group);
1856
+ }
1857
+ console.log(` Achievements ${companion.achievements.length}/${ACHIEVEMENTS.length} (use --badges for gallery)`);
1858
+ for (const [category, defs] of byCategory) {
1859
+ const label = CATEGORY_LABELS[category] ?? category;
1860
+ const unlockedCount = defs.filter((d) => unlocked.has(d.id)).length;
1861
+ console.log(` ${label} (${unlockedCount}/${defs.length})`);
1862
+ for (const def of defs) {
1863
+ const icon = unlocked.has(def.id) ? "\u2713" : "\xB7";
1864
+ console.log(` ${icon} ${def.name} \u2014 ${def.description}`);
1865
+ }
1866
+ }
1867
+ console.log();
1868
+ }
1869
+ const repos = Object.entries(companion.repos);
1870
+ if (repos.length > 0) {
1871
+ repos.sort(([, a], [, b]) => b.visits - a.visits);
1872
+ console.log(" Repositories");
1873
+ for (const [path, mem] of repos.slice(0, 10)) {
1874
+ const nick = mem.nickname ? ` "${mem.nickname}"` : "";
1875
+ const parts = [`${mem.visits} visits`, `${mem.completions} completions`];
1876
+ if (mem.crashes > 0) parts.push(`${mem.crashes} crashes`);
1877
+ console.log(` ${path}${nick}`);
1878
+ console.log(` ${parts.join(" \xB7 ")}`);
1879
+ }
1880
+ if (repos.length > 10) {
1881
+ console.log(` \u2026 and ${repos.length - 10} more`);
1882
+ }
1883
+ console.log();
1884
+ }
1885
+ if (companion.lastCommentary) {
1886
+ console.log(` "${companion.lastCommentary.text}"`);
1887
+ console.log();
1888
+ }
1889
+ });
1890
+ }
1891
+
1800
1892
  // src/cli/commands/getting-started.ts
1801
1893
  import { execSync as execSync10 } from "child_process";
1802
1894
  import { dirname as dirname3, join as join6 } from "path";
@@ -2833,6 +2925,8 @@ function printResults(result, daemonOk, keybindMsg) {
2833
2925
  console.log(" \u2717 Daemon: Failed to start");
2834
2926
  }
2835
2927
  console.log(` \u2713 Keybindings: ${keybindMsg}`);
2928
+ console.log(" \u2713 Status bar: daemon-rendered via @sisyphus_status");
2929
+ console.log(" Add to status-right: #{@sisyphus_status}");
2836
2930
  if (result.command.installed) {
2837
2931
  console.log(` \u2713 /begin command: ${result.command.path}${result.command.autoInstalled ? " (just installed)" : ""}`);
2838
2932
  } else {
@@ -2875,6 +2969,67 @@ function registerSetup(program2) {
2875
2969
  });
2876
2970
  }
2877
2971
 
2972
+ // src/cli/commands/tmux-status.ts
2973
+ import { execSync as execSync12 } from "child_process";
2974
+ function registerTmuxStatus(program2) {
2975
+ program2.command("tmux-status").description("Output session status dots for tmux status bar").action(() => {
2976
+ try {
2977
+ const status = execSync12(
2978
+ "tmux show-option -gv @sisyphus_status",
2979
+ { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }
2980
+ ).trim();
2981
+ if (status) process.stdout.write(status);
2982
+ } catch {
2983
+ }
2984
+ });
2985
+ }
2986
+
2987
+ // src/cli/commands/tmux-sessions.ts
2988
+ import { execSync as execSync13 } from "child_process";
2989
+ var DOT_MAP = {
2990
+ "orchestrator:processing": { icon: "\u25CF", color: "#d4ad6a" },
2991
+ "orchestrator:idle": { icon: "\u25CF", color: "#d47766" },
2992
+ "agents:running": { icon: "\u25C6", color: "#d4ad6a" },
2993
+ "between-cycles": { icon: "\u25C6", color: "#5e584e" },
2994
+ "paused": { icon: "\u25CB", color: "#d47766" },
2995
+ "completed": { icon: "\u25CF", color: "#a9b16e" }
2996
+ };
2997
+ function tmuxExec(cmd) {
2998
+ try {
2999
+ return execSync13(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
3000
+ } catch {
3001
+ return null;
3002
+ }
3003
+ }
3004
+ function registerTmuxSessions(program2) {
3005
+ program2.command("tmux-sessions").description("Output sisyphus session list for tmux status bar").action(() => {
3006
+ const cwd = tmuxExec("tmux show-option -v @sisyphus_cwd");
3007
+ if (!cwd) return;
3008
+ const currentSession = tmuxExec("tmux display-message -p '#{session_name}'");
3009
+ const sessionList = tmuxExec('tmux list-sessions -F "#{session_name}"');
3010
+ if (!sessionList) return;
3011
+ const entries = [];
3012
+ for (const name of sessionList.split("\n").filter(Boolean)) {
3013
+ const scwd = tmuxExec(`tmux show-option -t "${name}" -v @sisyphus_cwd`);
3014
+ if (scwd !== cwd) continue;
3015
+ const phase = tmuxExec(`tmux show-option -t "${name}" -v @sisyphus_phase`);
3016
+ const displayName = name.replace(/^ssyph_[^_]+_/, "");
3017
+ entries.push({ name, displayName, phase });
3018
+ }
3019
+ if (entries.length <= 1) return;
3020
+ const parts = entries.map((e) => {
3021
+ const dot = e.phase ? DOT_MAP[e.phase] : null;
3022
+ const dotStr = dot ? ` #[fg=${dot.color}]${dot.icon}` : "";
3023
+ const isCurrent = e.name === currentSession;
3024
+ if (isCurrent) {
3025
+ return `#[fg=#e2d9c6,bold]${e.displayName}${dotStr}#[default]`;
3026
+ }
3027
+ return `#[fg=#5e584e]${e.displayName}${dotStr}#[default]`;
3028
+ });
3029
+ process.stdout.write(parts.join("#[fg=#3a3d42] \u2502 "));
3030
+ });
3031
+ }
3032
+
2878
3033
  // src/cli/index.ts
2879
3034
  var nodeVersion = parseInt(process.versions.node.split(".")[0], 10);
2880
3035
  if (nodeVersion < 22) {
@@ -2911,9 +3066,12 @@ registerRestartAgent(program);
2911
3066
  registerSetupKeybind(program);
2912
3067
  registerDoctor(program);
2913
3068
  registerCompanionContext(program);
3069
+ registerCompanion(program);
2914
3070
  registerGettingStarted(program);
2915
3071
  registerInit(program);
2916
3072
  registerSetup(program);
3073
+ registerTmuxStatus(program);
3074
+ registerTmuxSessions(program);
2917
3075
  program.addHelpText("after", `
2918
3076
  Examples:
2919
3077
  $ sisyphus start "Implement auth system" Start a new session