@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,422 @@
1
+ /**
2
+ * Shell Setup Command
3
+ *
4
+ * Configures shell integration for Vellum CLI.
5
+ * Adds Vellum to PATH, installs completions, and configures shell RC files.
6
+ *
7
+ * @module cli/commands/shell/setup
8
+ */
9
+
10
+ import { existsSync } from "node:fs";
11
+
12
+ import { confirm, select } from "@inquirer/prompts";
13
+ import {
14
+ detectInstalledShells,
15
+ detectShell,
16
+ getPrimaryRcFile,
17
+ getSupportedShells,
18
+ isShellConfigured,
19
+ isShellSupported,
20
+ patchShellConfig,
21
+ removeShellConfig,
22
+ type ShellType,
23
+ } from "@vellum/core";
24
+ import chalk from "chalk";
25
+
26
+ import { EXIT_CODES } from "../exit-codes.js";
27
+
28
+ // =============================================================================
29
+ // Types
30
+ // =============================================================================
31
+
32
+ /**
33
+ * Shell setup command options
34
+ */
35
+ export interface ShellSetupOptions {
36
+ /** Target shell (auto-detect if not specified) */
37
+ shell?: string;
38
+ /** Remove Vellum configuration instead of adding */
39
+ uninstall?: boolean;
40
+ /** Force overwrite without confirmation */
41
+ force?: boolean;
42
+ /** Skip backup creation */
43
+ noBackup?: boolean;
44
+ /** Dry run - show what would be done */
45
+ dryRun?: boolean;
46
+ /** Non-interactive mode (for CI) */
47
+ nonInteractive?: boolean;
48
+ }
49
+
50
+ /**
51
+ * Shell setup command result
52
+ */
53
+ export interface SetupCommandResult {
54
+ /** Whether setup succeeded */
55
+ success: boolean;
56
+ /** Exit code */
57
+ exitCode: number;
58
+ /** Message to display */
59
+ message: string;
60
+ /** Detailed info */
61
+ details?: string[];
62
+ }
63
+
64
+ // =============================================================================
65
+ // Setup Implementation
66
+ // =============================================================================
67
+
68
+ /**
69
+ * Get Vellum binary path from process
70
+ *
71
+ * @returns Path to Vellum binary or undefined
72
+ */
73
+ function getVellumBinPath(): string | undefined {
74
+ // Try to find vellum in the current process's directory
75
+ const execPath = process.argv[1];
76
+ if (execPath && existsSync(execPath)) {
77
+ return execPath;
78
+ }
79
+ return undefined;
80
+ }
81
+
82
+ /**
83
+ * Run shell setup command
84
+ *
85
+ * @param options - Setup options
86
+ * @returns Setup result
87
+ */
88
+ export async function runShellSetup(options: ShellSetupOptions = {}): Promise<SetupCommandResult> {
89
+ const {
90
+ shell: shellArg,
91
+ uninstall = false,
92
+ force = false,
93
+ noBackup = false,
94
+ dryRun = false,
95
+ nonInteractive = false,
96
+ } = options;
97
+
98
+ // Validate shell argument if provided
99
+ if (shellArg && !isShellSupported(shellArg)) {
100
+ const supported = getSupportedShells().join(", ");
101
+ return {
102
+ success: false,
103
+ exitCode: EXIT_CODES.USAGE_ERROR,
104
+ message: `Unsupported shell: ${shellArg}`,
105
+ details: [`Supported shells: ${supported}`],
106
+ };
107
+ }
108
+
109
+ // Detect or use provided shell
110
+ const targetShell: ShellType = shellArg ? (shellArg as ShellType) : detectShell().shell;
111
+
112
+ // Skip CMD as it doesn't have RC file support
113
+ if (targetShell === "cmd") {
114
+ return {
115
+ success: false,
116
+ exitCode: EXIT_CODES.USAGE_ERROR,
117
+ message: "CMD does not support shell integration",
118
+ details: ["Consider using PowerShell instead:", " vellum shell setup --shell=powershell"],
119
+ };
120
+ }
121
+
122
+ const rcFile = getPrimaryRcFile(targetShell);
123
+ const configured = isShellConfigured(targetShell);
124
+
125
+ console.log(chalk.bold("\n🐚 Vellum Shell Setup\n"));
126
+ console.log(`Target shell: ${chalk.cyan(targetShell)}`);
127
+ console.log(`Config file: ${chalk.dim(rcFile)}`);
128
+ console.log(
129
+ `Status: ${configured ? chalk.green("configured") : chalk.yellow("not configured")}`
130
+ );
131
+ console.log("");
132
+
133
+ // Handle uninstall
134
+ if (uninstall) {
135
+ return await handleUninstall(targetShell, { dryRun, noBackup, force, nonInteractive });
136
+ }
137
+
138
+ // Handle install
139
+ return await handleInstall(targetShell, { dryRun, noBackup, force, nonInteractive, configured });
140
+ }
141
+
142
+ /**
143
+ * Handle shell uninstallation
144
+ */
145
+ async function handleUninstall(
146
+ shell: ShellType,
147
+ options: { dryRun: boolean; noBackup: boolean; force: boolean; nonInteractive: boolean }
148
+ ): Promise<SetupCommandResult> {
149
+ const { dryRun, force, nonInteractive } = options;
150
+
151
+ if (!isShellConfigured(shell)) {
152
+ return {
153
+ success: true,
154
+ exitCode: EXIT_CODES.SUCCESS,
155
+ message: "Vellum is not configured for this shell",
156
+ };
157
+ }
158
+
159
+ // Confirm uninstall
160
+ if (!force && !nonInteractive) {
161
+ const confirmed = await confirm({
162
+ message: `Remove Vellum configuration from ${shell}?`,
163
+ default: false,
164
+ });
165
+
166
+ if (!confirmed) {
167
+ return {
168
+ success: false,
169
+ exitCode: EXIT_CODES.INTERRUPTED,
170
+ message: "Uninstall cancelled",
171
+ };
172
+ }
173
+ }
174
+
175
+ if (dryRun) {
176
+ const rcFile = getPrimaryRcFile(shell);
177
+ console.log(chalk.yellow("\n[Dry Run] Would remove Vellum configuration from:"));
178
+ console.log(` ${rcFile}`);
179
+ return {
180
+ success: true,
181
+ exitCode: EXIT_CODES.SUCCESS,
182
+ message: "Dry run completed",
183
+ };
184
+ }
185
+
186
+ // Remove configuration
187
+ const result = await removeShellConfig(shell);
188
+
189
+ if (result.success) {
190
+ console.log(chalk.green("\n✓ Vellum configuration removed"));
191
+ if (result.backupPath) {
192
+ console.log(chalk.dim(` Backup: ${result.backupPath}`));
193
+ }
194
+ return {
195
+ success: true,
196
+ exitCode: EXIT_CODES.SUCCESS,
197
+ message: "Shell configuration removed",
198
+ details: ["Restart your shell or run:", ` source ${getPrimaryRcFile(shell)}`],
199
+ };
200
+ }
201
+
202
+ return {
203
+ success: false,
204
+ exitCode: EXIT_CODES.ERROR,
205
+ message: result.error ?? "Failed to remove configuration",
206
+ };
207
+ }
208
+
209
+ /**
210
+ * Handle shell installation
211
+ */
212
+ async function handleInstall(
213
+ shell: ShellType,
214
+ options: {
215
+ dryRun: boolean;
216
+ noBackup: boolean;
217
+ force: boolean;
218
+ nonInteractive: boolean;
219
+ configured: boolean;
220
+ }
221
+ ): Promise<SetupCommandResult> {
222
+ const { dryRun, noBackup, force, nonInteractive, configured } = options;
223
+
224
+ // Check if already configured
225
+ if (configured && !force) {
226
+ if (nonInteractive) {
227
+ return {
228
+ success: true,
229
+ exitCode: EXIT_CODES.SUCCESS,
230
+ message: "Shell is already configured",
231
+ };
232
+ }
233
+
234
+ const action = await select({
235
+ message: "Vellum is already configured. What would you like to do?",
236
+ choices: [
237
+ { name: "Update configuration", value: "update" },
238
+ { name: "Keep existing", value: "keep" },
239
+ { name: "Remove configuration", value: "remove" },
240
+ ],
241
+ });
242
+
243
+ if (action === "keep") {
244
+ return {
245
+ success: true,
246
+ exitCode: EXIT_CODES.SUCCESS,
247
+ message: "Keeping existing configuration",
248
+ };
249
+ }
250
+
251
+ if (action === "remove") {
252
+ return handleUninstall(shell, { dryRun, noBackup, force: true, nonInteractive: true });
253
+ }
254
+ }
255
+
256
+ if (dryRun) {
257
+ const rcFile = getPrimaryRcFile(shell);
258
+ console.log(chalk.yellow("\n[Dry Run] Would add Vellum configuration to:"));
259
+ console.log(` ${rcFile}`);
260
+ console.log("\nConfiguration would include:");
261
+ console.log(" • PATH modification (if needed)");
262
+ console.log(" • Shell completions setup");
263
+ return {
264
+ success: true,
265
+ exitCode: EXIT_CODES.SUCCESS,
266
+ message: "Dry run completed",
267
+ };
268
+ }
269
+
270
+ // Apply configuration
271
+ const vellumBinPath = getVellumBinPath();
272
+ const result = await patchShellConfig({
273
+ shell,
274
+ operation: configured ? "update" : "add",
275
+ createBackup: !noBackup,
276
+ vellumBinPath,
277
+ });
278
+
279
+ if (result.success) {
280
+ console.log(chalk.green("\n✓ Shell configured successfully"));
281
+
282
+ if (result.fileCreated) {
283
+ console.log(chalk.dim(` Created: ${result.filePath}`));
284
+ } else {
285
+ console.log(chalk.dim(` Modified: ${result.filePath}`));
286
+ }
287
+
288
+ if (result.backupPath) {
289
+ console.log(chalk.dim(` Backup: ${result.backupPath}`));
290
+ }
291
+
292
+ const instructions = getPostInstallInstructions(shell);
293
+ console.log(chalk.cyan("\nTo activate, run:"));
294
+ for (const instruction of instructions) {
295
+ console.log(` ${instruction}`);
296
+ }
297
+
298
+ return {
299
+ success: true,
300
+ exitCode: EXIT_CODES.SUCCESS,
301
+ message: "Shell configured successfully",
302
+ details: instructions,
303
+ };
304
+ }
305
+
306
+ return {
307
+ success: false,
308
+ exitCode: EXIT_CODES.ERROR,
309
+ message: result.error ?? "Failed to configure shell",
310
+ };
311
+ }
312
+
313
+ /**
314
+ * Get post-install instructions for a shell
315
+ */
316
+ function getPostInstallInstructions(shell: ShellType): string[] {
317
+ const rcFile = getPrimaryRcFile(shell);
318
+
319
+ switch (shell) {
320
+ case "bash":
321
+ case "zsh":
322
+ return [`source ${rcFile}`, "# Or restart your terminal"];
323
+ case "fish":
324
+ return [`source ${rcFile}`, "# Or restart your terminal"];
325
+ case "powershell":
326
+ case "pwsh":
327
+ return [`. $PROFILE`, "# Or restart PowerShell"];
328
+ default:
329
+ return ["Restart your terminal"];
330
+ }
331
+ }
332
+
333
+ /**
334
+ * Display all shells status
335
+ */
336
+ export async function displayShellsStatus(): Promise<void> {
337
+ console.log(chalk.bold("\n🐚 Shell Integration Status\n"));
338
+
339
+ const detected = detectShell();
340
+ console.log(`Current shell: ${chalk.cyan(detected.shell)}`);
341
+
342
+ const installed = detectInstalledShells();
343
+ console.log(`\nInstalled shells:`);
344
+
345
+ for (const shell of installed) {
346
+ const configured = isShellConfigured(shell.shell);
347
+ const isDefault = shell.isDefault ? chalk.dim(" (default)") : "";
348
+ const status = configured ? chalk.green("✓") : chalk.dim("○");
349
+
350
+ console.log(` ${status} ${shell.shell}${isDefault}`);
351
+ console.log(` ${chalk.dim(getPrimaryRcFile(shell.shell))}`);
352
+ }
353
+
354
+ console.log("");
355
+ }
356
+
357
+ // =============================================================================
358
+ // Command Definition
359
+ // =============================================================================
360
+
361
+ /**
362
+ * Create the shell setup command
363
+ *
364
+ * @returns Slash command definition
365
+ */
366
+ export function createShellSetupCommand() {
367
+ return {
368
+ name: "shell",
369
+ description: "Configure shell integration (PATH, completions)",
370
+ namedArgs: [
371
+ {
372
+ name: "shell",
373
+ description: "Target shell (bash, zsh, fish, powershell)",
374
+ required: false,
375
+ },
376
+ {
377
+ name: "uninstall",
378
+ description: "Remove Vellum configuration",
379
+ required: false,
380
+ },
381
+ {
382
+ name: "force",
383
+ description: "Force overwrite without confirmation",
384
+ required: false,
385
+ },
386
+ {
387
+ name: "no-backup",
388
+ description: "Skip backup creation",
389
+ required: false,
390
+ },
391
+ {
392
+ name: "dry-run",
393
+ description: "Show what would be done",
394
+ required: false,
395
+ },
396
+ {
397
+ name: "status",
398
+ description: "Show shell integration status",
399
+ required: false,
400
+ },
401
+ ],
402
+ handler: async (args: Record<string, string>): Promise<SetupCommandResult> => {
403
+ // Handle status flag
404
+ if (args.status !== undefined) {
405
+ await displayShellsStatus();
406
+ return {
407
+ success: true,
408
+ exitCode: EXIT_CODES.SUCCESS,
409
+ message: "",
410
+ };
411
+ }
412
+
413
+ return runShellSetup({
414
+ shell: args.shell,
415
+ uninstall: args.uninstall !== undefined,
416
+ force: args.force !== undefined,
417
+ noBackup: args["no-backup"] !== undefined,
418
+ dryRun: args["dry-run"] !== undefined,
419
+ });
420
+ },
421
+ };
422
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Shell Init Command (Phase 37)
3
+ * @module cli/commands/shell-init
4
+ */
5
+
6
+ import type { CommandResult, SlashCommand } from "./types.js";
7
+ import { success } from "./types.js";
8
+
9
+ export interface ShellInitOptions {
10
+ shell?: string;
11
+ }
12
+
13
+ export interface ShellInitResult {
14
+ success: boolean;
15
+ script?: string;
16
+ }
17
+
18
+ /**
19
+ * Create shell init command
20
+ */
21
+ export function createShellInitCommand(): SlashCommand {
22
+ return {
23
+ name: "shell-init",
24
+ description: "Initialize shell integration",
25
+ kind: "builtin",
26
+ category: "system",
27
+ execute: async (): Promise<CommandResult> => success("Shell init not yet implemented"),
28
+ };
29
+ }
30
+
31
+ /**
32
+ * Execute shell init
33
+ */
34
+ export async function executeShellInit(_options?: ShellInitOptions): Promise<ShellInitResult> {
35
+ return { success: true };
36
+ }
37
+
38
+ /**
39
+ * Handle shell init
40
+ */
41
+ export async function handleShellInit(_options?: ShellInitOptions): Promise<void> {
42
+ // Placeholder
43
+ }
44
+
45
+ /**
46
+ * Print shell init
47
+ */
48
+ export function printShellInit(_result: ShellInitResult): void {
49
+ // Placeholder
50
+ }
@@ -0,0 +1,194 @@
1
+ /**
2
+ * Shell Integration (Phase 37)
3
+ * @module cli/commands/shell-integration
4
+ */
5
+
6
+ import { z } from "zod";
7
+
8
+ // =============================================================================
9
+ // Completion Schemas
10
+ // =============================================================================
11
+
12
+ export const CompletionInputSchema = z.object({
13
+ input: z.string(),
14
+ cursorPosition: z.number().int().nonnegative().optional(),
15
+ previousWords: z.array(z.string()).optional(),
16
+ currentWord: z.string().optional(),
17
+ commandLine: z.string().optional(),
18
+ });
19
+ export type CompletionInput = z.infer<typeof CompletionInputSchema>;
20
+ export type CompletionInputInput = z.input<typeof CompletionInputSchema>;
21
+
22
+ export const CompletionResultTypeSchema = z.enum(["values"]);
23
+ export type CompletionResultType = z.infer<typeof CompletionResultTypeSchema>;
24
+
25
+ export const CompletionResultSchema = z.object({
26
+ type: CompletionResultTypeSchema.default("values"),
27
+ values: z.array(z.string()),
28
+ descriptions: z.array(z.string()).optional(),
29
+ });
30
+ export type CompletionResult = z.infer<typeof CompletionResultSchema>;
31
+ export type CompletionResultInput = z.input<typeof CompletionResultSchema>;
32
+
33
+ export interface CompletionProvider {
34
+ readonly name: string;
35
+ complete(input: CompletionInput): Promise<CompletionResult>;
36
+ }
37
+
38
+ export class CompletionCache {
39
+ private readonly cache = new Map<string, CompletionResult>();
40
+
41
+ get(key: string): CompletionResult | undefined {
42
+ return this.cache.get(key);
43
+ }
44
+
45
+ set(key: string, value: CompletionResult): void {
46
+ this.cache.set(key, value);
47
+ }
48
+
49
+ delete(key: string): boolean {
50
+ return this.cache.delete(key);
51
+ }
52
+
53
+ clear(): void {
54
+ this.cache.clear();
55
+ }
56
+ }
57
+
58
+ const sharedCache = new CompletionCache();
59
+
60
+ export function getSharedCache(): CompletionCache {
61
+ return sharedCache;
62
+ }
63
+
64
+ // =============================================================================
65
+ // Shell Type Schema
66
+ // =============================================================================
67
+
68
+ export const ShellTypeSchema = z.enum(["bash", "zsh", "fish", "powershell", "cmd"]);
69
+ export type ShellType = z.infer<typeof ShellTypeSchema>;
70
+
71
+ // =============================================================================
72
+ // Install Options Schema
73
+ // =============================================================================
74
+
75
+ export const InstallOptionsSchema = z.object({
76
+ shell: ShellTypeSchema.optional(),
77
+ force: z.boolean().optional(),
78
+ });
79
+ export type InstallOptions = z.infer<typeof InstallOptionsSchema>;
80
+ export type InstallOptionsInput = z.input<typeof InstallOptionsSchema>;
81
+
82
+ // =============================================================================
83
+ // Status Schema
84
+ // =============================================================================
85
+
86
+ export const ShellIntegrationStatusSchema = z.object({
87
+ installed: z.boolean(),
88
+ shell: ShellTypeSchema.optional(),
89
+ version: z.string().optional(),
90
+ });
91
+ export type ShellIntegrationStatus = z.infer<typeof ShellIntegrationStatusSchema>;
92
+ export type ShellIntegrationStatusInput = z.input<typeof ShellIntegrationStatusSchema>;
93
+
94
+ // =============================================================================
95
+ // Environment Config Schema
96
+ // =============================================================================
97
+
98
+ export const EnvironmentConfigSchema = z.object({
99
+ cwd: z.string().optional(),
100
+ env: z.record(z.string(), z.string()).optional(),
101
+ });
102
+ export type EnvironmentConfig = z.infer<typeof EnvironmentConfigSchema>;
103
+ export type EnvironmentConfigInput = z.input<typeof EnvironmentConfigSchema>;
104
+
105
+ // =============================================================================
106
+ // Shell Installer
107
+ // =============================================================================
108
+
109
+ export interface InstallResult {
110
+ success: boolean;
111
+ message?: string;
112
+ }
113
+
114
+ export class ShellInstaller {
115
+ async install(_options?: InstallOptions): Promise<InstallResult> {
116
+ return { success: true, message: "Shell integration installed" };
117
+ }
118
+
119
+ async uninstall(_shell?: ShellType): Promise<InstallResult> {
120
+ return { success: true, message: "Shell integration uninstalled" };
121
+ }
122
+
123
+ async status(): Promise<ShellIntegrationStatus> {
124
+ return { installed: false };
125
+ }
126
+ }
127
+
128
+ export const shellInstaller = new ShellInstaller();
129
+
130
+ // =============================================================================
131
+ // Completion Providers
132
+ // =============================================================================
133
+
134
+ export class AgentCompletionProvider implements CompletionProvider {
135
+ readonly name = "agent";
136
+
137
+ async complete(_input: CompletionInput): Promise<CompletionResult> {
138
+ return { type: "values", values: [] };
139
+ }
140
+ }
141
+
142
+ export class ModelCompletionProvider implements CompletionProvider {
143
+ readonly name = "models";
144
+
145
+ async getCompletions(_prefix: string): Promise<string[]> {
146
+ return [];
147
+ }
148
+
149
+ async complete(input: CompletionInput): Promise<CompletionResult> {
150
+ const prefix = input.currentWord ?? input.input;
151
+ const values = await this.getCompletions(prefix);
152
+ return { type: "values", values };
153
+ }
154
+ }
155
+
156
+ export class ProviderCompletionProvider implements CompletionProvider {
157
+ readonly name = "providers";
158
+
159
+ async getCompletions(_prefix: string): Promise<string[]> {
160
+ return [];
161
+ }
162
+
163
+ async complete(input: CompletionInput): Promise<CompletionResult> {
164
+ const prefix = input.currentWord ?? input.input;
165
+ const values = await this.getCompletions(prefix);
166
+ return { type: "values", values };
167
+ }
168
+ }
169
+
170
+ export function createDynamicProviders(_config?: EnvironmentConfig): CompletionProvider[] {
171
+ return [
172
+ new ModelCompletionProvider(),
173
+ new ProviderCompletionProvider(),
174
+ new AgentCompletionProvider(),
175
+ ];
176
+ }
177
+
178
+ // =============================================================================
179
+ // Environment
180
+ // =============================================================================
181
+
182
+ export const VELLUM_ENV_VARS = ["VELLUM_API_KEY", "VELLUM_DEBUG", "VELLUM_LOG_LEVEL"] as const;
183
+
184
+ export class VellumEnvironment {
185
+ get(key: string): string | undefined {
186
+ return process.env[key];
187
+ }
188
+
189
+ set(key: string, value: string): void {
190
+ process.env[key] = value;
191
+ }
192
+ }
193
+
194
+ export const vellumEnv = new VellumEnvironment();