@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,192 @@
1
+ /**
2
+ * LSP Context Provider
3
+ *
4
+ * Provides LSP (Language Server Protocol) state management for the TUI.
5
+ * Subscribes to LSP integration manager state updates and provides
6
+ * status information to UI components.
7
+ *
8
+ * @module tui/context/LspContext
9
+ */
10
+
11
+ import {
12
+ createContext,
13
+ type ReactNode,
14
+ useCallback,
15
+ useContext,
16
+ useEffect,
17
+ useMemo,
18
+ useState,
19
+ } from "react";
20
+
21
+ import { getLspManager, type LspIntegrationState } from "../lsp-integration.js";
22
+
23
+ // =============================================================================
24
+ // Types
25
+ // =============================================================================
26
+
27
+ /**
28
+ * LSP Context state
29
+ */
30
+ export interface LspContextState {
31
+ /** Whether LSP is initialized */
32
+ readonly isInitialized: boolean;
33
+ /** Number of running LSP servers */
34
+ readonly runningServers: number;
35
+ /** Total number of configured LSP servers */
36
+ readonly totalServers: number;
37
+ /** Currently running server IDs */
38
+ readonly runningServerIds: readonly string[];
39
+ /** Whether tools are registered */
40
+ readonly toolsRegistered: boolean;
41
+ /** Error that occurred, if any */
42
+ readonly error: Error | null;
43
+ /** Refresh LSP state */
44
+ readonly refresh: () => void;
45
+ }
46
+
47
+ /**
48
+ * LSP Context
49
+ */
50
+ const LspContext = createContext<LspContextState | null>(null);
51
+
52
+ // =============================================================================
53
+ // Provider Props
54
+ // =============================================================================
55
+
56
+ /**
57
+ * Props for LspProvider
58
+ */
59
+ export interface LspProviderProps {
60
+ /** Children to render */
61
+ readonly children: ReactNode;
62
+ /** Refresh interval in milliseconds (default: 2000) */
63
+ readonly refreshInterval?: number;
64
+ }
65
+
66
+ // =============================================================================
67
+ // Provider Component
68
+ // =============================================================================
69
+
70
+ /**
71
+ * LSP Provider component.
72
+ *
73
+ * Subscribes to LSP integration manager state and provides it to the component tree.
74
+ * Automatically refreshes state at the specified interval.
75
+ *
76
+ * @example
77
+ * ```tsx
78
+ * <LspProvider>
79
+ * <App />
80
+ * </LspProvider>
81
+ * ```
82
+ */
83
+ export function LspProvider({
84
+ children,
85
+ refreshInterval = 2000,
86
+ }: LspProviderProps): React.JSX.Element {
87
+ const [isInitialized, setIsInitialized] = useState(false);
88
+ const [runningServers, setRunningServers] = useState(0);
89
+ const [totalServers, setTotalServers] = useState(0);
90
+ const [runningServerIds, setRunningServerIds] = useState<readonly string[]>([]);
91
+ const [toolsRegistered, setToolsRegistered] = useState(false);
92
+ const [error, setError] = useState<Error | null>(null);
93
+
94
+ /**
95
+ * Refresh LSP state from the manager
96
+ */
97
+ const refresh = useCallback(() => {
98
+ try {
99
+ const manager = getLspManager();
100
+ const state: LspIntegrationState = manager.getState();
101
+ const hub = manager.getHub();
102
+
103
+ setIsInitialized(state.initialized);
104
+ setRunningServerIds(state.runningServers);
105
+ setRunningServers(state.runningServers.length);
106
+ setToolsRegistered(state.toolsRegistered);
107
+
108
+ // Get total configured servers from hub
109
+ if (hub) {
110
+ const servers = hub.getServers();
111
+ setTotalServers(servers.length);
112
+ } else {
113
+ setTotalServers(0);
114
+ }
115
+
116
+ setError(null);
117
+ } catch (err) {
118
+ setError(err instanceof Error ? err : new Error(String(err)));
119
+ }
120
+ }, []);
121
+
122
+ // Initial refresh and interval
123
+ useEffect(() => {
124
+ // Immediate refresh
125
+ refresh();
126
+
127
+ // Set up interval for periodic refresh
128
+ const intervalId = setInterval(refresh, refreshInterval);
129
+
130
+ return () => {
131
+ clearInterval(intervalId);
132
+ };
133
+ }, [refresh, refreshInterval]);
134
+
135
+ // Create context value
136
+ const contextValue = useMemo<LspContextState>(
137
+ () => ({
138
+ isInitialized,
139
+ runningServers,
140
+ totalServers,
141
+ runningServerIds,
142
+ toolsRegistered,
143
+ error,
144
+ refresh,
145
+ }),
146
+ [isInitialized, runningServers, totalServers, runningServerIds, toolsRegistered, error, refresh]
147
+ );
148
+
149
+ return <LspContext value={contextValue}>{children}</LspContext>;
150
+ }
151
+
152
+ // =============================================================================
153
+ // Hook
154
+ // =============================================================================
155
+
156
+ /**
157
+ * Hook to access LSP context.
158
+ *
159
+ * @returns LSP context state
160
+ * @throws Error if used outside LspProvider
161
+ *
162
+ * @example
163
+ * ```tsx
164
+ * function MyComponent() {
165
+ * const { isInitialized, runningServers, totalServers } = useLsp();
166
+ *
167
+ * if (!isInitialized) {
168
+ * return <Text>LSP: off</Text>;
169
+ * }
170
+ *
171
+ * return <Text>LSP: {runningServers}/{totalServers}</Text>;
172
+ * }
173
+ * ```
174
+ */
175
+ export function useLsp(): LspContextState {
176
+ const context = useContext(LspContext);
177
+
178
+ if (!context) {
179
+ throw new Error("useLsp must be used within a LspProvider");
180
+ }
181
+
182
+ return context;
183
+ }
184
+
185
+ /**
186
+ * Hook to access LSP context optionally (returns null if outside provider).
187
+ *
188
+ * @returns LSP context state or null
189
+ */
190
+ export function useLspOptional(): LspContextState | null {
191
+ return useContext(LspContext);
192
+ }
@@ -0,0 +1,325 @@
1
+ /**
2
+ * MCP Context Provider
3
+ *
4
+ * Provides McpHub initialization and lifecycle management for the TUI.
5
+ * Handles startup initialization and graceful shutdown via ProcessManager.
6
+ *
7
+ * @module tui/context/McpContext
8
+ */
9
+
10
+ import fs from "node:fs/promises";
11
+ import os from "node:os";
12
+ import path from "node:path";
13
+ import type { ToolExecutor, ToolRegistry } from "@vellum/core";
14
+ import {
15
+ type CoreCredentialManager,
16
+ createOAuthCredentialAdapter,
17
+ getProcessManager,
18
+ McpHub,
19
+ type McpHubOptions,
20
+ type OAuthCredentialManager,
21
+ } from "@vellum/mcp";
22
+ import {
23
+ createContext,
24
+ type ReactNode,
25
+ useCallback,
26
+ useContext,
27
+ useEffect,
28
+ useMemo,
29
+ useState,
30
+ } from "react";
31
+
32
+ // =============================================================================
33
+ // T047: MCP Context Types
34
+ // =============================================================================
35
+
36
+ /**
37
+ * MCP Context state
38
+ */
39
+ export interface McpContextState {
40
+ /** McpHub instance (null until initialized) */
41
+ readonly hub: McpHub | null;
42
+ /** Whether MCP is initialized */
43
+ readonly isInitialized: boolean;
44
+ /** Whether MCP is currently initializing */
45
+ readonly isInitializing: boolean;
46
+ /** Error that occurred during initialization, if any */
47
+ readonly error: Error | null;
48
+ /** Reinitialize MCP (e.g., after config change) */
49
+ readonly reinitialize: () => Promise<void>;
50
+ }
51
+
52
+ /**
53
+ * MCP Context
54
+ */
55
+ const McpContext = createContext<McpContextState | null>(null);
56
+
57
+ // =============================================================================
58
+ // T047: MCP Provider Props
59
+ // =============================================================================
60
+
61
+ /**
62
+ * Props for McpProvider
63
+ */
64
+ export interface McpProviderProps {
65
+ /** Children to render */
66
+ readonly children: ReactNode;
67
+ /** Whether to auto-initialize on mount (default: true) */
68
+ readonly autoInitialize?: boolean;
69
+ /** Client version for MCP protocol */
70
+ readonly clientVersion?: string;
71
+ /** Optional project config path override */
72
+ readonly projectConfigPath?: string;
73
+ /**
74
+ * Optional credential manager for OAuth token persistence.
75
+ * Can be either a CoreCredentialManager (from @vellum/core) or
76
+ * an OAuthCredentialManager directly.
77
+ */
78
+ readonly credentialManager?: CoreCredentialManager | OAuthCredentialManager;
79
+ /** Optional tool registry for MCP tool registration */
80
+ readonly toolRegistry?: ToolRegistry;
81
+ /** Optional tool executor for MCP tool execution */
82
+ readonly toolExecutor?: ToolExecutor;
83
+ }
84
+
85
+ // =============================================================================
86
+ // T047: Default Paths
87
+ // =============================================================================
88
+
89
+ /**
90
+ * Get the default Vellum settings directory path.
91
+ * On Windows: %USERPROFILE%\.vellum
92
+ * On Unix: ~/.vellum
93
+ */
94
+ async function getDefaultSettingsPath(): Promise<string> {
95
+ const home = os.homedir();
96
+ const settingsDir = path.join(home, ".vellum");
97
+
98
+ // Ensure directory exists
99
+ await fs.mkdir(settingsDir, { recursive: true });
100
+
101
+ return settingsDir;
102
+ }
103
+
104
+ /**
105
+ * Get the default MCP servers config path.
106
+ * Returns ~/.vellum/mcp.json
107
+ */
108
+ async function getDefaultMcpServersPath(): Promise<string> {
109
+ const settingsDir = await getDefaultSettingsPath();
110
+ return path.join(settingsDir, "mcp.json");
111
+ }
112
+
113
+ // =============================================================================
114
+ // T047: MCP Provider Component
115
+ // =============================================================================
116
+
117
+ /**
118
+ * MCP Provider component.
119
+ *
120
+ * Initializes McpHub on mount and registers cleanup with ProcessManager
121
+ * for graceful shutdown handling.
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * <McpProvider clientVersion="1.0.0">
126
+ * <App />
127
+ * </McpProvider>
128
+ * ```
129
+ */
130
+ export function McpProvider({
131
+ children,
132
+ autoInitialize = true,
133
+ clientVersion = "1.0.0",
134
+ projectConfigPath,
135
+ credentialManager,
136
+ toolRegistry,
137
+ toolExecutor,
138
+ }: McpProviderProps): React.JSX.Element {
139
+ const [hub, setHub] = useState<McpHub | null>(null);
140
+ const [isInitialized, setIsInitialized] = useState(false);
141
+ const [isInitializing, setIsInitializing] = useState(false);
142
+ const [error, setError] = useState<Error | null>(null);
143
+
144
+ /**
145
+ * Initialize McpHub and register with ProcessManager
146
+ */
147
+ const initialize = useCallback(async () => {
148
+ if (isInitializing || hub) {
149
+ return;
150
+ }
151
+
152
+ setIsInitializing(true);
153
+ setError(null);
154
+
155
+ try {
156
+ // Adapt credential manager if needed
157
+ // If it looks like a CoreCredentialManager (Result-based API), wrap it
158
+ let oauthCredentialManager: OAuthCredentialManager | undefined;
159
+ if (credentialManager) {
160
+ // Check if it's already an OAuthCredentialManager (has void-returning methods)
161
+ // vs a CoreCredentialManager (has Result-returning methods)
162
+ // We duck-type check by looking at resolve return type
163
+ const testResolve = credentialManager.resolve("test");
164
+ if (testResolve instanceof Promise) {
165
+ const result = await testResolve;
166
+ // If result has 'ok' property, it's a CoreCredentialManager
167
+ if (result && typeof result === "object" && "ok" in result) {
168
+ oauthCredentialManager = createOAuthCredentialAdapter(
169
+ credentialManager as CoreCredentialManager
170
+ );
171
+ } else {
172
+ // It's already an OAuthCredentialManager
173
+ oauthCredentialManager = credentialManager as OAuthCredentialManager;
174
+ }
175
+ }
176
+ }
177
+
178
+ // Create McpHub options
179
+ const options: McpHubOptions = {
180
+ getMcpServersPath: getDefaultMcpServersPath,
181
+ getSettingsDirectoryPath: getDefaultSettingsPath,
182
+ clientVersion,
183
+ projectConfigPath: projectConfigPath ? () => Promise.resolve(projectConfigPath) : undefined,
184
+ credentialManager: oauthCredentialManager,
185
+ toolRegistry,
186
+ toolExecutor,
187
+ };
188
+
189
+ // Create and initialize McpHub
190
+ const newHub = new McpHub(options);
191
+ await newHub.initialize();
192
+
193
+ // Register with ProcessManager for graceful shutdown
194
+ const processManager = getProcessManager();
195
+ processManager.onCleanup(async () => {
196
+ await newHub.dispose();
197
+ });
198
+
199
+ setHub(newHub);
200
+ setIsInitialized(true);
201
+ } catch (err) {
202
+ const initError = err instanceof Error ? err : new Error(String(err));
203
+ setError(initError);
204
+ console.error("[MCP] Initialization failed:", initError.message);
205
+ } finally {
206
+ setIsInitializing(false);
207
+ }
208
+ }, [
209
+ clientVersion,
210
+ projectConfigPath,
211
+ hub,
212
+ isInitializing,
213
+ credentialManager,
214
+ toolRegistry,
215
+ toolExecutor,
216
+ ]);
217
+
218
+ /**
219
+ * Reinitialize MCP (dispose and recreate)
220
+ */
221
+ const reinitialize = useCallback(async () => {
222
+ // Dispose existing hub
223
+ if (hub) {
224
+ try {
225
+ await hub.dispose();
226
+ } catch (err) {
227
+ console.warn("[MCP] Error disposing hub during reinitialize:", err);
228
+ }
229
+ setHub(null);
230
+ setIsInitialized(false);
231
+ }
232
+
233
+ // Re-initialize
234
+ await initialize();
235
+ }, [hub, initialize]);
236
+
237
+ // Auto-initialize on mount
238
+ useEffect(() => {
239
+ if (autoInitialize && !hub && !isInitializing) {
240
+ initialize();
241
+ }
242
+ }, [autoInitialize, hub, isInitializing, initialize]);
243
+
244
+ // Cleanup on unmount
245
+ useEffect(() => {
246
+ return () => {
247
+ if (hub) {
248
+ hub.dispose().catch((err) => {
249
+ console.warn("[MCP] Error disposing hub on unmount:", err);
250
+ });
251
+ }
252
+ };
253
+ }, [hub]);
254
+
255
+ // Create context value
256
+ const contextValue = useMemo<McpContextState>(
257
+ () => ({
258
+ hub,
259
+ isInitialized,
260
+ isInitializing,
261
+ error,
262
+ reinitialize,
263
+ }),
264
+ [hub, isInitialized, isInitializing, error, reinitialize]
265
+ );
266
+
267
+ return <McpContext value={contextValue}>{children}</McpContext>;
268
+ }
269
+
270
+ // =============================================================================
271
+ // T047: Hook
272
+ // =============================================================================
273
+
274
+ /**
275
+ * Hook to access MCP context.
276
+ *
277
+ * @returns MCP context state
278
+ * @throws Error if used outside McpProvider
279
+ *
280
+ * @example
281
+ * ```tsx
282
+ * function MyComponent() {
283
+ * const { hub, isInitialized, error } = useMcp();
284
+ *
285
+ * if (!isInitialized) {
286
+ * return <Text>Loading MCP...</Text>;
287
+ * }
288
+ *
289
+ * if (error) {
290
+ * return <Text color="red">MCP Error: {error.message}</Text>;
291
+ * }
292
+ *
293
+ * // Use hub...
294
+ * }
295
+ * ```
296
+ */
297
+ export function useMcp(): McpContextState {
298
+ const context = useContext(McpContext);
299
+
300
+ if (!context) {
301
+ throw new Error("useMcp must be used within a McpProvider");
302
+ }
303
+
304
+ return context;
305
+ }
306
+
307
+ /**
308
+ * Hook to access McpHub directly (throws if not initialized).
309
+ *
310
+ * @returns McpHub instance
311
+ * @throws Error if MCP is not initialized or used outside provider
312
+ */
313
+ export function useMcpHub(): McpHub {
314
+ const { hub, isInitialized, error } = useMcp();
315
+
316
+ if (error) {
317
+ throw error;
318
+ }
319
+
320
+ if (!isInitialized || !hub) {
321
+ throw new Error("McpHub is not initialized");
322
+ }
323
+
324
+ return hub;
325
+ }