@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,372 @@
1
+ /**
2
+ * Custom Agents Command Group (T020-T024)
3
+ *
4
+ * CLI commands for managing custom agent definitions.
5
+ *
6
+ * Subcommands:
7
+ * - `vellum custom-agents list` - List agents grouped by scope
8
+ * - `vellum custom-agents create` - Create new agent from template
9
+ * - `vellum custom-agents validate` - Validate agent files
10
+ * - `vellum custom-agents info` - Show full agent details
11
+ * - `vellum custom-agents export` - Export agent to file
12
+ * - `vellum custom-agents import` - Import agent from file
13
+ *
14
+ * @module cli/commands/custom-agents
15
+ */
16
+
17
+ import type { CommandContext, CommandResult, SlashCommand } from "../types.js";
18
+ import { success } from "../types.js";
19
+ import { handleCreate } from "./create.js";
20
+ import { handleExport } from "./export.js";
21
+ import { handleImport } from "./import.js";
22
+ import { handleInfo } from "./info.js";
23
+ import { handleList } from "./list.js";
24
+ import { handleValidate } from "./validate.js";
25
+
26
+ // =============================================================================
27
+ // Types
28
+ // =============================================================================
29
+
30
+ /**
31
+ * Custom agents subcommand names
32
+ */
33
+ export type CustomAgentsSubcommand =
34
+ | "list"
35
+ | "create"
36
+ | "validate"
37
+ | "info"
38
+ | "export"
39
+ | "import"
40
+ | "help";
41
+
42
+ /**
43
+ * Options for list subcommand (T020)
44
+ */
45
+ export interface ListOptions {
46
+ /** Output as JSON */
47
+ json?: boolean;
48
+ /** Show only global (user-level) agents */
49
+ global?: boolean;
50
+ /** Show only local (project-level) agents */
51
+ local?: boolean;
52
+ }
53
+
54
+ /**
55
+ * Options for create subcommand (T021)
56
+ */
57
+ export interface CreateOptions {
58
+ /** Template to use (basic, advanced, orchestrator) */
59
+ template?: string;
60
+ /** Create in global location (~/.vellum/agents) */
61
+ global?: boolean;
62
+ /** Skip interactive prompts */
63
+ noInteractive?: boolean;
64
+ }
65
+
66
+ /**
67
+ * Options for validate subcommand (T022)
68
+ */
69
+ export interface ValidateOptions {
70
+ /** Strict mode - treat warnings as errors */
71
+ strict?: boolean;
72
+ /** Agent slug or file path to validate */
73
+ target?: string;
74
+ }
75
+
76
+ /**
77
+ * Options for info subcommand (T023)
78
+ */
79
+ export interface InfoOptions {
80
+ /** Output as JSON */
81
+ json?: boolean;
82
+ /** Show full system prompt */
83
+ showPrompt?: boolean;
84
+ }
85
+
86
+ /**
87
+ * Options for export subcommand (T020a)
88
+ */
89
+ export interface ExportOptions {
90
+ /** Output file path */
91
+ output?: string;
92
+ /** Output format (yaml or json) */
93
+ format?: "yaml" | "json";
94
+ }
95
+
96
+ /**
97
+ * Options for import subcommand (T020b)
98
+ */
99
+ export interface ImportOptions {
100
+ /** Import file path */
101
+ file: string;
102
+ /** Import to global location */
103
+ global?: boolean;
104
+ }
105
+
106
+ // =============================================================================
107
+ // Help Text
108
+ // =============================================================================
109
+
110
+ /**
111
+ * Generate help text for custom-agents command group
112
+ */
113
+ function getCustomAgentsHelp(): string {
114
+ return `🤖 Custom Agents Commands
115
+
116
+ Manage custom agent definitions.
117
+
118
+ Subcommands:
119
+ list List agents grouped by scope (project/user/system)
120
+ create Create a new agent from template
121
+ validate Validate agent definition files
122
+ info Show full agent details (resolved config)
123
+ export Export agent definition to file
124
+ import Import agent definition from file
125
+
126
+ Usage:
127
+ /custom-agents Show this help
128
+ /custom-agents list List all agents
129
+ /custom-agents list --json Output as JSON
130
+ /custom-agents list --global Show only user-level agents
131
+ /custom-agents list --local Show only project-level agents
132
+ /custom-agents create <slug> Create new agent
133
+ /custom-agents create <slug> --template=advanced
134
+ /custom-agents validate Validate all agents
135
+ /custom-agents validate <slug> Validate specific agent
136
+ /custom-agents validate --strict Treat warnings as errors
137
+ /custom-agents info <slug> Show agent details
138
+ /custom-agents info <slug> --json Output as JSON
139
+ /custom-agents info <slug> --show-prompt
140
+ /custom-agents export <slug> Export agent
141
+ /custom-agents export <slug> --output=./agent.yaml
142
+ /custom-agents export <slug> --format=json
143
+ /custom-agents import <file> Import agent from file
144
+
145
+ Examples:
146
+ /custom-agents create test-runner --template=basic
147
+ /custom-agents validate --strict
148
+ /custom-agents info my-agent --show-prompt
149
+ /custom-agents export my-agent --format=yaml
150
+
151
+ See also:
152
+ /agents - AGENTS.md configuration management`;
153
+ }
154
+
155
+ // =============================================================================
156
+ // Subcommand Routing
157
+ // =============================================================================
158
+
159
+ /**
160
+ * Parse custom-agents subcommand from positional args
161
+ */
162
+ function parseSubcommand(positional: readonly unknown[]): CustomAgentsSubcommand {
163
+ const first = positional[0];
164
+ if (typeof first === "string") {
165
+ const sub = first.toLowerCase();
166
+ if (
167
+ sub === "list" ||
168
+ sub === "create" ||
169
+ sub === "validate" ||
170
+ sub === "info" ||
171
+ sub === "export" ||
172
+ sub === "import"
173
+ ) {
174
+ return sub;
175
+ }
176
+ }
177
+ return "help";
178
+ }
179
+
180
+ /**
181
+ * Execute custom-agents command group
182
+ *
183
+ * @param ctx - Command context
184
+ * @returns Command result
185
+ */
186
+ export async function executeCustomAgents(ctx: CommandContext): Promise<CommandResult> {
187
+ const subcommand = parseSubcommand(ctx.parsedArgs.positional);
188
+ const named = ctx.parsedArgs.named;
189
+ const positional = ctx.parsedArgs.positional;
190
+
191
+ switch (subcommand) {
192
+ case "list":
193
+ return handleList({
194
+ json: named.json as boolean | undefined,
195
+ global: named.global as boolean | undefined,
196
+ local: named.local as boolean | undefined,
197
+ });
198
+
199
+ case "create":
200
+ return handleCreate(
201
+ positional[1] as string | undefined, // slug
202
+ {
203
+ template: named.template as string | undefined,
204
+ global: named.global as boolean | undefined,
205
+ noInteractive: named["no-interactive"] as boolean | undefined,
206
+ }
207
+ );
208
+
209
+ case "validate":
210
+ return handleValidate({
211
+ target: positional[1] as string | undefined,
212
+ strict: named.strict as boolean | undefined,
213
+ });
214
+
215
+ case "info":
216
+ return handleInfo(positional[1] as string | undefined, {
217
+ json: named.json as boolean | undefined,
218
+ showPrompt: named["show-prompt"] as boolean | undefined,
219
+ });
220
+
221
+ case "export":
222
+ return handleExport(positional[1] as string | undefined, {
223
+ output: named.output as string | undefined,
224
+ format: named.format as "yaml" | "json" | undefined,
225
+ });
226
+
227
+ case "import":
228
+ return handleImport({
229
+ file: positional[1] as string,
230
+ global: named.global as boolean | undefined,
231
+ });
232
+
233
+ default:
234
+ return success(getCustomAgentsHelp());
235
+ }
236
+ }
237
+
238
+ // =============================================================================
239
+ // Slash Command Definition
240
+ // =============================================================================
241
+
242
+ /**
243
+ * Custom agents command group for TUI
244
+ *
245
+ * Provides access to custom agent management operations.
246
+ */
247
+ export const customAgentsCommand: SlashCommand = {
248
+ name: "custom-agents",
249
+ description: "Manage custom agent definitions",
250
+ kind: "builtin",
251
+ category: "config",
252
+ aliases: ["ca", "custom-agent"],
253
+ positionalArgs: [
254
+ {
255
+ name: "subcommand",
256
+ type: "string",
257
+ description: "Subcommand: list, create, validate, info, export, import",
258
+ required: false,
259
+ },
260
+ {
261
+ name: "target",
262
+ type: "string",
263
+ description: "Agent slug, file path, or other target",
264
+ required: false,
265
+ },
266
+ ],
267
+ namedArgs: [
268
+ // Common flags
269
+ {
270
+ name: "json",
271
+ shorthand: "j",
272
+ type: "boolean",
273
+ description: "Output as JSON",
274
+ required: false,
275
+ default: false,
276
+ },
277
+ // List flags
278
+ {
279
+ name: "global",
280
+ shorthand: "g",
281
+ type: "boolean",
282
+ description: "Global (user-level) scope",
283
+ required: false,
284
+ default: false,
285
+ },
286
+ {
287
+ name: "local",
288
+ shorthand: "l",
289
+ type: "boolean",
290
+ description: "Local (project-level) scope",
291
+ required: false,
292
+ default: false,
293
+ },
294
+ // Create flags
295
+ {
296
+ name: "template",
297
+ shorthand: "t",
298
+ type: "string",
299
+ description: "Template for new agent (basic, advanced, orchestrator)",
300
+ required: false,
301
+ },
302
+ {
303
+ name: "no-interactive",
304
+ type: "boolean",
305
+ description: "Skip interactive prompts",
306
+ required: false,
307
+ default: false,
308
+ },
309
+ // Validate flags
310
+ {
311
+ name: "strict",
312
+ shorthand: "s",
313
+ type: "boolean",
314
+ description: "Treat warnings as errors",
315
+ required: false,
316
+ default: false,
317
+ },
318
+ // Info flags
319
+ {
320
+ name: "show-prompt",
321
+ type: "boolean",
322
+ description: "Show full system prompt",
323
+ required: false,
324
+ default: false,
325
+ },
326
+ // Export flags
327
+ {
328
+ name: "output",
329
+ shorthand: "o",
330
+ type: "path",
331
+ description: "Output file path",
332
+ required: false,
333
+ },
334
+ {
335
+ name: "format",
336
+ shorthand: "f",
337
+ type: "string",
338
+ description: "Output format (yaml or json)",
339
+ required: false,
340
+ },
341
+ ],
342
+ examples: [
343
+ "/custom-agents - Show help",
344
+ "/custom-agents list - List all agents",
345
+ "/custom-agents list --json - Output as JSON",
346
+ "/custom-agents list --global - Show user-level agents only",
347
+ "/custom-agents create my-agent - Create new agent",
348
+ "/custom-agents create my-agent -t basic - Use basic template",
349
+ "/custom-agents validate - Validate all agents",
350
+ "/custom-agents validate --strict - Strict validation",
351
+ "/custom-agents info my-agent - Show agent details",
352
+ "/custom-agents info my-agent --show-prompt",
353
+ "/custom-agents export my-agent -o ./out.yaml",
354
+ "/custom-agents import ./agent.yaml - Import agent",
355
+ ],
356
+ subcommands: [
357
+ { name: "list", description: "List custom agents", aliases: ["ls"] },
358
+ { name: "create", description: "Create custom agent" },
359
+ { name: "validate", description: "Validate agent" },
360
+ { name: "edit", description: "Edit agent" },
361
+ { name: "export", description: "Export agent" },
362
+ { name: "import", description: "Import agent" },
363
+ ],
364
+
365
+ execute: executeCustomAgents,
366
+ };
367
+
368
+ // =============================================================================
369
+ // Re-exports
370
+ // =============================================================================
371
+
372
+ export { getCustomAgentsHelp };
@@ -0,0 +1,318 @@
1
+ /**
2
+ * Custom Agents Info Command (T023)
3
+ *
4
+ * Shows full agent details including resolved configuration.
5
+ *
6
+ * @module cli/commands/custom-agents/info
7
+ * @see REQ-021
8
+ */
9
+
10
+ import { AgentDiscovery, type DiscoveredAgent, DiscoverySource } from "@vellum/core";
11
+ import chalk from "chalk";
12
+
13
+ import type { CommandResult } from "../types.js";
14
+ import { error, success } from "../types.js";
15
+ import type { InfoOptions } from "./index.js";
16
+
17
+ // =============================================================================
18
+ // Types
19
+ // =============================================================================
20
+
21
+ /**
22
+ * JSON output format for info command
23
+ */
24
+ export interface InfoJsonOutput {
25
+ success: boolean;
26
+ agent: {
27
+ slug: string;
28
+ name: string;
29
+ description?: string;
30
+ mode?: string;
31
+ extends?: string;
32
+ icon?: string;
33
+ color?: string;
34
+ hidden?: boolean;
35
+ model?: string;
36
+ systemPrompt?: string;
37
+ version?: string;
38
+ author?: string;
39
+ tags?: string[];
40
+ docs?: string;
41
+ level?: string;
42
+ toolGroups?: unknown[];
43
+ restrictions?: unknown;
44
+ settings?: unknown;
45
+ whenToUse?: unknown;
46
+ hooks?: unknown;
47
+ coordination?: unknown;
48
+ };
49
+ source: {
50
+ path: string;
51
+ scope: string;
52
+ priority: number;
53
+ modifiedAt: string;
54
+ };
55
+ resolved?: {
56
+ inheritanceChain: string[];
57
+ effectiveConfig: Record<string, unknown>;
58
+ };
59
+ }
60
+
61
+ // =============================================================================
62
+ // Helpers
63
+ // =============================================================================
64
+
65
+ /**
66
+ * Get scope name from discovery source
67
+ */
68
+ function getSourceName(source: DiscoverySource): string {
69
+ switch (source) {
70
+ case DiscoverySource.PROJECT:
71
+ return "project";
72
+ case DiscoverySource.USER:
73
+ return "user";
74
+ case DiscoverySource.SYSTEM:
75
+ return "system";
76
+ case DiscoverySource.ENV:
77
+ return "environment";
78
+ case DiscoverySource.CLI:
79
+ return "cli";
80
+ default:
81
+ return "unknown";
82
+ }
83
+ }
84
+
85
+ /**
86
+ * Format value for display
87
+ */
88
+ function formatValue(value: unknown, indent = 0): string {
89
+ const prefix = " ".repeat(indent);
90
+
91
+ if (value === undefined || value === null) {
92
+ return chalk.gray("(not set)");
93
+ }
94
+
95
+ if (typeof value === "boolean") {
96
+ return value ? chalk.green("true") : chalk.red("false");
97
+ }
98
+
99
+ if (typeof value === "number") {
100
+ return chalk.yellow(String(value));
101
+ }
102
+
103
+ if (typeof value === "string") {
104
+ // Truncate long strings
105
+ if (value.length > 80) {
106
+ return chalk.white(`"${value.substring(0, 77)}..."`);
107
+ }
108
+ return chalk.white(`"${value}"`);
109
+ }
110
+
111
+ if (Array.isArray(value)) {
112
+ if (value.length === 0) {
113
+ return chalk.gray("[]");
114
+ }
115
+ const items = value.map((v) => `${prefix} - ${formatValue(v, 0)}`).join("\n");
116
+ return `\n${items}`;
117
+ }
118
+
119
+ if (typeof value === "object") {
120
+ const entries = Object.entries(value as Record<string, unknown>);
121
+ if (entries.length === 0) {
122
+ return chalk.gray("{}");
123
+ }
124
+ const items = entries
125
+ .map(([k, v]) => `${prefix} ${chalk.cyan(k)}: ${formatValue(v, indent + 1)}`)
126
+ .join("\n");
127
+ return `\n${items}`;
128
+ }
129
+
130
+ return String(value);
131
+ }
132
+
133
+ /**
134
+ * Format section header
135
+ */
136
+ function formatSection(title: string): string {
137
+ return chalk.bold.blue(`\n── ${title} ──`);
138
+ }
139
+
140
+ /**
141
+ * Format agent for display
142
+ */
143
+ function formatAgentInfo(discovered: DiscoveredAgent, options: InfoOptions): string {
144
+ const { definition: agent, sourcePath, source, modifiedAt } = discovered;
145
+ const lines: string[] = [];
146
+
147
+ // Header
148
+ const icon = agent.icon ?? "📦";
149
+ lines.push("");
150
+ lines.push(chalk.bold(`${icon} ${agent.name}`));
151
+ lines.push(chalk.gray(`Slug: ${agent.slug}`));
152
+
153
+ // Basic Info
154
+ lines.push(formatSection("Basic Information"));
155
+ lines.push(` ${chalk.cyan("Description")}: ${formatValue(agent.description)}`);
156
+ lines.push(` ${chalk.cyan("Mode")}: ${formatValue(agent.mode)}`);
157
+ lines.push(` ${chalk.cyan("Extends")}: ${formatValue(agent.extends)}`);
158
+ lines.push(` ${chalk.cyan("Level")}: ${formatValue(agent.level)}`);
159
+ lines.push(` ${chalk.cyan("Hidden")}: ${formatValue(agent.hidden)}`);
160
+
161
+ // UI Configuration
162
+ lines.push(formatSection("UI Configuration"));
163
+ lines.push(` ${chalk.cyan("Icon")}: ${formatValue(agent.icon)}`);
164
+ lines.push(` ${chalk.cyan("Color")}: ${formatValue(agent.color)}`);
165
+
166
+ // LLM Configuration
167
+ lines.push(formatSection("LLM Configuration"));
168
+ lines.push(` ${chalk.cyan("Model")}: ${formatValue(agent.model)}`);
169
+
170
+ if (options.showPrompt && agent.systemPrompt) {
171
+ lines.push(` ${chalk.cyan("System Prompt")}:`);
172
+ lines.push(chalk.gray(" ─".repeat(30)));
173
+ const promptLines = agent.systemPrompt.split("\n");
174
+ for (const line of promptLines) {
175
+ lines.push(chalk.white(` ${line}`));
176
+ }
177
+ lines.push(chalk.gray(" ─".repeat(30)));
178
+ } else if (agent.systemPrompt) {
179
+ const preview = agent.systemPrompt.substring(0, 60).replace(/\n/g, " ");
180
+ lines.push(` ${chalk.cyan("System Prompt")}: ${chalk.gray(`"${preview}..."`)}`);
181
+ lines.push(chalk.gray(" (use --show-prompt to see full prompt)"));
182
+ } else {
183
+ lines.push(` ${chalk.cyan("System Prompt")}: ${chalk.gray("(not set)")}`);
184
+ }
185
+
186
+ // Access & Restrictions
187
+ lines.push(formatSection("Access & Restrictions"));
188
+ lines.push(` ${chalk.cyan("Tool Groups")}: ${formatValue(agent.toolGroups)}`);
189
+ lines.push(` ${chalk.cyan("Restrictions")}: ${formatValue(agent.restrictions)}`);
190
+
191
+ // Runtime Settings
192
+ lines.push(formatSection("Runtime Settings"));
193
+ lines.push(` ${chalk.cyan("Settings")}: ${formatValue(agent.settings)}`);
194
+
195
+ // Activation
196
+ lines.push(formatSection("Activation"));
197
+ lines.push(` ${chalk.cyan("When to Use")}: ${formatValue(agent.whenToUse)}`);
198
+
199
+ // Hooks
200
+ if (agent.hooks) {
201
+ lines.push(formatSection("Lifecycle Hooks"));
202
+ lines.push(` ${chalk.cyan("Hooks")}: ${formatValue(agent.hooks)}`);
203
+ }
204
+
205
+ // Multi-Agent Coordination
206
+ if (agent.coordination) {
207
+ lines.push(formatSection("Multi-Agent Coordination"));
208
+ lines.push(` ${chalk.cyan("Coordination")}: ${formatValue(agent.coordination)}`);
209
+ }
210
+
211
+ // Metadata
212
+ lines.push(formatSection("Metadata"));
213
+ lines.push(` ${chalk.cyan("Version")}: ${formatValue(agent.version)}`);
214
+ lines.push(` ${chalk.cyan("Author")}: ${formatValue(agent.author)}`);
215
+ lines.push(` ${chalk.cyan("Tags")}: ${formatValue(agent.tags)}`);
216
+ lines.push(` ${chalk.cyan("Docs")}: ${formatValue(agent.docs)}`);
217
+
218
+ // Source Information
219
+ lines.push(formatSection("Source"));
220
+ lines.push(` ${chalk.cyan("Path")}: ${chalk.gray(sourcePath)}`);
221
+ lines.push(` ${chalk.cyan("Scope")}: ${formatValue(getSourceName(source))}`);
222
+ lines.push(` ${chalk.cyan("Priority")}: ${formatValue(source)}`);
223
+ lines.push(` ${chalk.cyan("Modified")}: ${formatValue(modifiedAt.toISOString())}`);
224
+
225
+ return lines.join("\n");
226
+ }
227
+
228
+ /**
229
+ * Convert agent to JSON output
230
+ */
231
+ function toJsonOutput(discovered: DiscoveredAgent): InfoJsonOutput {
232
+ const { definition: agent, sourcePath, source, modifiedAt } = discovered;
233
+
234
+ return {
235
+ success: true,
236
+ agent: {
237
+ slug: agent.slug,
238
+ name: agent.name,
239
+ description: agent.description,
240
+ mode: agent.mode,
241
+ extends: agent.extends,
242
+ icon: agent.icon,
243
+ color: agent.color,
244
+ hidden: agent.hidden,
245
+ model: agent.model,
246
+ systemPrompt: agent.systemPrompt,
247
+ version: agent.version,
248
+ author: agent.author,
249
+ tags: agent.tags,
250
+ docs: agent.docs,
251
+ level: agent.level !== undefined ? String(agent.level) : undefined,
252
+ toolGroups: agent.toolGroups,
253
+ restrictions: agent.restrictions,
254
+ settings: agent.settings,
255
+ whenToUse: agent.whenToUse,
256
+ hooks: agent.hooks,
257
+ coordination: agent.coordination,
258
+ },
259
+ source: {
260
+ path: sourcePath,
261
+ scope: getSourceName(source),
262
+ priority: source,
263
+ modifiedAt: modifiedAt.toISOString(),
264
+ },
265
+ };
266
+ }
267
+
268
+ // =============================================================================
269
+ // Command Handler
270
+ // =============================================================================
271
+
272
+ /**
273
+ * Handle info subcommand
274
+ *
275
+ * Shows full details for a specific agent, including resolved configuration.
276
+ *
277
+ * @param slug - Agent slug to show info for
278
+ * @param options - Info options
279
+ * @returns Command result
280
+ */
281
+ export async function handleInfo(
282
+ slug: string | undefined,
283
+ options: InfoOptions = {}
284
+ ): Promise<CommandResult> {
285
+ // Require slug
286
+ if (!slug) {
287
+ return error("MISSING_ARGUMENT", "Agent slug is required", [
288
+ "Usage: /custom-agents info <slug>",
289
+ "Use /custom-agents list to see available agents",
290
+ ]);
291
+ }
292
+
293
+ try {
294
+ // Discover agents
295
+ const discovery = new AgentDiscovery({ watchEnabled: false });
296
+ await discovery.discover();
297
+
298
+ // Find agent
299
+ const agent = discovery.get(slug);
300
+
301
+ if (!agent) {
302
+ return error("RESOURCE_NOT_FOUND", `Agent not found: ${slug}`, [
303
+ "Check the slug is correct",
304
+ "Use /custom-agents list to see available agents",
305
+ ]);
306
+ }
307
+
308
+ // Output format
309
+ if (options.json) {
310
+ return success(JSON.stringify(toJsonOutput(agent), null, 2));
311
+ }
312
+
313
+ return success(formatAgentInfo(agent, options));
314
+ } catch (err) {
315
+ const message = err instanceof Error ? err.message : String(err);
316
+ return error("INTERNAL_ERROR", `Failed to get agent info: ${message}`);
317
+ }
318
+ }