@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,506 @@
1
+ /**
2
+ * Agents Generate Command
3
+ *
4
+ * Generates AGENTS.md based on project analysis (package.json, tsconfig.json, etc.)
5
+ * Uses template-based generation without LLM calls.
6
+ *
7
+ * @module cli/commands/agents/generate
8
+ */
9
+
10
+ import * as fs from "node:fs/promises";
11
+ import * as path from "node:path";
12
+ import chalk from "chalk";
13
+
14
+ import type { CommandContext, CommandResult } from "../types.js";
15
+ import { error, success } from "../types.js";
16
+ import type { AgentsGenerateOptions } from "./index.js";
17
+
18
+ // =============================================================================
19
+ // Types
20
+ // =============================================================================
21
+
22
+ /**
23
+ * Detected project information
24
+ */
25
+ interface DetectedProjectInfo {
26
+ /** Project name from package.json */
27
+ name: string;
28
+ /** Description from package.json */
29
+ description?: string;
30
+ /** Detected programming language */
31
+ language: string;
32
+ /** Detected framework */
33
+ framework?: string;
34
+ /** Package manager (npm, pnpm, yarn) */
35
+ packageManager?: string;
36
+ /** Build tool (vite, webpack, etc.) */
37
+ buildTool?: string;
38
+ /** Test framework */
39
+ testFramework?: string;
40
+ /** Detected patterns/conventions */
41
+ patterns: string[];
42
+ }
43
+
44
+ /**
45
+ * Detection result with confidence
46
+ */
47
+ interface DetectionResult {
48
+ /** Detected project info */
49
+ info: DetectedProjectInfo;
50
+ /** Files that were analyzed */
51
+ analyzedFiles: string[];
52
+ }
53
+
54
+ // =============================================================================
55
+ // Project Detection
56
+ // =============================================================================
57
+
58
+ /**
59
+ * Read and parse package.json
60
+ */
61
+ async function readPackageJson(cwd: string): Promise<Record<string, unknown> | null> {
62
+ try {
63
+ const content = await fs.readFile(path.join(cwd, "package.json"), "utf-8");
64
+ return JSON.parse(content) as Record<string, unknown>;
65
+ } catch {
66
+ return null;
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Read and parse tsconfig.json
72
+ */
73
+ async function readTsConfig(cwd: string): Promise<Record<string, unknown> | null> {
74
+ try {
75
+ const content = await fs.readFile(path.join(cwd, "tsconfig.json"), "utf-8");
76
+ // Remove comments (tsconfig allows them)
77
+ const cleaned = content.replace(/\/\*[\s\S]*?\*\/|\/\/.*/g, "");
78
+ return JSON.parse(cleaned) as Record<string, unknown>;
79
+ } catch {
80
+ return null;
81
+ }
82
+ }
83
+
84
+ /**
85
+ * Check if a file exists
86
+ */
87
+ async function fileExists(filePath: string): Promise<boolean> {
88
+ try {
89
+ await fs.access(filePath);
90
+ return true;
91
+ } catch {
92
+ return false;
93
+ }
94
+ }
95
+
96
+ /**
97
+ * Detect framework from dependencies
98
+ */
99
+ function detectFramework(
100
+ deps: Record<string, string>,
101
+ devDeps: Record<string, string>
102
+ ): string | undefined {
103
+ const allDeps = { ...deps, ...devDeps };
104
+
105
+ // React-based
106
+ if (allDeps.next) return "Next.js";
107
+ if (allDeps.react) return "React";
108
+ if (allDeps.vue) return "Vue";
109
+ if (allDeps.svelte) return "Svelte";
110
+ if (allDeps["@angular/core"]) return "Angular";
111
+
112
+ // Node.js
113
+ if (allDeps.express) return "Express";
114
+ if (allDeps.fastify) return "Fastify";
115
+ if (allDeps.koa) return "Koa";
116
+ if (allDeps.hono) return "Hono";
117
+ if (allDeps.nestjs || allDeps["@nestjs/core"]) return "NestJS";
118
+
119
+ return undefined;
120
+ }
121
+
122
+ /**
123
+ * Detect package manager
124
+ */
125
+ async function detectPackageManager(cwd: string): Promise<string> {
126
+ if (await fileExists(path.join(cwd, "pnpm-lock.yaml"))) return "pnpm";
127
+ if (await fileExists(path.join(cwd, "yarn.lock"))) return "yarn";
128
+ if (await fileExists(path.join(cwd, "bun.lockb"))) return "bun";
129
+ return "npm";
130
+ }
131
+
132
+ /**
133
+ * Detect build tool
134
+ */
135
+ function detectBuildTool(
136
+ deps: Record<string, string>,
137
+ devDeps: Record<string, string>
138
+ ): string | undefined {
139
+ const allDeps = { ...deps, ...devDeps };
140
+
141
+ if (allDeps.vite) return "Vite";
142
+ if (allDeps.webpack) return "Webpack";
143
+ if (allDeps.esbuild) return "esbuild";
144
+ if (allDeps.rollup) return "Rollup";
145
+ if (allDeps.parcel) return "Parcel";
146
+ if (allDeps.turbo || allDeps.turbopack) return "Turbopack";
147
+
148
+ return undefined;
149
+ }
150
+
151
+ /**
152
+ * Detect test framework
153
+ */
154
+ function detectTestFramework(
155
+ deps: Record<string, string>,
156
+ devDeps: Record<string, string>
157
+ ): string | undefined {
158
+ const allDeps = { ...deps, ...devDeps };
159
+
160
+ if (allDeps.vitest) return "Vitest";
161
+ if (allDeps.jest) return "Jest";
162
+ if (allDeps.mocha) return "Mocha";
163
+ if (allDeps["@playwright/test"]) return "Playwright";
164
+ if (allDeps.cypress) return "Cypress";
165
+
166
+ return undefined;
167
+ }
168
+
169
+ /**
170
+ * Detect language from project files
171
+ */
172
+ async function detectLanguage(cwd: string, pkg: Record<string, unknown> | null): Promise<string> {
173
+ // Check for TypeScript
174
+ if (await fileExists(path.join(cwd, "tsconfig.json"))) return "TypeScript";
175
+
176
+ // Check package.json
177
+ if (pkg) {
178
+ const devDeps = (pkg.devDependencies as Record<string, string>) ?? {};
179
+ if (devDeps.typescript) return "TypeScript";
180
+ }
181
+
182
+ // Check for other languages
183
+ if (await fileExists(path.join(cwd, "pyproject.toml"))) return "Python";
184
+ if (await fileExists(path.join(cwd, "Cargo.toml"))) return "Rust";
185
+ if (await fileExists(path.join(cwd, "go.mod"))) return "Go";
186
+ if (await fileExists(path.join(cwd, "pom.xml"))) return "Java";
187
+ if (await fileExists(path.join(cwd, "build.gradle"))) return "Java";
188
+
189
+ // Default to JavaScript if package.json exists
190
+ if (pkg) return "JavaScript";
191
+
192
+ return "Unknown";
193
+ }
194
+
195
+ /**
196
+ * Detect project patterns/conventions
197
+ */
198
+ async function detectPatterns(cwd: string): Promise<string[]> {
199
+ const patterns: string[] = [];
200
+
201
+ // Check for monorepo
202
+ if (
203
+ (await fileExists(path.join(cwd, "pnpm-workspace.yaml"))) ||
204
+ (await fileExists(path.join(cwd, "lerna.json")))
205
+ ) {
206
+ patterns.push("Monorepo");
207
+ }
208
+
209
+ // Check for common configs
210
+ if (
211
+ (await fileExists(path.join(cwd, ".eslintrc.json"))) ||
212
+ (await fileExists(path.join(cwd, "eslint.config.js")))
213
+ ) {
214
+ patterns.push("ESLint");
215
+ }
216
+ if (
217
+ (await fileExists(path.join(cwd, ".prettierrc"))) ||
218
+ (await fileExists(path.join(cwd, "prettier.config.js")))
219
+ ) {
220
+ patterns.push("Prettier");
221
+ }
222
+ if (await fileExists(path.join(cwd, "biome.json"))) {
223
+ patterns.push("Biome");
224
+ }
225
+ if (await fileExists(path.join(cwd, ".github/workflows"))) {
226
+ patterns.push("GitHub Actions");
227
+ }
228
+
229
+ return patterns;
230
+ }
231
+
232
+ /**
233
+ * Analyze project and detect information
234
+ */
235
+ async function analyzeProject(cwd: string): Promise<DetectionResult> {
236
+ const analyzedFiles: string[] = [];
237
+
238
+ // Read package.json
239
+ const pkg = await readPackageJson(cwd);
240
+ if (pkg) analyzedFiles.push("package.json");
241
+
242
+ // Read tsconfig.json
243
+ const tsconfig = await readTsConfig(cwd);
244
+ if (tsconfig) analyzedFiles.push("tsconfig.json");
245
+
246
+ // Extract info from package.json
247
+ const deps = (pkg?.dependencies as Record<string, string>) ?? {};
248
+ const devDeps = (pkg?.devDependencies as Record<string, string>) ?? {};
249
+
250
+ // Detect various aspects
251
+ const language = await detectLanguage(cwd, pkg);
252
+ const framework = detectFramework(deps, devDeps);
253
+ const packageManager = await detectPackageManager(cwd);
254
+ const buildTool = detectBuildTool(deps, devDeps);
255
+ const testFramework = detectTestFramework(deps, devDeps);
256
+ const patterns = await detectPatterns(cwd);
257
+
258
+ return {
259
+ info: {
260
+ name: (pkg?.name as string) ?? path.basename(cwd),
261
+ description: pkg?.description as string | undefined,
262
+ language,
263
+ framework,
264
+ packageManager,
265
+ buildTool,
266
+ testFramework,
267
+ patterns,
268
+ },
269
+ analyzedFiles,
270
+ };
271
+ }
272
+
273
+ // =============================================================================
274
+ // Template Generation
275
+ // =============================================================================
276
+
277
+ /**
278
+ * Generate AGENTS.md content from detected info
279
+ */
280
+ function generateAgentsMd(info: DetectedProjectInfo): string {
281
+ const lines: string[] = [];
282
+
283
+ // Frontmatter
284
+ lines.push("---");
285
+ lines.push(`name: "${info.name}"`);
286
+ lines.push('version: "1.0.0"');
287
+ if (info.description) {
288
+ lines.push(`description: "${info.description.replace(/"/g, '\\"')}"`);
289
+ }
290
+ lines.push("priority: 100");
291
+ lines.push("merge:");
292
+ lines.push(" strategy: extend");
293
+ lines.push(" arrays: append");
294
+ lines.push("---");
295
+ lines.push("");
296
+
297
+ // Instructions header
298
+ lines.push("# Instructions");
299
+ lines.push("");
300
+ lines.push(`You are an AI coding assistant for ${info.name}.`);
301
+ lines.push("");
302
+
303
+ // Tech stack
304
+ lines.push("## Tech Stack");
305
+ lines.push("");
306
+ lines.push(`- ${info.language}`);
307
+ if (info.framework) {
308
+ lines.push(`- ${info.framework}`);
309
+ }
310
+ if (info.buildTool) {
311
+ lines.push(`- ${info.buildTool}`);
312
+ }
313
+ if (info.testFramework) {
314
+ lines.push(`- ${info.testFramework}`);
315
+ }
316
+ if (info.packageManager && info.packageManager !== "npm") {
317
+ lines.push(`- Package Manager: ${info.packageManager}`);
318
+ }
319
+ lines.push("");
320
+
321
+ // Patterns
322
+ if (info.patterns.length > 0) {
323
+ lines.push("## Project Patterns");
324
+ lines.push("");
325
+ for (const pattern of info.patterns) {
326
+ lines.push(`- ${pattern}`);
327
+ }
328
+ lines.push("");
329
+ }
330
+
331
+ // Coding standards
332
+ lines.push("## Coding Standards");
333
+ lines.push("");
334
+ lines.push("- Follow existing project conventions");
335
+ lines.push("- Write clean, readable, well-documented code");
336
+ lines.push("- Use meaningful variable and function names");
337
+ lines.push("- Add appropriate comments for complex logic");
338
+
339
+ // Language-specific standards
340
+ if (info.language === "TypeScript") {
341
+ lines.push("- Use proper TypeScript types, avoid `any`");
342
+ lines.push("- Prefer `const` over `let`, avoid `var`");
343
+ }
344
+ if (info.testFramework) {
345
+ lines.push(`- Write tests using ${info.testFramework}`);
346
+ }
347
+ lines.push("");
348
+
349
+ // Allowed tools
350
+ lines.push("## Allowed Tools");
351
+ lines.push("");
352
+ lines.push("allowed-tools:");
353
+ lines.push(' - "@readonly"');
354
+ lines.push(' - "@edit"');
355
+
356
+ // Safe shell commands based on package manager
357
+ if (info.packageManager) {
358
+ lines.push(` - "Bash(${info.packageManager} run *)"`);
359
+ lines.push(` - "Bash(${info.packageManager} test *)"`);
360
+ }
361
+ lines.push(' - "!Bash"');
362
+ lines.push("");
363
+
364
+ return lines.join("\n");
365
+ }
366
+
367
+ /**
368
+ * Format detection summary for display
369
+ */
370
+ function formatDetectionSummary(result: DetectionResult): string {
371
+ const { info, analyzedFiles } = result;
372
+ const lines: string[] = [];
373
+
374
+ lines.push(chalk.bold("📊 Project Analysis"));
375
+ lines.push(chalk.gray("━".repeat(40)));
376
+ lines.push("");
377
+ lines.push(`${chalk.gray("Name:")} ${info.name}`);
378
+ lines.push(`${chalk.gray("Language:")} ${chalk.cyan(info.language)}`);
379
+
380
+ if (info.framework) {
381
+ lines.push(`${chalk.gray("Framework:")} ${chalk.cyan(info.framework)}`);
382
+ }
383
+ if (info.packageManager) {
384
+ lines.push(`${chalk.gray("Package Manager:")} ${info.packageManager}`);
385
+ }
386
+ if (info.buildTool) {
387
+ lines.push(`${chalk.gray("Build Tool:")} ${info.buildTool}`);
388
+ }
389
+ if (info.testFramework) {
390
+ lines.push(`${chalk.gray("Test Framework:")} ${info.testFramework}`);
391
+ }
392
+ if (info.patterns.length > 0) {
393
+ lines.push(`${chalk.gray("Patterns:")} ${info.patterns.join(", ")}`);
394
+ }
395
+
396
+ lines.push("");
397
+ lines.push(chalk.gray(`Analyzed: ${analyzedFiles.join(", ")}`));
398
+
399
+ return lines.join("\n");
400
+ }
401
+
402
+ // =============================================================================
403
+ // Command Handler
404
+ // =============================================================================
405
+
406
+ /**
407
+ * Execute agents generate command
408
+ *
409
+ * @param options - Command options
410
+ * @returns Command result
411
+ */
412
+ export async function handleAgentsGenerate(options: AgentsGenerateOptions): Promise<CommandResult> {
413
+ const cwd = process.cwd();
414
+ const outputPath = options.output ? path.resolve(options.output) : path.join(cwd, "AGENTS.md");
415
+
416
+ try {
417
+ // Analyze project
418
+ const result = await analyzeProject(cwd);
419
+
420
+ // Generate content
421
+ const content = generateAgentsMd(result.info);
422
+
423
+ // Dry run - just show what would be generated
424
+ if (options.dryRun) {
425
+ const summary = formatDetectionSummary(result);
426
+ const preview = [
427
+ summary,
428
+ "",
429
+ chalk.bold("📄 Generated AGENTS.md Preview:"),
430
+ chalk.gray("━".repeat(40)),
431
+ "",
432
+ chalk.gray(content),
433
+ "",
434
+ chalk.yellow(`Would write to: ${outputPath}`),
435
+ ].join("\n");
436
+
437
+ return success(preview);
438
+ }
439
+
440
+ // Check if file exists (unless --merge is specified)
441
+ if (!options.merge) {
442
+ try {
443
+ await fs.access(outputPath);
444
+ return error(
445
+ "OPERATION_NOT_ALLOWED",
446
+ `${outputPath} already exists. Use --merge to combine with existing file, or delete it first.`
447
+ );
448
+ } catch {
449
+ // File doesn't exist, good to proceed
450
+ }
451
+ }
452
+
453
+ // Handle merge with existing file
454
+ if (options.merge) {
455
+ try {
456
+ const existing = await fs.readFile(outputPath, "utf-8");
457
+ // For basic merge, append generated content as a comment
458
+ const merged = [
459
+ existing,
460
+ "",
461
+ "<!-- Generated additions from `vellum agents generate` -->",
462
+ "",
463
+ content,
464
+ ].join("\n");
465
+ await fs.writeFile(outputPath, merged, "utf-8");
466
+ } catch {
467
+ // No existing file, just write new content
468
+ await fs.writeFile(outputPath, content, "utf-8");
469
+ }
470
+ } else {
471
+ // Write new file
472
+ await fs.writeFile(outputPath, content, "utf-8");
473
+ }
474
+
475
+ // Format success message
476
+ const summary = formatDetectionSummary(result);
477
+ const successMsg = [
478
+ summary,
479
+ "",
480
+ chalk.green(`✅ Created ${outputPath}`),
481
+ "",
482
+ chalk.gray("Next steps:"),
483
+ chalk.gray(" • Review and customize the generated AGENTS.md"),
484
+ chalk.gray(` • Run ${chalk.cyan("/agents validate")} to check syntax`),
485
+ chalk.gray(` • Run ${chalk.cyan("/agents show")} to view merged config`),
486
+ ].join("\n");
487
+
488
+ return success(successMsg, { filePath: outputPath });
489
+ } catch (err) {
490
+ const message = err instanceof Error ? err.message : String(err);
491
+ return error("INTERNAL_ERROR", `Failed to generate AGENTS.md: ${message}`);
492
+ }
493
+ }
494
+
495
+ /**
496
+ * Execute handler for command context
497
+ */
498
+ export async function executeGenerate(ctx: CommandContext): Promise<CommandResult> {
499
+ const options: AgentsGenerateOptions = {
500
+ output: ctx.parsedArgs.named.output as string | undefined,
501
+ merge: ctx.parsedArgs.named.merge as boolean | undefined,
502
+ dryRun: ctx.parsedArgs.named["dry-run"] as boolean | undefined,
503
+ };
504
+
505
+ return handleAgentsGenerate(options);
506
+ }