@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,434 @@
1
+ /**
2
+ * Search Command
3
+ *
4
+ * Full-text search across historical sessions using MiniSearch.
5
+ * Supports interactive session selection from search results.
6
+ *
7
+ * @module cli/commands/session/search
8
+ */
9
+
10
+ import { select } from "@inquirer/prompts";
11
+ import type { SearchService, Session, SessionSearchHit, StorageManager } from "@vellum/core";
12
+
13
+ import type { CommandContext, CommandResult, SlashCommand } from "../types.js";
14
+ import { error, pending, success } from "../types.js";
15
+
16
+ // =============================================================================
17
+ // Constants
18
+ // =============================================================================
19
+
20
+ /**
21
+ * Maximum number of search results to display.
22
+ */
23
+ const MAX_DISPLAY_RESULTS = 20;
24
+
25
+ /**
26
+ * Number of results per page in interactive selector.
27
+ */
28
+ const RESULTS_PER_PAGE = 10;
29
+
30
+ // =============================================================================
31
+ // Search Result Formatting
32
+ // =============================================================================
33
+
34
+ /**
35
+ * Format a search result for display.
36
+ *
37
+ * @param hit - Search result hit
38
+ * @param index - Display index (1-based)
39
+ * @returns Formatted string
40
+ */
41
+ function formatSearchResult(hit: SessionSearchHit, index: number): string {
42
+ const scorePercent = Math.round(hit.score * 10) / 10;
43
+ const matchTerms = hit.matches.slice(0, 3).join(", ");
44
+ const snippet = hit.snippet ? ` - "${hit.snippet}"` : "";
45
+
46
+ return `${index}. ${hit.title} (score: ${scorePercent})${snippet}${matchTerms ? ` [${matchTerms}]` : ""}`;
47
+ }
48
+
49
+ /**
50
+ * Format search results for text display.
51
+ *
52
+ * @param hits - Array of search hits
53
+ * @param query - Original search query
54
+ * @returns Formatted results string
55
+ */
56
+ function formatSearchResults(hits: SessionSearchHit[], query: string): string {
57
+ const lines: string[] = [];
58
+
59
+ lines.push(`🔍 搜索结果: "${query}"`);
60
+ lines.push("━".repeat(50));
61
+
62
+ if (hits.length === 0) {
63
+ lines.push("");
64
+ lines.push(" 未找到匹配的会话");
65
+ lines.push("");
66
+ lines.push("提示:");
67
+ lines.push(" • 尝试使用不同的关键词");
68
+ lines.push(" • 使用更少或更通用的搜索词");
69
+ lines.push(" • 使用 /search --rebuild 重建索引");
70
+ } else {
71
+ lines.push("");
72
+ for (let i = 0; i < hits.length; i++) {
73
+ const hit = hits[i];
74
+ if (!hit) continue;
75
+ lines.push(` ${formatSearchResult(hit, i + 1)}`);
76
+ }
77
+ lines.push("");
78
+ lines.push(`找到 ${hits.length} 个匹配会话`);
79
+ }
80
+
81
+ lines.push("━".repeat(50));
82
+
83
+ return lines.join("\n");
84
+ }
85
+
86
+ // =============================================================================
87
+ // Interactive Session Selection
88
+ // =============================================================================
89
+
90
+ /**
91
+ * Options for interactive search result selection.
92
+ */
93
+ interface SearchSelectOptions {
94
+ /** Search hits to select from */
95
+ hits: SessionSearchHit[];
96
+ /** Storage manager for loading sessions */
97
+ storage: StorageManager;
98
+ /** Original search query (for display) */
99
+ query: string;
100
+ }
101
+
102
+ /**
103
+ * Interactively select a session from search results.
104
+ *
105
+ * @param options - Selection options
106
+ * @returns Selected session or null if cancelled
107
+ */
108
+ async function selectFromSearchResults(options: SearchSelectOptions): Promise<Session | null> {
109
+ const { hits, storage, query } = options;
110
+
111
+ if (hits.length === 0) {
112
+ return null;
113
+ }
114
+
115
+ // Build choices for inquirer
116
+ interface SearchChoice {
117
+ name: string;
118
+ value: string;
119
+ description?: string;
120
+ }
121
+
122
+ const choices: SearchChoice[] = hits.map((hit, idx) => ({
123
+ name: formatSearchResult(hit, idx + 1),
124
+ value: hit.sessionId,
125
+ description: hit.snippet,
126
+ }));
127
+
128
+ try {
129
+ const selectedId = await select({
130
+ message: `选择要恢复的会话 (搜索: "${query}"):`,
131
+ choices,
132
+ pageSize: RESULTS_PER_PAGE,
133
+ });
134
+
135
+ // Load the selected session
136
+ const session = await storage.load(selectedId);
137
+ return session;
138
+ } catch {
139
+ // User cancelled (Ctrl+C)
140
+ return null;
141
+ }
142
+ }
143
+
144
+ // =============================================================================
145
+ // Search Event Data
146
+ // =============================================================================
147
+
148
+ /**
149
+ * Event data emitted when a session is selected from search.
150
+ */
151
+ export interface SearchSessionEventData {
152
+ /** The session being resumed */
153
+ session: Session;
154
+ /** The search query that found this session */
155
+ query: string;
156
+ }
157
+
158
+ // =============================================================================
159
+ // Helper Types and Functions
160
+ // =============================================================================
161
+
162
+ /**
163
+ * Maps search hits to a serializable data format.
164
+ */
165
+ function mapHitsToData(hits: SessionSearchHit[]) {
166
+ return hits.map((h) => ({
167
+ sessionId: h.sessionId,
168
+ title: h.title,
169
+ score: h.score,
170
+ matches: h.matches,
171
+ }));
172
+ }
173
+
174
+ /**
175
+ * Performs the actual search operation.
176
+ */
177
+ async function executeSearch(
178
+ searchService: SearchService,
179
+ query: string,
180
+ limit: number
181
+ ): Promise<SessionSearchHit[]> {
182
+ if (!searchService.isInitialized()) {
183
+ await searchService.initialize();
184
+ }
185
+ return searchService.search(query, { limit });
186
+ }
187
+
188
+ /**
189
+ * Handles interactive session selection from search results.
190
+ */
191
+ async function handleInteractiveSelection(
192
+ hits: SessionSearchHit[],
193
+ storage: StorageManager,
194
+ query: string,
195
+ ctx: CommandContext
196
+ ): Promise<CommandResult> {
197
+ const session = await selectFromSearchResults({ hits, storage, query });
198
+
199
+ if (!session) {
200
+ return error("COMMAND_ABORTED", "已取消选择");
201
+ }
202
+
203
+ const eventData: SearchSessionEventData = { session, query };
204
+ ctx.emit("session:search", eventData);
205
+
206
+ return success(`正在恢复会话: ${session.metadata.title}`, {
207
+ session,
208
+ sessionId: session.metadata.id,
209
+ title: session.metadata.title,
210
+ query,
211
+ });
212
+ }
213
+
214
+ /**
215
+ * Formats search results as a success response.
216
+ */
217
+ function createSearchResultResponse(hits: SessionSearchHit[], query: string): CommandResult {
218
+ const resultText = formatSearchResults(hits, query);
219
+ return success(resultText, {
220
+ query,
221
+ hits: mapHitsToData(hits),
222
+ count: hits.length,
223
+ });
224
+ }
225
+
226
+ // =============================================================================
227
+ // Search Command Factory
228
+ // =============================================================================
229
+
230
+ /**
231
+ * Creates the search command with injected dependencies.
232
+ *
233
+ * This factory allows the command to be created with specific
234
+ * storage and search service instances, enabling testing and
235
+ * different storage backends.
236
+ *
237
+ * @param storage - Storage manager for session data
238
+ * @param searchService - Search service for full-text search
239
+ * @returns SlashCommand instance
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * const storage = await StorageManager.create();
244
+ * const searchService = new SearchService(storage);
245
+ * await searchService.initialize();
246
+ * const searchCmd = createSearchCommand(storage, searchService);
247
+ * registry.register(searchCmd);
248
+ * ```
249
+ */
250
+ export function createSearchCommand(
251
+ storage: StorageManager,
252
+ searchService: SearchService
253
+ ): SlashCommand {
254
+ return {
255
+ name: "search",
256
+ description: "Search historical sessions by keywords",
257
+ kind: "builtin",
258
+ category: "session",
259
+ aliases: ["find", "s"],
260
+ positionalArgs: [
261
+ {
262
+ name: "query",
263
+ type: "string",
264
+ description: "Search keywords (multiple words allowed)",
265
+ required: false,
266
+ },
267
+ ],
268
+ namedArgs: [
269
+ {
270
+ name: "limit",
271
+ shorthand: "n",
272
+ type: "number",
273
+ description: "Maximum number of results (default: 10)",
274
+ required: false,
275
+ default: 10,
276
+ },
277
+ {
278
+ name: "select",
279
+ shorthand: "s",
280
+ type: "boolean",
281
+ description: "Interactive selection mode (default when no query)",
282
+ required: false,
283
+ default: false,
284
+ },
285
+ {
286
+ name: "rebuild",
287
+ shorthand: "r",
288
+ type: "boolean",
289
+ description: "Rebuild search index before searching",
290
+ required: false,
291
+ default: false,
292
+ },
293
+ ],
294
+ examples: [
295
+ "/search typescript - Search for 'typescript'",
296
+ "/search refactor api - Search for 'refactor' and 'api'",
297
+ "/search bug fix -n 20 - Search with max 20 results",
298
+ "/search --rebuild - Rebuild search index",
299
+ "/search auth -s - Search and select interactively",
300
+ ],
301
+
302
+ execute: async (ctx: CommandContext): Promise<CommandResult> => {
303
+ const query = ctx.parsedArgs.positional[0] as string | undefined;
304
+ const limit = Math.min(
305
+ (ctx.parsedArgs.named.limit as number | undefined) ?? 10,
306
+ MAX_DISPLAY_RESULTS
307
+ );
308
+ const interactiveSelect = (ctx.parsedArgs.named.select as boolean | undefined) ?? false;
309
+ const rebuildIndex = (ctx.parsedArgs.named.rebuild as boolean | undefined) ?? false;
310
+
311
+ // Handle rebuild request
312
+ if (rebuildIndex) {
313
+ return pending({
314
+ message: "正在重建搜索索引...",
315
+ showProgress: true,
316
+ promise: (async (): Promise<CommandResult> => {
317
+ try {
318
+ await searchService.rebuildIndex();
319
+ return success("✅ 搜索索引重建完成");
320
+ } catch (err) {
321
+ return error(
322
+ "INTERNAL_ERROR",
323
+ `重建索引失败: ${err instanceof Error ? err.message : String(err)}`
324
+ );
325
+ }
326
+ })(),
327
+ });
328
+ }
329
+
330
+ // No query provided - show usage or enter interactive mode
331
+ if (!query || query.trim().length === 0) {
332
+ return error("MISSING_ARGUMENT", "请提供搜索关键词", [
333
+ "/search <关键词> - 搜索会话",
334
+ "/search --rebuild - 重建索引",
335
+ "/help search - 查看完整帮助",
336
+ ]);
337
+ }
338
+
339
+ const trimmedQuery = query.trim();
340
+
341
+ // Perform search
342
+ return pending({
343
+ message: `正在搜索: "${trimmedQuery}"...`,
344
+ showProgress: true,
345
+ promise: (async (): Promise<CommandResult> => {
346
+ try {
347
+ const hits = await executeSearch(searchService, trimmedQuery, limit);
348
+
349
+ // Interactive selection when requested and results available
350
+ if (interactiveSelect && hits.length > 0) {
351
+ return handleInteractiveSelection(hits, storage, trimmedQuery, ctx);
352
+ }
353
+
354
+ // Default: show results as text
355
+ return createSearchResultResponse(hits, trimmedQuery);
356
+ } catch (err) {
357
+ return error(
358
+ "INTERNAL_ERROR",
359
+ `搜索失败: ${err instanceof Error ? err.message : String(err)}`
360
+ );
361
+ }
362
+ })(),
363
+ });
364
+ },
365
+ };
366
+ }
367
+
368
+ /**
369
+ * Default search command (requires initialization with storage).
370
+ *
371
+ * This is a placeholder that throws if executed without proper initialization.
372
+ * Use `createSearchCommand` factory for production use.
373
+ *
374
+ * @example
375
+ * ```typescript
376
+ * // For testing only - use createSearchCommand in production
377
+ * registry.register(searchCommand);
378
+ * ```
379
+ */
380
+ export const searchCommand: SlashCommand = {
381
+ name: "search",
382
+ description: "Search historical sessions by keywords",
383
+ kind: "builtin",
384
+ category: "session",
385
+ aliases: ["find", "s"],
386
+ positionalArgs: [
387
+ {
388
+ name: "query",
389
+ type: "string",
390
+ description: "Search keywords (multiple words allowed)",
391
+ required: false,
392
+ },
393
+ ],
394
+ namedArgs: [
395
+ {
396
+ name: "limit",
397
+ shorthand: "n",
398
+ type: "number",
399
+ description: "Maximum number of results (default: 10)",
400
+ required: false,
401
+ default: 10,
402
+ },
403
+ {
404
+ name: "select",
405
+ shorthand: "s",
406
+ type: "boolean",
407
+ description: "Interactive selection mode",
408
+ required: false,
409
+ default: false,
410
+ },
411
+ {
412
+ name: "rebuild",
413
+ shorthand: "r",
414
+ type: "boolean",
415
+ description: "Rebuild search index before searching",
416
+ required: false,
417
+ default: false,
418
+ },
419
+ ],
420
+ examples: [
421
+ "/search typescript - Search for 'typescript'",
422
+ "/search refactor api - Search for 'refactor' and 'api'",
423
+ "/search bug fix -n 20 - Search with max 20 results",
424
+ "/search --rebuild - Rebuild search index",
425
+ "/search auth -s - Search and select interactively",
426
+ ],
427
+
428
+ execute: async (_ctx: CommandContext): Promise<CommandResult> => {
429
+ return error(
430
+ "INTERNAL_ERROR",
431
+ "Search command not initialized. Use createSearchCommand with storage dependencies."
432
+ );
433
+ },
434
+ };
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Session Show Command (T032)
3
+ * @module cli/commands/session/show
4
+ */
5
+
6
+ import type { CommandResult, SlashCommand } from "../types.js";
7
+ import { success } from "../types.js";
8
+
9
+ /**
10
+ * Show command for displaying session details
11
+ */
12
+ export const showCommand: SlashCommand = {
13
+ name: "show",
14
+ aliases: ["view"],
15
+ description: "Show session details",
16
+ kind: "builtin",
17
+ category: "session",
18
+ execute: async (): Promise<CommandResult> => success("Session show not yet implemented"),
19
+ };
20
+
21
+ /**
22
+ * Factory function to create show command with context
23
+ */
24
+ export function createShowCommand(): SlashCommand {
25
+ return showCommand;
26
+ }