@compilr-dev/cli 0.4.0 → 0.5.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 (634) hide show
  1. package/README.md +254 -68
  2. package/dist/.tsbuildinfo.app +1 -0
  3. package/dist/.tsbuildinfo.data +1 -0
  4. package/dist/.tsbuildinfo.domain +1 -0
  5. package/dist/.tsbuildinfo.foundation +1 -0
  6. package/dist/agent.d.ts +134 -4
  7. package/dist/agent.js +345 -166
  8. package/dist/anchors/index.d.ts +9 -0
  9. package/dist/anchors/index.js +9 -0
  10. package/dist/anchors/project-anchors.d.ts +79 -0
  11. package/dist/anchors/project-anchors.js +202 -0
  12. package/dist/auth/api-client.d.ts +124 -0
  13. package/dist/auth/api-client.js +261 -0
  14. package/dist/auth/index.d.ts +172 -0
  15. package/dist/auth/index.js +545 -0
  16. package/dist/auth/storage.d.ts +52 -0
  17. package/dist/auth/storage.js +118 -0
  18. package/dist/changelog/index.d.ts +16 -0
  19. package/dist/changelog/index.js +24 -0
  20. package/dist/changelog/releases.d.ts +17 -0
  21. package/dist/changelog/releases.js +63 -0
  22. package/dist/commands/index.d.ts +2 -1
  23. package/dist/commands-v2/handlers/auth.d.ts +10 -0
  24. package/dist/commands-v2/handlers/auth.js +118 -0
  25. package/dist/commands-v2/handlers/background.d.ts +14 -0
  26. package/dist/commands-v2/handlers/background.js +276 -0
  27. package/dist/commands-v2/handlers/context.d.ts +13 -0
  28. package/dist/commands-v2/handlers/context.js +533 -0
  29. package/dist/commands-v2/handlers/core.d.ts +14 -0
  30. package/dist/commands-v2/handlers/core.js +290 -0
  31. package/dist/commands-v2/handlers/debug.d.ts +11 -0
  32. package/dist/commands-v2/handlers/debug.js +177 -0
  33. package/dist/commands-v2/handlers/delegations.d.ts +8 -0
  34. package/dist/commands-v2/handlers/delegations.js +29 -0
  35. package/dist/commands-v2/handlers/files.d.ts +8 -0
  36. package/dist/commands-v2/handlers/files.js +162 -0
  37. package/dist/commands-v2/handlers/filter.d.ts +9 -0
  38. package/dist/commands-v2/handlers/filter.js +130 -0
  39. package/dist/commands-v2/handlers/games.d.ts +7 -0
  40. package/dist/commands-v2/handlers/games.js +57 -0
  41. package/dist/commands-v2/handlers/index.d.ts +25 -0
  42. package/dist/commands-v2/handlers/index.js +63 -0
  43. package/dist/commands-v2/handlers/mcp.d.ts +8 -0
  44. package/dist/commands-v2/handlers/mcp.js +39 -0
  45. package/dist/commands-v2/handlers/notifications.d.ts +9 -0
  46. package/dist/commands-v2/handlers/notifications.js +34 -0
  47. package/dist/commands-v2/handlers/project.d.ts +22 -0
  48. package/dist/commands-v2/handlers/project.js +1035 -0
  49. package/dist/commands-v2/handlers/reset.d.ts +11 -0
  50. package/dist/commands-v2/handlers/reset.js +118 -0
  51. package/dist/commands-v2/handlers/session.d.ts +161 -0
  52. package/dist/commands-v2/handlers/session.js +805 -0
  53. package/dist/commands-v2/handlers/settings.d.ts +17 -0
  54. package/dist/commands-v2/handlers/settings.js +417 -0
  55. package/dist/commands-v2/handlers/tasks.d.ts +5 -0
  56. package/dist/commands-v2/handlers/tasks.js +36 -0
  57. package/dist/commands-v2/handlers/team.d.ts +9 -0
  58. package/dist/commands-v2/handlers/team.js +549 -0
  59. package/dist/commands-v2/handlers/terminals.d.ts +9 -0
  60. package/dist/commands-v2/handlers/terminals.js +34 -0
  61. package/dist/commands-v2/index.d.ts +14 -0
  62. package/dist/commands-v2/index.js +18 -0
  63. package/dist/commands-v2/registry.d.ts +52 -0
  64. package/dist/commands-v2/registry.js +114 -0
  65. package/dist/commands-v2/types.d.ts +153 -0
  66. package/dist/commands-v2/types.js +7 -0
  67. package/dist/commands.js +123 -7
  68. package/dist/compilr-diff-companion.vsix +0 -0
  69. package/dist/db/index.js +98 -4
  70. package/dist/db/repositories/document-repository.d.ts +2 -0
  71. package/dist/db/repositories/document-repository.js +5 -1
  72. package/dist/db/repositories/index.d.ts +2 -0
  73. package/dist/db/repositories/index.js +1 -0
  74. package/dist/db/repositories/plan-repository.d.ts +101 -0
  75. package/dist/db/repositories/plan-repository.js +275 -0
  76. package/dist/db/repositories/project-repository.d.ts +6 -0
  77. package/dist/db/repositories/project-repository.js +41 -0
  78. package/dist/db/repositories/work-item-repository.d.ts +15 -0
  79. package/dist/db/repositories/work-item-repository.js +69 -4
  80. package/dist/db/schema.d.ts +40 -3
  81. package/dist/db/schema.js +66 -3
  82. package/dist/episodes/index.d.ts +20 -0
  83. package/dist/episodes/index.js +27 -0
  84. package/dist/episodes/recorder.d.ts +51 -0
  85. package/dist/episodes/recorder.js +195 -0
  86. package/dist/episodes/significant-work.d.ts +21 -0
  87. package/dist/episodes/significant-work.js +56 -0
  88. package/dist/episodes/store.d.ts +38 -0
  89. package/dist/episodes/store.js +199 -0
  90. package/dist/episodes/types.d.ts +35 -0
  91. package/dist/episodes/types.js +6 -0
  92. package/dist/episodes/work-at-risk.d.ts +12 -0
  93. package/dist/episodes/work-at-risk.js +38 -0
  94. package/dist/episodes/work-summary-anchor.d.ts +23 -0
  95. package/dist/episodes/work-summary-anchor.js +73 -0
  96. package/dist/games/coins.d.ts +66 -0
  97. package/dist/games/coins.js +165 -0
  98. package/dist/games/game-base.d.ts +84 -0
  99. package/dist/games/game-base.js +204 -0
  100. package/dist/games/index.d.ts +16 -0
  101. package/dist/games/index.js +49 -0
  102. package/dist/games/scores.d.ts +69 -0
  103. package/dist/games/scores.js +191 -0
  104. package/dist/games/tetris/board.d.ts +59 -0
  105. package/dist/games/tetris/board.js +170 -0
  106. package/dist/games/tetris/index.d.ts +109 -0
  107. package/dist/games/tetris/index.js +610 -0
  108. package/dist/games/tetris/pieces.d.ts +44 -0
  109. package/dist/games/tetris/pieces.js +271 -0
  110. package/dist/games/tetris/renderer.d.ts +26 -0
  111. package/dist/games/tetris/renderer.js +77 -0
  112. package/dist/guide/guide-content.d.ts +23 -0
  113. package/dist/guide/guide-content.js +196 -0
  114. package/dist/guide/index.d.ts +8 -0
  115. package/dist/guide/index.js +7 -0
  116. package/dist/guide/shared-content.d.ts +37 -0
  117. package/dist/guide/shared-content.js +1272 -0
  118. package/dist/guide/tutorial-helpers.d.ts +57 -0
  119. package/dist/guide/tutorial-helpers.js +147 -0
  120. package/dist/handlers/ask-user-handlers.d.ts +32 -0
  121. package/dist/handlers/ask-user-handlers.js +104 -0
  122. package/dist/handlers/delegation-handlers.d.ts +34 -0
  123. package/dist/handlers/delegation-handlers.js +291 -0
  124. package/dist/handlers/permission-handler.d.ts +30 -0
  125. package/dist/handlers/permission-handler.js +205 -0
  126. package/dist/index.d.ts +11 -1
  127. package/dist/index.js +615 -179
  128. package/dist/input-handlers/index.d.ts +7 -0
  129. package/dist/input-handlers/index.js +7 -0
  130. package/dist/input-handlers/memory-handler.d.ts +26 -0
  131. package/dist/input-handlers/memory-handler.js +69 -0
  132. package/dist/models/index.d.ts +10 -0
  133. package/dist/models/index.js +12 -0
  134. package/dist/models/model-registry.d.ts +38 -0
  135. package/dist/models/model-registry.js +69 -0
  136. package/dist/models/model-tiers.d.ts +28 -0
  137. package/dist/models/model-tiers.js +71 -0
  138. package/dist/models/model-validation.d.ts +25 -0
  139. package/dist/models/model-validation.js +291 -0
  140. package/dist/models/ollama-models.d.ts +73 -0
  141. package/dist/models/ollama-models.js +178 -0
  142. package/dist/models/provider-types.d.ts +6 -0
  143. package/dist/models/provider-types.js +1 -0
  144. package/dist/models/providers.d.ts +35 -0
  145. package/dist/models/providers.js +58 -0
  146. package/dist/models/types.d.ts +4 -0
  147. package/dist/models/types.js +4 -0
  148. package/dist/multi-agent/activity.d.ts +21 -0
  149. package/dist/multi-agent/activity.js +34 -0
  150. package/dist/multi-agent/agent-selection.d.ts +55 -0
  151. package/dist/multi-agent/agent-selection.js +90 -0
  152. package/dist/multi-agent/artifacts.d.ts +197 -0
  153. package/dist/multi-agent/artifacts.js +379 -0
  154. package/dist/multi-agent/checkpointer.d.ts +138 -0
  155. package/dist/multi-agent/checkpointer.js +471 -0
  156. package/dist/multi-agent/collision-utils.d.ts +16 -0
  157. package/dist/multi-agent/collision-utils.js +28 -0
  158. package/dist/multi-agent/context-resolver.d.ts +97 -0
  159. package/dist/multi-agent/context-resolver.js +316 -0
  160. package/dist/multi-agent/custom-agents.d.ts +83 -0
  161. package/dist/multi-agent/custom-agents.js +227 -0
  162. package/dist/multi-agent/delegation-tracker.d.ts +157 -0
  163. package/dist/multi-agent/delegation-tracker.js +243 -0
  164. package/dist/multi-agent/file-lock-hook.d.ts +29 -0
  165. package/dist/multi-agent/file-lock-hook.js +97 -0
  166. package/dist/multi-agent/file-locks.d.ts +58 -0
  167. package/dist/multi-agent/file-locks.js +194 -0
  168. package/dist/multi-agent/index.d.ts +24 -0
  169. package/dist/multi-agent/index.js +30 -0
  170. package/dist/multi-agent/mention-parser.d.ts +64 -0
  171. package/dist/multi-agent/mention-parser.js +146 -0
  172. package/dist/multi-agent/notification-manager.d.ts +84 -0
  173. package/dist/multi-agent/notification-manager.js +224 -0
  174. package/dist/multi-agent/pending-requests.d.ts +122 -0
  175. package/dist/multi-agent/pending-requests.js +155 -0
  176. package/dist/multi-agent/session-registry.d.ts +139 -0
  177. package/dist/multi-agent/session-registry.js +514 -0
  178. package/dist/multi-agent/shared-context.d.ts +293 -0
  179. package/dist/multi-agent/shared-context.js +671 -0
  180. package/dist/multi-agent/skill-requirements.d.ts +66 -0
  181. package/dist/multi-agent/skill-requirements.js +178 -0
  182. package/dist/multi-agent/task-assignment.d.ts +69 -0
  183. package/dist/multi-agent/task-assignment.js +123 -0
  184. package/dist/multi-agent/task-suggestion.d.ts +31 -0
  185. package/dist/multi-agent/task-suggestion.js +72 -0
  186. package/dist/multi-agent/team-agent.d.ts +201 -0
  187. package/dist/multi-agent/team-agent.js +488 -0
  188. package/dist/multi-agent/team.d.ts +286 -0
  189. package/dist/multi-agent/team.js +610 -0
  190. package/dist/multi-agent/tool-config.d.ts +110 -0
  191. package/dist/multi-agent/tool-config.js +661 -0
  192. package/dist/multi-agent/types.d.ts +211 -0
  193. package/dist/multi-agent/types.js +617 -0
  194. package/dist/prompts/plan-mode-prompt.d.ts +11 -0
  195. package/dist/prompts/plan-mode-prompt.js +95 -0
  196. package/dist/repl-helpers.d.ts +63 -0
  197. package/dist/repl-helpers.js +319 -0
  198. package/dist/repl-v2.d.ts +554 -0
  199. package/dist/repl-v2.js +3286 -0
  200. package/dist/session/index.d.ts +6 -0
  201. package/dist/session/index.js +6 -0
  202. package/dist/session/project-session-manager.d.ts +158 -0
  203. package/dist/session/project-session-manager.js +650 -0
  204. package/dist/settings/index.d.ts +156 -13
  205. package/dist/settings/index.js +377 -24
  206. package/dist/settings/mcp-config.d.ts +76 -0
  207. package/dist/settings/mcp-config.js +143 -0
  208. package/dist/settings/paths.d.ts +114 -0
  209. package/dist/settings/paths.js +270 -0
  210. package/dist/shared-handlers.d.ts +62 -0
  211. package/dist/shared-handlers.js +48 -0
  212. package/dist/system-prompt/builder.d.ts +5 -0
  213. package/dist/system-prompt/builder.js +4 -0
  214. package/dist/system-prompt/index.d.ts +18 -0
  215. package/dist/system-prompt/index.js +18 -0
  216. package/dist/system-prompt/modules.d.ts +5 -0
  217. package/dist/system-prompt/modules.js +4 -0
  218. package/dist/tabbed-menu.js +2 -1
  219. package/dist/templates/compilr-md-import.d.ts +16 -0
  220. package/dist/templates/compilr-md-import.js +241 -0
  221. package/dist/templates/compilr-md.js +10 -58
  222. package/dist/templates/config-json.d.ts +1 -25
  223. package/dist/templates/index.d.ts +2 -0
  224. package/dist/templates/index.js +35 -75
  225. package/dist/themes/colors.js +3 -1
  226. package/dist/themes/registry.d.ts +5 -36
  227. package/dist/themes/registry.js +11 -95
  228. package/dist/themes/types.d.ts +3 -38
  229. package/dist/themes/types.js +2 -2
  230. package/dist/tool-names.d.ts +108 -0
  231. package/dist/tool-names.js +227 -0
  232. package/dist/tools/anchor-tools.d.ts +31 -0
  233. package/dist/tools/anchor-tools.js +255 -0
  234. package/dist/tools/artifact-tools.d.ts +42 -0
  235. package/dist/tools/artifact-tools.js +328 -0
  236. package/dist/tools/ask-user-simple.d.ts +1 -1
  237. package/dist/tools/ask-user-simple.js +2 -1
  238. package/dist/tools/ask-user.d.ts +1 -1
  239. package/dist/tools/ask-user.js +2 -1
  240. package/dist/tools/backlog-wrappers.d.ts +56 -0
  241. package/dist/tools/backlog-wrappers.js +353 -0
  242. package/dist/tools/backlog.d.ts +2 -2
  243. package/dist/tools/backlog.js +2 -2
  244. package/dist/tools/db-tools.d.ts +12 -0
  245. package/dist/tools/db-tools.js +14 -0
  246. package/dist/tools/delegate-background.d.ts +27 -0
  247. package/dist/tools/delegate-background.js +115 -0
  248. package/dist/tools/delegate.d.ts +22 -0
  249. package/dist/tools/delegate.js +97 -0
  250. package/dist/tools/delegation-status.d.ts +16 -0
  251. package/dist/tools/delegation-status.js +128 -0
  252. package/dist/tools/document-db.d.ts +43 -0
  253. package/dist/tools/document-db.js +220 -0
  254. package/dist/tools/guide-tool.d.ts +12 -0
  255. package/dist/tools/guide-tool.js +59 -0
  256. package/dist/tools/handoff.d.ts +25 -0
  257. package/dist/tools/handoff.js +99 -0
  258. package/dist/tools/meta-tools.d.ts +26 -0
  259. package/dist/tools/meta-tools.js +47 -0
  260. package/dist/tools/plan-tools.d.ts +54 -0
  261. package/dist/tools/plan-tools.js +338 -0
  262. package/dist/tools/platform-adapter.d.ts +29 -0
  263. package/dist/tools/platform-adapter.js +394 -0
  264. package/dist/tools/project-db.d.ts +34 -0
  265. package/dist/tools/project-db.js +39 -0
  266. package/dist/tools/recall-work-tool.d.ts +18 -0
  267. package/dist/tools/recall-work-tool.js +82 -0
  268. package/dist/tools/workitem-db.d.ts +135 -0
  269. package/dist/tools/workitem-db.js +730 -0
  270. package/dist/tools.d.ts +67 -2
  271. package/dist/tools.js +238 -38
  272. package/dist/ui/ask-user-overlay.d.ts +2 -2
  273. package/dist/ui/ask-user-overlay.js +443 -535
  274. package/dist/ui/ask-user-simple-overlay.d.ts +2 -2
  275. package/dist/ui/ask-user-simple-overlay.js +182 -209
  276. package/dist/ui/autocomplete-controller.d.ts +42 -0
  277. package/dist/ui/autocomplete-controller.js +384 -0
  278. package/dist/ui/base/index.d.ts +26 -0
  279. package/dist/ui/base/index.js +33 -0
  280. package/dist/ui/base/inline-overlay-utils.d.ts +217 -0
  281. package/dist/ui/base/inline-overlay-utils.js +320 -0
  282. package/dist/ui/base/inline-overlay.d.ts +159 -0
  283. package/dist/ui/base/inline-overlay.js +257 -0
  284. package/dist/ui/base/key-utils.d.ts +15 -0
  285. package/dist/ui/base/key-utils.js +30 -0
  286. package/dist/ui/base/overlay-base-v2.d.ts +203 -0
  287. package/dist/ui/base/overlay-base-v2.js +260 -0
  288. package/dist/ui/base/overlay-base.d.ts +156 -0
  289. package/dist/ui/base/overlay-base.js +238 -0
  290. package/dist/ui/base/overlay-lifecycle.d.ts +65 -0
  291. package/dist/ui/base/overlay-lifecycle.js +159 -0
  292. package/dist/ui/base/overlay-types.d.ts +185 -0
  293. package/dist/ui/base/overlay-types.js +7 -0
  294. package/dist/ui/base/render-utils.d.ts +27 -0
  295. package/dist/ui/base/render-utils.js +36 -0
  296. package/dist/ui/base/screen-stack.d.ts +148 -0
  297. package/dist/ui/base/screen-stack.js +184 -0
  298. package/dist/ui/base/tabbed-list-overlay-v2.d.ts +118 -0
  299. package/dist/ui/base/tabbed-list-overlay-v2.js +335 -0
  300. package/dist/ui/base/tabbed-list-overlay.d.ts +153 -0
  301. package/dist/ui/base/tabbed-list-overlay.js +369 -0
  302. package/dist/ui/constants/labels.d.ts +14 -0
  303. package/dist/ui/constants/labels.js +51 -0
  304. package/dist/ui/conversation-store.d.ts +55 -0
  305. package/dist/ui/conversation-store.js +107 -0
  306. package/dist/ui/conversation.d.ts +75 -4
  307. package/dist/ui/conversation.js +376 -165
  308. package/dist/ui/diff.d.ts +7 -1
  309. package/dist/ui/diff.js +85 -48
  310. package/dist/ui/ephemeral.d.ts +1 -1
  311. package/dist/ui/ephemeral.js +4 -10
  312. package/dist/ui/features/index.d.ts +34 -0
  313. package/dist/ui/features/index.js +34 -0
  314. package/dist/ui/features/input-feature.d.ts +85 -0
  315. package/dist/ui/features/input-feature.js +238 -0
  316. package/dist/ui/features/list-feature.d.ts +155 -0
  317. package/dist/ui/features/list-feature.js +244 -0
  318. package/dist/ui/features/pagination-feature.d.ts +154 -0
  319. package/dist/ui/features/pagination-feature.js +238 -0
  320. package/dist/ui/features/search-feature.d.ts +148 -0
  321. package/dist/ui/features/search-feature.js +185 -0
  322. package/dist/ui/features/tab-feature.d.ts +194 -0
  323. package/dist/ui/features/tab-feature.js +307 -0
  324. package/dist/ui/file-autocomplete.d.ts +24 -0
  325. package/dist/ui/file-autocomplete.js +56 -0
  326. package/dist/ui/footer-renderer.d.ts +69 -0
  327. package/dist/ui/footer-renderer.js +431 -0
  328. package/dist/ui/footer.d.ts +181 -7
  329. package/dist/ui/footer.js +523 -74
  330. package/dist/ui/guardrail-overlay.d.ts +29 -0
  331. package/dist/ui/guardrail-overlay.js +145 -0
  332. package/dist/ui/index.d.ts +1 -1
  333. package/dist/ui/index.js +1 -3
  334. package/dist/ui/input-controller.d.ts +51 -0
  335. package/dist/ui/input-controller.js +176 -0
  336. package/dist/ui/input-prompt.d.ts +135 -33
  337. package/dist/ui/input-prompt.js +728 -337
  338. package/dist/ui/iteration-limit-overlay.d.ts +2 -2
  339. package/dist/ui/iteration-limit-overlay.js +92 -128
  340. package/dist/ui/keyboard-handler.d.ts +57 -0
  341. package/dist/ui/keyboard-handler.js +557 -0
  342. package/dist/ui/keys-overlay.d.ts +1 -0
  343. package/dist/ui/keys-overlay.js +203 -141
  344. package/dist/ui/line-utils.d.ts +88 -0
  345. package/dist/ui/line-utils.js +150 -0
  346. package/dist/ui/live-region-facade.d.ts +42 -0
  347. package/dist/ui/live-region-facade.js +205 -0
  348. package/dist/ui/live-region.d.ts +157 -0
  349. package/dist/ui/live-region.js +379 -0
  350. package/dist/ui/mascot/expressions.d.ts +32 -0
  351. package/dist/ui/mascot/expressions.js +213 -0
  352. package/dist/ui/mascot/index.d.ts +8 -0
  353. package/dist/ui/mascot/index.js +8 -0
  354. package/dist/ui/mascot/renderer.d.ts +19 -0
  355. package/dist/ui/mascot/renderer.js +132 -0
  356. package/dist/ui/overlay/data/tutorial-content.d.ts +9 -0
  357. package/dist/ui/overlay/data/tutorial-content.js +9 -0
  358. package/dist/ui/overlay/data/tutorial-registry.d.ts +12 -0
  359. package/dist/ui/overlay/data/tutorial-registry.js +116 -0
  360. package/dist/ui/overlay/data/tutorial-types.d.ts +35 -0
  361. package/dist/ui/overlay/data/tutorial-types.js +6 -0
  362. package/dist/ui/overlay/data/tutorials/basics/first-conversation.d.ts +7 -0
  363. package/dist/ui/overlay/data/tutorials/basics/first-conversation.js +220 -0
  364. package/dist/ui/overlay/data/tutorials/basics/first-project.d.ts +7 -0
  365. package/dist/ui/overlay/data/tutorials/basics/first-project.js +284 -0
  366. package/dist/ui/overlay/data/tutorials/basics/navigation.d.ts +8 -0
  367. package/dist/ui/overlay/data/tutorials/basics/navigation.js +22 -0
  368. package/dist/ui/overlay/data/tutorials/basics/welcome.d.ts +7 -0
  369. package/dist/ui/overlay/data/tutorials/basics/welcome.js +174 -0
  370. package/dist/ui/overlay/data/tutorials/config/context-management.d.ts +7 -0
  371. package/dist/ui/overlay/data/tutorials/config/context-management.js +158 -0
  372. package/dist/ui/overlay/data/tutorials/config/mcp-servers.d.ts +8 -0
  373. package/dist/ui/overlay/data/tutorials/config/mcp-servers.js +155 -0
  374. package/dist/ui/overlay/data/tutorials/config/model-selection.d.ts +7 -0
  375. package/dist/ui/overlay/data/tutorials/config/model-selection.js +162 -0
  376. package/dist/ui/overlay/data/tutorials/config/permissions-safety.d.ts +7 -0
  377. package/dist/ui/overlay/data/tutorials/config/permissions-safety.js +163 -0
  378. package/dist/ui/overlay/data/tutorials/config/settings-config.d.ts +7 -0
  379. package/dist/ui/overlay/data/tutorials/config/settings-config.js +166 -0
  380. package/dist/ui/overlay/data/tutorials/planning/arch.d.ts +7 -0
  381. package/dist/ui/overlay/data/tutorials/planning/arch.js +168 -0
  382. package/dist/ui/overlay/data/tutorials/planning/backlog.d.ts +7 -0
  383. package/dist/ui/overlay/data/tutorials/planning/backlog.js +103 -0
  384. package/dist/ui/overlay/data/tutorials/planning/build.d.ts +7 -0
  385. package/dist/ui/overlay/data/tutorials/planning/build.js +173 -0
  386. package/dist/ui/overlay/data/tutorials/planning/design.d.ts +7 -0
  387. package/dist/ui/overlay/data/tutorials/planning/design.js +205 -0
  388. package/dist/ui/overlay/data/tutorials/planning/docs.d.ts +7 -0
  389. package/dist/ui/overlay/data/tutorials/planning/docs.js +143 -0
  390. package/dist/ui/overlay/data/tutorials/planning/prd.d.ts +7 -0
  391. package/dist/ui/overlay/data/tutorials/planning/prd.js +173 -0
  392. package/dist/ui/overlay/data/tutorials/planning/scaffold.d.ts +7 -0
  393. package/dist/ui/overlay/data/tutorials/planning/scaffold.js +164 -0
  394. package/dist/ui/overlay/data/tutorials/planning/sketch.d.ts +7 -0
  395. package/dist/ui/overlay/data/tutorials/planning/sketch.js +58 -0
  396. package/dist/ui/overlay/data/tutorials/projects/anchors.d.ts +7 -0
  397. package/dist/ui/overlay/data/tutorials/projects/anchors.js +248 -0
  398. package/dist/ui/overlay/data/tutorials/projects/import-project.d.ts +7 -0
  399. package/dist/ui/overlay/data/tutorials/projects/import-project.js +172 -0
  400. package/dist/ui/overlay/data/tutorials/projects/managing-projects.d.ts +8 -0
  401. package/dist/ui/overlay/data/tutorials/projects/managing-projects.js +212 -0
  402. package/dist/ui/overlay/data/tutorials/projects/new-project.d.ts +7 -0
  403. package/dist/ui/overlay/data/tutorials/projects/new-project.js +251 -0
  404. package/dist/ui/overlay/data/tutorials/projects/session-management.d.ts +7 -0
  405. package/dist/ui/overlay/data/tutorials/projects/session-management.js +169 -0
  406. package/dist/ui/overlay/data/tutorials/teams/background-execution.d.ts +7 -0
  407. package/dist/ui/overlay/data/tutorials/teams/background-execution.js +171 -0
  408. package/dist/ui/overlay/data/tutorials/teams/multi-terminal.d.ts +8 -0
  409. package/dist/ui/overlay/data/tutorials/teams/multi-terminal.js +147 -0
  410. package/dist/ui/overlay/data/tutorials/teams/task-assignment.d.ts +7 -0
  411. package/dist/ui/overlay/data/tutorials/teams/task-assignment.js +204 -0
  412. package/dist/ui/overlay/data/tutorials/teams/team-overview.d.ts +7 -0
  413. package/dist/ui/overlay/data/tutorials/teams/team-overview.js +165 -0
  414. package/dist/ui/overlay/data/tutorials/teams/working-with-agents.d.ts +7 -0
  415. package/dist/ui/overlay/data/tutorials/teams/working-with-agents.js +172 -0
  416. package/dist/ui/overlay/impl/agents-overlay-v2.d.ts +45 -0
  417. package/dist/ui/overlay/impl/agents-overlay-v2.js +814 -0
  418. package/dist/ui/overlay/impl/anchors-overlay-v2.d.ts +47 -0
  419. package/dist/ui/overlay/impl/anchors-overlay-v2.js +749 -0
  420. package/dist/ui/overlay/impl/arch-type-overlay-v2.d.ts +37 -0
  421. package/dist/ui/overlay/impl/arch-type-overlay-v2.js +240 -0
  422. package/dist/ui/overlay/impl/artifact-detail-overlay-v2.d.ts +43 -0
  423. package/dist/ui/overlay/impl/artifact-detail-overlay-v2.js +232 -0
  424. package/dist/ui/overlay/impl/artifact-overlay-v2.d.ts +40 -0
  425. package/dist/ui/overlay/impl/artifact-overlay-v2.js +115 -0
  426. package/dist/ui/overlay/impl/ask-user-overlay-v2.d.ts +72 -0
  427. package/dist/ui/overlay/impl/ask-user-overlay-v2.js +581 -0
  428. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.d.ts +46 -0
  429. package/dist/ui/overlay/impl/ask-user-simple-overlay-v2.js +204 -0
  430. package/dist/ui/overlay/impl/background-overlay-v2.d.ts +40 -0
  431. package/dist/ui/overlay/impl/background-overlay-v2.js +147 -0
  432. package/dist/ui/overlay/impl/backlog-overlay-v2.d.ts +52 -0
  433. package/dist/ui/overlay/impl/backlog-overlay-v2.js +681 -0
  434. package/dist/ui/overlay/impl/changelog-overlay-v2.d.ts +44 -0
  435. package/dist/ui/overlay/impl/changelog-overlay-v2.js +165 -0
  436. package/dist/ui/overlay/impl/commands-overlay-v2.d.ts +33 -0
  437. package/dist/ui/overlay/impl/commands-overlay-v2.js +439 -0
  438. package/dist/ui/overlay/impl/config-overlay-v2.d.ts +111 -0
  439. package/dist/ui/overlay/impl/config-overlay-v2.js +718 -0
  440. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.d.ts +83 -0
  441. package/dist/ui/overlay/impl/custom-agent-form-overlay-v2.js +711 -0
  442. package/dist/ui/overlay/impl/dashboard-overlay-v2.d.ts +57 -0
  443. package/dist/ui/overlay/impl/dashboard-overlay-v2.js +382 -0
  444. package/dist/ui/overlay/impl/delegations-overlay-v2.d.ts +28 -0
  445. package/dist/ui/overlay/impl/delegations-overlay-v2.js +279 -0
  446. package/dist/ui/overlay/impl/docs-overlay-v2.d.ts +45 -0
  447. package/dist/ui/overlay/impl/docs-overlay-v2.js +117 -0
  448. package/dist/ui/overlay/impl/document-detail-overlay-v2.d.ts +84 -0
  449. package/dist/ui/overlay/impl/document-detail-overlay-v2.js +1112 -0
  450. package/dist/ui/overlay/impl/filter-overlay-v2.d.ts +41 -0
  451. package/dist/ui/overlay/impl/filter-overlay-v2.js +110 -0
  452. package/dist/ui/overlay/impl/games-overlay-v2.d.ts +31 -0
  453. package/dist/ui/overlay/impl/games-overlay-v2.js +135 -0
  454. package/dist/ui/overlay/impl/guardrail-overlay-v2.d.ts +43 -0
  455. package/dist/ui/overlay/impl/guardrail-overlay-v2.js +114 -0
  456. package/dist/ui/overlay/impl/help-overlay-v2.d.ts +57 -0
  457. package/dist/ui/overlay/impl/help-overlay-v2.js +287 -0
  458. package/dist/ui/overlay/impl/init-setup-overlay-v2.d.ts +25 -0
  459. package/dist/ui/overlay/impl/init-setup-overlay-v2.js +97 -0
  460. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.d.ts +35 -0
  461. package/dist/ui/overlay/impl/iteration-limit-overlay-v2.js +105 -0
  462. package/dist/ui/overlay/impl/keys-overlay-v2.d.ts +41 -0
  463. package/dist/ui/overlay/impl/keys-overlay-v2.js +248 -0
  464. package/dist/ui/overlay/impl/login-overlay-v2.d.ts +49 -0
  465. package/dist/ui/overlay/impl/login-overlay-v2.js +277 -0
  466. package/dist/ui/overlay/impl/mascot-overlay-v2.d.ts +41 -0
  467. package/dist/ui/overlay/impl/mascot-overlay-v2.js +138 -0
  468. package/dist/ui/overlay/impl/mcp-overlay-v2.d.ts +63 -0
  469. package/dist/ui/overlay/impl/mcp-overlay-v2.js +907 -0
  470. package/dist/ui/overlay/impl/model-overlay-v2.d.ts +93 -0
  471. package/dist/ui/overlay/impl/model-overlay-v2.js +1143 -0
  472. package/dist/ui/overlay/impl/model-warning-overlay-v2.d.ts +46 -0
  473. package/dist/ui/overlay/impl/model-warning-overlay-v2.js +132 -0
  474. package/dist/ui/overlay/impl/new-overlay-v2.d.ts +108 -0
  475. package/dist/ui/overlay/impl/new-overlay-v2.js +1243 -0
  476. package/dist/ui/overlay/impl/notifications-overlay-v2.d.ts +20 -0
  477. package/dist/ui/overlay/impl/notifications-overlay-v2.js +116 -0
  478. package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.d.ts +76 -0
  479. package/dist/ui/overlay/impl/onboarding-wizard-overlay-v2.js +728 -0
  480. package/dist/ui/overlay/impl/pending-overlay-v2.d.ts +51 -0
  481. package/dist/ui/overlay/impl/pending-overlay-v2.js +445 -0
  482. package/dist/ui/overlay/impl/permission-overlay-v2.d.ts +36 -0
  483. package/dist/ui/overlay/impl/permission-overlay-v2.js +380 -0
  484. package/dist/ui/overlay/impl/permissions-overlay-v2.d.ts +85 -0
  485. package/dist/ui/overlay/impl/permissions-overlay-v2.js +820 -0
  486. package/dist/ui/overlay/impl/plan-approval-overlay-v2.d.ts +35 -0
  487. package/dist/ui/overlay/impl/plan-approval-overlay-v2.js +181 -0
  488. package/dist/ui/overlay/impl/project-edit-overlay-v2.d.ts +36 -0
  489. package/dist/ui/overlay/impl/project-edit-overlay-v2.js +195 -0
  490. package/dist/ui/overlay/impl/projects-overlay-v2.d.ts +37 -0
  491. package/dist/ui/overlay/impl/projects-overlay-v2.js +733 -0
  492. package/dist/ui/overlay/impl/reset-overlay-v2.d.ts +39 -0
  493. package/dist/ui/overlay/impl/reset-overlay-v2.js +107 -0
  494. package/dist/ui/overlay/impl/resume-overlay-v2.d.ts +60 -0
  495. package/dist/ui/overlay/impl/resume-overlay-v2.js +414 -0
  496. package/dist/ui/overlay/impl/session-mode-overlay-v2.d.ts +43 -0
  497. package/dist/ui/overlay/impl/session-mode-overlay-v2.js +124 -0
  498. package/dist/ui/overlay/impl/tasks-overlay-v2.d.ts +28 -0
  499. package/dist/ui/overlay/impl/tasks-overlay-v2.js +283 -0
  500. package/dist/ui/overlay/impl/team-overlay-v2.d.ts +86 -0
  501. package/dist/ui/overlay/impl/team-overlay-v2.js +692 -0
  502. package/dist/ui/overlay/impl/terminals-overlay-v2.d.ts +26 -0
  503. package/dist/ui/overlay/impl/terminals-overlay-v2.js +217 -0
  504. package/dist/ui/overlay/impl/theme-overlay-v2.d.ts +42 -0
  505. package/dist/ui/overlay/impl/theme-overlay-v2.js +135 -0
  506. package/dist/ui/overlay/impl/tools-overlay-v2.d.ts +47 -0
  507. package/dist/ui/overlay/impl/tools-overlay-v2.js +214 -0
  508. package/dist/ui/overlay/impl/tutorial-overlay-v2.d.ts +45 -0
  509. package/dist/ui/overlay/impl/tutorial-overlay-v2.js +212 -0
  510. package/dist/ui/overlay/impl/workflow-overlay-v2.d.ts +80 -0
  511. package/dist/ui/overlay/impl/workflow-overlay-v2.js +641 -0
  512. package/dist/ui/overlay/index.d.ts +52 -0
  513. package/dist/ui/overlay/index.js +54 -0
  514. package/dist/ui/overlay/key-utils.d.ts +6 -0
  515. package/dist/ui/overlay/key-utils.js +6 -0
  516. package/dist/ui/overlay/types.d.ts +140 -0
  517. package/dist/ui/overlay/types.js +22 -0
  518. package/dist/ui/overlay-manager.d.ts +43 -0
  519. package/dist/ui/overlay-manager.js +238 -0
  520. package/dist/ui/overlays.d.ts +0 -4
  521. package/dist/ui/overlays.js +4 -460
  522. package/dist/ui/permission-overlay.d.ts +1 -1
  523. package/dist/ui/permission-overlay.js +189 -300
  524. package/dist/ui/providers/types.d.ts +178 -0
  525. package/dist/ui/providers/types.js +9 -0
  526. package/dist/ui/render-modes.d.ts +36 -0
  527. package/dist/ui/render-modes.js +44 -0
  528. package/dist/ui/startup-menu.d.ts +36 -0
  529. package/dist/ui/startup-menu.js +236 -0
  530. package/dist/ui/status-bar-controller.d.ts +33 -0
  531. package/dist/ui/status-bar-controller.js +99 -0
  532. package/dist/ui/subagent-renderer.d.ts +117 -0
  533. package/dist/ui/subagent-renderer.js +318 -0
  534. package/dist/ui/terminal-autocomplete-utils.d.ts +23 -0
  535. package/dist/ui/terminal-autocomplete-utils.js +83 -0
  536. package/dist/ui/terminal-codes.d.ts +94 -0
  537. package/dist/ui/terminal-codes.js +124 -0
  538. package/dist/ui/terminal-line-builders.d.ts +17 -0
  539. package/dist/ui/terminal-line-builders.js +42 -0
  540. package/dist/ui/terminal-render-item.d.ts +16 -0
  541. package/dist/ui/terminal-render-item.js +267 -0
  542. package/dist/ui/terminal-renderer.d.ts +220 -0
  543. package/dist/ui/terminal-renderer.js +750 -0
  544. package/dist/ui/terminal-types.d.ts +179 -0
  545. package/dist/ui/terminal-types.js +34 -0
  546. package/dist/ui/terminal-ui.d.ts +331 -0
  547. package/dist/ui/terminal-ui.js +819 -0
  548. package/dist/ui/terminal.d.ts +20 -0
  549. package/dist/ui/terminal.js +72 -0
  550. package/dist/ui/todo-zone.d.ts +19 -1
  551. package/dist/ui/todo-zone.js +124 -38
  552. package/dist/ui/tool-formatters.d.ts +16 -0
  553. package/dist/ui/tool-formatters.js +1027 -0
  554. package/dist/ui/turn-metrics.d.ts +56 -0
  555. package/dist/ui/turn-metrics.js +75 -0
  556. package/dist/ui/types.d.ts +28 -0
  557. package/dist/ui/types.js +1 -0
  558. package/dist/ui/vscode-diff-ipc.d.ts +102 -0
  559. package/dist/ui/vscode-diff-ipc.js +385 -0
  560. package/dist/utils/credentials.d.ts +24 -5
  561. package/dist/utils/credentials.js +123 -9
  562. package/dist/utils/debug-log.d.ts +28 -0
  563. package/dist/utils/debug-log.js +57 -0
  564. package/dist/utils/format-tokens.d.ts +13 -0
  565. package/dist/utils/format-tokens.js +18 -0
  566. package/dist/utils/git-config.d.ts +26 -0
  567. package/dist/utils/git-config.js +54 -0
  568. package/dist/utils/message-utils.d.ts +61 -0
  569. package/dist/utils/message-utils.js +72 -0
  570. package/dist/utils/model-tiers.d.ts +8 -1
  571. package/dist/utils/model-tiers.js +39 -17
  572. package/dist/utils/open-browser.d.ts +5 -0
  573. package/dist/utils/open-browser.js +32 -0
  574. package/dist/utils/path-safety.d.ts +56 -0
  575. package/dist/utils/path-safety.js +240 -0
  576. package/dist/utils/project-detection.d.ts +58 -0
  577. package/dist/utils/project-detection.js +424 -0
  578. package/dist/utils/project-memory.js +2 -1
  579. package/dist/utils/project-status.d.ts +2 -2
  580. package/dist/utils/startup-perf.d.ts +18 -0
  581. package/dist/utils/startup-perf.js +60 -0
  582. package/dist/utils/token-tracker.d.ts +62 -0
  583. package/dist/utils/token-tracker.js +150 -0
  584. package/dist/utils/token-types.d.ts +23 -0
  585. package/dist/utils/token-types.js +18 -0
  586. package/dist/utils/types/config-types.d.ts +32 -0
  587. package/dist/utils/types/config-types.js +8 -0
  588. package/dist/utils/update-checker.d.ts +28 -0
  589. package/dist/utils/update-checker.js +106 -0
  590. package/dist/utils/version.d.ts +7 -0
  591. package/dist/utils/version.js +10 -0
  592. package/dist/utils/vscode-detect.d.ts +39 -0
  593. package/dist/utils/vscode-detect.js +137 -0
  594. package/dist/workflow/guided-mode-injector.d.ts +42 -0
  595. package/dist/workflow/guided-mode-injector.js +191 -0
  596. package/dist/workflow/index.d.ts +8 -0
  597. package/dist/workflow/index.js +8 -0
  598. package/dist/workflow/step-criteria.d.ts +62 -0
  599. package/dist/workflow/step-criteria.js +150 -0
  600. package/dist/workflow/step-tracker.d.ts +92 -0
  601. package/dist/workflow/step-tracker.js +141 -0
  602. package/package.json +32 -12
  603. package/dist/index.old.d.ts +0 -7
  604. package/dist/index.old.js +0 -1014
  605. package/dist/repl.d.ts +0 -121
  606. package/dist/repl.js +0 -1878
  607. package/dist/templates/claude-md.d.ts +0 -7
  608. package/dist/templates/claude-md.js +0 -189
  609. package/dist/test-autocomplete.d.ts +0 -7
  610. package/dist/test-autocomplete.js +0 -85
  611. package/dist/test-tabbed-menu.d.ts +0 -7
  612. package/dist/test-tabbed-menu.js +0 -25
  613. package/dist/tool-selector.d.ts +0 -71
  614. package/dist/tool-selector.js +0 -184
  615. package/dist/ui/agents-overlay.d.ts +0 -12
  616. package/dist/ui/agents-overlay.js +0 -501
  617. package/dist/ui/arch-type-overlay.d.ts +0 -20
  618. package/dist/ui/arch-type-overlay.js +0 -229
  619. package/dist/ui/backlog-overlay.d.ts +0 -17
  620. package/dist/ui/backlog-overlay.js +0 -786
  621. package/dist/ui/commands-overlay.d.ts +0 -11
  622. package/dist/ui/commands-overlay.js +0 -410
  623. package/dist/ui/config-overlay.d.ts +0 -34
  624. package/dist/ui/config-overlay.js +0 -977
  625. package/dist/ui/init-overlay.d.ts +0 -24
  626. package/dist/ui/init-overlay.js +0 -525
  627. package/dist/ui/input-prompt-v2.d.ts +0 -179
  628. package/dist/ui/input-prompt-v2.js +0 -991
  629. package/dist/ui/model-warning-overlay.d.ts +0 -30
  630. package/dist/ui/model-warning-overlay.js +0 -171
  631. package/dist/ui/tools-overlay.d.ts +0 -26
  632. package/dist/ui/tools-overlay.js +0 -278
  633. package/dist/ui/tutorial-overlay.d.ts +0 -10
  634. package/dist/ui/tutorial-overlay.js +0 -936
@@ -0,0 +1,907 @@
1
+ /**
2
+ * MCP Overlay V2
3
+ *
4
+ * Shows connected MCP servers and their tools.
5
+ * Extends TabbedListOverlayV2 for consistent UI.
6
+ *
7
+ * Features:
8
+ * - Single tab (all servers)
9
+ * - Server list with status and tool count
10
+ * - Detail view with tool list
11
+ * - Restart/disconnect actions
12
+ * - Add server form (with hot-reload)
13
+ * - Empty state with config file instructions
14
+ */
15
+ import { TabbedListOverlayV2, BaseScreen, stay, pushScreen, popScreen, closeOverlay, isEscape, isCtrlC, isQuit, isEnter, isSpace, isTab, isShiftTab, isBackspace, isDelete, isLeftArrow, isRightArrow, isUpArrow, isDownArrow, isHome, isEnd, isCtrlA, isCtrlE, isPrintable, getPrintableChar, renderBorder, truncate, wrapText, } from '../../base/index.js';
16
+ import { getMCPConfigPath, saveMCPServer, getExistingServerNames, } from '../../../settings/mcp-config.js';
17
+ // =============================================================================
18
+ // Constants
19
+ // =============================================================================
20
+ const PAGE_SIZE = 8;
21
+ // =============================================================================
22
+ // Detail Screen
23
+ // =============================================================================
24
+ class ServerDetailScreen extends BaseScreen {
25
+ item;
26
+ manager;
27
+ styles;
28
+ getWidth;
29
+ onRefresh;
30
+ message = null;
31
+ selectedToolIndex = 0;
32
+ toolScrollOffset = 0;
33
+ /** Max tools visible in the scrollable list area */
34
+ static TOOL_PAGE_SIZE = 8;
35
+ constructor(item, manager, styles, getWidth, onRefresh) {
36
+ super();
37
+ this.item = item;
38
+ this.manager = manager;
39
+ this.styles = styles;
40
+ this.getWidth = getWidth;
41
+ this.onRefresh = onRefresh;
42
+ }
43
+ getMinHeight() {
44
+ return 20;
45
+ }
46
+ render() {
47
+ const s = this.styles;
48
+ const cols = this.getWidth();
49
+ const border = renderBorder(cols, s);
50
+ const lines = [];
51
+ // Re-read status from client (may have changed after restart/disconnect)
52
+ const currentStatus = this.item.client.status;
53
+ const statusDisplay = formatStatus(currentStatus, s);
54
+ // Header
55
+ lines.push(border);
56
+ lines.push(` ${s.primaryBold(`MCP Server: ${this.item.name}`)}`);
57
+ lines.push('');
58
+ // Server info
59
+ lines.push(` ${s.secondary('Status:')} ${statusDisplay}`);
60
+ lines.push(` ${s.secondary('Transport:')} ${this.item.transport} ${s.muted(`\u2014 ${this.item.transportDetail}`)}`);
61
+ lines.push('');
62
+ // Message (after restart/disconnect)
63
+ if (this.message) {
64
+ lines.push(` ${s.secondary(this.message)}`);
65
+ lines.push('');
66
+ }
67
+ // Tools
68
+ const tools = this.item.tools;
69
+ if (tools.length > 0) {
70
+ lines.push(` ${s.secondary(`Tools (${String(tools.length)}):`)}`);
71
+ // Clamp selection
72
+ if (this.selectedToolIndex >= tools.length) {
73
+ this.selectedToolIndex = tools.length - 1;
74
+ }
75
+ // Adjust scroll offset to keep selection visible
76
+ const pageSize = ServerDetailScreen.TOOL_PAGE_SIZE;
77
+ if (this.selectedToolIndex < this.toolScrollOffset) {
78
+ this.toolScrollOffset = this.selectedToolIndex;
79
+ }
80
+ else if (this.selectedToolIndex >= this.toolScrollOffset + pageSize) {
81
+ this.toolScrollOffset = this.selectedToolIndex - pageSize + 1;
82
+ }
83
+ // Render visible tools
84
+ const visibleEnd = Math.min(this.toolScrollOffset + pageSize, tools.length);
85
+ // Scroll indicator (top)
86
+ if (this.toolScrollOffset > 0) {
87
+ lines.push(` ${s.muted(`\u2191 ${String(this.toolScrollOffset)} more above`)}`);
88
+ }
89
+ for (let i = this.toolScrollOffset; i < visibleEnd; i++) {
90
+ const tool = tools[i];
91
+ const isSelected = i === this.selectedToolIndex;
92
+ const prefix = isSelected ? s.primary(' \u25ba ') : ' ';
93
+ const toolName = truncate(tool.name, 30);
94
+ const desc = tool.description
95
+ ? s.muted(` \u2014 ${truncate(tool.description, Math.max(cols - 42, 20))}`)
96
+ : '';
97
+ const name = isSelected ? s.primary(toolName) : toolName;
98
+ lines.push(`${prefix}${name}${desc}`);
99
+ }
100
+ // Scroll indicator (bottom)
101
+ const remaining = tools.length - visibleEnd;
102
+ if (remaining > 0) {
103
+ lines.push(` ${s.muted(`\u2193 ${String(remaining)} more below`)}`);
104
+ }
105
+ }
106
+ else if (currentStatus === 'connected') {
107
+ lines.push(` ${s.muted('No tools discovered.')}`);
108
+ }
109
+ else {
110
+ lines.push(` ${s.muted('Server not connected \u2014 tools unavailable.')}`);
111
+ }
112
+ lines.push('');
113
+ // Pad to consistent height
114
+ while (lines.length < 16) {
115
+ lines.push('');
116
+ }
117
+ // Footer
118
+ lines.push(border);
119
+ const footerHint = tools.length > 0
120
+ ? '\u2191\u2193/jk Navigate \u00b7 Enter Details \u00b7 r Restart \u00b7 d Disconnect \u00b7 q/Esc Back'
121
+ : 'r Restart \u00b7 d Disconnect \u00b7 q/Esc Back';
122
+ lines.push(s.muted(` ${footerHint}`));
123
+ return lines;
124
+ }
125
+ handleKey(data) {
126
+ if (isCtrlC(data)) {
127
+ return closeOverlay({ viewed: true });
128
+ }
129
+ if (isEscape(data) || isQuit(data)) {
130
+ return popScreen();
131
+ }
132
+ const char = data.toString();
133
+ const tools = this.item.tools;
134
+ // Tool navigation — Up/Down/j/k
135
+ if (tools.length > 0) {
136
+ if (isUpArrow(data) || char === 'k') {
137
+ if (this.selectedToolIndex > 0) {
138
+ this.selectedToolIndex--;
139
+ }
140
+ return stay(true);
141
+ }
142
+ if (isDownArrow(data) || char === 'j') {
143
+ if (this.selectedToolIndex < tools.length - 1) {
144
+ this.selectedToolIndex++;
145
+ }
146
+ return stay(true);
147
+ }
148
+ // Enter — push tool detail screen
149
+ if (isEnter(data)) {
150
+ const selectedTool = tools[this.selectedToolIndex];
151
+ return pushScreen(new MCPToolDetailScreen(selectedTool, this.item.name, this.styles, this.getWidth));
152
+ }
153
+ }
154
+ // Restart
155
+ if (char === 'r') {
156
+ this.message = 'Restarting...';
157
+ this.onRefresh();
158
+ void (async () => {
159
+ try {
160
+ const client = this.item.client;
161
+ await client.disconnect();
162
+ await client.connect();
163
+ const newTools = await client.listTools();
164
+ this.item.tools = newTools;
165
+ this.item.toolCount = newTools.length;
166
+ this.selectedToolIndex = 0;
167
+ this.toolScrollOffset = 0;
168
+ this.message = `Restarted \u2014 ${String(newTools.length)} tools discovered`;
169
+ }
170
+ catch {
171
+ this.message = 'Restart failed';
172
+ }
173
+ this.onRefresh();
174
+ })();
175
+ return stay(false);
176
+ }
177
+ // Disconnect
178
+ if (char === 'd') {
179
+ this.message = 'Disconnecting...';
180
+ this.onRefresh();
181
+ void (async () => {
182
+ try {
183
+ await this.item.client.disconnect();
184
+ this.item.tools = [];
185
+ this.item.toolCount = 0;
186
+ this.selectedToolIndex = 0;
187
+ this.toolScrollOffset = 0;
188
+ this.message = 'Disconnected';
189
+ this.onRefresh();
190
+ }
191
+ catch {
192
+ this.message = 'Disconnect failed';
193
+ }
194
+ this.onRefresh();
195
+ })();
196
+ return stay(false);
197
+ }
198
+ return stay(false);
199
+ }
200
+ }
201
+ // =============================================================================
202
+ // Tool Detail Screen
203
+ // =============================================================================
204
+ /**
205
+ * Full-screen detail view for a single MCP tool.
206
+ * Shows name, description (word-wrapped), and input schema parameters.
207
+ * Follows the same pattern as ToolDetailScreen in tools-overlay-v2.
208
+ */
209
+ class MCPToolDetailScreen extends BaseScreen {
210
+ tool;
211
+ serverName;
212
+ styles;
213
+ getWidth;
214
+ constructor(tool, serverName, styles, getWidth) {
215
+ super();
216
+ this.tool = tool;
217
+ this.serverName = serverName;
218
+ this.styles = styles;
219
+ this.getWidth = getWidth;
220
+ }
221
+ render() {
222
+ const s = this.styles;
223
+ const cols = this.getWidth();
224
+ const border = renderBorder(cols, s);
225
+ const maxLineWidth = cols - 2;
226
+ const lines = [];
227
+ // Header
228
+ lines.push(border);
229
+ lines.push(` ${s.primaryBold('MCP Tool Details')}`);
230
+ lines.push('');
231
+ // Tool name (prefixed with server name)
232
+ lines.push(` ${s.muted('Name:')} ${s.primaryBold(`mcp_${this.serverName}_${this.tool.name}`)}`);
233
+ lines.push(` ${s.muted('Server:')} ${this.serverName}`);
234
+ lines.push('');
235
+ // Description (word-wrapped, never truncated)
236
+ lines.push(` ${s.muted('Description:')}`);
237
+ const description = this.tool.description ?? 'No description available.';
238
+ const wrappedDesc = wrapText(description, Math.min(maxLineWidth - 4, 70));
239
+ for (const line of wrappedDesc) {
240
+ lines.push(` ${s.secondary(line)}`);
241
+ }
242
+ lines.push('');
243
+ // Input schema parameters
244
+ const props = this.tool.inputSchema.properties;
245
+ const required = new Set(this.tool.inputSchema.required ?? []);
246
+ if (props && Object.keys(props).length > 0) {
247
+ const entries = Object.entries(props);
248
+ // Sort: required first, then optional
249
+ entries.sort(([a], [b]) => {
250
+ const aReq = required.has(a);
251
+ const bReq = required.has(b);
252
+ if (aReq && !bReq)
253
+ return -1;
254
+ if (!aReq && bReq)
255
+ return 1;
256
+ return 0;
257
+ });
258
+ lines.push(` ${s.muted('Parameters:')}`);
259
+ for (const [paramName, paramDef] of entries) {
260
+ const def = paramDef;
261
+ const paramType = typeof def.type === 'string' ? def.type : 'any';
262
+ const isRequired = required.has(paramName);
263
+ const reqLabel = isRequired ? s.warning('*') : ' ';
264
+ const typeStr = s.muted(`(${paramType})`);
265
+ lines.push(` ${reqLabel} ${s.secondary(paramName)} ${typeStr}`);
266
+ // Parameter description (word-wrapped under the param name)
267
+ if (typeof def.description === 'string') {
268
+ const paramDescWrapped = wrapText(def.description, Math.min(maxLineWidth - 10, 64));
269
+ for (const pdLine of paramDescWrapped) {
270
+ lines.push(` ${s.muted(pdLine)}`);
271
+ }
272
+ }
273
+ }
274
+ lines.push('');
275
+ lines.push(` ${s.muted('* = required')}`);
276
+ }
277
+ else {
278
+ lines.push(` ${s.muted('Parameters:')} ${s.muted('None')}`);
279
+ }
280
+ lines.push('');
281
+ // Footer
282
+ lines.push(border);
283
+ lines.push(` ${s.muted('q/Esc Back')}`);
284
+ return lines;
285
+ }
286
+ handleKey(data) {
287
+ if (isCtrlC(data)) {
288
+ return closeOverlay({ viewed: true });
289
+ }
290
+ if (isEscape(data) || isQuit(data)) {
291
+ return popScreen();
292
+ }
293
+ return stay(false);
294
+ }
295
+ getMinHeight() {
296
+ return 20;
297
+ }
298
+ }
299
+ /**
300
+ * Form screen for adding a new MCP server.
301
+ * Text fields accept character input; cycle fields toggle with Enter/Space.
302
+ * Follows the same navigation pattern as /config overlay.
303
+ */
304
+ class AddServerScreen extends BaseScreen {
305
+ agent;
306
+ getManager;
307
+ styles;
308
+ getWidth;
309
+ onServerAdded;
310
+ onRefresh;
311
+ projectRoot;
312
+ formState;
313
+ existingNames;
314
+ constructor(agent, getManager, styles, getWidth, onServerAdded, onRefresh, projectRoot) {
315
+ super();
316
+ this.agent = agent;
317
+ this.getManager = getManager;
318
+ this.styles = styles;
319
+ this.getWidth = getWidth;
320
+ this.onServerAdded = onServerAdded;
321
+ this.onRefresh = onRefresh;
322
+ this.projectRoot = projectRoot;
323
+ this.existingNames = getExistingServerNames(projectRoot);
324
+ const items = [
325
+ { type: 'text', id: 'name', label: 'Name', value: '', hint: 'Unique server name (e.g., filesystem)' },
326
+ { type: 'cycle', id: 'transport', label: 'Transport', value: 'stdio', options: ['stdio', 'http'] },
327
+ { type: 'text', id: 'command', label: 'Command', value: '', hint: 'Command to run (e.g., npx)' },
328
+ { type: 'text', id: 'args', label: 'Args', value: '', hint: 'Space-separated arguments (optional)' },
329
+ ];
330
+ // Add scope toggle only when a project is bound
331
+ if (this.projectRoot) {
332
+ items.push({ type: 'cycle', id: 'scope', label: 'Scope', value: 'Global', options: ['Global', 'Project'] });
333
+ }
334
+ this.formState = {
335
+ items,
336
+ activeIndex: 0,
337
+ cursorPos: 0,
338
+ saving: false,
339
+ message: null,
340
+ };
341
+ }
342
+ getMinHeight() {
343
+ return 20;
344
+ }
345
+ // ── helpers ──────────────────────────────────────────────────────────────
346
+ get activeItem() { return this.formState.items[this.formState.activeIndex]; }
347
+ get isTextItem() { return this.activeItem.type === 'text'; }
348
+ get transport() {
349
+ const t = this.formState.items.find((i) => i.id === 'transport');
350
+ return t ? t.value : 'stdio';
351
+ }
352
+ get scope() {
353
+ const s = this.formState.items.find((i) => i.id === 'scope');
354
+ return s ? s.value : 'Global';
355
+ }
356
+ get itemCount() { return this.formState.items.length; }
357
+ // ── render ───────────────────────────────────────────────────────────────
358
+ render() {
359
+ const s = this.styles;
360
+ const cols = this.getWidth();
361
+ const border = renderBorder(cols, s);
362
+ const lines = [];
363
+ const labelWidth = 12;
364
+ // Header
365
+ lines.push(border);
366
+ lines.push(` ${s.primaryBold('Add MCP Server')}`);
367
+ lines.push('');
368
+ for (let i = 0; i < this.formState.items.length; i++) {
369
+ const item = this.formState.items[i];
370
+ const isActive = i === this.formState.activeIndex && !this.formState.saving;
371
+ const prefix = isActive ? s.primary(' \u276f ') : ' ';
372
+ const label = isActive
373
+ ? s.primary(item.label.padEnd(labelWidth))
374
+ : s.secondary(item.label.padEnd(labelWidth));
375
+ // Skip args/headers row when it doesn't apply
376
+ if (item.id === 'args' && this.transport === 'http')
377
+ continue;
378
+ if (item.type === 'text') {
379
+ if (isActive) {
380
+ const before = item.value.slice(0, this.formState.cursorPos);
381
+ const after = item.value.slice(this.formState.cursorPos);
382
+ const cursor = s.primaryBold('\u2502');
383
+ lines.push(`${prefix}${label}${before}${cursor}${after}`);
384
+ }
385
+ else {
386
+ const display = item.value || s.muted(item.hint);
387
+ lines.push(`${prefix}${label}${display}`);
388
+ }
389
+ if (item.error) {
390
+ lines.push(` ${''.padEnd(labelWidth)}${s.error(item.error)}`);
391
+ }
392
+ }
393
+ else {
394
+ // Cycle toggle — render all options, highlight current
395
+ const optionStr = item.options
396
+ .map((opt) => (opt === item.value ? s.primary(opt) : s.muted(opt)))
397
+ .join(s.muted(' / '));
398
+ lines.push(`${prefix}${label}${optionStr}`);
399
+ }
400
+ }
401
+ lines.push('');
402
+ // Status message
403
+ if (this.formState.message) {
404
+ lines.push(` ${this.formState.saving ? s.warning(this.formState.message) : s.success(this.formState.message)}`);
405
+ }
406
+ // Pad to consistent height
407
+ while (lines.length < 16) {
408
+ lines.push('');
409
+ }
410
+ // Footer
411
+ lines.push(border);
412
+ const hint = this.isTextItem
413
+ ? '\u2191\u2193 Navigate \u00b7 Type to edit \u00b7 Enter Submit \u00b7 Esc Cancel'
414
+ : '\u2191\u2193 Navigate \u00b7 Space Toggle \u00b7 Enter Submit \u00b7 Esc Cancel';
415
+ lines.push(s.muted(` ${hint}`));
416
+ return lines;
417
+ }
418
+ // ── key handling ─────────────────────────────────────────────────────────
419
+ handleKey(data) {
420
+ if (isCtrlC(data)) {
421
+ return closeOverlay({ viewed: true });
422
+ }
423
+ if (this.formState.saving) {
424
+ return stay(false);
425
+ }
426
+ if (isEscape(data)) {
427
+ return popScreen();
428
+ }
429
+ // Navigation — Up/Down (always available)
430
+ if (isUpArrow(data) || isShiftTab(data)) {
431
+ return this.navigate(-1);
432
+ }
433
+ if (isDownArrow(data) || isTab(data)) {
434
+ return this.navigate(1);
435
+ }
436
+ // Enter always submits, regardless of active field
437
+ if (isEnter(data)) {
438
+ return this.handleSubmit();
439
+ }
440
+ // ── Cycle items: Space toggles ──────────────────────────────────────
441
+ if (this.activeItem.type === 'cycle') {
442
+ if (isSpace(data)) {
443
+ return this.cycleValue();
444
+ }
445
+ // Cycle items don't accept other input
446
+ return stay(false);
447
+ }
448
+ // At this point activeItem is guaranteed to be 'text' (cycle returned early above)
449
+ return this.handleTextInput(data);
450
+ return stay(false);
451
+ }
452
+ // ── text input handling ───────────────────────────────────────────────────
453
+ handleTextInput(data) {
454
+ const item = this.formState.items[this.formState.activeIndex];
455
+ if (item.type !== 'text')
456
+ return stay(false);
457
+ if (isBackspace(data)) {
458
+ if (this.formState.cursorPos > 0) {
459
+ item.value = item.value.slice(0, this.formState.cursorPos - 1) + item.value.slice(this.formState.cursorPos);
460
+ this.formState.cursorPos--;
461
+ item.error = undefined;
462
+ }
463
+ return stay(true);
464
+ }
465
+ if (isDelete(data)) {
466
+ if (this.formState.cursorPos < item.value.length) {
467
+ item.value = item.value.slice(0, this.formState.cursorPos) + item.value.slice(this.formState.cursorPos + 1);
468
+ item.error = undefined;
469
+ }
470
+ return stay(true);
471
+ }
472
+ if (isLeftArrow(data)) {
473
+ if (this.formState.cursorPos > 0)
474
+ this.formState.cursorPos--;
475
+ return stay(true);
476
+ }
477
+ if (isRightArrow(data)) {
478
+ if (this.formState.cursorPos < item.value.length)
479
+ this.formState.cursorPos++;
480
+ return stay(true);
481
+ }
482
+ if (isHome(data) || isCtrlA(data)) {
483
+ this.formState.cursorPos = 0;
484
+ return stay(true);
485
+ }
486
+ if (isEnd(data) || isCtrlE(data)) {
487
+ this.formState.cursorPos = item.value.length;
488
+ return stay(true);
489
+ }
490
+ if (isPrintable(data)) {
491
+ const ch = getPrintableChar(data);
492
+ if (ch) {
493
+ item.value = item.value.slice(0, this.formState.cursorPos) + ch + item.value.slice(this.formState.cursorPos);
494
+ this.formState.cursorPos++;
495
+ item.error = undefined;
496
+ }
497
+ return stay(true);
498
+ }
499
+ return stay(false);
500
+ }
501
+ // ── navigation helpers ───────────────────────────────────────────────────
502
+ navigate(direction) {
503
+ let next = this.formState.activeIndex + direction;
504
+ // Skip hidden items (args when transport is http)
505
+ while (next >= 0 && next < this.itemCount) {
506
+ const item = this.formState.items[next];
507
+ if (item.id === 'args' && this.transport === 'http') {
508
+ next += direction;
509
+ continue;
510
+ }
511
+ break;
512
+ }
513
+ if (next < 0 || next >= this.itemCount) {
514
+ return stay(false);
515
+ }
516
+ this.formState.activeIndex = next;
517
+ // Set cursor to end of text value when entering a text field
518
+ const newItem = this.formState.items[next];
519
+ if (newItem.type === 'text') {
520
+ this.formState.cursorPos = newItem.value.length;
521
+ }
522
+ return stay(true);
523
+ }
524
+ cycleValue() {
525
+ const item = this.activeItem;
526
+ if (item.type !== 'cycle')
527
+ return stay(false);
528
+ const currentIdx = item.options.indexOf(item.value);
529
+ const nextIdx = (currentIdx + 1) % item.options.length;
530
+ item.value = item.options[nextIdx];
531
+ // When transport changes, update the command/url field labels
532
+ if (item.id === 'transport') {
533
+ this.onTransportChange();
534
+ }
535
+ return stay(true);
536
+ }
537
+ onTransportChange() {
538
+ const isHttp = this.transport === 'http';
539
+ const cmdField = this.formState.items.find((i) => i.id === 'command' || i.id === 'url');
540
+ if (cmdField && cmdField.type === 'text') {
541
+ cmdField.id = isHttp ? 'url' : 'command';
542
+ cmdField.label = isHttp ? 'URL' : 'Command';
543
+ cmdField.hint = isHttp
544
+ ? 'Server URL (e.g., http://localhost:3000/mcp)'
545
+ : 'Command to run (e.g., npx)';
546
+ cmdField.error = undefined;
547
+ }
548
+ }
549
+ getTextItem(id) {
550
+ const item = this.formState.items.find((i) => i.id === id);
551
+ return item?.type === 'text' ? item : undefined;
552
+ }
553
+ handleSubmit() {
554
+ const nameField = this.getTextItem('name');
555
+ const cmdField = this.getTextItem('command') ?? this.getTextItem('url');
556
+ if (!nameField || !cmdField)
557
+ return stay(false);
558
+ let hasError = false;
559
+ const transport = this.transport;
560
+ // Name validation
561
+ const name = nameField.value.trim();
562
+ if (!name) {
563
+ nameField.error = 'Name is required';
564
+ hasError = true;
565
+ }
566
+ else if (this.existingNames.has(name)) {
567
+ nameField.error = 'Name already exists';
568
+ hasError = true;
569
+ }
570
+ else if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
571
+ nameField.error = 'Only letters, numbers, hyphens, underscores';
572
+ hasError = true;
573
+ }
574
+ // Command/URL validation
575
+ const commandOrUrl = cmdField.value.trim();
576
+ if (!commandOrUrl) {
577
+ cmdField.error = `${transport === 'stdio' ? 'Command' : 'URL'} is required`;
578
+ hasError = true;
579
+ }
580
+ if (hasError)
581
+ return stay(true);
582
+ // Build config entry
583
+ const entry = {};
584
+ if (transport === 'stdio') {
585
+ entry.command = commandOrUrl;
586
+ const argsField = this.getTextItem('args');
587
+ const argsStr = argsField?.value.trim();
588
+ if (argsStr) {
589
+ entry.args = argsStr.split(/\s+/);
590
+ }
591
+ }
592
+ else {
593
+ entry.url = commandOrUrl;
594
+ }
595
+ const scope = this.scope === 'Project' ? 'project' : 'global';
596
+ // Save and connect
597
+ this.formState.saving = true;
598
+ this.formState.message = 'Connecting...';
599
+ this.onRefresh();
600
+ void (async () => {
601
+ try {
602
+ // 1. Save to config file
603
+ saveMCPServer(name, entry, scope, this.projectRoot);
604
+ // 2. Get or create manager
605
+ const manager = await this.getManager();
606
+ // 3. Add server and connect
607
+ const client = await manager.addServer({
608
+ name,
609
+ transport: transport,
610
+ command: entry.command,
611
+ args: entry.args,
612
+ url: entry.url,
613
+ });
614
+ // 4. Discover tools
615
+ let tools = [];
616
+ try {
617
+ tools = await client.listTools();
618
+ }
619
+ catch {
620
+ // Tools may not be available yet
621
+ }
622
+ // 5. Register tools with agent
623
+ if (this.agent && tools.length > 0) {
624
+ const agentTools = await manager.discoverToolsFrom(name);
625
+ this.agent.registerTools(agentTools);
626
+ }
627
+ // 6. Build server item for the list
628
+ const newItem = {
629
+ tabId: 'all',
630
+ name,
631
+ status: client.status,
632
+ transport,
633
+ transportDetail: entry.command ?? entry.url ?? '',
634
+ toolCount: tools.length,
635
+ tools,
636
+ client,
637
+ };
638
+ // 7. Notify parent overlay
639
+ this.onServerAdded(newItem);
640
+ this.formState.saving = false;
641
+ this.formState.message = `Added "${name}" \u2014 ${String(tools.length)} tools`;
642
+ this.onRefresh();
643
+ }
644
+ catch (err) {
645
+ this.formState.saving = false;
646
+ this.formState.message = `Failed: ${err instanceof Error ? err.message : 'Unknown error'}`;
647
+ this.onRefresh();
648
+ }
649
+ })();
650
+ return stay(true);
651
+ }
652
+ }
653
+ // =============================================================================
654
+ // Helpers
655
+ // =============================================================================
656
+ function formatStatus(status, s) {
657
+ switch (status) {
658
+ case 'connected':
659
+ return s.success('connected');
660
+ case 'connecting':
661
+ return s.warning('connecting');
662
+ case 'error':
663
+ return s.error('error');
664
+ case 'disconnected':
665
+ return s.muted('disconnected');
666
+ default:
667
+ return s.muted(status);
668
+ }
669
+ }
670
+ async function buildServerItems(manager) {
671
+ const items = [];
672
+ for (const client of manager.getServers()) {
673
+ let tools = [];
674
+ try {
675
+ if (client.isConnected) {
676
+ tools = await client.listTools();
677
+ }
678
+ }
679
+ catch {
680
+ // Failed to list tools — show 0
681
+ }
682
+ // Determine transport info from the client name
683
+ // We don't have direct access to config, so use what we can
684
+ const transport = client.isConnected ? 'stdio/http' : 'unknown';
685
+ items.push({
686
+ tabId: 'all',
687
+ name: client.name,
688
+ status: client.status,
689
+ transport,
690
+ transportDetail: '',
691
+ toolCount: tools.length,
692
+ tools,
693
+ client,
694
+ });
695
+ }
696
+ return items;
697
+ }
698
+ // =============================================================================
699
+ // MCP Overlay V2
700
+ // =============================================================================
701
+ export class MCPOverlayV2 extends TabbedListOverlayV2 {
702
+ type = 'inline';
703
+ id = 'mcp-overlay-v2';
704
+ manager;
705
+ agent;
706
+ getManager;
707
+ projectRoot;
708
+ initialized = false;
709
+ listMessage = null;
710
+ constructor(manager, agent, getManager, projectRoot) {
711
+ const tabs = [
712
+ { id: 'all', label: 'All' },
713
+ ];
714
+ super({
715
+ title: 'MCP Servers',
716
+ tabs,
717
+ items: [],
718
+ pageSize: PAGE_SIZE,
719
+ filterByTab: () => true,
720
+ getSearchText: (item) => `${item.name} ${item.status} ${item.tools.map((t) => t.name).join(' ')}`,
721
+ renderItem: (item, isSelected, styles) => {
722
+ const prefix = isSelected ? styles.primary(' \u25ba ') : ' ';
723
+ const namePadded = item.name.padEnd(20);
724
+ const statusPadded = formatStatus(item.status, styles).padEnd(20);
725
+ const toolInfo = item.status === 'connected'
726
+ ? styles.muted(`${String(item.toolCount)} tools`)
727
+ : styles.muted('\u2014');
728
+ const name = isSelected ? styles.primary(namePadded) : namePadded;
729
+ return `${prefix}${name} ${statusPadded} ${toolInfo}`;
730
+ },
731
+ footerHints: (searchMode) => {
732
+ if (searchMode) {
733
+ return 'Type to filter \u00b7 \u2191\u2193/jk Navigate \u00b7 Enter Details \u00b7 Esc Exit search';
734
+ }
735
+ return '\u2191\u2193/jk \u00b7 / Search \u00b7 Enter Details \u00b7 a Add \u00b7 r Restart \u00b7 d Disconnect \u00b7 q/Esc Close';
736
+ },
737
+ emptyMessage: '', // We handle empty state in render()
738
+ noResultsMessage: 'No servers match the search.',
739
+ showCount: false,
740
+ });
741
+ this.manager = manager;
742
+ this.agent = agent;
743
+ this.getManager = getManager;
744
+ this.projectRoot = projectRoot;
745
+ this.minHeight = 18;
746
+ }
747
+ /**
748
+ * Load server data on first render.
749
+ */
750
+ async loadItems() {
751
+ if (this.initialized)
752
+ return;
753
+ this.initialized = true;
754
+ if (!this.manager)
755
+ return;
756
+ const items = await buildServerItems(this.manager);
757
+ this.state.items = items;
758
+ this.state.filteredItems = [...items];
759
+ }
760
+ /**
761
+ * Override render to load items on first call and handle empty state.
762
+ */
763
+ render(context) {
764
+ this.styles = context.styles;
765
+ this.termWidth = context.width;
766
+ // Async load — render loading state first, then re-render
767
+ if (!this.initialized) {
768
+ void this.loadItems().then(() => {
769
+ this.renderCallback?.();
770
+ });
771
+ const s = this.getStyles();
772
+ const border = renderBorder(context.width, s);
773
+ return {
774
+ lines: [
775
+ border,
776
+ ` ${s.primaryBold('MCP Servers')}`,
777
+ '',
778
+ ` ${s.muted('Loading...')}`,
779
+ '',
780
+ border,
781
+ s.muted(' q/Esc Close'),
782
+ ],
783
+ minHeight: 18,
784
+ };
785
+ }
786
+ // Empty state — show config instructions (but allow 'a' to add)
787
+ if (this.state.items.length === 0 && this.screenStack.size() <= 1) {
788
+ return this.renderEmptyState(context);
789
+ }
790
+ // Inject list message if present (shown after add)
791
+ const result = super.render(context);
792
+ if (this.listMessage) {
793
+ const s = this.getStyles();
794
+ // Insert message before the footer border
795
+ const msg = ` ${s.success(this.listMessage)}`;
796
+ result.lines.splice(-3, 0, msg);
797
+ // Clear message after a brief display
798
+ setTimeout(() => {
799
+ this.listMessage = null;
800
+ this.renderCallback?.();
801
+ }, 3000);
802
+ }
803
+ return result;
804
+ }
805
+ /**
806
+ * Render helpful empty state with config file instructions.
807
+ */
808
+ renderEmptyState(context) {
809
+ const s = this.getStyles();
810
+ const border = renderBorder(context.width, s);
811
+ const configPath = getMCPConfigPath();
812
+ const lines = [
813
+ border,
814
+ ` ${s.primaryBold('MCP Servers')} ${s.muted('(0 configured)')}`,
815
+ '',
816
+ ` ${s.muted('No MCP servers configured.')}`,
817
+ '',
818
+ ` ${s.secondary('Press')} ${s.primary('a')} ${s.secondary('to add a server, or edit the config file:')}`,
819
+ ` ${s.muted(configPath)}`,
820
+ '',
821
+ ` ${s.muted('{')}`,
822
+ ` ${s.muted(' "mcpServers": {')}`,
823
+ ` ${s.muted(' "filesystem": {')}`,
824
+ ` ${s.muted(' "command": "npx",')}`,
825
+ ` ${s.muted(' "args": ["-y", "@modelcontextprotocol/server-filesystem", "/tmp"]')}`,
826
+ ` ${s.muted(' }')}`,
827
+ ` ${s.muted(' }')}`,
828
+ ` ${s.muted('}')}`,
829
+ '',
830
+ border,
831
+ s.muted(' a Add \u00b7 q/Esc Close'),
832
+ ];
833
+ return { lines, minHeight: 18 };
834
+ }
835
+ /**
836
+ * Handle custom keys (a/r/d) on the list screen.
837
+ * Only intercepts when the screen stack is at the root list screen.
838
+ */
839
+ handleKey(key) {
840
+ const char = key.raw.toString();
841
+ // Only handle custom keys when on the list screen (not on detail/add screens)
842
+ if (this.screenStack.size() <= 1 && !this.state.searchMode) {
843
+ // Add server
844
+ if (char === 'a') {
845
+ const styles = this.getStyles();
846
+ const addScreen = new AddServerScreen(this.agent, this.getManager, styles, () => this.termWidth, (newItem) => {
847
+ // Callback: add new server to list, refresh
848
+ this.state.items.push(newItem);
849
+ this.state.filteredItems = [...this.state.items];
850
+ }, () => {
851
+ this.renderCallback?.();
852
+ }, this.projectRoot);
853
+ this.screenStack.push(addScreen);
854
+ return this.rerender();
855
+ }
856
+ // Restart/disconnect only when items exist
857
+ if (this.state.filteredItems.length > 0) {
858
+ const selectedItem = this.state.filteredItems[this.state.selectedIndex];
859
+ // Restart selected server
860
+ if (char === 'r') {
861
+ void (async () => {
862
+ try {
863
+ const client = selectedItem.client;
864
+ await client.disconnect();
865
+ await client.connect();
866
+ const tools = await client.listTools();
867
+ selectedItem.tools = tools;
868
+ selectedItem.toolCount = tools.length;
869
+ selectedItem.status = client.status;
870
+ }
871
+ catch {
872
+ selectedItem.status = selectedItem.client.status;
873
+ }
874
+ this.renderCallback?.();
875
+ })();
876
+ return this.rerender();
877
+ }
878
+ // Disconnect selected server
879
+ if (char === 'd') {
880
+ void (async () => {
881
+ try {
882
+ await selectedItem.client.disconnect();
883
+ selectedItem.tools = [];
884
+ selectedItem.toolCount = 0;
885
+ selectedItem.status = 'disconnected';
886
+ }
887
+ catch {
888
+ selectedItem.status = selectedItem.client.status;
889
+ }
890
+ this.renderCallback?.();
891
+ })();
892
+ return this.rerender();
893
+ }
894
+ }
895
+ }
896
+ return super.handleKey(key);
897
+ }
898
+ createDetailScreen(item) {
899
+ if (!this.manager)
900
+ return null;
901
+ const styles = this.getStyles();
902
+ return new ServerDetailScreen(item, this.manager, styles, () => this.termWidth, () => {
903
+ // Refresh list items after restart/disconnect in detail screen
904
+ this.renderCallback?.();
905
+ });
906
+ }
907
+ }