@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,344 @@
1
+ /**
2
+ * Config Slash Commands
3
+ *
4
+ * Provides slash commands for config file management:
5
+ * - /config - Show configuration file path and status
6
+ * - /config path - Show only the config file path
7
+ * - /config edit - Open config file in editor
8
+ * - /config reset - Reset to default configuration
9
+ *
10
+ * @module cli/commands/config
11
+ */
12
+
13
+ import { spawn } from "node:child_process";
14
+ import * as fs from "node:fs";
15
+ import * as os from "node:os";
16
+ import * as path from "node:path";
17
+ import { findProjectConfig, loadConfig } from "@vellum/core";
18
+ import type { CommandContext, CommandResult, SlashCommand } from "./types.js";
19
+ import { error, success } from "./types.js";
20
+
21
+ // =============================================================================
22
+ // Constants
23
+ // =============================================================================
24
+
25
+ /**
26
+ * Global config directory.
27
+ */
28
+ const GLOBAL_CONFIG_DIR = path.join(os.homedir(), ".config", "vellum");
29
+
30
+ /**
31
+ * Global config file path.
32
+ */
33
+ const GLOBAL_CONFIG_PATH = path.join(GLOBAL_CONFIG_DIR, "vellum.json");
34
+
35
+ /**
36
+ * Settings file path (user preferences).
37
+ */
38
+ const SETTINGS_PATH = path.join(GLOBAL_CONFIG_DIR, "settings.json");
39
+
40
+ // =============================================================================
41
+ // Helper Functions
42
+ // =============================================================================
43
+
44
+ /**
45
+ * Find the active config file path.
46
+ */
47
+ function findConfigPath(cwd: string): { path: string; type: "project" | "global" | "none" } {
48
+ // Check for project config
49
+ const projectConfig = findProjectConfig(cwd);
50
+ if (projectConfig) {
51
+ return { path: projectConfig, type: "project" };
52
+ }
53
+
54
+ // Check for global config
55
+ if (fs.existsSync(GLOBAL_CONFIG_PATH)) {
56
+ return { path: GLOBAL_CONFIG_PATH, type: "global" };
57
+ }
58
+
59
+ return { path: GLOBAL_CONFIG_PATH, type: "none" };
60
+ }
61
+
62
+ /**
63
+ * Get editor command based on environment.
64
+ */
65
+ function getEditorCommand(): string {
66
+ // Check EDITOR environment variable
67
+ const editor = process.env.EDITOR || process.env.VISUAL;
68
+ if (editor) return editor;
69
+
70
+ // Platform-specific defaults
71
+ if (process.platform === "win32") {
72
+ return "notepad";
73
+ }
74
+ if (process.platform === "darwin") {
75
+ return "open -e"; // TextEdit
76
+ }
77
+ return "nano"; // Linux default
78
+ }
79
+
80
+ /**
81
+ * Open a file in the system editor.
82
+ */
83
+ async function openInEditor(filePath: string): Promise<void> {
84
+ const editorCmd = getEditorCommand();
85
+ const parts = editorCmd.split(" ");
86
+ const cmd = parts[0]!;
87
+ const args = [...parts.slice(1), filePath];
88
+
89
+ return new Promise((resolve, reject) => {
90
+ const child = spawn(cmd, args, {
91
+ stdio: "inherit",
92
+ shell: process.platform === "win32",
93
+ detached: process.platform !== "win32",
94
+ });
95
+
96
+ child.on("error", reject);
97
+ child.on("close", (code) => {
98
+ if (code === 0 || process.platform !== "win32") {
99
+ resolve();
100
+ } else {
101
+ reject(new Error(`Editor exited with code ${code}`));
102
+ }
103
+ });
104
+
105
+ // Detach on non-Windows to allow editor to run independently
106
+ if (process.platform !== "win32") {
107
+ child.unref();
108
+ resolve();
109
+ }
110
+ });
111
+ }
112
+
113
+ /**
114
+ * Create default config file.
115
+ */
116
+ function createDefaultConfig(configPath: string): void {
117
+ const defaultConfig = {
118
+ $schema: "https://vellum.dev/schemas/config.json",
119
+ llm: {
120
+ provider: "anthropic",
121
+ model: "claude-sonnet-4-20250514",
122
+ maxTokens: 4096,
123
+ temperature: 0.7,
124
+ },
125
+ agent: {
126
+ maxToolCalls: 50,
127
+ maxTurns: 100,
128
+ maxRetries: 3,
129
+ },
130
+ permissions: {
131
+ fileRead: "ask",
132
+ fileWrite: "ask",
133
+ shellExecute: "ask",
134
+ networkAccess: "ask",
135
+ },
136
+ debug: false,
137
+ logLevel: "info",
138
+ theme: "dark",
139
+ };
140
+
141
+ // Ensure directory exists
142
+ const dir = path.dirname(configPath);
143
+ if (!fs.existsSync(dir)) {
144
+ fs.mkdirSync(dir, { recursive: true });
145
+ }
146
+
147
+ fs.writeFileSync(configPath, JSON.stringify(defaultConfig, null, 2), "utf-8");
148
+ }
149
+
150
+ // =============================================================================
151
+ // Config Subcommand Handlers
152
+ // =============================================================================
153
+
154
+ /**
155
+ * Handle /config (no subcommand) - show config status.
156
+ */
157
+ function handleShowConfig(cwd: string): CommandResult {
158
+ const configInfo = findConfigPath(cwd);
159
+ const settingsExists = fs.existsSync(SETTINGS_PATH);
160
+
161
+ // Try to load and validate config
162
+ const configResult = loadConfig({ cwd, suppressDeprecationWarnings: true });
163
+ const configValid = configResult.ok;
164
+
165
+ const lines: string[] = [];
166
+ lines.push("⚙️ Configuration Status");
167
+ lines.push("═".repeat(40));
168
+ lines.push("");
169
+
170
+ // Config file info
171
+ if (configInfo.type === "project") {
172
+ lines.push(`📁 Project config: ${configInfo.path}`);
173
+ lines.push(` Status: ${configValid ? "✅ Valid" : "❌ Invalid"}`);
174
+ } else if (configInfo.type === "global") {
175
+ lines.push(`🌐 Global config: ${configInfo.path}`);
176
+ lines.push(` Status: ${configValid ? "✅ Valid" : "❌ Invalid"}`);
177
+ } else {
178
+ lines.push("📁 Config file: Not found");
179
+ lines.push(` Default location: ${GLOBAL_CONFIG_PATH}`);
180
+ }
181
+
182
+ lines.push("");
183
+
184
+ // Settings file info
185
+ lines.push(`📝 Settings file: ${SETTINGS_PATH}`);
186
+ lines.push(` Status: ${settingsExists ? "✅ Exists" : "⚪ Not created"}`);
187
+
188
+ lines.push("");
189
+ lines.push("─".repeat(40));
190
+ lines.push("Commands:");
191
+ lines.push(" /config path - Show config file path");
192
+ lines.push(" /config edit - Open config in editor");
193
+ lines.push(" /config reset - Reset to defaults");
194
+
195
+ return success(lines.join("\n"));
196
+ }
197
+
198
+ /**
199
+ * Handle /config path - show only the config path.
200
+ */
201
+ function handleConfigPath(cwd: string): CommandResult {
202
+ const configInfo = findConfigPath(cwd);
203
+
204
+ if (configInfo.type === "none") {
205
+ return success(`Config file not found.\nDefault location: ${GLOBAL_CONFIG_PATH}`);
206
+ }
207
+
208
+ return success(configInfo.path);
209
+ }
210
+
211
+ /**
212
+ * Handle /config edit - open config in editor.
213
+ */
214
+ async function handleConfigEdit(cwd: string): Promise<CommandResult> {
215
+ const configInfo = findConfigPath(cwd);
216
+ let configPath = configInfo.path;
217
+
218
+ // Create default config if it doesn't exist
219
+ if (configInfo.type === "none") {
220
+ try {
221
+ createDefaultConfig(GLOBAL_CONFIG_PATH);
222
+ configPath = GLOBAL_CONFIG_PATH;
223
+ } catch (err) {
224
+ return error(
225
+ "INTERNAL_ERROR",
226
+ `Failed to create config file: ${err instanceof Error ? err.message : String(err)}`
227
+ );
228
+ }
229
+ }
230
+
231
+ // Open in editor
232
+ try {
233
+ await openInEditor(configPath);
234
+ return success(`Opening config file in editor: ${configPath}`);
235
+ } catch (err) {
236
+ return error(
237
+ "INTERNAL_ERROR",
238
+ `Failed to open editor: ${err instanceof Error ? err.message : String(err)}\n\nConfig file location: ${configPath}`
239
+ );
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Handle /config reset - reset to default configuration.
245
+ */
246
+ function handleConfigReset(cwd: string): CommandResult {
247
+ const configInfo = findConfigPath(cwd);
248
+ const targetPath = configInfo.type === "project" ? configInfo.path : GLOBAL_CONFIG_PATH;
249
+
250
+ // Backup existing config if it exists
251
+ if (fs.existsSync(targetPath)) {
252
+ const backupPath = `${targetPath}.backup.${Date.now()}`;
253
+ try {
254
+ fs.copyFileSync(targetPath, backupPath);
255
+ } catch {
256
+ // Ignore backup failure
257
+ }
258
+ }
259
+
260
+ try {
261
+ createDefaultConfig(targetPath);
262
+ return success(`Configuration reset to defaults.\nConfig file: ${targetPath}`);
263
+ } catch (err) {
264
+ return error(
265
+ "INTERNAL_ERROR",
266
+ `Failed to reset config: ${err instanceof Error ? err.message : String(err)}`
267
+ );
268
+ }
269
+ }
270
+
271
+ // =============================================================================
272
+ // /config Command
273
+ // =============================================================================
274
+
275
+ /**
276
+ * /config command - Manage configuration files.
277
+ *
278
+ * Usage:
279
+ * - /config - Show configuration status
280
+ * - /config path - Show config file path
281
+ * - /config edit - Open config in editor
282
+ * - /config reset - Reset to default configuration
283
+ */
284
+ export const configCommand: SlashCommand = {
285
+ name: "config",
286
+ description: "Manage configuration files",
287
+ kind: "builtin",
288
+ category: "config",
289
+ aliases: ["cfg"],
290
+ positionalArgs: [
291
+ {
292
+ name: "subcommand",
293
+ type: "string",
294
+ description: "Subcommand: path, edit, reset",
295
+ required: false,
296
+ },
297
+ ],
298
+ examples: [
299
+ "/config - Show configuration status",
300
+ "/config path - Show config file path",
301
+ "/config edit - Open config in editor",
302
+ "/config reset - Reset to default configuration",
303
+ ],
304
+ subcommands: [
305
+ { name: "path", description: "Show config file path" },
306
+ { name: "edit", description: "Open config in editor" },
307
+ { name: "reset", description: "Reset to default configuration" },
308
+ ],
309
+
310
+ execute: async (ctx: CommandContext): Promise<CommandResult> => {
311
+ const subcommand = ctx.parsedArgs.positional[0] as string | undefined;
312
+ const cwd = ctx.session.cwd;
313
+
314
+ switch (subcommand) {
315
+ case undefined:
316
+ case "":
317
+ return handleShowConfig(cwd);
318
+
319
+ case "path":
320
+ return handleConfigPath(cwd);
321
+
322
+ case "edit":
323
+ return handleConfigEdit(cwd);
324
+
325
+ case "reset":
326
+ return handleConfigReset(cwd);
327
+
328
+ default:
329
+ return error(
330
+ "INVALID_ARGUMENT",
331
+ `Unknown subcommand: ${subcommand}\n\nValid subcommands: path, edit, reset`
332
+ );
333
+ }
334
+ },
335
+ };
336
+
337
+ // =============================================================================
338
+ // Export Collection
339
+ // =============================================================================
340
+
341
+ /**
342
+ * All config-related slash commands.
343
+ */
344
+ export const configSlashCommands: readonly SlashCommand[] = [configCommand] as const;
@@ -0,0 +1,173 @@
1
+ /**
2
+ * Command Context Provider Implementation
3
+ *
4
+ * Provides CommandContext instances with all dependencies
5
+ * for command execution.
6
+ *
7
+ * @module cli/commands/context-provider
8
+ */
9
+
10
+ import type { CredentialManager, ToolRegistry } from "@vellum/core";
11
+
12
+ import type { CommandContextProvider } from "./executor.js";
13
+ import type { CommandContext, ParsedArgs, Session } from "./types.js";
14
+
15
+ // =============================================================================
16
+ // T037: DefaultContextProvider Implementation
17
+ // =============================================================================
18
+
19
+ /**
20
+ * Event emitter function type
21
+ */
22
+ export type EventEmitter = (event: string, data?: unknown) => void;
23
+
24
+ /**
25
+ * Options for creating a DefaultContextProvider
26
+ */
27
+ export interface DefaultContextProviderOptions {
28
+ /** Current session state */
29
+ readonly session: Session;
30
+ /** Credential manager instance */
31
+ readonly credentials: CredentialManager;
32
+ /** Tool registry instance */
33
+ readonly toolRegistry: ToolRegistry;
34
+ /** Event emitter function */
35
+ readonly emit?: EventEmitter;
36
+ }
37
+
38
+ /**
39
+ * Default implementation of CommandContextProvider
40
+ *
41
+ * Creates CommandContext instances with all required dependencies
42
+ * for command execution.
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const provider = new DefaultContextProvider({
47
+ * session: {
48
+ * id: 'session-123',
49
+ * provider: 'anthropic',
50
+ * cwd: process.cwd(),
51
+ * },
52
+ * credentials: credentialManager,
53
+ * toolRegistry: toolRegistry,
54
+ * emit: (event, data) => eventBus.emit(event, data),
55
+ * });
56
+ *
57
+ * const executor = new CommandExecutor(registry, provider);
58
+ * ```
59
+ */
60
+ export class DefaultContextProvider implements CommandContextProvider {
61
+ private readonly session: Session;
62
+ private readonly credentials: CredentialManager;
63
+ private readonly toolRegistry: ToolRegistry;
64
+ private readonly eventEmitter: EventEmitter;
65
+
66
+ /**
67
+ * Create a new DefaultContextProvider
68
+ *
69
+ * @param options - Provider configuration
70
+ */
71
+ constructor(options: DefaultContextProviderOptions) {
72
+ this.session = options.session;
73
+ this.credentials = options.credentials;
74
+ this.toolRegistry = options.toolRegistry;
75
+ this.eventEmitter = options.emit ?? (() => {});
76
+ }
77
+
78
+ /**
79
+ * Create a CommandContext for command execution
80
+ *
81
+ * @param parsedArgs - Parsed command arguments
82
+ * @param signal - Optional abort signal for cancellation
83
+ * @returns CommandContext with all dependencies
84
+ */
85
+ createContext(parsedArgs: ParsedArgs, signal?: AbortSignal): CommandContext {
86
+ return {
87
+ session: this.session,
88
+ credentials: this.credentials,
89
+ toolRegistry: this.toolRegistry,
90
+ parsedArgs,
91
+ signal,
92
+ emit: this.eventEmitter,
93
+ };
94
+ }
95
+
96
+ /**
97
+ * Update the session state
98
+ *
99
+ * @param session - New session state (partial update)
100
+ */
101
+ updateSession(session: Partial<Session>): void {
102
+ Object.assign(this.session, session);
103
+ }
104
+ }
105
+
106
+ // =============================================================================
107
+ // Factory Functions
108
+ // =============================================================================
109
+
110
+ /**
111
+ * Create a context provider with default settings
112
+ *
113
+ * @param options - Provider configuration
114
+ * @returns CommandContextProvider instance
115
+ */
116
+ export function createContextProvider(
117
+ options: DefaultContextProviderOptions
118
+ ): CommandContextProvider {
119
+ return new DefaultContextProvider(options);
120
+ }
121
+
122
+ /**
123
+ * Create a minimal context provider for testing
124
+ *
125
+ * @param overrides - Optional overrides for context values
126
+ * @returns CommandContextProvider instance
127
+ */
128
+ export function createTestContextProvider(
129
+ overrides?: Partial<DefaultContextProviderOptions>
130
+ ): CommandContextProvider {
131
+ // Create mock session
132
+ const session: Session = {
133
+ id: "test-session",
134
+ provider: "anthropic",
135
+ cwd: process.cwd(),
136
+ ...overrides?.session,
137
+ };
138
+
139
+ // Create mock credential manager
140
+ const credentials =
141
+ overrides?.credentials ??
142
+ ({
143
+ exists: async () => ({ ok: true, value: false }),
144
+ resolve: async () => ({ ok: false, error: { code: "NOT_FOUND", message: "Not found" } }),
145
+ store: async () => ({ ok: false, error: { code: "UNSUPPORTED", message: "Not supported" } }),
146
+ delete: async () => ({ ok: true, value: 0 }),
147
+ list: async () => ({ ok: true, value: [] }),
148
+ getStoreAvailability: async () => ({}),
149
+ } as unknown as CredentialManager);
150
+
151
+ // Create mock tool registry
152
+ const toolRegistry =
153
+ overrides?.toolRegistry ??
154
+ ({
155
+ register: () => {},
156
+ get: () => undefined,
157
+ has: () => false,
158
+ list: () => [],
159
+ listByKind: () => [],
160
+ getLLMDefinitions: () => [],
161
+ size: 0,
162
+ } as unknown as ToolRegistry);
163
+
164
+ // Create mock event emitter
165
+ const emit = overrides?.emit ?? (() => {});
166
+
167
+ return new DefaultContextProvider({
168
+ session,
169
+ credentials,
170
+ toolRegistry,
171
+ emit,
172
+ });
173
+ }