@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,809 @@
1
+ /**
2
+ * Agents Overlay V2
3
+ *
4
+ * Modal overlay for viewing and managing agent configurations.
5
+ * Uses TabbedListOverlayV2 for consistent navigation patterns.
6
+ *
7
+ * Features:
8
+ * - Built-in tab: Lists predefined agent types with detail view
9
+ * - Custom tab: Lists user-defined agents with detail/edit + create new
10
+ * - Wizard mode: Step-by-step agent creation
11
+ */
12
+ import chalk from 'chalk';
13
+ import * as terminal from './terminal.js';
14
+ import { TabbedListOverlayV2, BaseScreen, stay, popScreen, closeOverlay, isEscape, isCtrlC, isEnter, isNavigateUp, isNavigateDown, isBackspace, isClose, extractPrintable, renderBorder, wrapText, } from './base/index.js';
15
+ import { InputFeature } from './features/index.js';
16
+ import { getAgentRegistry } from '../agents/registry.js';
17
+ // =============================================================================
18
+ // Constants
19
+ // =============================================================================
20
+ const TABS = [
21
+ { id: 'builtin', label: 'Built-in' },
22
+ { id: 'custom', label: 'Custom' },
23
+ ];
24
+ const PAGE_SIZE = 12;
25
+ // =============================================================================
26
+ // Helpers
27
+ // =============================================================================
28
+ function isCreateItem(item) {
29
+ return item.isCreateNew === true;
30
+ }
31
+ function buildItemsList(registry) {
32
+ const items = [];
33
+ // Add built-in agents
34
+ for (const agent of registry.getBuiltinAgents()) {
35
+ items.push(agentToItem(agent, true));
36
+ }
37
+ // Add custom agents
38
+ for (const agent of registry.getCustomAgents()) {
39
+ items.push(agentToItem(agent, false));
40
+ }
41
+ // Add "Create new agent" option for custom tab
42
+ items.push({
43
+ name: '',
44
+ model: '',
45
+ description: '',
46
+ isBuiltin: false,
47
+ isCreateNew: true,
48
+ });
49
+ return items;
50
+ }
51
+ function agentToItem(agent, isBuiltin) {
52
+ return {
53
+ name: agent.name,
54
+ model: agent.model,
55
+ description: agent.description,
56
+ location: agent.location,
57
+ systemPrompt: agent.systemPrompt,
58
+ filePath: agent.filePath,
59
+ isBuiltin,
60
+ };
61
+ }
62
+ // =============================================================================
63
+ // Detail Screen (View Agent Info)
64
+ // =============================================================================
65
+ class AgentDetailScreen extends BaseScreen {
66
+ item;
67
+ registry;
68
+ styles;
69
+ onEdit;
70
+ constructor(item, registry, styles, onEdit) {
71
+ super();
72
+ this.item = item;
73
+ this.registry = registry;
74
+ this.styles = styles;
75
+ this.onEdit = onEdit;
76
+ }
77
+ render() {
78
+ const s = this.styles;
79
+ const cols = terminal.getTerminalWidth();
80
+ const border = renderBorder(cols, s);
81
+ const lines = [];
82
+ // Header
83
+ lines.push(border);
84
+ lines.push(` ${s.primaryBold('Agent Details')}`);
85
+ lines.push('');
86
+ // Name and model
87
+ lines.push(` ${s.muted('Name:')} ${s.primary(this.item.name)}`);
88
+ lines.push(` ${s.muted('Model:')} ${s.secondary(this.item.model)}`);
89
+ lines.push(` ${s.muted('Type:')} ${this.item.isBuiltin ? s.muted('Built-in') : s.secondary('Custom')}`);
90
+ // Location for custom agents
91
+ if (!this.item.isBuiltin && this.item.location) {
92
+ const locationLabel = this.item.location === 'project' ? 'Project' : 'Personal';
93
+ lines.push(` ${s.muted('Location:')} ${s.secondary(locationLabel)}`);
94
+ }
95
+ lines.push('');
96
+ // Description
97
+ lines.push(` ${s.muted('Description:')}`);
98
+ const descLines = wrapText(this.item.description, cols - 6, ' ');
99
+ lines.push(...descLines);
100
+ // System prompt for custom agents
101
+ if (!this.item.isBuiltin && this.item.systemPrompt) {
102
+ lines.push('');
103
+ lines.push(` ${s.muted('System Prompt:')}`);
104
+ // Show first few lines of system prompt
105
+ const promptLines = this.item.systemPrompt.split('\n').slice(0, 5);
106
+ for (const line of promptLines) {
107
+ const truncated = line.length > cols - 6 ? line.slice(0, cols - 9) + '...' : line;
108
+ lines.push(` ${s.secondary(truncated)}`);
109
+ }
110
+ if (this.item.systemPrompt.split('\n').length > 5) {
111
+ lines.push(` ${s.muted('...')}`);
112
+ }
113
+ }
114
+ // File path for custom agents
115
+ if (!this.item.isBuiltin && this.item.filePath) {
116
+ lines.push('');
117
+ lines.push(` ${s.muted('File:')} ${s.secondary(this.item.filePath)}`);
118
+ }
119
+ // Usage hint for built-in agents
120
+ if (this.item.isBuiltin) {
121
+ lines.push('');
122
+ lines.push(` ${s.muted('Usage:')}`);
123
+ lines.push(` ${s.secondary('This agent is invoked via the Task tool.')}`);
124
+ lines.push(` ${s.secondary(`Example: Task(subagent_type="${this.item.name}", prompt="...")`)}`);
125
+ }
126
+ lines.push('');
127
+ lines.push(border);
128
+ // Show edit hint for custom agents
129
+ if (!this.item.isBuiltin) {
130
+ lines.push(` ${s.muted('e Edit · q/Esc Back')}`);
131
+ }
132
+ else {
133
+ lines.push(` ${s.muted('q/Esc Back')}`);
134
+ }
135
+ lines.push(border);
136
+ return lines;
137
+ }
138
+ handleKey(data) {
139
+ // Ctrl+C closes everything
140
+ if (isCtrlC(data)) {
141
+ return closeOverlay(undefined);
142
+ }
143
+ // Escape or q - back to list
144
+ if (isEscape(data) || isClose(data)) {
145
+ return popScreen();
146
+ }
147
+ // 'e' opens edit screen for custom agents
148
+ const char = extractPrintable(data);
149
+ if (char === 'e' && !this.item.isBuiltin) {
150
+ const editScreen = new AgentEditScreen(this.item, this.registry, this.styles);
151
+ return this.onEdit(editScreen);
152
+ }
153
+ return stay(false);
154
+ }
155
+ getMinHeight() {
156
+ return 24;
157
+ }
158
+ }
159
+ // =============================================================================
160
+ // Edit Screen (Edit Custom Agent)
161
+ // =============================================================================
162
+ class AgentEditScreen extends BaseScreen {
163
+ originalItem;
164
+ registry;
165
+ styles;
166
+ step = 'field-select';
167
+ selectedOption = 0;
168
+ input;
169
+ error = null;
170
+ editedAgent;
171
+ constructor(originalItem, registry, styles) {
172
+ super();
173
+ this.originalItem = originalItem;
174
+ this.registry = registry;
175
+ this.styles = styles;
176
+ this.input = new InputFeature({ placeholder: '' });
177
+ // Initialize with current values
178
+ const loc = originalItem.location;
179
+ this.editedAgent = {
180
+ name: originalItem.name,
181
+ prompt: originalItem.systemPrompt ?? '',
182
+ description: originalItem.description,
183
+ model: originalItem.model,
184
+ location: (loc === 'project' || loc === 'personal') ? loc : 'project',
185
+ };
186
+ }
187
+ render() {
188
+ const s = this.styles;
189
+ const cols = terminal.getTerminalWidth();
190
+ const border = renderBorder(cols, s);
191
+ const lines = [];
192
+ lines.push(border);
193
+ lines.push(` ${s.primaryBold('Edit Agent:')} ${s.primary(this.originalItem.name)}`);
194
+ lines.push('');
195
+ switch (this.step) {
196
+ case 'field-select': {
197
+ lines.push(` ${s.secondary('Select field to edit:')}`);
198
+ lines.push('');
199
+ const fields = [
200
+ { id: 'model', label: 'Model', value: this.editedAgent.model },
201
+ { id: 'description', label: 'Description', value: this.truncate(this.editedAgent.description, 40) },
202
+ { id: 'prompt', label: 'System Prompt', value: this.truncate(this.editedAgent.prompt, 40) },
203
+ { id: 'save', label: 'Save Changes', value: '' },
204
+ { id: 'delete', label: 'Delete Agent', value: '' },
205
+ { id: 'cancel', label: 'Cancel', value: '' },
206
+ ];
207
+ for (let i = 0; i < fields.length; i++) {
208
+ const f = fields[i];
209
+ const isSelected = this.selectedOption === i;
210
+ const prefix = isSelected ? s.primary(' ❯ ') : ' ';
211
+ if (f.id === 'save') {
212
+ lines.push(`${prefix}${isSelected ? s.primary(f.label) : s.muted(f.label)}`);
213
+ }
214
+ else if (f.id === 'delete') {
215
+ lines.push(`${prefix}${isSelected ? s.error(f.label) : s.muted(f.label)}`);
216
+ }
217
+ else if (f.id === 'cancel') {
218
+ lines.push(`${prefix}${isSelected ? s.secondary(f.label) : s.muted(f.label)}`);
219
+ }
220
+ else {
221
+ const label = `${f.label.padEnd(16)}${f.value}`;
222
+ lines.push(`${prefix}${isSelected ? s.primary(label) : s.muted(label)}`);
223
+ }
224
+ }
225
+ break;
226
+ }
227
+ case 'edit-model': {
228
+ lines.push(` ${s.secondary('Select model')}`);
229
+ lines.push('');
230
+ const models = [
231
+ { id: 'sonnet', label: 'Sonnet', desc: 'Balanced (recommended)' },
232
+ { id: 'opus', label: 'Opus', desc: 'Most capable' },
233
+ { id: 'haiku', label: 'Haiku', desc: 'Fast and efficient' },
234
+ { id: 'inherit', label: 'Inherit', desc: "Use parent's model" },
235
+ ];
236
+ for (let i = 0; i < models.length; i++) {
237
+ const m = models[i];
238
+ const isSelected = this.selectedOption === i;
239
+ const prefix = isSelected ? s.primary(' ❯ ') : ' ';
240
+ const current = this.editedAgent.model === m.id ? s.muted(' (current)') : '';
241
+ const label = `${String(i + 1)}. ${m.label.padEnd(10)} - ${m.desc}${current}`;
242
+ lines.push(`${prefix}${isSelected ? s.primary(label) : s.muted(label)}`);
243
+ }
244
+ break;
245
+ }
246
+ case 'edit-description':
247
+ lines.push(` ${s.secondary('Edit description')}`);
248
+ lines.push('');
249
+ lines.push(` When should the LLM use this agent?`);
250
+ lines.push(` > ${this.input.render(s)}`);
251
+ lines.push('');
252
+ if (this.error) {
253
+ lines.push(` ${s.error(this.error)}`);
254
+ }
255
+ else {
256
+ lines.push(` ${s.muted('Press Enter to save, Esc to cancel')}`);
257
+ }
258
+ break;
259
+ case 'edit-prompt':
260
+ lines.push(` ${s.secondary('Edit system prompt')}`);
261
+ lines.push('');
262
+ lines.push(` Enter the agent's instructions:`);
263
+ lines.push(` > ${this.input.render(s)}`);
264
+ lines.push('');
265
+ if (this.error) {
266
+ lines.push(` ${s.error(this.error)}`);
267
+ }
268
+ else {
269
+ lines.push(` ${s.muted('Press Enter to save, Esc to cancel')}`);
270
+ lines.push(` ${s.muted('(For multiline prompts, edit the .md file directly)')}`);
271
+ }
272
+ break;
273
+ case 'confirm-delete':
274
+ lines.push(` ${s.error('Delete this agent?')}`);
275
+ lines.push('');
276
+ lines.push(` ${s.muted('Name:')} ${s.primary(this.originalItem.name)}`);
277
+ lines.push(` ${s.muted('File:')} ${s.secondary(this.originalItem.filePath ?? 'unknown')}`);
278
+ lines.push('');
279
+ lines.push(this.selectedOption === 0
280
+ ? ` ${s.error(' ❯ Yes, delete')}`
281
+ : ` ${s.muted(' Yes, delete')}`);
282
+ lines.push(this.selectedOption === 1
283
+ ? ` ${s.primary(' ❯ No, cancel')}`
284
+ : ` ${s.muted(' No, cancel')}`);
285
+ break;
286
+ }
287
+ lines.push('');
288
+ lines.push(border);
289
+ lines.push(` ${s.muted('Esc Back')}`);
290
+ lines.push(border);
291
+ return lines;
292
+ }
293
+ handleKey(data) {
294
+ // Ctrl+C closes everything
295
+ if (isCtrlC(data)) {
296
+ return closeOverlay(undefined);
297
+ }
298
+ // Escape goes back
299
+ if (isEscape(data)) {
300
+ return this.handleBack();
301
+ }
302
+ // Text input steps
303
+ if (this.step === 'edit-description' || this.step === 'edit-prompt') {
304
+ if (isEnter(data)) {
305
+ const text = this.input.trimmedValue;
306
+ if (!text) {
307
+ this.error = 'Cannot be empty';
308
+ return stay();
309
+ }
310
+ if (this.step === 'edit-description') {
311
+ this.editedAgent.description = text;
312
+ }
313
+ else {
314
+ this.editedAgent.prompt = text;
315
+ }
316
+ this.step = 'field-select';
317
+ this.input.clear();
318
+ this.error = null;
319
+ return stay();
320
+ }
321
+ if (isBackspace(data)) {
322
+ const result = this.input.handleKey(data);
323
+ if (result.handled) {
324
+ this.error = null;
325
+ return stay(result.render);
326
+ }
327
+ return stay(false);
328
+ }
329
+ // Regular character input
330
+ const result = this.input.handleKey(data);
331
+ if (result.handled) {
332
+ this.error = null;
333
+ return stay(result.render);
334
+ }
335
+ return stay(false);
336
+ }
337
+ // Selection steps
338
+ const maxOptions = this.step === 'field-select' ? 6 : this.step === 'edit-model' ? 4 : 2;
339
+ if (isNavigateUp(data) && this.selectedOption > 0) {
340
+ this.selectedOption--;
341
+ return stay();
342
+ }
343
+ if (isNavigateDown(data) && this.selectedOption < maxOptions - 1) {
344
+ this.selectedOption++;
345
+ return stay();
346
+ }
347
+ if (isEnter(data)) {
348
+ return this.handleSelect();
349
+ }
350
+ return stay(false);
351
+ }
352
+ handleBack() {
353
+ switch (this.step) {
354
+ case 'field-select':
355
+ return popScreen();
356
+ case 'edit-model':
357
+ case 'edit-description':
358
+ case 'edit-prompt':
359
+ case 'confirm-delete':
360
+ this.step = 'field-select';
361
+ this.selectedOption = 0;
362
+ this.input.clear();
363
+ this.error = null;
364
+ break;
365
+ }
366
+ return stay();
367
+ }
368
+ handleSelect() {
369
+ switch (this.step) {
370
+ case 'field-select':
371
+ switch (this.selectedOption) {
372
+ case 0: { // Model
373
+ this.step = 'edit-model';
374
+ const models = ['sonnet', 'opus', 'haiku', 'inherit'];
375
+ this.selectedOption = models.indexOf(this.editedAgent.model);
376
+ if (this.selectedOption < 0)
377
+ this.selectedOption = 0;
378
+ break;
379
+ }
380
+ case 1: // Description
381
+ this.step = 'edit-description';
382
+ this.input.value = this.editedAgent.description;
383
+ break;
384
+ case 2: // System Prompt
385
+ this.step = 'edit-prompt';
386
+ this.input.value = this.editedAgent.prompt;
387
+ break;
388
+ case 3: // Save
389
+ return this.saveAgent();
390
+ case 4: // Delete
391
+ this.step = 'confirm-delete';
392
+ this.selectedOption = 1; // Default to "No"
393
+ break;
394
+ case 5: // Cancel
395
+ return popScreen();
396
+ }
397
+ break;
398
+ case 'edit-model': {
399
+ const models = ['sonnet', 'opus', 'haiku', 'inherit'];
400
+ this.editedAgent.model = models[this.selectedOption];
401
+ this.step = 'field-select';
402
+ this.selectedOption = 0;
403
+ break;
404
+ }
405
+ case 'confirm-delete':
406
+ if (this.selectedOption === 0) {
407
+ // Delete
408
+ return this.deleteAgent();
409
+ }
410
+ else {
411
+ // Cancel
412
+ this.step = 'field-select';
413
+ this.selectedOption = 0;
414
+ }
415
+ break;
416
+ }
417
+ return stay();
418
+ }
419
+ saveAgent() {
420
+ try {
421
+ this.registry.saveAgent({
422
+ name: this.editedAgent.name,
423
+ description: this.editedAgent.description,
424
+ model: this.editedAgent.model,
425
+ systemPrompt: this.editedAgent.prompt,
426
+ }, this.editedAgent.location);
427
+ this.registry.load();
428
+ return closeOverlay({ edited: this.editedAgent.name });
429
+ }
430
+ catch (error) {
431
+ this.error = error.message;
432
+ return stay();
433
+ }
434
+ }
435
+ deleteAgent() {
436
+ try {
437
+ this.registry.deleteAgent(this.originalItem.name);
438
+ this.registry.load();
439
+ return closeOverlay({ deleted: this.originalItem.name });
440
+ }
441
+ catch (error) {
442
+ this.error = error.message;
443
+ return stay();
444
+ }
445
+ }
446
+ truncate(text, max) {
447
+ if (!text)
448
+ return '';
449
+ if (text.length <= max)
450
+ return text;
451
+ return text.slice(0, max - 3) + '...';
452
+ }
453
+ getMinHeight() {
454
+ return 22;
455
+ }
456
+ }
457
+ // =============================================================================
458
+ // Wizard Screen (Multi-Step Agent Creation)
459
+ // =============================================================================
460
+ class AgentWizardScreen extends BaseScreen {
461
+ registry;
462
+ styles;
463
+ step = 'location';
464
+ selectedOption = 0;
465
+ input;
466
+ error = null;
467
+ newAgent = {
468
+ location: 'project',
469
+ name: '',
470
+ prompt: '',
471
+ description: '',
472
+ model: 'sonnet',
473
+ };
474
+ constructor(registry, styles) {
475
+ super();
476
+ this.registry = registry;
477
+ this.styles = styles;
478
+ this.input = new InputFeature({ placeholder: '' });
479
+ }
480
+ render() {
481
+ const s = this.styles;
482
+ const cols = terminal.getTerminalWidth();
483
+ const border = renderBorder(cols, s);
484
+ const lines = [];
485
+ lines.push(border);
486
+ lines.push(` ${s.primaryBold('Create New Agent')}`);
487
+ lines.push('');
488
+ switch (this.step) {
489
+ case 'location':
490
+ lines.push(chalk.bold(' Choose location'));
491
+ lines.push('');
492
+ lines.push(this.selectedOption === 0
493
+ ? ` ${s.primary(' ❯ 1. Project (.compilr-dev/agents/)')}`
494
+ : ` ${s.muted(' 1. Project (.compilr-dev/agents/)')}`);
495
+ lines.push(this.selectedOption === 1
496
+ ? ` ${s.primary(' ❯ 2. Personal (~/.compilr-dev/agents/)')}`
497
+ : ` ${s.muted(' 2. Personal (~/.compilr-dev/agents/)')}`);
498
+ lines.push('');
499
+ lines.push(` ${s.muted('Project agents are shared with your team.')}`);
500
+ lines.push(` ${s.muted('Personal agents apply to all your projects.')}`);
501
+ break;
502
+ case 'name':
503
+ lines.push(chalk.bold(' Agent name (identifier)'));
504
+ lines.push('');
505
+ lines.push(' Enter a unique identifier:');
506
+ lines.push(` > ${this.input.render(s)}`);
507
+ lines.push('');
508
+ if (this.error) {
509
+ lines.push(` ${s.error(this.error)}`);
510
+ }
511
+ else {
512
+ lines.push(` ${s.muted('Use lowercase letters, numbers, hyphens (e.g., code-reviewer)')}`);
513
+ }
514
+ break;
515
+ case 'prompt':
516
+ lines.push(chalk.bold(' System prompt'));
517
+ lines.push('');
518
+ lines.push(' Enter the agent\'s instructions:');
519
+ lines.push(` > ${this.input.render(s)}`);
520
+ lines.push('');
521
+ lines.push(` ${s.muted('This defines how the agent behaves.')}`);
522
+ lines.push(` ${s.muted('Press Enter to continue.')}`);
523
+ break;
524
+ case 'description':
525
+ lines.push(chalk.bold(' Description'));
526
+ lines.push('');
527
+ lines.push(' When should the LLM use this agent?');
528
+ lines.push(` > ${this.input.render(s)}`);
529
+ lines.push('');
530
+ lines.push(` ${s.muted('This helps the LLM know when to invoke this agent.')}`);
531
+ break;
532
+ case 'model': {
533
+ lines.push(chalk.bold(' Select model'));
534
+ lines.push('');
535
+ const models = [
536
+ { id: 'sonnet', label: 'Sonnet', desc: 'Balanced (recommended)' },
537
+ { id: 'opus', label: 'Opus', desc: 'Most capable' },
538
+ { id: 'haiku', label: 'Haiku', desc: 'Fast and efficient' },
539
+ { id: 'inherit', label: 'Inherit', desc: "Use parent's model" },
540
+ ];
541
+ for (let i = 0; i < models.length; i++) {
542
+ const m = models[i];
543
+ const isSelected = this.selectedOption === i;
544
+ const prefix = isSelected ? s.primary(' ❯ ') : ' ';
545
+ const label = `${String(i + 1)}. ${m.label.padEnd(10)} - ${m.desc}`;
546
+ lines.push(` ${prefix}${isSelected ? s.primary(label) : s.muted(label)}`);
547
+ }
548
+ break;
549
+ }
550
+ case 'confirm': {
551
+ lines.push(chalk.bold(' Confirm'));
552
+ lines.push('');
553
+ lines.push(` Name: ${s.primary(this.newAgent.name)}`);
554
+ const locationPath = this.newAgent.location === 'project'
555
+ ? '.compilr-dev/agents/'
556
+ : '~/.compilr-dev/agents/';
557
+ lines.push(` Location: ${s.primary(locationPath)}${this.newAgent.name}.md`);
558
+ lines.push(` Model: ${s.primary(this.newAgent.model)}`);
559
+ lines.push('');
560
+ lines.push(chalk.bold(' Description:'));
561
+ const descPreview = this.newAgent.description.length > 60
562
+ ? this.newAgent.description.slice(0, 57) + '...'
563
+ : this.newAgent.description;
564
+ lines.push(` ${s.muted(descPreview)}`);
565
+ lines.push('');
566
+ lines.push(chalk.bold(' System prompt:'));
567
+ const promptPreview = this.newAgent.prompt.length > 60
568
+ ? this.newAgent.prompt.slice(0, 57) + '...'
569
+ : this.newAgent.prompt;
570
+ lines.push(` ${s.muted(promptPreview)}`);
571
+ lines.push('');
572
+ lines.push(this.selectedOption === 0
573
+ ? ` ${s.primary(' ❯ Save')}`
574
+ : ` ${s.muted(' Save')}`);
575
+ lines.push(this.selectedOption === 1
576
+ ? ` ${s.primary(' ❯ Cancel')}`
577
+ : ` ${s.muted(' Cancel')}`);
578
+ if (this.error) {
579
+ lines.push('');
580
+ lines.push(` ${s.error(this.error)}`);
581
+ }
582
+ break;
583
+ }
584
+ }
585
+ lines.push('');
586
+ lines.push(border);
587
+ lines.push(` ${s.muted('Esc to go back')}`);
588
+ lines.push(border);
589
+ return lines;
590
+ }
591
+ handleKey(data) {
592
+ // Ctrl+C closes everything
593
+ if (isCtrlC(data)) {
594
+ return closeOverlay(undefined);
595
+ }
596
+ // Escape goes back
597
+ if (isEscape(data)) {
598
+ return this.handleBack();
599
+ }
600
+ // Input steps: name, prompt, description
601
+ if (this.step === 'name' || this.step === 'prompt' || this.step === 'description') {
602
+ if (isEnter(data)) {
603
+ const text = this.input.trimmedValue;
604
+ if (!text) {
605
+ return stay(false);
606
+ }
607
+ // Validate name
608
+ if (this.step === 'name') {
609
+ if (!/^[a-z][a-z0-9-]{1,49}$/.test(text)) {
610
+ this.error = 'Invalid name. Use lowercase letters, numbers, hyphens.';
611
+ return stay();
612
+ }
613
+ if (this.registry.hasAgent(text)) {
614
+ this.error = `Agent "${text}" already exists.`;
615
+ return stay();
616
+ }
617
+ this.newAgent.name = text;
618
+ this.step = 'prompt';
619
+ this.input.clear();
620
+ this.error = null;
621
+ }
622
+ else if (this.step === 'prompt') {
623
+ this.newAgent.prompt = text;
624
+ this.step = 'description';
625
+ this.input.clear();
626
+ }
627
+ else {
628
+ this.newAgent.description = text;
629
+ this.step = 'model';
630
+ this.selectedOption = 0;
631
+ }
632
+ return stay();
633
+ }
634
+ if (isBackspace(data)) {
635
+ const result = this.input.handleKey(data);
636
+ if (result.handled) {
637
+ this.error = null;
638
+ return stay(result.render);
639
+ }
640
+ return stay(false);
641
+ }
642
+ // Regular character input
643
+ const result = this.input.handleKey(data);
644
+ if (result.handled) {
645
+ this.error = null;
646
+ return stay(result.render);
647
+ }
648
+ return stay(false);
649
+ }
650
+ // Selection steps: location, model, confirm
651
+ const maxOptions = this.step === 'model' ? 4 : 2;
652
+ if (isNavigateUp(data) && this.selectedOption > 0) {
653
+ this.selectedOption--;
654
+ return stay();
655
+ }
656
+ if (isNavigateDown(data) && this.selectedOption < maxOptions - 1) {
657
+ this.selectedOption++;
658
+ return stay();
659
+ }
660
+ if (isEnter(data)) {
661
+ return this.handleSelect();
662
+ }
663
+ return stay(false);
664
+ }
665
+ handleBack() {
666
+ switch (this.step) {
667
+ case 'location':
668
+ return popScreen();
669
+ case 'name':
670
+ this.step = 'location';
671
+ this.selectedOption = this.newAgent.location === 'project' ? 0 : 1;
672
+ break;
673
+ case 'prompt':
674
+ this.step = 'name';
675
+ this.input.value = this.newAgent.name;
676
+ break;
677
+ case 'description':
678
+ this.step = 'prompt';
679
+ this.input.value = this.newAgent.prompt;
680
+ break;
681
+ case 'model':
682
+ this.step = 'description';
683
+ this.input.value = this.newAgent.description;
684
+ break;
685
+ case 'confirm': {
686
+ this.step = 'model';
687
+ const models = ['sonnet', 'opus', 'haiku', 'inherit'];
688
+ this.selectedOption = models.indexOf(this.newAgent.model);
689
+ break;
690
+ }
691
+ }
692
+ this.error = null;
693
+ return stay();
694
+ }
695
+ handleSelect() {
696
+ switch (this.step) {
697
+ case 'location':
698
+ this.newAgent.location = this.selectedOption === 0 ? 'project' : 'personal';
699
+ this.step = 'name';
700
+ this.input.clear();
701
+ break;
702
+ case 'model': {
703
+ const models = ['sonnet', 'opus', 'haiku', 'inherit'];
704
+ this.newAgent.model = models[this.selectedOption];
705
+ this.step = 'confirm';
706
+ this.selectedOption = 0;
707
+ break;
708
+ }
709
+ case 'confirm':
710
+ if (this.selectedOption === 0) {
711
+ // Save
712
+ try {
713
+ this.registry.saveAgent({
714
+ name: this.newAgent.name,
715
+ description: this.newAgent.description,
716
+ model: this.newAgent.model,
717
+ systemPrompt: this.newAgent.prompt,
718
+ }, this.newAgent.location);
719
+ this.registry.load();
720
+ return closeOverlay({ created: this.newAgent.name });
721
+ }
722
+ catch (error) {
723
+ this.error = error.message;
724
+ return stay();
725
+ }
726
+ }
727
+ else {
728
+ // Cancel
729
+ return popScreen();
730
+ }
731
+ }
732
+ return stay();
733
+ }
734
+ getMinHeight() {
735
+ return 22;
736
+ }
737
+ }
738
+ // =============================================================================
739
+ // Agents Overlay V2
740
+ // =============================================================================
741
+ /**
742
+ * Agents overlay using TabbedListOverlayV2.
743
+ * Displays agents in a searchable, tabbed list.
744
+ */
745
+ export class AgentsOverlayV2 extends TabbedListOverlayV2 {
746
+ type = 'inline';
747
+ id = 'agents-overlay-v2';
748
+ registry;
749
+ constructor() {
750
+ const registry = getAgentRegistry();
751
+ registry.load();
752
+ const items = buildItemsList(registry);
753
+ super({
754
+ title: 'Agents',
755
+ tabs: TABS,
756
+ items,
757
+ pageSize: PAGE_SIZE,
758
+ filterByTab: (item, tabId) => {
759
+ if (tabId === 'builtin')
760
+ return item.isBuiltin;
761
+ return !item.isBuiltin;
762
+ },
763
+ getSearchText: (item) => {
764
+ if (isCreateItem(item))
765
+ return 'create new';
766
+ return `${item.name} ${item.description}`;
767
+ },
768
+ renderItem: (item, isSelected, styles) => {
769
+ const prefix = isSelected ? styles.primary(' ❯ ') : ' ';
770
+ // Special "Create new agent" option
771
+ if (isCreateItem(item)) {
772
+ return isSelected
773
+ ? `${prefix}${styles.primary('Create new agent')}`
774
+ : `${prefix}${styles.muted('Create new agent')}`;
775
+ }
776
+ const cols = terminal.getTerminalWidth();
777
+ const name = `${item.name} · ${item.model}`;
778
+ const nameStyled = isSelected
779
+ ? styles.primary(name.padEnd(30))
780
+ : styles.secondary(name.padEnd(30));
781
+ if (item.isBuiltin) {
782
+ const maxDesc = Math.max(20, cols - 45);
783
+ const desc = item.description.slice(0, maxDesc) + (item.description.length > maxDesc ? '...' : '');
784
+ return `${prefix}${nameStyled}${styles.muted(desc)}`;
785
+ }
786
+ else {
787
+ return `${prefix}${nameStyled}${styles.muted(`(${item.location ?? 'unknown'})`)}`;
788
+ }
789
+ },
790
+ footerHints: (searchMode) => {
791
+ if (searchMode) {
792
+ return 'Type to filter · ↑↓/jk Navigate · Enter Select · Esc Exit search';
793
+ }
794
+ return 'Tab Filter · ↑↓/jk · / Search · Enter Select · q/Esc Close';
795
+ },
796
+ emptyMessage: 'No agents found.',
797
+ noResultsMessage: 'No agents match the search.',
798
+ });
799
+ this.registry = registry;
800
+ }
801
+ createDetailScreen(item) {
802
+ // "Create new agent" opens the wizard
803
+ if (isCreateItem(item)) {
804
+ return new AgentWizardScreen(this.registry, this.getStyles());
805
+ }
806
+ // All other agents open the detail view
807
+ return new AgentDetailScreen(item, this.registry, this.getStyles(), (editScreen) => ({ action: 'push', screen: editScreen }));
808
+ }
809
+ }