@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,136 @@
1
+ /**
2
+ * Root Provider Composition
3
+ *
4
+ * Composes all context providers in the correct order for the Vellum TUI.
5
+ * This is the single entry point for providing all application contexts.
6
+ *
7
+ * @module tui/context/RootProvider
8
+ */
9
+
10
+ import type { ToolExecutor, ToolRegistry } from "@vellum/core";
11
+ import type { ThemeName, ThemePreset, VellumTheme } from "@vellum/shared";
12
+ import type React from "react";
13
+ import type { ReactNode } from "react";
14
+
15
+ import { ThemeProvider } from "../theme/provider.js";
16
+ import { AnimationProvider } from "./AnimationContext.js";
17
+ import { AppProvider, type AppState } from "./AppContext.js";
18
+ import { BracketedPasteProvider } from "./BracketedPasteContext.js";
19
+ import { LspProvider } from "./LspContext.js";
20
+ import { McpProvider } from "./McpContext.js";
21
+ import { type Message, MessagesProvider } from "./MessagesContext.js";
22
+ import { OverflowProvider } from "./OverflowContext.js";
23
+ import { ResilienceProvider } from "./ResilienceContext.js";
24
+ import { ScrollProvider } from "./ScrollContext.js";
25
+ import { ToolsProvider } from "./ToolsContext.js";
26
+
27
+ // =============================================================================
28
+ // Types
29
+ // =============================================================================
30
+
31
+ /**
32
+ * Props for the RootProvider component
33
+ */
34
+ export interface RootProviderProps {
35
+ /**
36
+ * Children to render within all contexts
37
+ */
38
+ readonly children: ReactNode;
39
+
40
+ /**
41
+ * Theme configuration - can be a theme name, preset, or VellumTheme object
42
+ *
43
+ * @default "dark"
44
+ */
45
+ readonly theme?: ThemeName | ThemePreset | VellumTheme;
46
+
47
+ /**
48
+ * Initial application state overrides
49
+ *
50
+ * Partial state that will be merged with the default initial state
51
+ */
52
+ readonly initialAppState?: Partial<AppState>;
53
+
54
+ /**
55
+ * Initial messages to populate the conversation
56
+ */
57
+ readonly initialMessages?: readonly Message[];
58
+
59
+ /**
60
+ * Optional tool registry for MCP tool registration
61
+ */
62
+ readonly toolRegistry?: ToolRegistry;
63
+
64
+ /**
65
+ * Optional tool executor for MCP tool execution
66
+ */
67
+ readonly toolExecutor?: ToolExecutor;
68
+ }
69
+
70
+ // =============================================================================
71
+ // Component
72
+ // =============================================================================
73
+
74
+ /**
75
+ * Root provider component that composes all context providers
76
+ *
77
+ * Provider order (outermost to innermost):
78
+ * 1. ThemeProvider - Theme context for styling
79
+ * 2. AppProvider - Application state (mode, loading, errors)
80
+ * 3. MessagesProvider - Message/conversation state
81
+ * 4. ToolsProvider - Tool execution state
82
+ *
83
+ * @example
84
+ * ```tsx
85
+ * // Basic usage with defaults
86
+ * <RootProvider>
87
+ * <App />
88
+ * </RootProvider>
89
+ *
90
+ * // With custom theme
91
+ * <RootProvider theme="dracula">
92
+ * <App />
93
+ * </RootProvider>
94
+ *
95
+ * // With initial state
96
+ * <RootProvider
97
+ * theme="dark"
98
+ * initialAppState={{ vimMode: true }}
99
+ * initialMessages={[]}
100
+ * >
101
+ * <App />
102
+ * </RootProvider>
103
+ * ```
104
+ */
105
+ export function RootProvider({
106
+ children,
107
+ theme = "dark",
108
+ initialAppState,
109
+ initialMessages,
110
+ toolRegistry,
111
+ toolExecutor,
112
+ }: RootProviderProps): React.JSX.Element {
113
+ return (
114
+ <ThemeProvider theme={theme}>
115
+ <AnimationProvider>
116
+ <BracketedPasteProvider>
117
+ <OverflowProvider>
118
+ <ScrollProvider autoScrollToBottom>
119
+ <AppProvider initialState={initialAppState}>
120
+ <ResilienceProvider>
121
+ <McpProvider toolRegistry={toolRegistry} toolExecutor={toolExecutor}>
122
+ <LspProvider>
123
+ <MessagesProvider initialMessages={initialMessages}>
124
+ <ToolsProvider>{children}</ToolsProvider>
125
+ </MessagesProvider>
126
+ </LspProvider>
127
+ </McpProvider>
128
+ </ResilienceProvider>
129
+ </AppProvider>
130
+ </ScrollProvider>
131
+ </OverflowProvider>
132
+ </BracketedPasteProvider>
133
+ </AnimationProvider>
134
+ </ThemeProvider>
135
+ );
136
+ }
@@ -0,0 +1,331 @@
1
+ /**
2
+ * Scroll Context
3
+ *
4
+ * Centralized scroll state management for the Vellum TUI.
5
+ * Provides a unified API for scroll position tracking and control
6
+ * across virtualized lists and scrollable regions.
7
+ *
8
+ * Ported from Gemini CLI for Vellum TUI.
9
+ *
10
+ * @module tui/context/ScrollContext
11
+ */
12
+
13
+ import React, {
14
+ createContext,
15
+ type ReactNode,
16
+ useCallback,
17
+ useContext,
18
+ useMemo,
19
+ useRef,
20
+ useState,
21
+ } from "react";
22
+
23
+ // =============================================================================
24
+ // Types
25
+ // =============================================================================
26
+
27
+ /**
28
+ * Current scroll state
29
+ */
30
+ export interface ScrollState {
31
+ /** Current scroll position from top (in lines/rows) */
32
+ readonly scrollTop: number;
33
+ /** Maximum scroll position (totalHeight - containerHeight) */
34
+ readonly maxScrollTop: number;
35
+ /** Whether scrolled to the bottom */
36
+ readonly isAtBottom: boolean;
37
+ /** Whether scrolled to the top */
38
+ readonly isAtTop: boolean;
39
+ }
40
+
41
+ /**
42
+ * Context value providing scroll state and control functions
43
+ */
44
+ export interface ScrollContextValue {
45
+ /** Current scroll state */
46
+ readonly state: ScrollState;
47
+ /**
48
+ * Scroll to an absolute position
49
+ * @param position - Target scroll position (clamped to valid range)
50
+ */
51
+ readonly scrollTo: (position: number) => void;
52
+ /**
53
+ * Scroll to the bottom of the content
54
+ */
55
+ readonly scrollToBottom: () => void;
56
+ /**
57
+ * Scroll to the top of the content
58
+ */
59
+ readonly scrollToTop: () => void;
60
+ /**
61
+ * Scroll by a relative amount
62
+ * @param delta - Amount to scroll (positive = down, negative = up)
63
+ */
64
+ readonly scrollBy: (delta: number) => void;
65
+ /**
66
+ * Update the content dimensions (called by scrollable components)
67
+ * @param totalHeight - Total content height
68
+ * @param containerHeight - Visible container height
69
+ */
70
+ readonly updateDimensions: (totalHeight: number, containerHeight: number) => void;
71
+ /**
72
+ * Register a scroll callback for external scroll events
73
+ * @param callback - Function called when scroll position changes externally
74
+ * @returns Cleanup function to unregister
75
+ */
76
+ readonly onScrollChange: (callback: (scrollTop: number) => void) => () => void;
77
+ }
78
+
79
+ /**
80
+ * Props for the ScrollProvider component
81
+ */
82
+ export interface ScrollProviderProps {
83
+ /** Children to render within the scroll context */
84
+ readonly children: ReactNode;
85
+ /** Initial scroll position (default: 0) */
86
+ readonly initialScrollTop?: number;
87
+ /** Whether to auto-scroll to bottom on new content (default: true) */
88
+ readonly autoScrollToBottom?: boolean;
89
+ }
90
+
91
+ // =============================================================================
92
+ // Context
93
+ // =============================================================================
94
+
95
+ /**
96
+ * React context for scroll state management
97
+ */
98
+ export const ScrollContext = createContext<ScrollContextValue | null>(null);
99
+
100
+ // Set display name for debugging
101
+ ScrollContext.displayName = "ScrollContext";
102
+
103
+ // =============================================================================
104
+ // Provider Component
105
+ // =============================================================================
106
+
107
+ /**
108
+ * ScrollProvider manages centralized scroll state for the TUI.
109
+ *
110
+ * This provider enables coordinated scrolling across multiple components,
111
+ * such as synchronized sidebar and main content scrolling, or global
112
+ * keyboard-driven scroll control.
113
+ *
114
+ * @example
115
+ * ```tsx
116
+ * <ScrollProvider autoScrollToBottom>
117
+ * <Layout>
118
+ * <MessageList />
119
+ * </Layout>
120
+ * </ScrollProvider>
121
+ *
122
+ * // In a child component:
123
+ * const { state, scrollBy, scrollToBottom } = useScroll();
124
+ *
125
+ * // Handle keyboard scroll
126
+ * useEffect(() => {
127
+ * if (keyPressed === 'j') scrollBy(1);
128
+ * if (keyPressed === 'k') scrollBy(-1);
129
+ * if (keyPressed === 'G') scrollToBottom();
130
+ * }, [keyPressed]);
131
+ * ```
132
+ */
133
+ export function ScrollProvider({
134
+ children,
135
+ initialScrollTop = 0,
136
+ autoScrollToBottom = true,
137
+ }: ScrollProviderProps): React.JSX.Element {
138
+ // Scroll position state
139
+ const [scrollTop, setScrollTop] = useState(initialScrollTop);
140
+
141
+ // Content dimensions (updated by scrollable components)
142
+ const [dimensions, setDimensions] = useState({
143
+ totalHeight: 0,
144
+ containerHeight: 0,
145
+ });
146
+
147
+ // Track if user has scrolled away from bottom
148
+ const [userScrolledAway, setUserScrolledAway] = useState(false);
149
+
150
+ // Callback registry for external scroll listeners
151
+ const scrollCallbacks = useRef<Set<(scrollTop: number) => void>>(new Set());
152
+
153
+ /**
154
+ * Calculate derived scroll state
155
+ */
156
+ const maxScrollTop = Math.max(0, dimensions.totalHeight - dimensions.containerHeight);
157
+ const isAtBottom = scrollTop >= maxScrollTop - 1; // Allow 1-line tolerance
158
+ const isAtTop = scrollTop <= 0;
159
+
160
+ /**
161
+ * Notify all registered callbacks of scroll change
162
+ */
163
+ const notifyScrollChange = useCallback((newScrollTop: number) => {
164
+ for (const callback of scrollCallbacks.current) {
165
+ callback(newScrollTop);
166
+ }
167
+ }, []);
168
+
169
+ /**
170
+ * Scroll to an absolute position (clamped to valid range)
171
+ */
172
+ const scrollTo = useCallback(
173
+ (position: number) => {
174
+ const clamped = Math.max(0, Math.min(maxScrollTop, position));
175
+ setScrollTop(clamped);
176
+ setUserScrolledAway(clamped < maxScrollTop - 1);
177
+ notifyScrollChange(clamped);
178
+ },
179
+ [maxScrollTop, notifyScrollChange]
180
+ );
181
+
182
+ /**
183
+ * Scroll to the bottom
184
+ */
185
+ const scrollToBottom = useCallback(() => {
186
+ setScrollTop(maxScrollTop);
187
+ setUserScrolledAway(false);
188
+ notifyScrollChange(maxScrollTop);
189
+ }, [maxScrollTop, notifyScrollChange]);
190
+
191
+ /**
192
+ * Scroll to the top
193
+ */
194
+ const scrollToTop = useCallback(() => {
195
+ setScrollTop(0);
196
+ setUserScrolledAway(true);
197
+ notifyScrollChange(0);
198
+ }, [notifyScrollChange]);
199
+
200
+ /**
201
+ * Scroll by a relative amount
202
+ */
203
+ const scrollBy = useCallback(
204
+ (delta: number) => {
205
+ setScrollTop((prev) => {
206
+ const newPos = Math.max(0, Math.min(maxScrollTop, prev + delta));
207
+ if (delta < 0) {
208
+ setUserScrolledAway(true);
209
+ } else if (newPos >= maxScrollTop - 1) {
210
+ setUserScrolledAway(false);
211
+ }
212
+ notifyScrollChange(newPos);
213
+ return newPos;
214
+ });
215
+ },
216
+ [maxScrollTop, notifyScrollChange]
217
+ );
218
+
219
+ /**
220
+ * Update content dimensions (called by scrollable components)
221
+ */
222
+ const updateDimensions = useCallback(
223
+ (totalHeight: number, containerHeight: number) => {
224
+ setDimensions({ totalHeight, containerHeight });
225
+
226
+ // Auto-scroll to bottom if enabled and user hasn't scrolled away
227
+ if (autoScrollToBottom && !userScrolledAway) {
228
+ const newMax = Math.max(0, totalHeight - containerHeight);
229
+ setScrollTop(newMax);
230
+ notifyScrollChange(newMax);
231
+ }
232
+ },
233
+ [autoScrollToBottom, userScrolledAway, notifyScrollChange]
234
+ );
235
+
236
+ /**
237
+ * Register a scroll change callback
238
+ */
239
+ const onScrollChange = useCallback((callback: (scrollTop: number) => void): (() => void) => {
240
+ scrollCallbacks.current.add(callback);
241
+ return () => {
242
+ scrollCallbacks.current.delete(callback);
243
+ };
244
+ }, []);
245
+
246
+ /**
247
+ * Memoized scroll state
248
+ */
249
+ const state = useMemo<ScrollState>(
250
+ () => ({
251
+ scrollTop,
252
+ maxScrollTop,
253
+ isAtBottom,
254
+ isAtTop,
255
+ }),
256
+ [scrollTop, maxScrollTop, isAtBottom, isAtTop]
257
+ );
258
+
259
+ /**
260
+ * Memoized context value
261
+ */
262
+ const contextValue = useMemo<ScrollContextValue>(
263
+ () => ({
264
+ state,
265
+ scrollTo,
266
+ scrollToBottom,
267
+ scrollToTop,
268
+ scrollBy,
269
+ updateDimensions,
270
+ onScrollChange,
271
+ }),
272
+ [state, scrollTo, scrollToBottom, scrollToTop, scrollBy, updateDimensions, onScrollChange]
273
+ );
274
+
275
+ return <ScrollContext.Provider value={contextValue}>{children}</ScrollContext.Provider>;
276
+ }
277
+
278
+ // =============================================================================
279
+ // Hooks
280
+ // =============================================================================
281
+
282
+ /**
283
+ * Hook to access the scroll context.
284
+ *
285
+ * @returns The scroll context value
286
+ * @throws Error if used outside of a ScrollProvider
287
+ *
288
+ * @example
289
+ * ```tsx
290
+ * function ScrollIndicator() {
291
+ * const { state } = useScroll();
292
+ *
293
+ * return (
294
+ * <Text>
295
+ * {state.isAtTop ? '⬆ Top' : state.isAtBottom ? '⬇ Bottom' : `${state.scrollTop}/${state.maxScrollTop}`}
296
+ * </Text>
297
+ * );
298
+ * }
299
+ * ```
300
+ */
301
+ export function useScroll(): ScrollContextValue {
302
+ const context = useContext(ScrollContext);
303
+
304
+ if (context === null) {
305
+ throw new Error("useScroll must be used within a ScrollProvider");
306
+ }
307
+
308
+ return context;
309
+ }
310
+
311
+ /**
312
+ * Optional hook that returns null instead of throwing when used outside provider.
313
+ * Useful for components that may work with or without scroll context.
314
+ *
315
+ * @returns The scroll context value or null if not within a provider
316
+ */
317
+ export function useScrollOptional(): ScrollContextValue | null {
318
+ return useContext(ScrollContext);
319
+ }
320
+
321
+ /**
322
+ * Hook that returns only the scroll state (no control functions).
323
+ * Useful for read-only scroll position display.
324
+ *
325
+ * @returns The current scroll state
326
+ * @throws Error if used outside of a ScrollProvider
327
+ */
328
+ export function useScrollState(): ScrollState {
329
+ const { state } = useScroll();
330
+ return state;
331
+ }