@nemus-cli/nemus 0.2.1

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.
Files changed (320) hide show
  1. package/CHANGELOG.md +86 -0
  2. package/LICENSE +21 -0
  3. package/README.md +275 -0
  4. package/assets/README.md +53 -0
  5. package/assets/banner.png +0 -0
  6. package/assets/banner.svg +66 -0
  7. package/assets/favicon-32.png +0 -0
  8. package/assets/favicon-64.png +0 -0
  9. package/assets/icon-256.png +0 -0
  10. package/assets/icon.svg +23 -0
  11. package/assets/logo-256.png +0 -0
  12. package/assets/logo-512.png +0 -0
  13. package/assets/logo-wordmark.svg +35 -0
  14. package/assets/logo.svg +32 -0
  15. package/bin/workspace.js +130 -0
  16. package/dist/cli/ai-prompt.js +421 -0
  17. package/dist/cli/dashboard/AgentList.js +61 -0
  18. package/dist/cli/dashboard/DashboardSidebar.js +280 -0
  19. package/dist/cli/dashboard/HelpFooter.js +73 -0
  20. package/dist/cli/dashboard/StatusBadge.js +50 -0
  21. package/dist/cli/dashboard/index.js +11 -0
  22. package/dist/cli/dashboard/types.js +2 -0
  23. package/dist/cli/tui.js +48 -0
  24. package/dist/commands/ai-prompt.js +22 -0
  25. package/dist/commands/analyze-deps.js +138 -0
  26. package/dist/commands/archive.js +113 -0
  27. package/dist/commands/branch/create.js +119 -0
  28. package/dist/commands/branch/index.js +104 -0
  29. package/dist/commands/branch/merge.js +90 -0
  30. package/dist/commands/branch/rebase.js +84 -0
  31. package/dist/commands/branch/switch.js +165 -0
  32. package/dist/commands/cache/index.js +80 -0
  33. package/dist/commands/cache/manager.js +198 -0
  34. package/dist/commands/cleanup.js +153 -0
  35. package/dist/commands/configure-claude.js +55 -0
  36. package/dist/commands/configure.js +231 -0
  37. package/dist/commands/create.js +204 -0
  38. package/dist/commands/dashboard/hook-handler.js +162 -0
  39. package/dist/commands/dashboard/index.js +258 -0
  40. package/dist/commands/dashboard/launcher.js +40 -0
  41. package/dist/commands/dashboard/session-picker.js +106 -0
  42. package/dist/commands/dashboard/sidebar.js +39 -0
  43. package/dist/commands/dashboard/workspace-picker.js +95 -0
  44. package/dist/commands/delete.js +194 -0
  45. package/dist/commands/deprecated-aliases.js +44 -0
  46. package/dist/commands/diff.js +129 -0
  47. package/dist/commands/doctor.js +141 -0
  48. package/dist/commands/generate-docs.js +77 -0
  49. package/dist/commands/ghq-status.js +72 -0
  50. package/dist/commands/go.js +154 -0
  51. package/dist/commands/history.js +124 -0
  52. package/dist/commands/list.js +191 -0
  53. package/dist/commands/mcp/index.js +69 -0
  54. package/dist/commands/migrate.js +296 -0
  55. package/dist/commands/remove-repo.js +217 -0
  56. package/dist/commands/report-bug.js +112 -0
  57. package/dist/commands/run.js +147 -0
  58. package/dist/commands/save-context.js +171 -0
  59. package/dist/commands/sessions.js +129 -0
  60. package/dist/commands/status.js +138 -0
  61. package/dist/commands/suite/create.js +212 -0
  62. package/dist/commands/suite/delete.js +64 -0
  63. package/dist/commands/suite/export.js +126 -0
  64. package/dist/commands/suite/import.js +128 -0
  65. package/dist/commands/suite/index.js +94 -0
  66. package/dist/commands/suite/list.js +49 -0
  67. package/dist/commands/suite/use.js +227 -0
  68. package/dist/commands/sync.js +117 -0
  69. package/dist/commands/update.js +203 -0
  70. package/dist/mcp/install.js +550 -0
  71. package/dist/mcp/server.js +398 -0
  72. package/dist/mcp/tools.js +922 -0
  73. package/dist/pi-extensions/permission-sync.ts.template +41 -0
  74. package/dist/pi-extensions/permissions-gate.ts.template +69 -0
  75. package/dist/pi-extensions/pr-fix-trigger.ts.template +124 -0
  76. package/dist/pi-extensions/review-reminder.ts.template +58 -0
  77. package/dist/pi-extensions/workspace-input-status.ts.template +919 -0
  78. package/dist/program.js +136 -0
  79. package/dist/scripts/workspace-table.py +394 -0
  80. package/dist/types/dashboard.js +11 -0
  81. package/dist/types/index.js +2 -0
  82. package/dist/utils/agent-config.js +263 -0
  83. package/dist/utils/agent-state.js +178 -0
  84. package/dist/utils/banner.js +24 -0
  85. package/dist/utils/branch-operations.js +232 -0
  86. package/dist/utils/bug-report.js +355 -0
  87. package/dist/utils/cache.js +168 -0
  88. package/dist/utils/claude-integration.js +617 -0
  89. package/dist/utils/claude-sessions.js +260 -0
  90. package/dist/utils/cleanup-operations.js +120 -0
  91. package/dist/utils/colors.js +26 -0
  92. package/dist/utils/command-helpers.js +44 -0
  93. package/dist/utils/config.js +150 -0
  94. package/dist/utils/context-file.js +33 -0
  95. package/dist/utils/dashboard-hooks.js +172 -0
  96. package/dist/utils/dependency-analyzer.js +234 -0
  97. package/dist/utils/diff-operations.js +80 -0
  98. package/dist/utils/doc-generator.js +184 -0
  99. package/dist/utils/ghq-integration.js +332 -0
  100. package/dist/utils/git-operations.js +237 -0
  101. package/dist/utils/git-status.js +187 -0
  102. package/dist/utils/github.js +68 -0
  103. package/dist/utils/health-checks.js +345 -0
  104. package/dist/utils/history.js +150 -0
  105. package/dist/utils/hooks.js +100 -0
  106. package/dist/utils/logger.js +40 -0
  107. package/dist/utils/permission-sync.js +681 -0
  108. package/dist/utils/pi-extensions.js +224 -0
  109. package/dist/utils/progress.js +92 -0
  110. package/dist/utils/prompts.js +279 -0
  111. package/dist/utils/repo-resolver.js +260 -0
  112. package/dist/utils/retry.js +65 -0
  113. package/dist/utils/run-operations.js +30 -0
  114. package/dist/utils/suite.js +159 -0
  115. package/dist/utils/sync-operations.js +107 -0
  116. package/dist/utils/tmux-dashboard.js +184 -0
  117. package/dist/utils/validation.js +153 -0
  118. package/dist/utils/version-check.js +121 -0
  119. package/dist/utils/workspace-meta.js +185 -0
  120. package/install-shell-integration.sh +532 -0
  121. package/install.sh +401 -0
  122. package/package.json +90 -0
  123. package/remove-shell-block.awk +44 -0
  124. package/scripts/postinstall.js +85 -0
  125. package/skills/analyze-deps.md +23 -0
  126. package/skills/archive-workspace.md +26 -0
  127. package/skills/branch-create.md +18 -0
  128. package/skills/create-workspace.md +39 -0
  129. package/skills/delete-workspace.md +37 -0
  130. package/skills/list-org-repos.md +26 -0
  131. package/skills/list-suites.md +24 -0
  132. package/skills/list-workspaces.md +27 -0
  133. package/skills/refresh-workspace-docs.md +89 -0
  134. package/skills/remove-repo.md +25 -0
  135. package/skills/run-command.md +23 -0
  136. package/skills/save-context.md +68 -0
  137. package/skills/search-repos.md +31 -0
  138. package/skills/snapshot-list.md +18 -0
  139. package/skills/snapshot-save.md +12 -0
  140. package/skills/switch-branch.md +18 -0
  141. package/skills/update-cache.md +21 -0
  142. package/skills/update-workspace.md +66 -0
  143. package/skills/workspace-cleanup.md +18 -0
  144. package/skills/workspace-diff.md +23 -0
  145. package/skills/workspace-doctor.md +23 -0
  146. package/skills/workspace-info.md +45 -0
  147. package/skills/workspace-manager/SKILL.md +201 -0
  148. package/skills/workspace-manager/references/ai-prompt.md +44 -0
  149. package/skills/workspace-manager/references/analyze-deps.md +45 -0
  150. package/skills/workspace-manager/references/archive-workspace.md +38 -0
  151. package/skills/workspace-manager/references/branch-create.md +31 -0
  152. package/skills/workspace-manager/references/branch-merge.md +22 -0
  153. package/skills/workspace-manager/references/branch-rebase.md +22 -0
  154. package/skills/workspace-manager/references/cache-clear.md +18 -0
  155. package/skills/workspace-manager/references/cache-info.md +22 -0
  156. package/skills/workspace-manager/references/configure-claude.md +31 -0
  157. package/skills/workspace-manager/references/configure.md +35 -0
  158. package/skills/workspace-manager/references/create-workspace.md +45 -0
  159. package/skills/workspace-manager/references/dashboard.md +61 -0
  160. package/skills/workspace-manager/references/delete-workspace.md +33 -0
  161. package/skills/workspace-manager/references/generate-docs.md +36 -0
  162. package/skills/workspace-manager/references/ghq-status.md +28 -0
  163. package/skills/workspace-manager/references/go.md +33 -0
  164. package/skills/workspace-manager/references/history.md +41 -0
  165. package/skills/workspace-manager/references/list-org-repos.md +26 -0
  166. package/skills/workspace-manager/references/list-suites.md +21 -0
  167. package/skills/workspace-manager/references/list-workspaces.md +27 -0
  168. package/skills/workspace-manager/references/mcp.md +49 -0
  169. package/skills/workspace-manager/references/remove-repo.md +26 -0
  170. package/skills/workspace-manager/references/run-command.md +44 -0
  171. package/skills/workspace-manager/references/search-repos.md +24 -0
  172. package/skills/workspace-manager/references/sessions.md +27 -0
  173. package/skills/workspace-manager/references/suite-create.md +22 -0
  174. package/skills/workspace-manager/references/suite-delete.md +21 -0
  175. package/skills/workspace-manager/references/suite-export.md +19 -0
  176. package/skills/workspace-manager/references/suite-import.md +19 -0
  177. package/skills/workspace-manager/references/suite-use.md +27 -0
  178. package/skills/workspace-manager/references/switch-branch.md +25 -0
  179. package/skills/workspace-manager/references/update-cache.md +22 -0
  180. package/skills/workspace-manager/references/update-workspace.md +50 -0
  181. package/skills/workspace-manager/references/workspace-cleanup.md +33 -0
  182. package/skills/workspace-manager/references/workspace-diff.md +27 -0
  183. package/skills/workspace-manager/references/workspace-doctor.md +27 -0
  184. package/skills/workspace-manager/references/workspace-info.md +33 -0
  185. package/skills/workspace-manager/references/workspace-status.md +43 -0
  186. package/skills/workspace-manager/references/workspace-sync.md +26 -0
  187. package/skills/workspace-status.md +26 -0
  188. package/skills/workspace-sync.md +23 -0
  189. package/src/cli/ai-prompt.test.ts +667 -0
  190. package/src/cli/ai-prompt.ts +421 -0
  191. package/src/cli/dashboard/AgentList.tsx +44 -0
  192. package/src/cli/dashboard/DashboardSidebar.tsx +291 -0
  193. package/src/cli/dashboard/HelpFooter.tsx +22 -0
  194. package/src/cli/dashboard/StatusBadge.tsx +23 -0
  195. package/src/cli/dashboard/index.ts +5 -0
  196. package/src/cli/dashboard/types.ts +16 -0
  197. package/src/cli/tui.tsx +51 -0
  198. package/src/cli/workspace-cli.test.ts +30 -0
  199. package/src/commands/ai-prompt.ts +21 -0
  200. package/src/commands/analyze-deps.ts +119 -0
  201. package/src/commands/archive.ts +114 -0
  202. package/src/commands/branch/create.ts +94 -0
  203. package/src/commands/branch/index.ts +74 -0
  204. package/src/commands/branch/merge.ts +61 -0
  205. package/src/commands/branch/rebase.ts +54 -0
  206. package/src/commands/branch/switch.ts +150 -0
  207. package/src/commands/cache/index.ts +51 -0
  208. package/src/commands/cache/manager.ts +168 -0
  209. package/src/commands/cleanup.ts +132 -0
  210. package/src/commands/configure-claude.ts +55 -0
  211. package/src/commands/configure.ts +204 -0
  212. package/src/commands/create.ts +196 -0
  213. package/src/commands/dashboard/hook-handler.ts +138 -0
  214. package/src/commands/dashboard/index.ts +248 -0
  215. package/src/commands/dashboard/launcher.ts +42 -0
  216. package/src/commands/dashboard/session-picker.ts +73 -0
  217. package/src/commands/dashboard/sidebar.js +39 -0
  218. package/src/commands/dashboard/workspace-picker.ts +62 -0
  219. package/src/commands/delete.test.ts +250 -0
  220. package/src/commands/delete.ts +171 -0
  221. package/src/commands/deprecated-aliases.ts +55 -0
  222. package/src/commands/diff.ts +106 -0
  223. package/src/commands/doctor.ts +110 -0
  224. package/src/commands/generate-docs.ts +45 -0
  225. package/src/commands/ghq-status.ts +70 -0
  226. package/src/commands/go.ts +125 -0
  227. package/src/commands/history.ts +136 -0
  228. package/src/commands/list.test.ts +219 -0
  229. package/src/commands/list.ts +176 -0
  230. package/src/commands/mcp/index.ts +39 -0
  231. package/src/commands/migrate.ts +277 -0
  232. package/src/commands/remove-repo.ts +194 -0
  233. package/src/commands/report-bug.ts +88 -0
  234. package/src/commands/run.ts +125 -0
  235. package/src/commands/save-context.test.ts +113 -0
  236. package/src/commands/save-context.ts +141 -0
  237. package/src/commands/sessions.ts +99 -0
  238. package/src/commands/status.ts +111 -0
  239. package/src/commands/suite/create.ts +240 -0
  240. package/src/commands/suite/delete.ts +65 -0
  241. package/src/commands/suite/export.ts +97 -0
  242. package/src/commands/suite/import.ts +100 -0
  243. package/src/commands/suite/index.ts +66 -0
  244. package/src/commands/suite/list.ts +54 -0
  245. package/src/commands/suite/use.ts +232 -0
  246. package/src/commands/sync.ts +97 -0
  247. package/src/commands/update.ts +197 -0
  248. package/src/mcp/install.ts +529 -0
  249. package/src/mcp/server.ts +579 -0
  250. package/src/mcp/tools.test.ts +545 -0
  251. package/src/mcp/tools.ts +1019 -0
  252. package/src/mcp/update-workspace.test.ts +220 -0
  253. package/src/pi-extensions/permission-sync.ts.template +41 -0
  254. package/src/pi-extensions/permissions-gate.ts.template +69 -0
  255. package/src/pi-extensions/pr-fix-trigger.ts.template +124 -0
  256. package/src/pi-extensions/review-reminder.ts.template +58 -0
  257. package/src/pi-extensions/workspace-input-status.ts.template +919 -0
  258. package/src/program.ts +112 -0
  259. package/src/scripts/workspace-table.py +394 -0
  260. package/src/types/dashboard.ts +29 -0
  261. package/src/types/index.ts +109 -0
  262. package/src/types/ink.d.ts +171 -0
  263. package/src/utils/agent-config.test.ts +303 -0
  264. package/src/utils/agent-config.ts +264 -0
  265. package/src/utils/agent-state.test.ts +166 -0
  266. package/src/utils/agent-state.ts +135 -0
  267. package/src/utils/banner.ts +24 -0
  268. package/src/utils/branch-operations.ts +237 -0
  269. package/src/utils/bug-report.test.ts +174 -0
  270. package/src/utils/bug-report.ts +355 -0
  271. package/src/utils/cache.ts +150 -0
  272. package/src/utils/claude-integration.test.ts +381 -0
  273. package/src/utils/claude-integration.ts +649 -0
  274. package/src/utils/claude-sessions.test.ts +262 -0
  275. package/src/utils/claude-sessions.ts +251 -0
  276. package/src/utils/cleanup-operations.ts +94 -0
  277. package/src/utils/colors.ts +25 -0
  278. package/src/utils/command-helpers.ts +46 -0
  279. package/src/utils/config.test.ts +203 -0
  280. package/src/utils/config.ts +133 -0
  281. package/src/utils/context-file.ts +36 -0
  282. package/src/utils/dashboard-hooks.test.ts +168 -0
  283. package/src/utils/dashboard-hooks.ts +163 -0
  284. package/src/utils/dependency-analyzer.ts +243 -0
  285. package/src/utils/diff-operations.ts +59 -0
  286. package/src/utils/doc-generator.ts +187 -0
  287. package/src/utils/ghq-integration.test.ts +195 -0
  288. package/src/utils/ghq-integration.ts +317 -0
  289. package/src/utils/git-operations.test.ts +265 -0
  290. package/src/utils/git-operations.ts +233 -0
  291. package/src/utils/git-status.ts +171 -0
  292. package/src/utils/github.ts +74 -0
  293. package/src/utils/health-checks.ts +359 -0
  294. package/src/utils/history.ts +140 -0
  295. package/src/utils/hooks.ts +92 -0
  296. package/src/utils/logger.ts +37 -0
  297. package/src/utils/permission-sync.test.ts +593 -0
  298. package/src/utils/permission-sync.ts +720 -0
  299. package/src/utils/pi-extensions.test.ts +182 -0
  300. package/src/utils/pi-extensions.ts +226 -0
  301. package/src/utils/progress.ts +73 -0
  302. package/src/utils/prompts.test.ts +169 -0
  303. package/src/utils/prompts.ts +296 -0
  304. package/src/utils/repo-resolver.test.ts +313 -0
  305. package/src/utils/repo-resolver.ts +294 -0
  306. package/src/utils/retry.test.ts +124 -0
  307. package/src/utils/retry.ts +85 -0
  308. package/src/utils/run-operations.ts +38 -0
  309. package/src/utils/suite.test.ts +256 -0
  310. package/src/utils/suite.ts +144 -0
  311. package/src/utils/sync-operations.ts +87 -0
  312. package/src/utils/tmux-dashboard.ts +193 -0
  313. package/src/utils/validation.test.ts +139 -0
  314. package/src/utils/validation.ts +128 -0
  315. package/src/utils/version-check.test.ts +108 -0
  316. package/src/utils/version-check.ts +96 -0
  317. package/src/utils/workspace-meta.ts +173 -0
  318. package/sync-permissions.sh +137 -0
  319. package/tsconfig.json +20 -0
  320. package/uninstall.sh +162 -0
@@ -0,0 +1,130 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require('path');
4
+ const command = process.argv[2];
5
+
6
+ // Handle --version / -V directly (works without compiled dist/)
7
+ if (command === '--version' || command === '-V') {
8
+ const pkg = require(path.join(__dirname, '..', 'package.json'));
9
+ console.log(pkg.version);
10
+ process.exit(0);
11
+ }
12
+
13
+ // Pre-check: if dist/ doesn't exist, show fallback help and exit.
14
+ // If dist/ exists, the module is cached and the else block below handles execution.
15
+ if (!command || command === '--help' || command === '-h' || command === 'help') {
16
+ try {
17
+ require(path.join(__dirname, '..', 'dist', 'program.js'));
18
+ } catch {
19
+ // Fallback: dist/ not built yet (e.g., CI test step runs before build)
20
+ const pkg = require(path.join(__dirname, '..', 'package.json'));
21
+ console.log(`Nemus v${pkg.version} · multi-repo workspaces`);
22
+ console.log(`Use "npm run build" then "nemus --help" for full command reference.`);
23
+ process.exit(0);
24
+ }
25
+ }
26
+
27
+ // Best-effort version upgrade check (non-blocking)
28
+ try {
29
+ const { checkForUpdate } = require(path.join(__dirname, '..', 'dist', 'utils', 'version-check.js'));
30
+ checkForUpdate().then((msg) => { if (msg) process.stderr.write(msg + '\n'); }).catch(() => {});
31
+ } catch {}
32
+
33
+ // Best-effort self-heal: repair Claude Code hook paths that point to a stale
34
+ // install location (e.g. Volta's ephemeral postinstall temp dir). Runs from the
35
+ // package's stable location so re-resolved paths are correct. Silent + cheap.
36
+ try {
37
+ const { repairStaleHooks } = require(path.join(__dirname, '..', 'dist', 'utils', 'permission-sync.js'));
38
+ const fixed = repairStaleHooks();
39
+ if (fixed > 0) {
40
+ process.stderr.write(`[nemus] Repaired ${fixed} stale Claude Code hook path(s).\n`);
41
+ }
42
+ } catch {}
43
+
44
+ // Shared handler: capture the error for `w report-bug`, optionally auto-file it.
45
+ // Build a privacy-safe command string for the bug report. The AI prompt in
46
+ // `w -- <prompt>` can contain private/sensitive text, so never publish it.
47
+ function redactCommand(command) {
48
+ const argv = Array.isArray(command) ? command : [String(command || '')];
49
+ if (argv[0] === '--') return '-- <prompt omitted for privacy>';
50
+ // No `--`, but `-p/--prompt <text>` (create/iterate) also carries a private
51
+ // task/prompt — redact its value too so it never lands in a bug report.
52
+ const out = [];
53
+ for (let i = 0; i < argv.length; i++) {
54
+ const a = argv[i];
55
+ if (a === '-p' || a === '--prompt') {
56
+ out.push(a, '<omitted>');
57
+ i++; // skip the value
58
+ } else if (a.startsWith('--prompt=')) {
59
+ out.push('--prompt=<omitted>');
60
+ } else if (a.startsWith('-p=')) {
61
+ out.push('-p=<omitted>');
62
+ } else {
63
+ out.push(a);
64
+ }
65
+ }
66
+ return out.join(' ');
67
+ }
68
+
69
+ function handleFatalError(err, command) {
70
+ const msg = (err && (err.message || String(err))) || 'Unknown error';
71
+ console.error(msg);
72
+ try {
73
+ const { captureLastError, reportBug } = require(path.join(__dirname, '..', 'dist', 'utils', 'bug-report.js'));
74
+ const pkg = require(path.join(__dirname, '..', 'package.json'));
75
+ const captured = {
76
+ command: 'w ' + redactCommand(command),
77
+ message: msg,
78
+ stack: err && err.stack ? String(err.stack) : undefined,
79
+ timestamp: new Date().toISOString(),
80
+ version: pkg.version,
81
+ };
82
+ captureLastError(captured);
83
+
84
+ let autoReport = false;
85
+ try {
86
+ const { getUserConfig } = require(path.join(__dirname, '..', 'dist', 'utils', 'config.js'));
87
+ autoReport = getUserConfig().autoReportBugs === true;
88
+ } catch {}
89
+
90
+ if (autoReport) {
91
+ const result = reportBug(captured, pkg.version);
92
+ if (result.status === 'created') {
93
+ console.error('\n[nemus] Filed bug report: ' + result.url);
94
+ } else if (result.status === 'duplicate') {
95
+ console.error('\n[nemus] Known issue: ' + result.url);
96
+ } else {
97
+ // skipped (e.g. environmental) or failed (e.g. gh not authed) —
98
+ // surface the specific reason instead of a generic hint.
99
+ if (result.reason) console.error('\n[nemus] Not filed: ' + result.reason);
100
+ const retry = result.status === 'skipped'
101
+ ? 'Run "w report-bug --force" to file it anyway.'
102
+ : 'Run "w report-bug" to try again.';
103
+ console.error('[nemus] ' + retry);
104
+ }
105
+ } else {
106
+ console.error('\n[nemus] Run "w report-bug" to file this as a GitHub issue.');
107
+ }
108
+ } catch {
109
+ // bug-report machinery is best-effort; never mask the original error
110
+ }
111
+ process.exit(1);
112
+ }
113
+
114
+ // Intercept `w -- <prompt>` before Commander (Commander treats -- as end-of-options)
115
+ if (command === '--') {
116
+ try {
117
+ const { handleAiPrompt } = require(path.join(__dirname, '..', 'dist', 'commands', 'ai-prompt.js'));
118
+ handleAiPrompt(process.argv.slice(3).join(' ')).catch((err) => {
119
+ handleFatalError(err, process.argv.slice(2));
120
+ });
121
+ } catch {
122
+ console.error('Run "npm run build" first to use the AI prompt feature.');
123
+ process.exit(1);
124
+ }
125
+ } else {
126
+ const { program } = require(path.join(__dirname, '..', 'dist', 'program.js'));
127
+ program.parseAsync(process.argv).catch((err) => {
128
+ handleFatalError(err, process.argv.slice(2));
129
+ });
130
+ }
@@ -0,0 +1,421 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.isClaudeAvailable = exports.AI_PROMPT_FILE = void 0;
37
+ exports.buildExtractionPrompt = buildExtractionPrompt;
38
+ exports.buildInvestigationPreamble = buildInvestigationPreamble;
39
+ exports.isPrimaryAgentAvailable = isPrimaryAgentAvailable;
40
+ exports.extractIntent = extractIntent;
41
+ exports.run = run;
42
+ exports.main = main;
43
+ const child_process_1 = require("child_process");
44
+ const util_1 = require("util");
45
+ const fs = __importStar(require("fs"));
46
+ const path = __importStar(require("path"));
47
+ const os = __importStar(require("os"));
48
+ const config_1 = require("../utils/config");
49
+ const logger_1 = require("../utils/logger");
50
+ const colors_1 = require("../utils/colors");
51
+ const agent_config_1 = require("../utils/agent-config");
52
+ const validation_1 = require("../utils/validation");
53
+ const execAsync = (0, util_1.promisify)(child_process_1.exec);
54
+ exports.AI_PROMPT_FILE = path.join(os.homedir(), '.workspace-ai-prompt');
55
+ const EXTRACT_SCHEMA = JSON.stringify({
56
+ type: 'object',
57
+ properties: {
58
+ workspaceName: { type: 'string', description: 'Workspace name (kebab-case, e.g. "payments-team")' },
59
+ repos: {
60
+ type: 'array',
61
+ items: { type: 'string' },
62
+ description: 'Repository names to clone (e.g. ["api", "web"]). Empty array when the repos cannot be known without investigation first.',
63
+ },
64
+ investigateFirst: {
65
+ type: 'boolean',
66
+ description: 'True when the user does NOT name concrete repos and instead wants the agent to investigate first (e.g. "search the logs and figure out which repos") and add the relevant repos itself. When true, repos must be an empty array.',
67
+ },
68
+ remainingIntent: {
69
+ type: 'string',
70
+ description: 'What the user wants done AFTER workspace creation (empty string if nothing beyond creating the workspace)',
71
+ },
72
+ },
73
+ required: ['workspaceName', 'repos', 'investigateFirst', 'remainingIntent'],
74
+ });
75
+ /**
76
+ * Build the extraction prompt for parsing workspace details from natural language.
77
+ */
78
+ function buildExtractionPrompt(userPrompt) {
79
+ return `Extract the workspace name and repository names from this request. If the user didn't specify a workspace name, generate a short descriptive kebab-case name. Repository names should be exact GitHub repo names (without org prefix). If the user's request includes things to do AFTER creating the workspace (like fixing code, creating branches, etc.), put that in remainingIntent.
80
+
81
+ IMPORTANT — investigate-first requests: if the user does NOT name concrete repositories and instead wants the agent to figure out which repos are relevant by investigating (e.g. "search the logs for X and open the repos involved", "look at this trace and pull the services' code", "find which repo owns this error"), then set "investigateFirst": true and "repos": [] (empty), and put the full investigation task in remainingIntent. Only list repos explicitly when the user actually names them or they're unambiguous.
82
+
83
+ Respond with ONLY a raw JSON object (no markdown, no backticks, no explanation). The JSON must have exactly these fields:
84
+ {"workspaceName": "short-kebab-name", "repos": ["repo-name-1", "repo-name-2"], "investigateFirst": false, "remainingIntent": "what to do after creation or empty string"}
85
+
86
+ User request: ${userPrompt}`;
87
+ }
88
+ /**
89
+ * Build the in-session task for an investigate-first workspace: the workspace
90
+ * starts empty, and the agent must discover which repos are relevant and add
91
+ * them itself before reading any code.
92
+ *
93
+ * Deliberately GENERIC (works for log/trace searches, GitHub search, stack
94
+ * traces, etc.). The discovery step adapts to the active agent: MCP tools when
95
+ * available, otherwise the always-present `gh` CLI (honouring a configured org).
96
+ */
97
+ function buildInvestigationPreamble(workspaceName, task, opts = {}) {
98
+ const org = (opts.githubOrg || '').trim();
99
+ const ownerFlag = org ? ` --owner ${org}` : '';
100
+ const repoListCmd = org ? `gh repo list ${org} --limit 200` : `gh repo list --limit 200`;
101
+ // Discovery differs by agent capability: "search-repos"/"list-org-repos" exist
102
+ // ONLY as Nemus MCP tools (there are no `nemus search-repos` CLI commands).
103
+ // When the active agent can't use MCP (e.g. Pi) or MCP is disabled, point it
104
+ // at the always-available `gh` CLI so we never name tools it doesn't have.
105
+ const discoveryStep = opts.useMcpTools
106
+ ? `3. Map each service to its GitHub repository using the Nemus MCP tools: try the "search-repos" tool (fuzzy) and "list-org-repos" to confirm the real repo name. Do not guess — verify the repo exists.`
107
+ : `3. Map each service to its GitHub repository using the \`gh\` CLI: \`gh search repos <name>${ownerFlag} --limit 20\` (or \`${repoListCmd}\`) to find and confirm the real repo name. Do not guess — verify the repo exists.`;
108
+ return [
109
+ `You are in a NEW, EMPTY workspace named "${workspaceName}" — it has no repositories cloned yet.`,
110
+ `Your job is to investigate first, then add the repositories you discover, and only then dig into the code.`,
111
+ ``,
112
+ `Follow this workflow:`,
113
+ `1. Investigate the request below using whatever sources it points to (e.g. logs/traces, a stack trace, GitHub search). Use your available tools/skills.`,
114
+ `2. From the investigation, identify the SERVICE / component names involved (e.g. from a trace's spans). Strip environment prefixes/suffixes like "production-", "-prod", "staging-" to get the base service name.`,
115
+ discoveryStep,
116
+ `4. Add the repositories you identified to THIS workspace by running: \`nemus update --workspace ${workspaceName} --repos <repo1,repo2,...> --yes\`. This clones them into the workspace.`,
117
+ `5. Briefly tell me which repos you added and why (which service/evidence pointed to each).`,
118
+ `6. THEN read the relevant code in those repos to complete the task.`,
119
+ ``,
120
+ `If the investigation points to no repos, say so instead of adding unrelated ones.`,
121
+ ``,
122
+ `--- Task ---`,
123
+ task,
124
+ ].join('\n');
125
+ }
126
+ /**
127
+ * Check if the primary agent CLI is available on the system.
128
+ */
129
+ async function isPrimaryAgentAvailable() {
130
+ const agent = (0, agent_config_1.getPrimaryAgent)();
131
+ try {
132
+ await execAsync(`which ${agent.launchCommand}`);
133
+ return true;
134
+ }
135
+ catch {
136
+ return false;
137
+ }
138
+ }
139
+ // Backward compat alias
140
+ exports.isClaudeAvailable = isPrimaryAgentAvailable;
141
+ /**
142
+ * Use the configured AI agent to extract structured workspace details from a natural language prompt.
143
+ */
144
+ // Extraction is a tiny JSON task, but the underlying model call can stall
145
+ // intermittently — e.g. a slow/large default model (Opus) plus provider
146
+ // retries/backoff (Bedrock rate-limits), or a cold agent startup. 60s was
147
+ // too tight and produced flaky `spawnSync ETIMEDOUT`. 120s gives those
148
+ // transient cases room while still bounding a genuine hang.
149
+ const EXTRACTION_TIMEOUT_MS = 120000;
150
+ /**
151
+ * Run an agent CLI for intent extraction, turning a timeout or non-zero exit
152
+ * into a clear, actionable error (instead of a cryptic `spawnSync ETIMEDOUT`).
153
+ *
154
+ * `fullArgs` is the preferred (lean) invocation. `fallbackArgs`, when provided,
155
+ * is a plainer invocation retried ONCE if the lean run fails fast (i.e. not a
156
+ * timeout or buffer overflow) — this covers older agent versions that reject
157
+ * newer speed flags like `--bare` / `--no-extensions` with an instant non-zero
158
+ * exit. Older versions then still work (just without the speedup).
159
+ */
160
+ function runExtraction(cmd, fullArgs, fallbackArgs) {
161
+ const exec = (args) => (0, child_process_1.execFileSync)(cmd, args, {
162
+ encoding: 'utf-8',
163
+ timeout: EXTRACTION_TIMEOUT_MS,
164
+ maxBuffer: 10 * 1024 * 1024,
165
+ });
166
+ const classify = (err) => {
167
+ const message = String(err?.message ?? '');
168
+ return {
169
+ timedOut: err?.code === 'ETIMEDOUT' || /ETIMEDOUT/.test(message),
170
+ bufferOverflow: err?.code === 'ENOBUFS' || /maxBuffer/i.test(message),
171
+ stderr: typeof err?.stderr === 'string' ? err.stderr.trim() : '',
172
+ stdout: typeof err?.stdout === 'string' ? err.stdout.trim() : '',
173
+ message,
174
+ };
175
+ };
176
+ try {
177
+ return exec(fullArgs);
178
+ }
179
+ catch (err) {
180
+ const c = classify(err);
181
+ // Fast failure (unsupported flag, etc.) on the lean invocation — retry
182
+ // once with the plainer args so older agent versions still work.
183
+ if (fallbackArgs && !c.timedOut && !c.bufferOverflow) {
184
+ try {
185
+ return exec(fallbackArgs);
186
+ }
187
+ catch (err2) {
188
+ return throwExtractionError(cmd, classify(err2));
189
+ }
190
+ }
191
+ return throwExtractionError(cmd, c);
192
+ }
193
+ }
194
+ function throwExtractionError(cmd, c) {
195
+ const testCmd = cmd === 'opencode'
196
+ ? `opencode run "reply with OK"`
197
+ : `${cmd} -p "reply with OK"`;
198
+ // claude -p --output-format json emits error details on stdout, not stderr.
199
+ const detail = c.stderr || c.stdout;
200
+ if (c.timedOut) {
201
+ const secs = Math.round(EXTRACTION_TIMEOUT_MS / 1000);
202
+ let msg = `${cmd} did not respond within ${secs}s while parsing your request.\n` +
203
+ ` This is usually a transient model/provider stall, not a workspace-manager bug.\n` +
204
+ ` • Verify the agent itself responds quickly: time ${testCmd}\n` +
205
+ ` • If it's slow, your default model may be heavy (e.g. Opus) or the provider\n` +
206
+ ` may be rate-limiting/refreshing credentials. Retry, or switch to a faster model.\n` +
207
+ ` • You can still create the workspace manually: nemus create --workspace <name> --repos <repos>`;
208
+ if (detail)
209
+ msg += `\n agent output: ${detail.slice(0, 500)}`;
210
+ throw new Error(msg);
211
+ }
212
+ if (c.bufferOverflow) {
213
+ throw new Error(`${cmd} produced more output than expected while parsing your request ` +
214
+ `(maxBuffer exceeded). Try a shorter request, or create the workspace ` +
215
+ `manually: nemus create --workspace <name> --repos <repos>` +
216
+ (detail ? `\n agent output: ${detail.slice(0, 500)}` : ''));
217
+ }
218
+ throw new Error(`${cmd} failed while parsing your request.\n` +
219
+ ` • Verify the agent works: ${testCmd}\n` +
220
+ ` • Or create the workspace manually: nemus create --workspace <name> --repos <repos>` +
221
+ (detail ? `\n agent output: ${detail.slice(0, 800)}` : ` (${c.message || 'unknown error'})`));
222
+ }
223
+ async function extractIntent(prompt) {
224
+ const extractionPrompt = buildExtractionPrompt(prompt);
225
+ const agent = (0, agent_config_1.getPrimaryAgent)();
226
+ let result;
227
+ if (agent.type === 'claude') {
228
+ // Preferred: structured + lean. --output-format/--json-schema give clean
229
+ // structured output; --bare/--strict-mcp-config/--disable-slash-commands
230
+ // skip the heavy ~/.claude (hooks, MCP servers, skills, plugins, context)
231
+ // so a bloated setup can't time out.
232
+ const preferred = [
233
+ '-p', extractionPrompt,
234
+ '--output-format', 'json',
235
+ '--json-schema', EXTRACT_SCHEMA,
236
+ '--bare',
237
+ '--strict-mcp-config',
238
+ '--disable-slash-commands',
239
+ ];
240
+ // Fallback: the most basic invocation that works on ANY claude version.
241
+ // If the user's claude rejects ANY of the flags above (it exits instantly
242
+ // non-zero), retry with plain `-p <prompt>` and parse the raw JSON text
243
+ // (same approach as pi). The extraction prompt already asks for raw JSON.
244
+ const fallback = ['-p', extractionPrompt];
245
+ result = runExtraction('claude', preferred, fallback);
246
+ }
247
+ else if (agent.type === 'opencode') {
248
+ // OpenCode: use 'run' subcommand with positional message argument
249
+ result = runExtraction('opencode', ['run', extractionPrompt]);
250
+ }
251
+ else {
252
+ // Pi: run as LEAN as possible. Intent extraction is a pure text->JSON
253
+ // transform that needs no extensions, skills, prompt-templates, context
254
+ // files, tools, or saved session. Loading the user's full environment
255
+ // (especially many MCP tools/skills or a large AGENTS.md context) is what
256
+ // made `pi -p` slow enough to blow past the timeout on bloated setups.
257
+ // These flags also avoid spawning MCP servers / credential-refresh
258
+ // extensions that can hang a non-interactive subprocess.
259
+ const piCore = ['-p', extractionPrompt];
260
+ const piLean = [
261
+ '--no-extensions',
262
+ '--no-skills',
263
+ '--no-prompt-templates',
264
+ '--no-context-files',
265
+ '--no-tools',
266
+ '--no-session',
267
+ ];
268
+ result = runExtraction('pi', [...piLean, ...piCore], piCore);
269
+ }
270
+ // Strip markdown code fences if present (Pi may wrap JSON in ```json...```)
271
+ let jsonStr = result.trim();
272
+ const fenceMatch = jsonStr.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
273
+ if (fenceMatch) {
274
+ jsonStr = fenceMatch[1].trim();
275
+ }
276
+ const parsed = JSON.parse(jsonStr);
277
+ // Handle different output formats:
278
+ // - Claude: { structured_output: {...} } or { result: "..." }
279
+ // - Pi: may return the object directly or wrap it
280
+ let intent;
281
+ if (parsed.structured_output) {
282
+ intent = parsed.structured_output;
283
+ }
284
+ else if (typeof parsed.result === 'string' && parsed.result) {
285
+ try {
286
+ intent = JSON.parse(parsed.result);
287
+ }
288
+ catch { /* ignore */ }
289
+ }
290
+ else if (typeof parsed.result === 'object' && parsed.result !== null) {
291
+ intent = parsed.result;
292
+ }
293
+ else if (parsed.workspaceName || parsed.repos || parsed.remainingIntent !== undefined) {
294
+ // Pi may return the extracted object directly
295
+ intent = parsed;
296
+ }
297
+ if (!intent) {
298
+ throw new Error(`Could not extract intent from agent response. Parsed: ${JSON.stringify(parsed).slice(0, 200)}`);
299
+ }
300
+ // Coerce/validate field types so malformed model output can't crash the
301
+ // downstream .trim()/sanitize path (a stringly-typed workspaceName or a
302
+ // non-array repos would otherwise throw). Non-conforming values are dropped
303
+ // to their safe empty form, so run()'s existing "could not determine" guard
304
+ // handles them cleanly instead of an unhandled exception.
305
+ const normalized = {
306
+ workspaceName: typeof intent.workspaceName === 'string' ? intent.workspaceName : '',
307
+ repos: Array.isArray(intent.repos)
308
+ ? intent.repos.filter((r) => typeof r === 'string')
309
+ : [],
310
+ remainingIntent: typeof intent.remainingIntent === 'string' ? intent.remainingIntent : '',
311
+ investigateFirst: intent.investigateFirst === true,
312
+ };
313
+ return normalized;
314
+ }
315
+ /**
316
+ * Run the AI prompt command.
317
+ *
318
+ * 1. Extract workspace name + repos from the prompt (fast, no tool use).
319
+ * 2. Create the workspace using the CLI directly (shows progress).
320
+ * 3. Shell integration CDs to workspace and launches interactive Claude.
321
+ */
322
+ async function run(prompt) {
323
+ const agentAvailable = await (0, exports.isClaudeAvailable)();
324
+ if (!agentAvailable) {
325
+ const agent = (0, agent_config_1.getPrimaryAgent)();
326
+ (0, logger_1.logError)(`${agent.type} CLI not found. Install it first.`);
327
+ return 1;
328
+ }
329
+ const displayPrompt = prompt.length > 80 ? prompt.slice(0, 77) + '...' : prompt;
330
+ (0, logger_1.logInfo)(`AI prompt: ${(0, colors_1.colorize)(displayPrompt, 'cyan')}`);
331
+ fs.mkdirSync(config_1.WORKSPACES_DIR, { recursive: true });
332
+ // Step 1: Extract workspace details from natural language
333
+ (0, logger_1.logStep)(1, 2, 'Understanding request...');
334
+ let intent;
335
+ try {
336
+ intent = await extractIntent(prompt);
337
+ }
338
+ catch (err) {
339
+ (0, logger_1.logError)('Failed to parse workspace request');
340
+ if (err instanceof Error)
341
+ (0, logger_1.logError)(err.message);
342
+ return 1;
343
+ }
344
+ const repos = Array.isArray(intent.repos) ? intent.repos : [];
345
+ // Investigate-first: no concrete repos yet — create an empty workspace and let
346
+ // the in-session agent discover + add the repos. This only applies when the
347
+ // model produced NO repos: if it already identified some, we must clone them
348
+ // (never silently discard them for an empty workspace), even if it also set
349
+ // the investigateFirst flag. An empty repo list with a real task is treated
350
+ // as investigate-mode too, even if the model forgot the flag.
351
+ const investigateFirst = repos.length === 0
352
+ && (intent.investigateFirst === true || !!(intent.remainingIntent || '').trim());
353
+ if (!intent.workspaceName || (repos.length === 0 && !investigateFirst)) {
354
+ (0, logger_1.logError)('Could not determine workspace name or repos from prompt');
355
+ (0, logger_1.logInfo)(`Parsed: name=${intent.workspaceName || '(none)'}, repos=${repos.join(', ') || '(none)'}`);
356
+ return 1;
357
+ }
358
+ // In investigate-first mode the preamble tells the agent to run
359
+ // `nemus update --workspace <name> ...`, so that name MUST match the workspace
360
+ // `nemus create` actually produces. Pre-resolve it here (same sanitize +
361
+ // conflict resolution create uses) and pass the SAME resolved name to both
362
+ // the preamble and create, so a sanitized/de-duplicated name can't drift.
363
+ let workspaceName = intent.workspaceName;
364
+ if (investigateFirst) {
365
+ workspaceName = (0, validation_1.sanitizeWorkspaceName)(intent.workspaceName);
366
+ if (await (0, validation_1.checkWorkspaceExists)(workspaceName)) {
367
+ workspaceName = await (0, validation_1.resolveWorkspaceNameConflict)(workspaceName, []);
368
+ }
369
+ }
370
+ if (investigateFirst) {
371
+ (0, logger_1.logInfo)(`Workspace: ${(0, colors_1.colorize)(workspaceName, 'cyan')} ${(0, colors_1.colorize)('(investigate-first — no repos yet)', 'gray')}`);
372
+ }
373
+ else {
374
+ (0, logger_1.logInfo)(`Workspace: ${(0, colors_1.colorize)(workspaceName, 'cyan')}, Repos: ${(0, colors_1.colorize)(repos.join(', '), 'cyan')}`);
375
+ }
376
+ // Save the task for the follow-up interactive session. In investigate-first
377
+ // mode, wrap it with a workflow preamble so the agent discovers repos and
378
+ // adds them itself before reading code.
379
+ const baseTask = intent.remainingIntent || prompt;
380
+ // The "search-repos"/"list-org-repos" discovery helpers are MCP-only, so the
381
+ // preamble may reference them only when the active agent supports MCP AND MCP
382
+ // is enabled; otherwise it falls back to the `gh` CLI.
383
+ const cfg = (0, config_1.getUserConfig)();
384
+ const useMcpTools = (0, agent_config_1.getPrimaryAgent)().supportsMcp && cfg.installMcp;
385
+ const remaining = investigateFirst
386
+ ? buildInvestigationPreamble(workspaceName, baseTask, { useMcpTools, githubOrg: cfg.githubOrg })
387
+ : baseTask;
388
+ try {
389
+ fs.writeFileSync(exports.AI_PROMPT_FILE, remaining, 'utf-8');
390
+ }
391
+ catch { }
392
+ // Step 2: Create workspace using the CLI directly
393
+ (0, logger_1.logStep)(2, 2, 'Creating workspace...');
394
+ const createArgs = investigateFirst
395
+ ? ['create', '--workspace', workspaceName, '--allow-empty', '--prompt', prompt, '--yes']
396
+ : ['create', '--workspace', workspaceName, '--repos', repos.join(','), '--prompt', prompt, '--yes'];
397
+ return new Promise((resolve) => {
398
+ const child = (0, child_process_1.spawn)('nemus', createArgs, {
399
+ stdio: 'inherit',
400
+ });
401
+ child.on('error', (err) => {
402
+ (0, logger_1.logError)(`Failed to create workspace: ${err.message}`);
403
+ resolve(1);
404
+ });
405
+ child.on('exit', (code) => {
406
+ resolve(code || 0);
407
+ });
408
+ });
409
+ }
410
+ async function main() {
411
+ const prompt = process.argv.slice(2).join(' ').trim();
412
+ if (!prompt) {
413
+ (0, logger_1.logError)('No prompt provided');
414
+ console.log(`\n Usage: ${(0, colors_1.colorize)('nemus -- <prompt>', 'green')}`);
415
+ console.log(` Example: ${(0, colors_1.colorize)('nemus -- create a workspace for the payments team', 'gray')}\n`);
416
+ process.exit(1);
417
+ return;
418
+ }
419
+ const exitCode = await run(prompt);
420
+ process.exit(exitCode);
421
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.AgentList = void 0;
37
+ const React = __importStar(require("react"));
38
+ const StatusBadge_1 = require("./StatusBadge");
39
+ const AgentList = ({ agents, selectedIndex, onSelect, Box, Text }) => {
40
+ if (agents.length === 0) {
41
+ return (React.createElement(Box, { flexDirection: "column" },
42
+ React.createElement(Text, { dimColor: true }, "No agents running"),
43
+ React.createElement(Text, { dimColor: true }, "Press n to launch")));
44
+ }
45
+ return (React.createElement(Box, { flexDirection: "column" }, agents.map((agent, i) => {
46
+ const isSelected = i === selectedIndex;
47
+ const ws = agent.workspace.length > 13
48
+ ? agent.workspace.slice(0, 12) + '…'
49
+ : agent.workspace;
50
+ const num = `${i + 1}`;
51
+ return (React.createElement(Box, { key: agent.sessionId, gap: 1 },
52
+ isSelected ? (React.createElement(Text, { backgroundColor: "blue", color: "white", bold: true },
53
+ "\u25B8",
54
+ num)) : (React.createElement(Text, { dimColor: true },
55
+ " ",
56
+ num)),
57
+ React.createElement(Text, { color: "cyan", bold: isSelected }, ws.padEnd(13)),
58
+ React.createElement(StatusBadge_1.StatusBadge, { status: agent.status, Box: Box, Text: Text })));
59
+ })));
60
+ };
61
+ exports.AgentList = AgentList;