@butlerw/vellum 0.1.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 (446) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +411 -0
  3. package/__fixtures__/responses/code-generation.json +42 -0
  4. package/__fixtures__/responses/error-response.json +20 -0
  5. package/__fixtures__/responses/hello-world.json +32 -0
  6. package/dist/auth-6MCXESOH.js +26 -0
  7. package/dist/chunk-SECXJGWA.js +597 -0
  8. package/dist/index.js +34023 -0
  9. package/package.json +67 -0
  10. package/src/__tests__/commands.e2e.test.ts +728 -0
  11. package/src/__tests__/credentials.test.ts +713 -0
  12. package/src/__tests__/mode-e2e.test.ts +391 -0
  13. package/src/__tests__/tui-integration.test.tsx +1271 -0
  14. package/src/agents/__tests__/task-persistence.test.ts +235 -0
  15. package/src/agents/commands/delegate.ts +240 -0
  16. package/src/agents/commands/index.ts +10 -0
  17. package/src/agents/commands/resume.ts +335 -0
  18. package/src/agents/index.ts +29 -0
  19. package/src/agents/task-persistence.ts +272 -0
  20. package/src/agents/task-resumption.ts +242 -0
  21. package/src/app.tsx +4737 -0
  22. package/src/commands/__tests__/.gitkeep +1 -0
  23. package/src/commands/__tests__/agents.test.ts +606 -0
  24. package/src/commands/__tests__/auth.test.ts +626 -0
  25. package/src/commands/__tests__/autocomplete.test.ts +683 -0
  26. package/src/commands/__tests__/batch.test.ts +287 -0
  27. package/src/commands/__tests__/chain-pipe-parser.test.ts +654 -0
  28. package/src/commands/__tests__/completion.test.ts +238 -0
  29. package/src/commands/__tests__/core.test.ts +363 -0
  30. package/src/commands/__tests__/executor.test.ts +496 -0
  31. package/src/commands/__tests__/exit-codes.test.ts +220 -0
  32. package/src/commands/__tests__/init.test.ts +243 -0
  33. package/src/commands/__tests__/language.test.ts +353 -0
  34. package/src/commands/__tests__/mode-cli.test.ts +667 -0
  35. package/src/commands/__tests__/model.test.ts +277 -0
  36. package/src/commands/__tests__/parser.test.ts +493 -0
  37. package/src/commands/__tests__/performance.bench.ts +380 -0
  38. package/src/commands/__tests__/registry.test.ts +534 -0
  39. package/src/commands/__tests__/resume.test.ts +449 -0
  40. package/src/commands/__tests__/security.test.ts +845 -0
  41. package/src/commands/__tests__/stream-json.test.ts +372 -0
  42. package/src/commands/__tests__/user-commands.test.ts +597 -0
  43. package/src/commands/adapters.ts +267 -0
  44. package/src/commands/agent.ts +395 -0
  45. package/src/commands/agents/generate.ts +506 -0
  46. package/src/commands/agents/index.ts +272 -0
  47. package/src/commands/agents/show.ts +271 -0
  48. package/src/commands/agents/validate.ts +387 -0
  49. package/src/commands/auth.ts +883 -0
  50. package/src/commands/autocomplete.ts +480 -0
  51. package/src/commands/batch/command.ts +388 -0
  52. package/src/commands/batch/executor.ts +361 -0
  53. package/src/commands/batch/index.ts +12 -0
  54. package/src/commands/commit.ts +235 -0
  55. package/src/commands/completion/index.ts +371 -0
  56. package/src/commands/condense.ts +191 -0
  57. package/src/commands/config.ts +344 -0
  58. package/src/commands/context-provider.ts +173 -0
  59. package/src/commands/copy.ts +329 -0
  60. package/src/commands/core/clear.ts +38 -0
  61. package/src/commands/core/exit.ts +43 -0
  62. package/src/commands/core/help.ts +354 -0
  63. package/src/commands/core/index.ts +15 -0
  64. package/src/commands/cost.ts +179 -0
  65. package/src/commands/credentials.tsx +618 -0
  66. package/src/commands/custom-agents/__tests__/custom-agents.test.ts +709 -0
  67. package/src/commands/custom-agents/create.ts +377 -0
  68. package/src/commands/custom-agents/export.ts +135 -0
  69. package/src/commands/custom-agents/import.ts +199 -0
  70. package/src/commands/custom-agents/index.ts +372 -0
  71. package/src/commands/custom-agents/info.ts +318 -0
  72. package/src/commands/custom-agents/list.ts +267 -0
  73. package/src/commands/custom-agents/validate.ts +388 -0
  74. package/src/commands/diff-mode.ts +241 -0
  75. package/src/commands/env.ts +53 -0
  76. package/src/commands/executor.ts +579 -0
  77. package/src/commands/exit-codes.ts +202 -0
  78. package/src/commands/index.ts +701 -0
  79. package/src/commands/init/index.ts +15 -0
  80. package/src/commands/init/prompts.ts +366 -0
  81. package/src/commands/init/templates/commands-readme.md +80 -0
  82. package/src/commands/init/templates/example-command.md +79 -0
  83. package/src/commands/init/templates/example-skill.md +168 -0
  84. package/src/commands/init/templates/example-workflow.md +101 -0
  85. package/src/commands/init/templates/prompts-readme.md +52 -0
  86. package/src/commands/init/templates/rules-readme.md +63 -0
  87. package/src/commands/init/templates/skills-readme.md +83 -0
  88. package/src/commands/init/templates/workflows-readme.md +94 -0
  89. package/src/commands/init.ts +391 -0
  90. package/src/commands/install.ts +90 -0
  91. package/src/commands/language.ts +191 -0
  92. package/src/commands/loaders/.gitkeep +1 -0
  93. package/src/commands/lsp.ts +199 -0
  94. package/src/commands/markdown-commands.ts +253 -0
  95. package/src/commands/mcp.ts +588 -0
  96. package/src/commands/memory/export.ts +341 -0
  97. package/src/commands/memory/index.ts +148 -0
  98. package/src/commands/memory/list.ts +261 -0
  99. package/src/commands/memory/search.ts +346 -0
  100. package/src/commands/memory/utils.ts +15 -0
  101. package/src/commands/metrics.ts +75 -0
  102. package/src/commands/migrate/index.ts +16 -0
  103. package/src/commands/migrate/prompts.ts +477 -0
  104. package/src/commands/mode.ts +331 -0
  105. package/src/commands/model.ts +298 -0
  106. package/src/commands/onboard.ts +205 -0
  107. package/src/commands/open.ts +169 -0
  108. package/src/commands/output/stream-json.ts +373 -0
  109. package/src/commands/parser/chain-parser.ts +370 -0
  110. package/src/commands/parser/index.ts +29 -0
  111. package/src/commands/parser/pipe-parser.ts +480 -0
  112. package/src/commands/parser.ts +588 -0
  113. package/src/commands/persistence.ts +355 -0
  114. package/src/commands/progress.ts +18 -0
  115. package/src/commands/prompt/index.ts +17 -0
  116. package/src/commands/prompt/validate.ts +621 -0
  117. package/src/commands/prompt-priority.ts +401 -0
  118. package/src/commands/registry.ts +374 -0
  119. package/src/commands/sandbox/index.ts +131 -0
  120. package/src/commands/security/index.ts +21 -0
  121. package/src/commands/security/input-sanitizer.ts +168 -0
  122. package/src/commands/security/permission-checker.ts +456 -0
  123. package/src/commands/security/sensitive-data.ts +350 -0
  124. package/src/commands/session/delete.ts +38 -0
  125. package/src/commands/session/export.ts +39 -0
  126. package/src/commands/session/index.ts +26 -0
  127. package/src/commands/session/list.ts +26 -0
  128. package/src/commands/session/resume.ts +562 -0
  129. package/src/commands/session/search.ts +434 -0
  130. package/src/commands/session/show.ts +26 -0
  131. package/src/commands/settings.ts +368 -0
  132. package/src/commands/setup.ts +23 -0
  133. package/src/commands/shell/index.ts +16 -0
  134. package/src/commands/shell/setup.ts +422 -0
  135. package/src/commands/shell-init.ts +50 -0
  136. package/src/commands/shell-integration/index.ts +194 -0
  137. package/src/commands/skill.ts +1220 -0
  138. package/src/commands/spec.ts +558 -0
  139. package/src/commands/status.ts +246 -0
  140. package/src/commands/theme.ts +211 -0
  141. package/src/commands/think.ts +551 -0
  142. package/src/commands/trust.ts +211 -0
  143. package/src/commands/tutorial.ts +522 -0
  144. package/src/commands/types.ts +512 -0
  145. package/src/commands/update.ts +274 -0
  146. package/src/commands/usage.ts +213 -0
  147. package/src/commands/user-commands.ts +630 -0
  148. package/src/commands/utils.ts +142 -0
  149. package/src/commands/vim.ts +152 -0
  150. package/src/commands/workflow.ts +257 -0
  151. package/src/components/header.tsx +25 -0
  152. package/src/components/input.tsx +25 -0
  153. package/src/components/message-list.tsx +32 -0
  154. package/src/components/status-bar.tsx +23 -0
  155. package/src/index.tsx +614 -0
  156. package/src/onboarding/__tests__/tutorial.test.ts +740 -0
  157. package/src/onboarding/index.ts +69 -0
  158. package/src/onboarding/tips/index.ts +9 -0
  159. package/src/onboarding/tips/tip-engine.ts +459 -0
  160. package/src/onboarding/tutorial/index.ts +88 -0
  161. package/src/onboarding/tutorial/lessons/basics.ts +151 -0
  162. package/src/onboarding/tutorial/lessons/index.ts +151 -0
  163. package/src/onboarding/tutorial/lessons/modes.ts +230 -0
  164. package/src/onboarding/tutorial/lessons/tools.ts +172 -0
  165. package/src/onboarding/tutorial/progress-tracker.ts +350 -0
  166. package/src/onboarding/tutorial/storage.ts +249 -0
  167. package/src/onboarding/tutorial/tutorial-system.ts +462 -0
  168. package/src/onboarding/tutorial/types.ts +310 -0
  169. package/src/orchestrator-singleton.ts +129 -0
  170. package/src/shutdown.ts +33 -0
  171. package/src/test/e2e/assertions.ts +267 -0
  172. package/src/test/e2e/fixtures.ts +204 -0
  173. package/src/test/e2e/harness.ts +575 -0
  174. package/src/test/e2e/index.ts +57 -0
  175. package/src/test/e2e/types.ts +228 -0
  176. package/src/test/fixtures/__tests__/fake-response-loader.test.ts +314 -0
  177. package/src/test/fixtures/fake-response-loader.ts +314 -0
  178. package/src/test/fixtures/index.ts +20 -0
  179. package/src/tui/__tests__/mcp-panel.test.tsx +82 -0
  180. package/src/tui/__tests__/mcp-wiring.test.tsx +78 -0
  181. package/src/tui/__tests__/mode-components.test.tsx +395 -0
  182. package/src/tui/__tests__/permission-ask-flow.test.tsx +138 -0
  183. package/src/tui/__tests__/sidebar-panel-data.test.tsx +148 -0
  184. package/src/tui/__tests__/tools-panel-hotkeys.test.tsx +41 -0
  185. package/src/tui/adapters/agent-adapter.ts +1008 -0
  186. package/src/tui/adapters/index.ts +48 -0
  187. package/src/tui/adapters/message-adapter.ts +315 -0
  188. package/src/tui/adapters/persistence-bridge.ts +331 -0
  189. package/src/tui/adapters/session-adapter.ts +419 -0
  190. package/src/tui/buffered-stdout.ts +223 -0
  191. package/src/tui/components/AgentProgress.tsx +424 -0
  192. package/src/tui/components/Banner/AsciiArt.ts +160 -0
  193. package/src/tui/components/Banner/Banner.tsx +355 -0
  194. package/src/tui/components/Banner/ShimmerContext.tsx +131 -0
  195. package/src/tui/components/Banner/ShimmerText.tsx +193 -0
  196. package/src/tui/components/Banner/TypeWriterGradient.tsx +321 -0
  197. package/src/tui/components/Banner/index.ts +61 -0
  198. package/src/tui/components/Banner/useShimmer.ts +241 -0
  199. package/src/tui/components/ChatView.tsx +11 -0
  200. package/src/tui/components/Checkpoint/CheckpointDiffView.tsx +371 -0
  201. package/src/tui/components/Checkpoint/SnapshotCheckpointPanel.tsx +440 -0
  202. package/src/tui/components/Checkpoint/index.ts +19 -0
  203. package/src/tui/components/CostDisplay.tsx +226 -0
  204. package/src/tui/components/InitErrorBanner.tsx +122 -0
  205. package/src/tui/components/Input/Autocomplete.tsx +603 -0
  206. package/src/tui/components/Input/EnhancedCommandInput.tsx +471 -0
  207. package/src/tui/components/Input/HighlightedText.tsx +236 -0
  208. package/src/tui/components/Input/MentionAutocomplete.tsx +375 -0
  209. package/src/tui/components/Input/TextInput.tsx +1002 -0
  210. package/src/tui/components/Input/__tests__/Autocomplete.test.tsx +374 -0
  211. package/src/tui/components/Input/__tests__/TextInput.test.tsx +241 -0
  212. package/src/tui/components/Input/__tests__/highlight.test.ts +219 -0
  213. package/src/tui/components/Input/__tests__/slash-command-utils.test.ts +104 -0
  214. package/src/tui/components/Input/highlight.ts +362 -0
  215. package/src/tui/components/Input/index.ts +36 -0
  216. package/src/tui/components/Input/slash-command-utils.ts +135 -0
  217. package/src/tui/components/Layout.tsx +432 -0
  218. package/src/tui/components/McpPanel.tsx +137 -0
  219. package/src/tui/components/MemoryPanel.tsx +448 -0
  220. package/src/tui/components/Messages/CodeBlock.tsx +527 -0
  221. package/src/tui/components/Messages/DiffView.tsx +679 -0
  222. package/src/tui/components/Messages/ImageReference.tsx +89 -0
  223. package/src/tui/components/Messages/MarkdownBlock.tsx +228 -0
  224. package/src/tui/components/Messages/MarkdownRenderer.tsx +498 -0
  225. package/src/tui/components/Messages/MessageBubble.tsx +270 -0
  226. package/src/tui/components/Messages/MessageList.tsx +1719 -0
  227. package/src/tui/components/Messages/StreamingText.tsx +216 -0
  228. package/src/tui/components/Messages/ThinkingBlock.tsx +408 -0
  229. package/src/tui/components/Messages/ToolResultPreview.tsx +243 -0
  230. package/src/tui/components/Messages/__tests__/CodeBlock.test.tsx +296 -0
  231. package/src/tui/components/Messages/__tests__/DiffView.test.tsx +239 -0
  232. package/src/tui/components/Messages/__tests__/MarkdownRenderer.test.tsx +303 -0
  233. package/src/tui/components/Messages/__tests__/MessageBubble.test.tsx +268 -0
  234. package/src/tui/components/Messages/__tests__/MessageList.test.tsx +324 -0
  235. package/src/tui/components/Messages/__tests__/StreamingText.test.tsx +215 -0
  236. package/src/tui/components/Messages/index.ts +25 -0
  237. package/src/tui/components/ModeIndicator.tsx +177 -0
  238. package/src/tui/components/ModeSelector.tsx +216 -0
  239. package/src/tui/components/ModelSelector.tsx +339 -0
  240. package/src/tui/components/OnboardingWizard.tsx +670 -0
  241. package/src/tui/components/PhaseProgressIndicator.tsx +270 -0
  242. package/src/tui/components/RateLimitIndicator.tsx +82 -0
  243. package/src/tui/components/ScreenReaderLayout.tsx +295 -0
  244. package/src/tui/components/SettingsPanel.tsx +643 -0
  245. package/src/tui/components/Sidebar/SystemStatusPanel.tsx +284 -0
  246. package/src/tui/components/Sidebar/index.ts +9 -0
  247. package/src/tui/components/Status/ModelStatusBar.tsx +270 -0
  248. package/src/tui/components/Status/index.ts +12 -0
  249. package/src/tui/components/StatusBar/AgentModeIndicator.tsx +257 -0
  250. package/src/tui/components/StatusBar/ContextProgress.tsx +167 -0
  251. package/src/tui/components/StatusBar/FileChangesIndicator.tsx +62 -0
  252. package/src/tui/components/StatusBar/GitIndicator.tsx +89 -0
  253. package/src/tui/components/StatusBar/HeaderBar.tsx +126 -0
  254. package/src/tui/components/StatusBar/ModelIndicator.tsx +157 -0
  255. package/src/tui/components/StatusBar/PersistenceStatusIndicator.tsx +210 -0
  256. package/src/tui/components/StatusBar/ResilienceIndicator.tsx +106 -0
  257. package/src/tui/components/StatusBar/SandboxIndicator.tsx +167 -0
  258. package/src/tui/components/StatusBar/StatusBar.tsx +368 -0
  259. package/src/tui/components/StatusBar/ThinkingModeIndicator.tsx +170 -0
  260. package/src/tui/components/StatusBar/TokenBreakdown.tsx +246 -0
  261. package/src/tui/components/StatusBar/TokenCounter.tsx +135 -0
  262. package/src/tui/components/StatusBar/TrustModeIndicator.tsx +130 -0
  263. package/src/tui/components/StatusBar/WorkspaceIndicator.tsx +86 -0
  264. package/src/tui/components/StatusBar/__tests__/AgentModeIndicator.test.tsx +193 -0
  265. package/src/tui/components/StatusBar/__tests__/StatusBar.test.tsx +729 -0
  266. package/src/tui/components/StatusBar/index.ts +60 -0
  267. package/src/tui/components/TipBanner.tsx +115 -0
  268. package/src/tui/components/TodoItem.tsx +208 -0
  269. package/src/tui/components/TodoPanel.tsx +455 -0
  270. package/src/tui/components/Tools/ApprovalQueue.tsx +407 -0
  271. package/src/tui/components/Tools/OptionSelector.tsx +160 -0
  272. package/src/tui/components/Tools/PermissionDialog.tsx +286 -0
  273. package/src/tui/components/Tools/ToolParams.tsx +483 -0
  274. package/src/tui/components/Tools/ToolsPanel.tsx +178 -0
  275. package/src/tui/components/Tools/__tests__/PermissionDialog.test.tsx +510 -0
  276. package/src/tui/components/Tools/__tests__/ToolParams.test.tsx +432 -0
  277. package/src/tui/components/Tools/index.ts +21 -0
  278. package/src/tui/components/TrustPrompt.tsx +279 -0
  279. package/src/tui/components/UpdateBanner.tsx +166 -0
  280. package/src/tui/components/VimModeIndicator.tsx +112 -0
  281. package/src/tui/components/backtrack/BacktrackControls.tsx +402 -0
  282. package/src/tui/components/backtrack/index.ts +13 -0
  283. package/src/tui/components/common/AutoApprovalStatus.tsx +251 -0
  284. package/src/tui/components/common/CostWarning.tsx +294 -0
  285. package/src/tui/components/common/DynamicShortcutHints.tsx +209 -0
  286. package/src/tui/components/common/EnhancedLoadingIndicator.tsx +305 -0
  287. package/src/tui/components/common/ErrorBoundary.tsx +140 -0
  288. package/src/tui/components/common/GradientText.tsx +224 -0
  289. package/src/tui/components/common/HotkeyHelpModal.tsx +193 -0
  290. package/src/tui/components/common/HotkeyHints.tsx +70 -0
  291. package/src/tui/components/common/MaxSizedBox.tsx +354 -0
  292. package/src/tui/components/common/NewMessagesBadge.tsx +65 -0
  293. package/src/tui/components/common/ProtectedFileLegend.tsx +89 -0
  294. package/src/tui/components/common/ScrollIndicator.tsx +160 -0
  295. package/src/tui/components/common/Spinner.tsx +342 -0
  296. package/src/tui/components/common/StreamingIndicator.tsx +316 -0
  297. package/src/tui/components/common/VirtualizedList/VirtualizedList.tsx +428 -0
  298. package/src/tui/components/common/VirtualizedList/hooks/index.ts +19 -0
  299. package/src/tui/components/common/VirtualizedList/hooks/useBatchedScroll.ts +64 -0
  300. package/src/tui/components/common/VirtualizedList/hooks/useScrollAnchor.ts +290 -0
  301. package/src/tui/components/common/VirtualizedList/hooks/useVirtualization.ts +340 -0
  302. package/src/tui/components/common/VirtualizedList/index.ts +30 -0
  303. package/src/tui/components/common/VirtualizedList/types.ts +107 -0
  304. package/src/tui/components/common/__tests__/NewMessagesBadge.test.tsx +74 -0
  305. package/src/tui/components/common/__tests__/ScrollIndicator.test.tsx +193 -0
  306. package/src/tui/components/common/index.ts +110 -0
  307. package/src/tui/components/index.ts +79 -0
  308. package/src/tui/components/session/CheckpointPanel.tsx +323 -0
  309. package/src/tui/components/session/RollbackDialog.tsx +169 -0
  310. package/src/tui/components/session/SessionItem.tsx +136 -0
  311. package/src/tui/components/session/SessionListPanel.tsx +252 -0
  312. package/src/tui/components/session/SessionPicker.tsx +449 -0
  313. package/src/tui/components/session/SessionPreview.tsx +240 -0
  314. package/src/tui/components/session/__tests__/session.test.tsx +408 -0
  315. package/src/tui/components/session/index.ts +28 -0
  316. package/src/tui/components/session/types.ts +116 -0
  317. package/src/tui/components/theme/__tests__/tokens.test.ts +471 -0
  318. package/src/tui/components/theme/index.ts +227 -0
  319. package/src/tui/components/theme/tokens.ts +484 -0
  320. package/src/tui/config/defaults.ts +134 -0
  321. package/src/tui/config/index.ts +17 -0
  322. package/src/tui/context/AnimationContext.tsx +284 -0
  323. package/src/tui/context/AppContext.tsx +349 -0
  324. package/src/tui/context/BracketedPasteContext.tsx +372 -0
  325. package/src/tui/context/LspContext.tsx +192 -0
  326. package/src/tui/context/McpContext.tsx +325 -0
  327. package/src/tui/context/MessagesContext.tsx +870 -0
  328. package/src/tui/context/OverflowContext.tsx +213 -0
  329. package/src/tui/context/RateLimitContext.tsx +108 -0
  330. package/src/tui/context/ResilienceContext.tsx +275 -0
  331. package/src/tui/context/RootProvider.tsx +136 -0
  332. package/src/tui/context/ScrollContext.tsx +331 -0
  333. package/src/tui/context/ToolsContext.tsx +702 -0
  334. package/src/tui/context/__tests__/BracketedPasteContext.test.tsx +416 -0
  335. package/src/tui/context/index.ts +140 -0
  336. package/src/tui/enterprise-integration.ts +282 -0
  337. package/src/tui/hooks/__tests__/useBacktrack.test.tsx +138 -0
  338. package/src/tui/hooks/__tests__/useBracketedPaste.test.tsx +222 -0
  339. package/src/tui/hooks/__tests__/useCopyMode.test.tsx +336 -0
  340. package/src/tui/hooks/__tests__/useHotkeys.ctrl-input.test.tsx +96 -0
  341. package/src/tui/hooks/__tests__/useHotkeys.test.tsx +454 -0
  342. package/src/tui/hooks/__tests__/useInputHistory.test.tsx +660 -0
  343. package/src/tui/hooks/__tests__/useLineBuffer.test.ts +295 -0
  344. package/src/tui/hooks/__tests__/useModeController.test.ts +137 -0
  345. package/src/tui/hooks/__tests__/useModeShortcuts.test.tsx +142 -0
  346. package/src/tui/hooks/__tests__/useScrollController.test.ts +464 -0
  347. package/src/tui/hooks/__tests__/useVim.test.tsx +531 -0
  348. package/src/tui/hooks/index.ts +252 -0
  349. package/src/tui/hooks/useAgentLoop.ts +712 -0
  350. package/src/tui/hooks/useAlternateBuffer.ts +398 -0
  351. package/src/tui/hooks/useAnimatedScrollbar.ts +241 -0
  352. package/src/tui/hooks/useBacktrack.ts +443 -0
  353. package/src/tui/hooks/useBracketedPaste.ts +104 -0
  354. package/src/tui/hooks/useCollapsible.ts +240 -0
  355. package/src/tui/hooks/useCopyMode.ts +382 -0
  356. package/src/tui/hooks/useCostSummary.ts +75 -0
  357. package/src/tui/hooks/useDesktopNotification.ts +414 -0
  358. package/src/tui/hooks/useDiffMode.ts +44 -0
  359. package/src/tui/hooks/useFileChangeStats.ts +110 -0
  360. package/src/tui/hooks/useFileSuggestions.ts +284 -0
  361. package/src/tui/hooks/useFlickerDetector.ts +250 -0
  362. package/src/tui/hooks/useGitStatus.ts +200 -0
  363. package/src/tui/hooks/useHotkeys.ts +579 -0
  364. package/src/tui/hooks/useImagePaste.ts +114 -0
  365. package/src/tui/hooks/useInputHighlight.ts +145 -0
  366. package/src/tui/hooks/useInputHistory.ts +246 -0
  367. package/src/tui/hooks/useKeyboardScroll.ts +209 -0
  368. package/src/tui/hooks/useLineBuffer.ts +356 -0
  369. package/src/tui/hooks/useMentionAutocomplete.ts +235 -0
  370. package/src/tui/hooks/useModeController.ts +167 -0
  371. package/src/tui/hooks/useModeShortcuts.ts +196 -0
  372. package/src/tui/hooks/usePermissionHandler.ts +146 -0
  373. package/src/tui/hooks/usePersistence.ts +480 -0
  374. package/src/tui/hooks/usePersistenceShortcuts.ts +225 -0
  375. package/src/tui/hooks/usePlaceholderRotation.ts +143 -0
  376. package/src/tui/hooks/useProviderStatus.ts +270 -0
  377. package/src/tui/hooks/useRateLimitStatus.ts +90 -0
  378. package/src/tui/hooks/useScreenReader.ts +315 -0
  379. package/src/tui/hooks/useScrollController.ts +450 -0
  380. package/src/tui/hooks/useScrollEventBatcher.ts +185 -0
  381. package/src/tui/hooks/useSidebarPanelData.ts +115 -0
  382. package/src/tui/hooks/useSmoothScroll.ts +202 -0
  383. package/src/tui/hooks/useSnapshots.ts +300 -0
  384. package/src/tui/hooks/useStateAndRef.ts +50 -0
  385. package/src/tui/hooks/useTerminalSize.ts +206 -0
  386. package/src/tui/hooks/useToolApprovalController.ts +91 -0
  387. package/src/tui/hooks/useVim.ts +334 -0
  388. package/src/tui/hooks/useWorkspace.ts +56 -0
  389. package/src/tui/i18n/__tests__/init.test.ts +278 -0
  390. package/src/tui/i18n/__tests__/language-config.test.ts +199 -0
  391. package/src/tui/i18n/__tests__/locale-detection.test.ts +250 -0
  392. package/src/tui/i18n/__tests__/settings-integration.test.ts +262 -0
  393. package/src/tui/i18n/index.ts +72 -0
  394. package/src/tui/i18n/init.ts +131 -0
  395. package/src/tui/i18n/language-config.ts +106 -0
  396. package/src/tui/i18n/locale-detection.ts +173 -0
  397. package/src/tui/i18n/settings-integration.ts +557 -0
  398. package/src/tui/i18n/tui-namespace.ts +538 -0
  399. package/src/tui/i18n/types.ts +312 -0
  400. package/src/tui/index.ts +43 -0
  401. package/src/tui/lsp-integration.ts +409 -0
  402. package/src/tui/metrics-integration.ts +366 -0
  403. package/src/tui/plugins.ts +383 -0
  404. package/src/tui/resilience.ts +342 -0
  405. package/src/tui/sandbox-integration.ts +317 -0
  406. package/src/tui/services/clipboard.ts +348 -0
  407. package/src/tui/services/fuzzy-search.ts +441 -0
  408. package/src/tui/services/index.ts +72 -0
  409. package/src/tui/services/markdown-renderer.ts +565 -0
  410. package/src/tui/services/open-external.ts +247 -0
  411. package/src/tui/services/syntax-highlighter.ts +483 -0
  412. package/src/tui/slash-commands.ts +12 -0
  413. package/src/tui/theme/index.ts +15 -0
  414. package/src/tui/theme/provider.tsx +206 -0
  415. package/src/tui/tip-integration.ts +300 -0
  416. package/src/tui/types/__tests__/ink-extended.test.ts +121 -0
  417. package/src/tui/types/ink-extended.ts +87 -0
  418. package/src/tui/utils/__tests__/bracketedPaste.test.ts +231 -0
  419. package/src/tui/utils/__tests__/heightEstimator.test.ts +157 -0
  420. package/src/tui/utils/__tests__/text-width.test.ts +158 -0
  421. package/src/tui/utils/__tests__/textSanitizer.test.ts +266 -0
  422. package/src/tui/utils/__tests__/ui-sizing.test.ts +169 -0
  423. package/src/tui/utils/bracketedPaste.ts +107 -0
  424. package/src/tui/utils/cursor-manager.ts +131 -0
  425. package/src/tui/utils/detectTerminal.ts +596 -0
  426. package/src/tui/utils/findLastSafeSplitPoint.ts +92 -0
  427. package/src/tui/utils/heightEstimator.ts +198 -0
  428. package/src/tui/utils/index.ts +91 -0
  429. package/src/tui/utils/isNarrowWidth.ts +52 -0
  430. package/src/tui/utils/stdoutGuard.ts +90 -0
  431. package/src/tui/utils/synchronized-update.ts +70 -0
  432. package/src/tui/utils/text-width.ts +225 -0
  433. package/src/tui/utils/textSanitizer.ts +225 -0
  434. package/src/tui/utils/textUtils.ts +114 -0
  435. package/src/tui/utils/ui-sizing.ts +192 -0
  436. package/src/tui-blessed/app.ts +160 -0
  437. package/src/tui-blessed/index.ts +2 -0
  438. package/src/tui-blessed/neo-blessed.d.ts +6 -0
  439. package/src/tui-blessed/test.ts +21 -0
  440. package/src/tui-blessed/types.ts +14 -0
  441. package/src/utils/icons.ts +130 -0
  442. package/src/utils/index.ts +33 -0
  443. package/src/utils/resume-hint.ts +86 -0
  444. package/src/version.ts +1 -0
  445. package/tsconfig.json +8 -0
  446. package/vitest.config.ts +35 -0
@@ -0,0 +1,588 @@
1
+ /**
2
+ * MCP Slash Commands (Phase 40)
3
+ *
4
+ * Provides slash commands for MCP (Model Context Protocol) server management:
5
+ * - /mcp list - List configured MCP servers
6
+ * - /mcp status - Show connection status and tool count
7
+ * - /mcp add - Add a new MCP server (interactive)
8
+ * - /mcp remove - Remove an MCP server
9
+ * - /mcp tools - List available tools from MCP servers
10
+ *
11
+ * @module cli/commands/mcp
12
+ */
13
+
14
+ import * as fs from "node:fs/promises";
15
+ import * as os from "node:os";
16
+ import * as path from "node:path";
17
+ import type { McpHub, McpServer, McpSettings, McpStdioConfig } from "@vellum/mcp";
18
+ import { ICONS } from "../utils/icons.js";
19
+ import type { CommandContext, CommandResult, SlashCommand } from "./types.js";
20
+ import { error, interactive, success } from "./types.js";
21
+
22
+ // =============================================================================
23
+ // Module State
24
+ // =============================================================================
25
+
26
+ /**
27
+ * Reference to the active McpHub instance.
28
+ * Set by the App component when initialized.
29
+ */
30
+ let mcpHub: McpHub | null = null;
31
+
32
+ /**
33
+ * Set the McpHub instance for MCP commands.
34
+ * Called by the App component during initialization.
35
+ *
36
+ * @param hub - The McpHub instance to use
37
+ */
38
+ export function setMcpCommandsHub(hub: McpHub | null): void {
39
+ mcpHub = hub;
40
+ }
41
+
42
+ /**
43
+ * Get the current McpHub instance.
44
+ * Returns null if not yet initialized.
45
+ */
46
+ export function getMcpCommandsHub(): McpHub | null {
47
+ return mcpHub;
48
+ }
49
+
50
+ // =============================================================================
51
+ // Status Helpers
52
+ // =============================================================================
53
+
54
+ /**
55
+ * Get text indicator for a server connection status.
56
+ */
57
+ function getStatusIndicator(status: string): string {
58
+ switch (status) {
59
+ case "connected":
60
+ return "[ON]";
61
+ case "connecting":
62
+ return "[...]";
63
+ case "disconnected":
64
+ return "[OFF]";
65
+ case "disabled":
66
+ return "[DIS]";
67
+ case "failed":
68
+ return ICONS.error;
69
+ case "needs_auth":
70
+ return "[Auth]";
71
+ case "needs_client_registration":
72
+ return "[Reg]";
73
+ default:
74
+ return "[?]";
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Format server info for list display.
80
+ */
81
+ function formatServerListItem(server: McpServer): string {
82
+ const indicator = getStatusIndicator(server.statusInfo.status);
83
+ const disabledTag = server.disabled ? " [disabled]" : "";
84
+ return ` ${indicator} ${server.name}${disabledTag}`;
85
+ }
86
+
87
+ /**
88
+ * Format detailed server status.
89
+ */
90
+ function formatServerStatus(server: McpServer): string {
91
+ const indicator = getStatusIndicator(server.statusInfo.status);
92
+ const toolCount = server.tools?.length ?? 0;
93
+ const resourceCount = server.resources?.length ?? 0;
94
+
95
+ const lines = [`${indicator} ${server.name}`, ` Status: ${server.statusInfo.status}`];
96
+
97
+ if (server.statusInfo.status === "failed" && "error" in server.statusInfo) {
98
+ lines.push(` Error: ${server.statusInfo.error}`);
99
+ }
100
+
101
+ if (server.statusInfo.status === "connected") {
102
+ lines.push(` Tools: ${toolCount}`);
103
+ lines.push(` Resources: ${resourceCount}`);
104
+ }
105
+
106
+ if (server.disabled) {
107
+ lines.push(" Note: Server is disabled in config");
108
+ }
109
+
110
+ if (server.uid) {
111
+ lines.push(` UID: ${server.uid}`);
112
+ }
113
+
114
+ return lines.join("\n");
115
+ }
116
+
117
+ // =============================================================================
118
+ // Subcommand Handlers
119
+ // =============================================================================
120
+
121
+ /**
122
+ * Handle /mcp list - List configured MCP servers
123
+ */
124
+ async function handleList(_ctx: CommandContext): Promise<CommandResult> {
125
+ if (!mcpHub) {
126
+ return error("OPERATION_NOT_ALLOWED", "MCP hub not initialized. No MCP servers available.", [
127
+ "/help mcp",
128
+ ]);
129
+ }
130
+
131
+ const servers = mcpHub.getServers();
132
+
133
+ if (servers.length === 0) {
134
+ return success(
135
+ "📡 No MCP servers configured.\n\n" + "Add servers to ~/.vellum/mcp.json or use /mcp add"
136
+ );
137
+ }
138
+
139
+ const lines = [
140
+ "📡 Configured MCP Servers",
141
+ "",
142
+ ...servers.map(formatServerListItem),
143
+ "",
144
+ `Total: ${servers.length} server(s)`,
145
+ "",
146
+ "Use /mcp status for detailed information.",
147
+ ];
148
+
149
+ return success(lines.join("\n"));
150
+ }
151
+
152
+ /**
153
+ * Handle /mcp status - Show connection status and tool count
154
+ */
155
+ async function handleStatus(ctx: CommandContext): Promise<CommandResult> {
156
+ if (!mcpHub) {
157
+ return error("OPERATION_NOT_ALLOWED", "MCP hub not initialized. No MCP servers available.", [
158
+ "/help mcp",
159
+ ]);
160
+ }
161
+
162
+ const serverName = ctx.parsedArgs.positional[1] as string | undefined;
163
+ const servers = mcpHub.getServers();
164
+
165
+ if (servers.length === 0) {
166
+ return success("📡 No MCP servers configured.");
167
+ }
168
+
169
+ // If specific server requested
170
+ if (serverName) {
171
+ const server = servers.find((s) => s.name === serverName);
172
+ if (!server) {
173
+ return error("RESOURCE_NOT_FOUND", `Server "${serverName}" not found.`, [
174
+ `Available servers: ${servers.map((s) => s.name).join(", ")}`,
175
+ ]);
176
+ }
177
+ return success(formatServerStatus(server));
178
+ }
179
+
180
+ // Show all servers
181
+ const connectedCount = servers.filter((s) => s.statusInfo.status === "connected").length;
182
+ const totalTools = servers.reduce((sum, s) => sum + (s.tools?.length ?? 0), 0);
183
+
184
+ const lines = [
185
+ "📡 MCP Server Status",
186
+ "",
187
+ ...servers.map(formatServerStatus),
188
+ "",
189
+ "─".repeat(40),
190
+ `Connected: ${connectedCount}/${servers.length}`,
191
+ `Total Tools: ${totalTools}`,
192
+ ];
193
+
194
+ return success(lines.join("\n"));
195
+ }
196
+
197
+ // =============================================================================
198
+ // Config File Helpers
199
+ // =============================================================================
200
+
201
+ /**
202
+ * Get the global MCP config file path.
203
+ * Uses ~/.vellum/mcp.json on all platforms.
204
+ */
205
+ function getGlobalMcpConfigPath(): string {
206
+ return path.join(os.homedir(), ".vellum", "mcp.json");
207
+ }
208
+
209
+ /**
210
+ * Get the project-level MCP config file path.
211
+ */
212
+ function getProjectMcpConfigPath(): string {
213
+ return path.join(process.cwd(), ".vellum", "mcp.json");
214
+ }
215
+
216
+ /**
217
+ * Read existing MCP config file or return empty config.
218
+ */
219
+ async function readMcpConfig(configPath: string): Promise<McpSettings> {
220
+ try {
221
+ const content = await fs.readFile(configPath, "utf-8");
222
+ return JSON.parse(content) as McpSettings;
223
+ } catch {
224
+ // File doesn't exist or invalid JSON - return empty config
225
+ return { mcpServers: {} };
226
+ }
227
+ }
228
+
229
+ /**
230
+ * Write MCP config to file, creating directories if needed.
231
+ */
232
+ async function writeMcpConfig(configPath: string, config: McpSettings): Promise<void> {
233
+ await fs.mkdir(path.dirname(configPath), { recursive: true });
234
+ await fs.writeFile(configPath, JSON.stringify(config, null, 2), "utf-8");
235
+ }
236
+
237
+ /**
238
+ * Handle /mcp add - Add a new MCP server (interactive)
239
+ */
240
+ async function handleAdd(_ctx: CommandContext): Promise<CommandResult> {
241
+ if (!mcpHub) {
242
+ return error("OPERATION_NOT_ALLOWED", "MCP hub not initialized.", ["/help mcp"]);
243
+ }
244
+
245
+ // Interactive flow: collect server name
246
+ return interactive({
247
+ inputType: "text",
248
+ message: "[MCP] Enter server name:",
249
+ placeholder: "my-mcp-server",
250
+ handler: async (serverName: string): Promise<CommandResult> => {
251
+ if (!serverName.trim()) {
252
+ return error("INVALID_ARGUMENT", "Server name cannot be empty.", []);
253
+ }
254
+
255
+ // Check if server already exists
256
+ const existing = mcpHub?.getServer(serverName);
257
+ if (existing) {
258
+ return error("INVALID_ARGUMENT", `Server "${serverName}" already exists.`, [
259
+ `/mcp remove ${serverName}`,
260
+ ]);
261
+ }
262
+
263
+ // Collect command
264
+ return interactive({
265
+ inputType: "text",
266
+ message: `${ICONS.package} Enter command to run:`,
267
+ placeholder: "npx -y @my-org/mcp-server",
268
+ handler: async (command: string): Promise<CommandResult> => {
269
+ if (!command.trim()) {
270
+ return error("INVALID_ARGUMENT", "Command cannot be empty.", []);
271
+ }
272
+
273
+ // Parse command into parts
274
+ const parts = command.trim().split(/\s+/);
275
+ const cmd = parts[0] ?? "";
276
+ const args = parts.slice(1);
277
+
278
+ const serverConfig: McpStdioConfig = {
279
+ command: cmd,
280
+ args: args.length > 0 ? args : undefined,
281
+ };
282
+
283
+ // Ask where to save
284
+ return interactive({
285
+ inputType: "select",
286
+ message: "Where do you want to save this configuration?",
287
+ options: [
288
+ "Save to global config (~/.vellum/mcp.json)",
289
+ "Save to project config (.vellum/mcp.json)",
290
+ "Just show me the JSON (manual)",
291
+ ],
292
+ handler: async (choice: string): Promise<CommandResult> => {
293
+ // Determine save location based on selection
294
+ const isGlobal = choice.includes("global");
295
+ const isProject = choice.includes("project");
296
+ const isManual = choice.includes("manual") || choice.includes("JSON");
297
+
298
+ // Manual mode - just output JSON (backward compatible)
299
+ if (isManual) {
300
+ const configDisplay = {
301
+ [serverName]: serverConfig,
302
+ };
303
+ const configJson = JSON.stringify(configDisplay, null, 2);
304
+
305
+ return success(
306
+ `${ICONS.success} Server configuration ready!\n\n` +
307
+ "Add this to your ~/.vellum/mcp.json:\n\n" +
308
+ "```json\n" +
309
+ `"mcpServers": ${configJson}\n` +
310
+ "```\n\n" +
311
+ "After adding, the server will be auto-detected.\n" +
312
+ "Or restart Vellum to connect."
313
+ );
314
+ }
315
+
316
+ // Determine config path
317
+ const configPath = isGlobal
318
+ ? getGlobalMcpConfigPath()
319
+ : isProject
320
+ ? getProjectMcpConfigPath()
321
+ : getGlobalMcpConfigPath(); // Default to global
322
+
323
+ try {
324
+ // Read existing config
325
+ const existingConfig = await readMcpConfig(configPath);
326
+
327
+ // Merge new server
328
+ existingConfig.mcpServers = {
329
+ ...existingConfig.mcpServers,
330
+ [serverName]: serverConfig,
331
+ };
332
+
333
+ // Write back
334
+ await writeMcpConfig(configPath, existingConfig);
335
+
336
+ return success(
337
+ `${ICONS.success} Server "${serverName}" added to ${configPath}\n\n` +
338
+ "The server will be auto-detected.\n" +
339
+ "Use /mcp status to check connection status."
340
+ );
341
+ } catch (err) {
342
+ const message = err instanceof Error ? err.message : String(err);
343
+ return error("INTERNAL_ERROR", `Failed to write config file: ${message}`, [
344
+ "Check file permissions",
345
+ "Try the manual option instead",
346
+ ]);
347
+ }
348
+ },
349
+ onCancel: () => success("Server addition cancelled."),
350
+ });
351
+ },
352
+ onCancel: () => success("Server addition cancelled."),
353
+ });
354
+ },
355
+ onCancel: () => success("Server addition cancelled."),
356
+ });
357
+ }
358
+
359
+ /**
360
+ * Handle /mcp remove - Remove an MCP server
361
+ */
362
+ async function handleRemove(ctx: CommandContext): Promise<CommandResult> {
363
+ if (!mcpHub) {
364
+ return error("OPERATION_NOT_ALLOWED", "MCP hub not initialized.", ["/help mcp"]);
365
+ }
366
+
367
+ const serverName = ctx.parsedArgs.positional[1] as string | undefined;
368
+
369
+ if (!serverName) {
370
+ const servers = mcpHub.getServers();
371
+ if (servers.length === 0) {
372
+ return error("RESOURCE_NOT_FOUND", "No MCP servers configured.", []);
373
+ }
374
+
375
+ return error("MISSING_ARGUMENT", "Please specify a server name to remove.", [
376
+ `Usage: /mcp remove <server-name>`,
377
+ `Available: ${servers.map((s) => s.name).join(", ")}`,
378
+ ]);
379
+ }
380
+
381
+ const server = mcpHub.getServer(serverName);
382
+ if (!server) {
383
+ return error("RESOURCE_NOT_FOUND", `Server "${serverName}" not found.`, [
384
+ `Use /mcp list to see available servers.`,
385
+ ]);
386
+ }
387
+
388
+ // Confirm removal
389
+ return interactive({
390
+ inputType: "confirm",
391
+ message: `${ICONS.warning} Remove server "${serverName}"? This will disconnect it.`,
392
+ defaultValue: "n",
393
+ handler: async (value: string): Promise<CommandResult> => {
394
+ const confirmed = value.toLowerCase() === "y" || value.toLowerCase() === "yes";
395
+ if (!confirmed) {
396
+ return success("Removal cancelled.");
397
+ }
398
+
399
+ // Note: We can't actually delete from config file here.
400
+ // User needs to manually edit mcp.json
401
+ return success(
402
+ `ℹ️ To remove "${serverName}", delete its entry from ~/.vellum/mcp.json\n\n` +
403
+ "The server will be disconnected automatically after config change."
404
+ );
405
+ },
406
+ onCancel: () => success("Removal cancelled."),
407
+ });
408
+ }
409
+
410
+ /**
411
+ * Handle /mcp tools - List available tools from MCP servers
412
+ */
413
+ async function handleTools(ctx: CommandContext): Promise<CommandResult> {
414
+ if (!mcpHub) {
415
+ return error("OPERATION_NOT_ALLOWED", "MCP hub not initialized.", ["/help mcp"]);
416
+ }
417
+
418
+ const serverName = ctx.parsedArgs.positional[1] as string | undefined;
419
+ const servers = mcpHub.getServers();
420
+
421
+ if (servers.length === 0) {
422
+ return success("📡 No MCP servers configured. No tools available.");
423
+ }
424
+
425
+ // If specific server requested
426
+ if (serverName) {
427
+ const server = servers.find((s) => s.name === serverName);
428
+ if (!server) {
429
+ return error("RESOURCE_NOT_FOUND", `Server "${serverName}" not found.`, [
430
+ `Available servers: ${servers.map((s) => s.name).join(", ")}`,
431
+ ]);
432
+ }
433
+
434
+ if (server.statusInfo.status !== "connected") {
435
+ return error(
436
+ "OPERATION_NOT_ALLOWED",
437
+ `Server "${serverName}" is not connected (status: ${server.statusInfo.status}).`,
438
+ ["/mcp status"]
439
+ );
440
+ }
441
+
442
+ const tools = server.tools ?? [];
443
+ if (tools.length === 0) {
444
+ return success(`[MCP] ${serverName} - No tools available.`);
445
+ }
446
+
447
+ const lines = [
448
+ `${ICONS.tools} Tools from ${serverName}`,
449
+ "",
450
+ ...tools.map((t) => ` - ${t.name}${t.description ? ` - ${t.description}` : ""}`),
451
+ "",
452
+ `Total: ${tools.length} tool(s)`,
453
+ ];
454
+
455
+ return success(lines.join("\n"));
456
+ }
457
+
458
+ // Show tools from all connected servers
459
+ const allTools = mcpHub.getAllTools();
460
+
461
+ if (allTools.length === 0) {
462
+ return success(`${ICONS.tools} No tools available from connected MCP servers.`);
463
+ }
464
+
465
+ // Group by server
466
+ const toolsByServer = new Map<string, typeof allTools>();
467
+ for (const tool of allTools) {
468
+ const existing = toolsByServer.get(tool.serverName) ?? [];
469
+ existing.push(tool);
470
+ toolsByServer.set(tool.serverName, existing);
471
+ }
472
+
473
+ const lines = [`${ICONS.tools} Available MCP Tools`, ""];
474
+
475
+ for (const [server, tools] of toolsByServer) {
476
+ lines.push(`[MCP] ${server}:`);
477
+ for (const tool of tools) {
478
+ lines.push(` - ${tool.name}${tool.description ? ` - ${tool.description}` : ""}`);
479
+ }
480
+ lines.push("");
481
+ }
482
+
483
+ lines.push(`Total: ${allTools.length} tool(s) from ${toolsByServer.size} server(s)`);
484
+
485
+ return success(lines.join("\n"));
486
+ }
487
+
488
+ /**
489
+ * Show help for /mcp command
490
+ */
491
+ function showHelp(): CommandResult {
492
+ const lines = [
493
+ "[MCP] Server Management",
494
+ "",
495
+ "Subcommands:",
496
+ " list - List configured MCP servers",
497
+ " status - Show connection status and tool count",
498
+ " add - Add a new MCP server (interactive)",
499
+ " remove - Remove an MCP server",
500
+ " tools - List available tools from MCP servers",
501
+ "",
502
+ "Examples:",
503
+ " /mcp list",
504
+ " /mcp status",
505
+ " /mcp status my-server",
506
+ " /mcp tools",
507
+ " /mcp tools my-server",
508
+ " /mcp add",
509
+ " /mcp remove my-server",
510
+ ];
511
+
512
+ return success(lines.join("\n"));
513
+ }
514
+
515
+ // =============================================================================
516
+ // /mcp Command - MCP Server Management
517
+ // =============================================================================
518
+
519
+ /**
520
+ * /mcp command - Manage MCP (Model Context Protocol) servers.
521
+ *
522
+ * Provides subcommands for listing, inspecting, adding, and removing
523
+ * MCP servers configured in ~/.vellum/mcp.json.
524
+ */
525
+ export const mcpCommand: SlashCommand = {
526
+ name: "mcp",
527
+ description: "Manage MCP (Model Context Protocol) servers",
528
+ kind: "builtin",
529
+ category: "tools",
530
+ aliases: [],
531
+ positionalArgs: [
532
+ {
533
+ name: "subcommand",
534
+ type: "string",
535
+ description: "Subcommand (list, status, add, remove, tools)",
536
+ required: false,
537
+ },
538
+ {
539
+ name: "server",
540
+ type: "string",
541
+ description: "Server name (for status, remove, tools)",
542
+ required: false,
543
+ },
544
+ ],
545
+ examples: [
546
+ "/mcp - Show help",
547
+ "/mcp list - List configured servers",
548
+ "/mcp status - Show all server status",
549
+ "/mcp tools - List all available tools",
550
+ "/mcp add - Add a new server",
551
+ "/mcp remove X - Remove server X",
552
+ ],
553
+ subcommands: [
554
+ { name: "list", description: "List configured MCP servers" },
555
+ { name: "status", description: "Show connection status and tool count" },
556
+ { name: "add", description: "Add a new MCP server" },
557
+ { name: "remove", description: "Remove an MCP server" },
558
+ { name: "tools", description: "List available tools from MCP servers" },
559
+ ],
560
+
561
+ execute: async (ctx: CommandContext): Promise<CommandResult> => {
562
+ const subcommand = ctx.parsedArgs.positional[0] as string | undefined;
563
+
564
+ switch (subcommand) {
565
+ case "list":
566
+ return handleList(ctx);
567
+ case "status":
568
+ return handleStatus(ctx);
569
+ case "add":
570
+ return handleAdd(ctx);
571
+ case "remove":
572
+ return handleRemove(ctx);
573
+ case "tools":
574
+ return handleTools(ctx);
575
+ default:
576
+ return showHelp();
577
+ }
578
+ },
579
+ };
580
+
581
+ // =============================================================================
582
+ // Export All MCP Commands
583
+ // =============================================================================
584
+
585
+ /**
586
+ * All MCP-related slash commands for registration.
587
+ */
588
+ export const mcpSlashCommands: SlashCommand[] = [mcpCommand];