@compilr-dev/cli 0.4.0 → 0.5.0

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 (315) hide show
  1. package/README.md +30 -12
  2. package/dist/agent.d.ts +74 -1
  3. package/dist/agent.js +259 -76
  4. package/dist/anchors/index.d.ts +9 -0
  5. package/dist/anchors/index.js +9 -0
  6. package/dist/anchors/project-anchors.d.ts +79 -0
  7. package/dist/anchors/project-anchors.js +202 -0
  8. package/dist/commands/handler-types.d.ts +68 -0
  9. package/dist/commands/handler-types.js +8 -0
  10. package/dist/commands/handlers/agent-commands.d.ts +13 -0
  11. package/dist/commands/handlers/agent-commands.js +305 -0
  12. package/dist/commands/handlers/design-commands.d.ts +15 -0
  13. package/dist/commands/handlers/design-commands.js +334 -0
  14. package/dist/commands/handlers/index.d.ts +20 -0
  15. package/dist/commands/handlers/index.js +43 -0
  16. package/dist/commands/handlers/overlay-commands.d.ts +21 -0
  17. package/dist/commands/handlers/overlay-commands.js +287 -0
  18. package/dist/commands/handlers/project-commands.d.ts +11 -0
  19. package/dist/commands/handlers/project-commands.js +167 -0
  20. package/dist/commands/handlers/simple-commands.d.ts +19 -0
  21. package/dist/commands/handlers/simple-commands.js +144 -0
  22. package/dist/commands/index.d.ts +2 -1
  23. package/dist/commands/registry.d.ts +50 -0
  24. package/dist/commands/registry.js +75 -0
  25. package/dist/commands-v2/handlers/context.d.ts +13 -0
  26. package/dist/commands-v2/handlers/context.js +348 -0
  27. package/dist/commands-v2/handlers/core.d.ts +13 -0
  28. package/dist/commands-v2/handlers/core.js +165 -0
  29. package/dist/commands-v2/handlers/debug.d.ts +11 -0
  30. package/dist/commands-v2/handlers/debug.js +159 -0
  31. package/dist/commands-v2/handlers/index.d.ts +12 -0
  32. package/dist/commands-v2/handlers/index.js +24 -0
  33. package/dist/commands-v2/handlers/project.d.ts +22 -0
  34. package/dist/commands-v2/handlers/project.js +814 -0
  35. package/dist/commands-v2/handlers/settings.d.ts +15 -0
  36. package/dist/commands-v2/handlers/settings.js +235 -0
  37. package/dist/commands-v2/index.d.ts +13 -0
  38. package/dist/commands-v2/index.js +15 -0
  39. package/dist/commands-v2/registry.d.ts +37 -0
  40. package/dist/commands-v2/registry.js +80 -0
  41. package/dist/commands-v2/types.d.ts +75 -0
  42. package/dist/commands-v2/types.js +7 -0
  43. package/dist/commands.js +110 -7
  44. package/dist/index.js +288 -29
  45. package/dist/input-handlers/index.d.ts +7 -0
  46. package/dist/input-handlers/index.js +7 -0
  47. package/dist/input-handlers/memory-handler.d.ts +26 -0
  48. package/dist/input-handlers/memory-handler.js +68 -0
  49. package/dist/repl-helpers.d.ts +63 -0
  50. package/dist/repl-helpers.js +318 -0
  51. package/dist/repl-v2.d.ts +155 -0
  52. package/dist/repl-v2.js +774 -0
  53. package/dist/repl.d.ts +32 -4
  54. package/dist/repl.js +250 -977
  55. package/dist/settings/index.d.ts +23 -0
  56. package/dist/settings/index.js +48 -0
  57. package/dist/settings/paths.d.ts +110 -0
  58. package/dist/settings/paths.js +264 -0
  59. package/dist/templates/compilr-md.js +7 -4
  60. package/dist/templates/index.js +3 -4
  61. package/dist/themes/colors.js +3 -1
  62. package/dist/themes/registry.d.ts +5 -36
  63. package/dist/themes/registry.js +11 -95
  64. package/dist/themes/types.d.ts +3 -38
  65. package/dist/themes/types.js +2 -2
  66. package/dist/tools/anchor-tools.d.ts +31 -0
  67. package/dist/tools/anchor-tools.js +255 -0
  68. package/dist/tools/backlog-wrappers.d.ts +54 -0
  69. package/dist/tools/backlog-wrappers.js +338 -0
  70. package/dist/tools/backlog.js +1 -1
  71. package/dist/tools/db-tools.d.ts +65 -0
  72. package/dist/tools/db-tools.js +19 -0
  73. package/dist/tools/document-db.d.ts +43 -0
  74. package/dist/tools/document-db.js +220 -0
  75. package/dist/tools/project-db.d.ts +102 -0
  76. package/dist/tools/project-db.js +370 -0
  77. package/dist/tools/workitem-db.d.ts +103 -0
  78. package/dist/tools/workitem-db.js +549 -0
  79. package/dist/tools.js +13 -3
  80. package/dist/ui/agents-overlay-v2.d.ts +43 -0
  81. package/dist/ui/agents-overlay-v2.js +809 -0
  82. package/dist/ui/agents-overlay.d.ts +5 -5
  83. package/dist/ui/agents-overlay.js +782 -420
  84. package/dist/ui/anchors-overlay.d.ts +12 -0
  85. package/dist/ui/anchors-overlay.js +775 -0
  86. package/dist/ui/arch-type-overlay.d.ts +1 -6
  87. package/dist/ui/arch-type-overlay.js +175 -203
  88. package/dist/ui/ask-user-overlay-v2.d.ts +26 -0
  89. package/dist/ui/ask-user-overlay-v2.js +555 -0
  90. package/dist/ui/ask-user-overlay.d.ts +2 -2
  91. package/dist/ui/ask-user-overlay.js +443 -535
  92. package/dist/ui/ask-user-simple-overlay-v2.d.ts +25 -0
  93. package/dist/ui/ask-user-simple-overlay-v2.js +215 -0
  94. package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
  95. package/dist/ui/ask-user-simple-overlay.js +182 -209
  96. package/dist/ui/backlog-overlay.d.ts +16 -1
  97. package/dist/ui/backlog-overlay.js +525 -659
  98. package/dist/ui/base/index.d.ts +26 -0
  99. package/dist/ui/base/index.js +33 -0
  100. package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
  101. package/dist/ui/base/inline-overlay-utils.js +320 -0
  102. package/dist/ui/base/inline-overlay.d.ts +159 -0
  103. package/dist/ui/base/inline-overlay.js +257 -0
  104. package/dist/ui/base/key-utils.d.ts +15 -0
  105. package/dist/ui/base/key-utils.js +30 -0
  106. package/dist/ui/base/overlay-base-v2.d.ts +193 -0
  107. package/dist/ui/base/overlay-base-v2.js +246 -0
  108. package/dist/ui/base/overlay-base.d.ts +156 -0
  109. package/dist/ui/base/overlay-base.js +238 -0
  110. package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
  111. package/dist/ui/base/overlay-lifecycle.js +159 -0
  112. package/dist/ui/base/overlay-types.d.ts +185 -0
  113. package/dist/ui/base/overlay-types.js +7 -0
  114. package/dist/ui/base/render-utils.d.ts +8 -0
  115. package/dist/ui/base/render-utils.js +11 -0
  116. package/dist/ui/base/screen-stack.d.ts +148 -0
  117. package/dist/ui/base/screen-stack.js +184 -0
  118. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +103 -0
  119. package/dist/ui/base/tabbed-list-overlay-v2.js +317 -0
  120. package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
  121. package/dist/ui/base/tabbed-list-overlay.js +369 -0
  122. package/dist/ui/commands-overlay-v2.d.ts +33 -0
  123. package/dist/ui/commands-overlay-v2.js +441 -0
  124. package/dist/ui/commands-overlay.d.ts +7 -2
  125. package/dist/ui/commands-overlay.js +384 -355
  126. package/dist/ui/config-overlay.d.ts +5 -4
  127. package/dist/ui/config-overlay.js +243 -513
  128. package/dist/ui/conversation.d.ts +75 -4
  129. package/dist/ui/conversation.js +374 -161
  130. package/dist/ui/docs-overlay.d.ts +17 -0
  131. package/dist/ui/docs-overlay.js +303 -0
  132. package/dist/ui/ephemeral.d.ts +1 -1
  133. package/dist/ui/ephemeral.js +1 -1
  134. package/dist/ui/features/index.d.ts +34 -0
  135. package/dist/ui/features/index.js +34 -0
  136. package/dist/ui/features/input-feature.d.ts +85 -0
  137. package/dist/ui/features/input-feature.js +238 -0
  138. package/dist/ui/features/list-feature.d.ts +155 -0
  139. package/dist/ui/features/list-feature.js +244 -0
  140. package/dist/ui/features/pagination-feature.d.ts +154 -0
  141. package/dist/ui/features/pagination-feature.js +238 -0
  142. package/dist/ui/features/search-feature.d.ts +148 -0
  143. package/dist/ui/features/search-feature.js +185 -0
  144. package/dist/ui/features/tab-feature.d.ts +194 -0
  145. package/dist/ui/features/tab-feature.js +307 -0
  146. package/dist/ui/footer-v2.d.ts +222 -0
  147. package/dist/ui/footer-v2.js +1349 -0
  148. package/dist/ui/footer.d.ts +107 -0
  149. package/dist/ui/footer.js +359 -67
  150. package/dist/ui/guardrail-overlay.d.ts +29 -0
  151. package/dist/ui/guardrail-overlay.js +145 -0
  152. package/dist/ui/help-overlay-v2.d.ts +34 -0
  153. package/dist/ui/help-overlay-v2.js +309 -0
  154. package/dist/ui/help-overlay.d.ts +16 -0
  155. package/dist/ui/help-overlay.js +316 -0
  156. package/dist/ui/index.d.ts +1 -1
  157. package/dist/ui/index.js +1 -3
  158. package/dist/ui/init-overlay-v2.d.ts +34 -0
  159. package/dist/ui/init-overlay-v2.js +600 -0
  160. package/dist/ui/init-overlay.d.ts +12 -2
  161. package/dist/ui/init-overlay.js +349 -270
  162. package/dist/ui/input-prompt-v2.d.ts +1 -0
  163. package/dist/ui/input-prompt-v2.js +14 -6
  164. package/dist/ui/input-prompt.d.ts +116 -33
  165. package/dist/ui/input-prompt.js +536 -337
  166. package/dist/ui/iteration-limit-overlay-v2.d.ts +21 -0
  167. package/dist/ui/iteration-limit-overlay-v2.js +114 -0
  168. package/dist/ui/iteration-limit-overlay.d.ts +2 -2
  169. package/dist/ui/iteration-limit-overlay.js +92 -128
  170. package/dist/ui/keys-overlay-v2.d.ts +41 -0
  171. package/dist/ui/keys-overlay-v2.js +248 -0
  172. package/dist/ui/keys-overlay.d.ts +1 -0
  173. package/dist/ui/keys-overlay.js +203 -141
  174. package/dist/ui/line-utils.d.ts +88 -0
  175. package/dist/ui/line-utils.js +150 -0
  176. package/dist/ui/live-region.d.ts +161 -0
  177. package/dist/ui/live-region.js +387 -0
  178. package/dist/ui/mascot/expressions.d.ts +32 -0
  179. package/dist/ui/mascot/expressions.js +213 -0
  180. package/dist/ui/mascot/index.d.ts +8 -0
  181. package/dist/ui/mascot/index.js +8 -0
  182. package/dist/ui/mascot/renderer.d.ts +19 -0
  183. package/dist/ui/mascot/renderer.js +97 -0
  184. package/dist/ui/mascot-overlay-v2.d.ts +41 -0
  185. package/dist/ui/mascot-overlay-v2.js +138 -0
  186. package/dist/ui/mascot-overlay.d.ts +21 -0
  187. package/dist/ui/mascot-overlay.js +146 -0
  188. package/dist/ui/model-overlay-v2.d.ts +49 -0
  189. package/dist/ui/model-overlay-v2.js +118 -0
  190. package/dist/ui/model-overlay.d.ts +27 -0
  191. package/dist/ui/model-overlay.js +221 -0
  192. package/dist/ui/model-warning-overlay.js +3 -5
  193. package/dist/ui/new-overlay.d.ts +34 -0
  194. package/dist/ui/new-overlay.js +604 -0
  195. package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
  196. package/dist/ui/overlay/impl/agents-overlay-v2.js +825 -0
  197. package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
  198. package/dist/ui/overlay/impl/anchors-overlay-v2.js +783 -0
  199. package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
  200. package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
  201. package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
  202. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +584 -0
  203. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
  204. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
  205. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +49 -0
  206. package/dist/ui/overlay/impl/backlog-overlay-v2.js +642 -0
  207. package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
  208. package/dist/ui/overlay/impl/commands-overlay-v2.js +441 -0
  209. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +100 -0
  210. package/dist/ui/overlay/impl/config-overlay-v2.js +654 -0
  211. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +55 -0
  212. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +359 -0
  213. package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
  214. package/dist/ui/overlay/impl/docs-overlay-v2.js +114 -0
  215. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +77 -0
  216. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1071 -0
  217. package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
  218. package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
  219. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +34 -0
  220. package/dist/ui/overlay/impl/help-overlay-v2.js +309 -0
  221. package/dist/ui/overlay/impl/init-overlay-v2.d.ts +77 -0
  222. package/dist/ui/overlay/impl/init-overlay-v2.js +593 -0
  223. package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
  224. package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
  225. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
  226. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
  227. package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
  228. package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
  229. package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
  230. package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
  231. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +49 -0
  232. package/dist/ui/overlay/impl/model-overlay-v2.js +118 -0
  233. package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
  234. package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
  235. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +77 -0
  236. package/dist/ui/overlay/impl/new-overlay-v2.js +593 -0
  237. package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
  238. package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
  239. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +36 -0
  240. package/dist/ui/overlay/impl/projects-overlay-v2.js +499 -0
  241. package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
  242. package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
  243. package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
  244. package/dist/ui/overlay/impl/tools-overlay-v2.js +218 -0
  245. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +31 -0
  246. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +1035 -0
  247. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
  248. package/dist/ui/overlay/impl/workflow-overlay-v2.js +637 -0
  249. package/dist/ui/overlay/index.d.ts +33 -0
  250. package/dist/ui/overlay/index.js +35 -0
  251. package/dist/ui/overlay/key-utils.d.ts +6 -0
  252. package/dist/ui/overlay/key-utils.js +6 -0
  253. package/dist/ui/overlay/overlay-types.d.ts +128 -0
  254. package/dist/ui/overlay/overlay-types.js +22 -0
  255. package/dist/ui/overlay/types.d.ts +135 -0
  256. package/dist/ui/overlay/types.js +22 -0
  257. package/dist/ui/overlays/help-overlay-v2.d.ts +28 -0
  258. package/dist/ui/overlays/help-overlay-v2.js +198 -0
  259. package/dist/ui/overlays/index.d.ts +11 -0
  260. package/dist/ui/overlays/index.js +11 -0
  261. package/dist/ui/overlays.d.ts +0 -4
  262. package/dist/ui/overlays.js +0 -444
  263. package/dist/ui/permission-overlay-v2.d.ts +36 -0
  264. package/dist/ui/permission-overlay-v2.js +380 -0
  265. package/dist/ui/permission-overlay.d.ts +1 -1
  266. package/dist/ui/permission-overlay.js +186 -298
  267. package/dist/ui/projects-overlay.d.ts +19 -0
  268. package/dist/ui/projects-overlay.js +484 -0
  269. package/dist/ui/providers/types.d.ts +178 -0
  270. package/dist/ui/providers/types.js +9 -0
  271. package/dist/ui/render-modes.d.ts +36 -0
  272. package/dist/ui/render-modes.js +44 -0
  273. package/dist/ui/startup-menu.d.ts +36 -0
  274. package/dist/ui/startup-menu.js +236 -0
  275. package/dist/ui/subagent-renderer.d.ts +117 -0
  276. package/dist/ui/subagent-renderer.js +334 -0
  277. package/dist/ui/terminal-codes.d.ts +94 -0
  278. package/dist/ui/terminal-codes.js +124 -0
  279. package/dist/ui/terminal-renderer.d.ts +221 -0
  280. package/dist/ui/terminal-renderer.js +751 -0
  281. package/dist/ui/terminal-ui.d.ts +463 -0
  282. package/dist/ui/terminal-ui.js +2296 -0
  283. package/dist/ui/terminal.d.ts +20 -0
  284. package/dist/ui/terminal.js +72 -0
  285. package/dist/ui/theme-overlay-v2.d.ts +42 -0
  286. package/dist/ui/theme-overlay-v2.js +135 -0
  287. package/dist/ui/theme-overlay.d.ts +24 -0
  288. package/dist/ui/theme-overlay.js +127 -0
  289. package/dist/ui/todo-zone.js +53 -25
  290. package/dist/ui/tool-formatters.d.ts +16 -0
  291. package/dist/ui/tool-formatters.js +516 -0
  292. package/dist/ui/tools-overlay-v2.d.ts +47 -0
  293. package/dist/ui/tools-overlay-v2.js +218 -0
  294. package/dist/ui/tools-overlay.d.ts +10 -2
  295. package/dist/ui/tools-overlay.js +172 -220
  296. package/dist/ui/tutorial-overlay-v2.d.ts +31 -0
  297. package/dist/ui/tutorial-overlay-v2.js +1035 -0
  298. package/dist/ui/tutorial-overlay.d.ts +1 -0
  299. package/dist/ui/tutorial-overlay.js +400 -302
  300. package/dist/ui/workflow-overlay.d.ts +22 -0
  301. package/dist/ui/workflow-overlay.js +636 -0
  302. package/dist/utils/debug-log.d.ts +28 -0
  303. package/dist/utils/debug-log.js +57 -0
  304. package/dist/utils/model-tiers.js +1 -1
  305. package/dist/utils/path-safety.d.ts +56 -0
  306. package/dist/utils/path-safety.js +239 -0
  307. package/dist/workflow/guided-mode-injector.d.ts +42 -0
  308. package/dist/workflow/guided-mode-injector.js +191 -0
  309. package/dist/workflow/index.d.ts +8 -0
  310. package/dist/workflow/index.js +8 -0
  311. package/dist/workflow/step-criteria.d.ts +62 -0
  312. package/dist/workflow/step-criteria.js +150 -0
  313. package/dist/workflow/step-tracker.d.ts +92 -0
  314. package/dist/workflow/step-tracker.js +141 -0
  315. package/package.json +12 -5
@@ -0,0 +1,441 @@
1
+ /**
2
+ * Commands Overlay V2
3
+ *
4
+ * Modal overlay for viewing and managing custom command definitions.
5
+ * Uses TabbedListOverlayV2 for consistent navigation patterns.
6
+ *
7
+ * Features:
8
+ * - Tabs: All, Project, Personal
9
+ * - Search with / toggle
10
+ * - Detail view for command information
11
+ * - Wizard for creating new commands
12
+ */
13
+ import chalk from 'chalk';
14
+ import * as terminal from './terminal.js';
15
+ import { getCustomCommandRegistry, } from '../commands/index.js';
16
+ import { TabbedListOverlayV2, BaseScreen, stay, popScreen, closeOverlay, isEscape, isEnter, isCtrlC, isNavigateUp, isNavigateDown, isBackspace, renderBorder, wrapText, } from './base/index.js';
17
+ import { InputFeature } from './features/index.js';
18
+ // =============================================================================
19
+ // Constants
20
+ // =============================================================================
21
+ const TABS = [
22
+ { id: 'all', label: 'All' },
23
+ { id: 'project', label: 'Project' },
24
+ { id: 'personal', label: 'Personal' },
25
+ ];
26
+ const PAGE_SIZE = 10;
27
+ // =============================================================================
28
+ // Helpers
29
+ // =============================================================================
30
+ function isCreateItem(item) {
31
+ return 'type' in item;
32
+ }
33
+ function buildItemsList(registry) {
34
+ const commands = registry.getAll();
35
+ return [...commands, { type: 'create' }];
36
+ }
37
+ function defaultWizardState() {
38
+ return {
39
+ step: 'location',
40
+ location: 'project',
41
+ name: '',
42
+ description: '',
43
+ prompt: '',
44
+ selectedOption: 0,
45
+ error: null,
46
+ };
47
+ }
48
+ // =============================================================================
49
+ // Detail Screen
50
+ // =============================================================================
51
+ class CommandDetailScreen extends BaseScreen {
52
+ command;
53
+ registry;
54
+ styles;
55
+ constructor(command, registry, styles) {
56
+ super();
57
+ this.command = command;
58
+ this.registry = registry;
59
+ this.styles = styles;
60
+ }
61
+ render() {
62
+ const s = this.styles;
63
+ const lines = [];
64
+ const cols = terminal.getTerminalWidth();
65
+ const border = renderBorder(cols, s);
66
+ const cmd = this.command;
67
+ // Header
68
+ lines.push(border);
69
+ lines.push(' ' + s.primaryBold('Command Details'));
70
+ lines.push('');
71
+ // Command name
72
+ lines.push(chalk.bold(` /${cmd.name}`));
73
+ lines.push('');
74
+ // Location
75
+ lines.push(' ' + s.primary('LOCATION'));
76
+ lines.push(` ${cmd.location === 'project' ? 'Project' : 'Personal'} (${cmd.location})`);
77
+ lines.push('');
78
+ // File path
79
+ lines.push(' ' + s.primary('FILE'));
80
+ const basePath = cmd.location === 'project'
81
+ ? this.registry.getProjectDir()
82
+ : this.registry.getUserDir();
83
+ lines.push(s.muted(` ${basePath}/${cmd.name}.md`));
84
+ lines.push('');
85
+ // Description
86
+ lines.push(' ' + s.primary('DESCRIPTION'));
87
+ const descLines = wrapText(cmd.description, cols - 6, ' ');
88
+ lines.push(...descLines);
89
+ lines.push('');
90
+ // Prompt
91
+ lines.push(' ' + s.primary('PROMPT TEMPLATE'));
92
+ const promptLines = wrapText(cmd.prompt, cols - 6, ' ');
93
+ lines.push(...promptLines);
94
+ lines.push('');
95
+ // Footer
96
+ lines.push(border);
97
+ lines.push(` ${s.muted('q/Esc Back')}`);
98
+ lines.push(border);
99
+ return lines;
100
+ }
101
+ handleKey(data) {
102
+ if (isCtrlC(data)) {
103
+ return closeOverlay(undefined);
104
+ }
105
+ if (isEscape(data) || data.toString() === 'q') {
106
+ return popScreen();
107
+ }
108
+ return stay(false);
109
+ }
110
+ /**
111
+ * Minimum height for stable rendering.
112
+ * Covers: header(3) + name(2) + location(3) + file(3) + desc(5) + prompt(5) + footer(3) = 24
113
+ */
114
+ getMinHeight() {
115
+ return 24;
116
+ }
117
+ }
118
+ // =============================================================================
119
+ // Wizard Screen
120
+ // =============================================================================
121
+ class WizardScreen extends BaseScreen {
122
+ registry;
123
+ styles;
124
+ state;
125
+ input;
126
+ constructor(registry, styles) {
127
+ super();
128
+ this.registry = registry;
129
+ this.styles = styles;
130
+ this.state = defaultWizardState();
131
+ this.input = new InputFeature({ placeholder: '' });
132
+ }
133
+ render() {
134
+ const s = this.styles;
135
+ const lines = [];
136
+ const cols = terminal.getTerminalWidth();
137
+ const border = renderBorder(cols, s);
138
+ lines.push(border);
139
+ lines.push(' ' + s.primaryBold('Create New Command'));
140
+ lines.push('');
141
+ switch (this.state.step) {
142
+ case 'location':
143
+ lines.push(chalk.bold(' Choose location'));
144
+ lines.push('');
145
+ lines.push(this.state.selectedOption === 0
146
+ ? s.primary(' ❯ 1. Project (.compilr-dev/commands/)')
147
+ : s.muted(' 1. Project (.compilr-dev/commands/)'));
148
+ lines.push(this.state.selectedOption === 1
149
+ ? s.primary(' ❯ 2. Personal (~/.compilr-dev/commands/)')
150
+ : s.muted(' 2. Personal (~/.compilr-dev/commands/)'));
151
+ lines.push('');
152
+ lines.push(s.muted(' Project commands are shared with your team.'));
153
+ lines.push(s.muted(' Personal commands apply to all your projects.'));
154
+ break;
155
+ case 'name':
156
+ lines.push(chalk.bold(' Command name'));
157
+ lines.push('');
158
+ lines.push(' Enter a unique name:');
159
+ lines.push(` > ${this.input.render(s)}`);
160
+ lines.push('');
161
+ if (this.state.error) {
162
+ lines.push(s.error(` ${this.state.error}`));
163
+ }
164
+ else {
165
+ lines.push(s.muted(' Use lowercase letters, numbers, hyphens (e.g., code-review)'));
166
+ lines.push(s.muted(' This becomes the command: /{name}'));
167
+ }
168
+ break;
169
+ case 'description':
170
+ lines.push(chalk.bold(' Description'));
171
+ lines.push('');
172
+ lines.push(' Enter a short description:');
173
+ lines.push(` > ${this.input.render(s)}`);
174
+ lines.push('');
175
+ lines.push(s.muted(' This is shown in the help menu.'));
176
+ break;
177
+ case 'prompt':
178
+ lines.push(chalk.bold(' Prompt template'));
179
+ lines.push('');
180
+ lines.push(' Enter the prompt to send:');
181
+ lines.push(` > ${this.input.render(s)}`);
182
+ lines.push('');
183
+ lines.push(s.muted(' Use $1, $2 for positional args, $ARGUMENTS for all args.'));
184
+ lines.push(s.muted(' Example: "Review $1 for bugs and security issues"'));
185
+ break;
186
+ case 'confirm': {
187
+ lines.push(chalk.bold(' Confirm'));
188
+ lines.push('');
189
+ lines.push(` Command: ${s.primary('/' + this.state.name)}`);
190
+ const locationPath = this.state.location === 'project'
191
+ ? '.compilr-dev/commands/'
192
+ : '~/.compilr-dev/commands/';
193
+ lines.push(` Location: ${s.primary(locationPath)}${this.state.name}.md`);
194
+ lines.push('');
195
+ lines.push(chalk.bold(' Description:'));
196
+ const descPreview = this.state.description.slice(0, 60) +
197
+ (this.state.description.length > 60 ? '...' : '');
198
+ lines.push(s.muted(` ${descPreview}`));
199
+ lines.push('');
200
+ lines.push(chalk.bold(' Prompt template:'));
201
+ const promptPreview = this.state.prompt.slice(0, 60) +
202
+ (this.state.prompt.length > 60 ? '...' : '');
203
+ lines.push(s.muted(` ${promptPreview}`));
204
+ lines.push('');
205
+ lines.push(this.state.selectedOption === 0
206
+ ? s.primary(' ❯ Save')
207
+ : s.muted(' Save'));
208
+ lines.push(this.state.selectedOption === 1
209
+ ? s.primary(' ❯ Cancel')
210
+ : s.muted(' Cancel'));
211
+ if (this.state.error) {
212
+ lines.push('');
213
+ lines.push(s.error(` ${this.state.error}`));
214
+ }
215
+ break;
216
+ }
217
+ }
218
+ lines.push('');
219
+ lines.push(border);
220
+ lines.push(` ${s.muted('Esc to go back')}`);
221
+ lines.push(border);
222
+ return lines;
223
+ }
224
+ handleKey(data) {
225
+ // Ctrl+C always closes
226
+ if (isCtrlC(data)) {
227
+ return closeOverlay(undefined);
228
+ }
229
+ // Escape goes back one step (or exits wizard)
230
+ if (isEscape(data)) {
231
+ return this.handleBack();
232
+ }
233
+ // Input steps: name, description, prompt
234
+ if (['name', 'description', 'prompt'].includes(this.state.step)) {
235
+ return this.handleInputStep(data);
236
+ }
237
+ // Selection steps: location, confirm
238
+ if (['location', 'confirm'].includes(this.state.step)) {
239
+ return this.handleSelectionStep(data);
240
+ }
241
+ return stay();
242
+ }
243
+ handleBack() {
244
+ switch (this.state.step) {
245
+ case 'location':
246
+ return popScreen();
247
+ case 'name':
248
+ this.state.step = 'location';
249
+ this.state.selectedOption = this.state.location === 'project' ? 0 : 1;
250
+ break;
251
+ case 'description':
252
+ this.state.step = 'name';
253
+ this.input.value = this.state.name;
254
+ break;
255
+ case 'prompt':
256
+ this.state.step = 'description';
257
+ this.input.value = this.state.description;
258
+ break;
259
+ case 'confirm':
260
+ this.state.step = 'prompt';
261
+ this.input.value = this.state.prompt;
262
+ break;
263
+ }
264
+ this.state.error = null;
265
+ return stay();
266
+ }
267
+ handleInputStep(data) {
268
+ if (isEnter(data)) {
269
+ const value = this.input.trimmedValue;
270
+ if (value) {
271
+ // Validate name
272
+ if (this.state.step === 'name') {
273
+ if (!/^[a-z][a-z0-9-]{1,29}$/.test(value)) {
274
+ this.state.error = 'Invalid name. Use lowercase letters, numbers, hyphens (2-30 chars).';
275
+ return stay();
276
+ }
277
+ if (this.registry.has(value)) {
278
+ this.state.error = `Command "${value}" already exists.`;
279
+ return stay();
280
+ }
281
+ }
282
+ this.advanceStep();
283
+ }
284
+ return stay();
285
+ }
286
+ if (isBackspace(data)) {
287
+ const result = this.input.handleKey(data);
288
+ if (result.handled) {
289
+ this.state.error = null;
290
+ return stay(result.render);
291
+ }
292
+ return stay(false);
293
+ }
294
+ // Regular character input
295
+ const result = this.input.handleKey(data);
296
+ if (result.handled) {
297
+ this.state.error = null;
298
+ return stay(result.render);
299
+ }
300
+ return stay(false);
301
+ }
302
+ handleSelectionStep(data) {
303
+ const maxOptions = 2;
304
+ if (isNavigateUp(data) && this.state.selectedOption > 0) {
305
+ this.state.selectedOption--;
306
+ return stay();
307
+ }
308
+ if (isNavigateDown(data) && this.state.selectedOption < maxOptions - 1) {
309
+ this.state.selectedOption++;
310
+ return stay();
311
+ }
312
+ if (isEnter(data)) {
313
+ if (this.state.step === 'confirm') {
314
+ if (this.state.selectedOption === 0) {
315
+ // Save
316
+ try {
317
+ this.registry.save({
318
+ name: this.state.name,
319
+ description: this.state.description,
320
+ prompt: this.state.prompt,
321
+ }, this.state.location);
322
+ this.registry.load();
323
+ return closeOverlay({ created: this.state.name });
324
+ }
325
+ catch (error) {
326
+ this.state.error = error.message;
327
+ return stay();
328
+ }
329
+ }
330
+ else {
331
+ return popScreen();
332
+ }
333
+ }
334
+ else {
335
+ this.advanceStep();
336
+ }
337
+ }
338
+ return stay(false);
339
+ }
340
+ advanceStep() {
341
+ switch (this.state.step) {
342
+ case 'location':
343
+ this.state.location = this.state.selectedOption === 0 ? 'project' : 'personal';
344
+ this.state.step = 'name';
345
+ this.input.clear();
346
+ break;
347
+ case 'name':
348
+ this.state.name = this.input.trimmedValue;
349
+ this.state.step = 'description';
350
+ this.input.clear();
351
+ break;
352
+ case 'description':
353
+ this.state.description = this.input.trimmedValue;
354
+ this.state.step = 'prompt';
355
+ this.input.clear();
356
+ break;
357
+ case 'prompt':
358
+ this.state.prompt = this.input.trimmedValue;
359
+ this.state.step = 'confirm';
360
+ this.state.selectedOption = 0;
361
+ break;
362
+ }
363
+ this.state.error = null;
364
+ }
365
+ /**
366
+ * Minimum height for stable rendering.
367
+ * Covers: header(3) + form fields (up to 12) + options(4) + footer(3) = 22
368
+ */
369
+ getMinHeight() {
370
+ return 22;
371
+ }
372
+ }
373
+ // =============================================================================
374
+ // Commands Overlay V2
375
+ // =============================================================================
376
+ /**
377
+ * Commands overlay using TabbedListOverlayV2.
378
+ * Displays custom commands in a searchable, tabbed list.
379
+ */
380
+ export class CommandsOverlayV2 extends TabbedListOverlayV2 {
381
+ type = 'inline';
382
+ id = 'commands-overlay-v2';
383
+ registry;
384
+ constructor() {
385
+ const registry = getCustomCommandRegistry();
386
+ registry.load();
387
+ const items = buildItemsList(registry);
388
+ super({
389
+ title: 'Custom Commands',
390
+ tabs: TABS,
391
+ items,
392
+ pageSize: PAGE_SIZE,
393
+ filterByTab: (item, tabId) => {
394
+ // "Create new command" always shows
395
+ if (isCreateItem(item))
396
+ return true;
397
+ // Filter by location
398
+ if (tabId === 'all')
399
+ return true;
400
+ return item.location === tabId;
401
+ },
402
+ getSearchText: (item) => {
403
+ if (isCreateItem(item))
404
+ return 'create new';
405
+ return `${item.name} ${item.description}`;
406
+ },
407
+ renderItem: (item, isSelected, styles) => {
408
+ const cols = terminal.getTerminalWidth();
409
+ if (isCreateItem(item)) {
410
+ return isSelected
411
+ ? styles.primary(' ❯ Create new command')
412
+ : styles.muted(' Create new command');
413
+ }
414
+ const cmd = item;
415
+ const prefix = isSelected ? styles.primary(' ❯ ') : ' ';
416
+ const name = `/${cmd.name}`;
417
+ const nameStyled = isSelected ? styles.primary(name.padEnd(25)) : name.padEnd(25);
418
+ const maxDesc = Math.max(20, cols - 45);
419
+ const desc = cmd.description.slice(0, maxDesc) + (cmd.description.length > maxDesc ? '...' : '');
420
+ const descStyled = styles.muted(desc);
421
+ const location = styles.muted(` (${cmd.location})`);
422
+ return prefix + nameStyled + descStyled + location;
423
+ },
424
+ footerHints: (searchMode) => {
425
+ if (searchMode) {
426
+ return 'Type to filter · ↑↓/jk Navigate · Enter Select · Esc Exit search';
427
+ }
428
+ return 'Tab Filter · ↑↓/jk · / Search · Enter Select · q/Esc Close';
429
+ },
430
+ emptyMessage: 'No custom commands found.',
431
+ noResultsMessage: 'No commands match the search.',
432
+ });
433
+ this.registry = registry;
434
+ }
435
+ createDetailScreen(item) {
436
+ if (isCreateItem(item)) {
437
+ return new WizardScreen(this.registry, this.getStyles());
438
+ }
439
+ return new CommandDetailScreen(item, this.registry, this.getStyles());
440
+ }
441
+ }
@@ -2,8 +2,13 @@
2
2
  * Commands Overlay
3
3
  *
4
4
  * Modal overlay for viewing and managing custom command definitions.
5
- * - List tab: Shows existing custom commands
6
- * - Wizard mode: Step-by-step command creation
5
+ * Uses TabbedListOverlay for consistent navigation patterns.
6
+ *
7
+ * Features:
8
+ * - Tabs: All, Project, Personal
9
+ * - Search with / toggle
10
+ * - Detail view for command information
11
+ * - Wizard for creating new commands
7
12
  */
8
13
  /**
9
14
  * Show the commands overlay