@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,371 @@
1
+ /**
2
+ * Shell Completion Generator (T-047)
3
+ *
4
+ * Generates shell completion scripts for various shells.
5
+ * Supports: bash, zsh, fish, powershell
6
+ *
7
+ * @module cli/commands/completion
8
+ */
9
+
10
+ import type { CommandRegistry } from "../registry.js";
11
+ import type { SlashCommand } from "../types.js";
12
+
13
+ // =============================================================================
14
+ // Interfaces
15
+ // =============================================================================
16
+
17
+ /**
18
+ * Shell completion generator interface
19
+ *
20
+ * Implementations generate shell-specific completion scripts.
21
+ */
22
+ export interface CompletionGenerator {
23
+ /** Shell name for identification */
24
+ readonly shell: ShellType;
25
+
26
+ /**
27
+ * Generate completion script
28
+ *
29
+ * @param commands - Available commands to complete
30
+ * @param programName - CLI program name (e.g., 'vellum')
31
+ * @returns Shell script as string
32
+ */
33
+ generate(commands: readonly SlashCommand[], programName: string): string;
34
+ }
35
+
36
+ /**
37
+ * Supported shell types
38
+ */
39
+ export type ShellType = "bash" | "zsh" | "fish" | "powershell";
40
+
41
+ /**
42
+ * Completion generation options
43
+ */
44
+ export interface CompletionOptions {
45
+ /** CLI program name */
46
+ programName: string;
47
+ /** Target shell */
48
+ shell: ShellType;
49
+ /** Include command descriptions in completions */
50
+ includeDescriptions?: boolean;
51
+ }
52
+
53
+ // =============================================================================
54
+ // Bash Completion Generator
55
+ // =============================================================================
56
+
57
+ /**
58
+ * Generates Bash completion script
59
+ */
60
+ export class BashCompletionGenerator implements CompletionGenerator {
61
+ readonly shell: ShellType = "bash";
62
+
63
+ generate(commands: readonly SlashCommand[], programName: string): string {
64
+ const commandNames = commands.map((c) => c.name).join(" ");
65
+ const commandCompletions = commands
66
+ .map((c) => {
67
+ const flags = (c.namedArgs ?? []).map((a) => `--${a.name}`).join(" ");
68
+ return flags
69
+ ? ` ${c.name}) COMPREPLY=( $(compgen -W "${flags}" -- "\${cur}") );;`
70
+ : "";
71
+ })
72
+ .filter(Boolean)
73
+ .join("\n");
74
+
75
+ return `# Bash completion for ${programName}
76
+ # Add to ~/.bashrc: source <(${programName} completion bash)
77
+
78
+ _${programName}_completions() {
79
+ local cur prev commands
80
+ COMPREPLY=()
81
+ cur="\${COMP_WORDS[COMP_CWORD]}"
82
+ prev="\${COMP_WORDS[COMP_CWORD-1]}"
83
+ commands="${commandNames}"
84
+
85
+ if [[ \${COMP_CWORD} -eq 1 ]]; then
86
+ # Complete command names (with / prefix)
87
+ if [[ \${cur} == /* ]]; then
88
+ COMPREPLY=( $(compgen -P "/" -W "\${commands}" -- "\${cur#/}") )
89
+ else
90
+ COMPREPLY=( $(compgen -W "\${commands}" -- "\${cur}") )
91
+ fi
92
+ return 0
93
+ fi
94
+
95
+ # Complete command-specific flags
96
+ case "\${COMP_WORDS[1]#/}" in
97
+ ${commandCompletions}
98
+ *);;
99
+ esac
100
+
101
+ return 0
102
+ }
103
+
104
+ complete -F _${programName}_completions ${programName}
105
+ `;
106
+ }
107
+ }
108
+
109
+ // =============================================================================
110
+ // Zsh Completion Generator
111
+ // =============================================================================
112
+
113
+ /**
114
+ * Generates Zsh completion script
115
+ */
116
+ export class ZshCompletionGenerator implements CompletionGenerator {
117
+ readonly shell: ShellType = "zsh";
118
+
119
+ generate(commands: readonly SlashCommand[], programName: string): string {
120
+ const commandCompletions = commands
121
+ .map((c) => ` '/${c.name}:${this.escapeDescription(c.description)}'`)
122
+ .join(" \\\n");
123
+
124
+ const subcommandCompletions = commands
125
+ .filter((c) => c.namedArgs && c.namedArgs.length > 0)
126
+ .map((c) => {
127
+ const flags = (c.namedArgs ?? [])
128
+ .map((a) => {
129
+ const desc = this.escapeDescription(a.description);
130
+ return ` '--${a.name}[${desc}]'`;
131
+ })
132
+ .join(" \\\n");
133
+ return ` ${c.name})\n _arguments \\\n${flags}\n ;;`;
134
+ })
135
+ .join("\n");
136
+
137
+ return `#compdef ${programName}
138
+ # Zsh completion for ${programName}
139
+ # Add to fpath or source directly
140
+
141
+ _${programName}() {
142
+ local -a commands
143
+ commands=(
144
+ ${commandCompletions}
145
+ )
146
+
147
+ _arguments -C \\
148
+ '1: :->command' \\
149
+ '*: :->args'
150
+
151
+ case $state in
152
+ command)
153
+ _describe 'commands' commands
154
+ ;;
155
+ args)
156
+ case \${words[2]#/} in
157
+ ${subcommandCompletions}
158
+ esac
159
+ ;;
160
+ esac
161
+ }
162
+
163
+ _${programName} "$@"
164
+ `;
165
+ }
166
+
167
+ private escapeDescription(desc: string): string {
168
+ return desc.replace(/'/g, "'\\''").replace(/\[/g, "\\[").replace(/\]/g, "\\]");
169
+ }
170
+ }
171
+
172
+ // =============================================================================
173
+ // Fish Completion Generator
174
+ // =============================================================================
175
+
176
+ /**
177
+ * Generates Fish shell completion script
178
+ */
179
+ export class FishCompletionGenerator implements CompletionGenerator {
180
+ readonly shell: ShellType = "fish";
181
+
182
+ generate(commands: readonly SlashCommand[], programName: string): string {
183
+ const commandCompletions = commands
184
+ .map(
185
+ (c) =>
186
+ `complete -c ${programName} -n "__fish_use_subcommand" -a "/${c.name}" -d '${this.escapeDescription(c.description)}'`
187
+ )
188
+ .join("\n");
189
+
190
+ const flagCompletions = commands
191
+ .filter((c) => c.namedArgs && c.namedArgs.length > 0)
192
+ .flatMap((c) =>
193
+ (c.namedArgs ?? []).map(
194
+ (a) =>
195
+ `complete -c ${programName} -n "__fish_seen_subcommand_from /${c.name}" -l ${a.name} -d '${this.escapeDescription(a.description)}'`
196
+ )
197
+ )
198
+ .join("\n");
199
+
200
+ return `# Fish completion for ${programName}
201
+ # Save to ~/.config/fish/completions/${programName}.fish
202
+
203
+ # Disable file completions for command position
204
+ complete -c ${programName} -f
205
+
206
+ # Command completions
207
+ ${commandCompletions}
208
+
209
+ # Flag completions
210
+ ${flagCompletions}
211
+ `;
212
+ }
213
+
214
+ private escapeDescription(desc: string): string {
215
+ return desc.replace(/'/g, "\\'");
216
+ }
217
+ }
218
+
219
+ // =============================================================================
220
+ // PowerShell Completion Generator
221
+ // =============================================================================
222
+
223
+ /**
224
+ * Generates PowerShell completion script
225
+ */
226
+ export class PowerShellCompletionGenerator implements CompletionGenerator {
227
+ readonly shell: ShellType = "powershell";
228
+
229
+ generate(commands: readonly SlashCommand[], programName: string): string {
230
+ const commandCompletions = commands
231
+ .map(
232
+ (c) =>
233
+ ` @{ Command = '/${c.name}'; Description = '${this.escapeDescription(c.description)}'; Flags = @(${this.formatFlags(c)}) }`
234
+ )
235
+ .join("\n");
236
+
237
+ return `# PowerShell completion for ${programName}
238
+ # Add to $PROFILE: . <(${programName} completion powershell)
239
+
240
+ $${programName}Commands = @(
241
+ ${commandCompletions}
242
+ )
243
+
244
+ Register-ArgumentCompleter -Native -CommandName ${programName} -ScriptBlock {
245
+ param($wordToComplete, $commandAst, $cursorPosition)
246
+
247
+ $commands = $${programName}Commands
248
+
249
+ # Get current command state
250
+ $elements = $commandAst.CommandElements
251
+ $command = $null
252
+
253
+ if ($elements.Count -gt 1) {
254
+ $command = $elements[1].ToString()
255
+ }
256
+
257
+ if (-not $command -or $wordToComplete -eq $command) {
258
+ # Complete command names
259
+ $commands | Where-Object {
260
+ $_.Command -like "$wordToComplete*"
261
+ } | ForEach-Object {
262
+ [System.Management.Automation.CompletionResult]::new(
263
+ $_.Command,
264
+ $_.Command,
265
+ 'ParameterValue',
266
+ $_.Description
267
+ )
268
+ }
269
+ }
270
+ else {
271
+ # Complete flags for command
272
+ $cmdInfo = $commands | Where-Object { $_.Command -eq $command }
273
+ if ($cmdInfo) {
274
+ $cmdInfo.Flags | Where-Object {
275
+ $_ -like "$wordToComplete*"
276
+ } | ForEach-Object {
277
+ [System.Management.Automation.CompletionResult]::new(
278
+ $_,
279
+ $_,
280
+ 'ParameterName',
281
+ $_
282
+ )
283
+ }
284
+ }
285
+ }
286
+ }
287
+ `;
288
+ }
289
+
290
+ private escapeDescription(desc: string): string {
291
+ return desc.replace(/'/g, "''");
292
+ }
293
+
294
+ private formatFlags(command: SlashCommand): string {
295
+ if (!command.namedArgs || command.namedArgs.length === 0) {
296
+ return "";
297
+ }
298
+ return command.namedArgs.map((a) => `'--${a.name}'`).join(", ");
299
+ }
300
+ }
301
+
302
+ // =============================================================================
303
+ // Completion Factory
304
+ // =============================================================================
305
+
306
+ /**
307
+ * Registry of shell completion generators
308
+ */
309
+ const GENERATORS: Record<ShellType, CompletionGenerator> = {
310
+ bash: new BashCompletionGenerator(),
311
+ zsh: new ZshCompletionGenerator(),
312
+ fish: new FishCompletionGenerator(),
313
+ powershell: new PowerShellCompletionGenerator(),
314
+ };
315
+
316
+ /**
317
+ * Get available shell types
318
+ */
319
+ export function getAvailableShells(): readonly ShellType[] {
320
+ return Object.keys(GENERATORS) as ShellType[];
321
+ }
322
+
323
+ /**
324
+ * Check if a shell type is supported
325
+ */
326
+ export function isValidShell(shell: string): shell is ShellType {
327
+ return shell in GENERATORS;
328
+ }
329
+
330
+ /**
331
+ * Get a completion generator for a specific shell
332
+ *
333
+ * @param shell - Target shell type
334
+ * @returns Completion generator for the shell
335
+ * @throws Error if shell is not supported
336
+ */
337
+ export function getGenerator(shell: ShellType): CompletionGenerator {
338
+ const generator = GENERATORS[shell];
339
+ if (!generator) {
340
+ throw new Error(`Unsupported shell: ${shell}. Supported: ${getAvailableShells().join(", ")}`);
341
+ }
342
+ return generator;
343
+ }
344
+
345
+ /**
346
+ * Generate completion script for a shell
347
+ *
348
+ * @param options - Completion options
349
+ * @param registry - Command registry to get commands from
350
+ * @returns Generated shell script
351
+ */
352
+ export function generateCompletion(options: CompletionOptions, registry: CommandRegistry): string {
353
+ const generator = getGenerator(options.shell);
354
+ const commands = registry.list();
355
+ return generator.generate(commands, options.programName);
356
+ }
357
+
358
+ /**
359
+ * Generate completion script from a list of commands
360
+ *
361
+ * @param options - Completion options
362
+ * @param commands - Commands to generate completions for
363
+ * @returns Generated shell script
364
+ */
365
+ export function generateCompletionFromCommands(
366
+ options: CompletionOptions,
367
+ commands: readonly SlashCommand[]
368
+ ): string {
369
+ const generator = getGenerator(options.shell);
370
+ return generator.generate(commands, options.programName);
371
+ }
@@ -0,0 +1,191 @@
1
+ /**
2
+ * Condense Slash Command (Context Management)
3
+ *
4
+ * Provides slash command for manually triggering context window optimization:
5
+ * - /condense - Compact the conversation context
6
+ * - /condense status - Show current context state
7
+ *
8
+ * @module cli/commands/condense
9
+ */
10
+
11
+ import type { AgentLoop, ContextManageResult } from "@vellum/core";
12
+ import type { CommandContext, CommandResult, SlashCommand } from "./types.js";
13
+ import { error, success } from "./types.js";
14
+
15
+ // =============================================================================
16
+ // Module State
17
+ // =============================================================================
18
+
19
+ /**
20
+ * Reference to the active AgentLoop instance.
21
+ * Set by the App component when an agent session is active.
22
+ */
23
+ let agentLoopRef: AgentLoop | null = null;
24
+
25
+ /**
26
+ * Set the AgentLoop instance for context management commands.
27
+ * Called by the App component when an agent session starts/ends.
28
+ *
29
+ * @param loop - The AgentLoop instance to use, or null when session ends
30
+ */
31
+ export function setCondenseCommandLoop(loop: AgentLoop | null): void {
32
+ agentLoopRef = loop;
33
+ }
34
+
35
+ /**
36
+ * Get the current AgentLoop instance.
37
+ * Returns null if no agent session is active.
38
+ */
39
+ export function getCondenseCommandLoop(): AgentLoop | null {
40
+ return agentLoopRef;
41
+ }
42
+
43
+ // =============================================================================
44
+ // Types
45
+ // =============================================================================
46
+
47
+ /**
48
+ * Context state descriptions for user display
49
+ */
50
+ const CONTEXT_STATE_DESCRIPTIONS: Record<string, string> = {
51
+ healthy: "Context is healthy, no action needed",
52
+ warning: "Context is approaching limits, may compress soon",
53
+ critical: "Context is near capacity, compression recommended",
54
+ overflow: "Context has exceeded limits, compression required",
55
+ };
56
+
57
+ /**
58
+ * Get human-readable description for context state
59
+ */
60
+ function getStateDescription(state: string): string {
61
+ return CONTEXT_STATE_DESCRIPTIONS[state] ?? `Unknown state: ${state}`;
62
+ }
63
+
64
+ /**
65
+ * Format context management result for display
66
+ */
67
+ function formatResult(result: ContextManageResult): string {
68
+ const lines: string[] = [];
69
+
70
+ if (result.modified) {
71
+ lines.push("✅ Context compacted successfully");
72
+ lines.push("");
73
+ lines.push(`📊 State: ${result.state}`);
74
+
75
+ if (result.actions.length > 0) {
76
+ lines.push(`🔧 Actions taken:`);
77
+ for (const action of result.actions) {
78
+ lines.push(` â€ĸ ${action}`);
79
+ }
80
+ }
81
+
82
+ lines.push(`📝 Messages: ${result.messages.length}`);
83
+ } else {
84
+ lines.push("â„šī¸ No compaction needed");
85
+ lines.push("");
86
+ lines.push(`📊 State: ${result.state}`);
87
+ lines.push(`💡 ${getStateDescription(result.state)}`);
88
+ }
89
+
90
+ return lines.join("\n");
91
+ }
92
+
93
+ // =============================================================================
94
+ // /condense Command
95
+ // =============================================================================
96
+
97
+ /**
98
+ * /condense command - Manually compact the conversation context.
99
+ *
100
+ * Usage:
101
+ * /condense - Compact the context immediately
102
+ * /condense status - Show current context state
103
+ */
104
+ export const condenseCommand: SlashCommand = {
105
+ name: "condense",
106
+ description: "Compact conversation context to free up token space",
107
+ kind: "builtin",
108
+ category: "workflow",
109
+ aliases: ["compact", "compress"],
110
+ subcommands: [{ name: "status", description: "Show current context state" }],
111
+ positionalArgs: [
112
+ {
113
+ name: "subcommand",
114
+ type: "string",
115
+ description: "Subcommand (status)",
116
+ required: false,
117
+ },
118
+ ],
119
+ namedArgs: [],
120
+
121
+ async execute(ctx: CommandContext): Promise<CommandResult> {
122
+ const { parsedArgs } = ctx;
123
+
124
+ // Check if we have access to the agent loop
125
+ if (!agentLoopRef) {
126
+ return error("RESOURCE_NOT_FOUND", "Context management is not available", [
127
+ "No active agent session found. Start a conversation first.",
128
+ ]);
129
+ }
130
+
131
+ // Check if context management is enabled
132
+ if (!agentLoopRef.isContextManagementEnabled()) {
133
+ return error("OPERATION_NOT_ALLOWED", "Context management is disabled", [
134
+ "Enable context management in your configuration to use this command.",
135
+ "",
136
+ "Add to your vellum.config.ts:",
137
+ "",
138
+ " contextManagement: {",
139
+ " enabled: true",
140
+ " }",
141
+ ]);
142
+ }
143
+
144
+ // Handle subcommands
145
+ const subcommand = parsedArgs.positional[0] as string | undefined;
146
+
147
+ if (subcommand === "status") {
148
+ const state = agentLoopRef.getContextState();
149
+ const messages = agentLoopRef.getMessages();
150
+
151
+ const lines: string[] = [
152
+ "📊 Context Status",
153
+ "",
154
+ ` State: ${state ?? "unknown"}`,
155
+ ` Messages: ${messages.length}`,
156
+ "",
157
+ `💡 ${getStateDescription(state ?? "healthy")}`,
158
+ ];
159
+
160
+ return success(lines.join("\n"));
161
+ }
162
+
163
+ if (subcommand && subcommand !== "status") {
164
+ return error("INVALID_ARGUMENT", `Unknown subcommand: ${subcommand}`, [
165
+ "Use /condense or /condense status",
166
+ ]);
167
+ }
168
+
169
+ // Execute compaction
170
+ try {
171
+ const result = await agentLoopRef.compactContext();
172
+
173
+ if (!result) {
174
+ return error("INTERNAL_ERROR", "Compaction failed", [
175
+ "Context management returned no result. This may indicate an internal error.",
176
+ ]);
177
+ }
178
+
179
+ return success(formatResult(result));
180
+ } catch (err) {
181
+ const message = err instanceof Error ? err.message : String(err);
182
+ return error("INTERNAL_ERROR", `Failed to compact context: ${message}`);
183
+ }
184
+ },
185
+ };
186
+
187
+ // =============================================================================
188
+ // Exports
189
+ // =============================================================================
190
+
191
+ export default condenseCommand;