@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,354 @@
1
+ /**
2
+ * Help Command
3
+ *
4
+ * Displays help information for commands and categories.
5
+ *
6
+ * @module cli/commands/core/help
7
+ */
8
+
9
+ import type { CommandRegistry } from "../registry.js";
10
+ import type { CommandCategory, CommandContext, CommandResult, SlashCommand } from "../types.js";
11
+ import { error, success } from "../types.js";
12
+
13
+ // =============================================================================
14
+ // Category Display Names
15
+ // =============================================================================
16
+
17
+ /**
18
+ * Human-readable names for command categories
19
+ */
20
+ const CATEGORY_NAMES: Record<CommandCategory, string> = {
21
+ system: "System",
22
+ workflow: "Workflow",
23
+ auth: "Authentication",
24
+ session: "Session",
25
+ navigation: "Navigation",
26
+ tools: "Tools",
27
+ config: "Configuration",
28
+ debug: "Debug",
29
+ };
30
+
31
+ /**
32
+ * Category display order
33
+ */
34
+ const CATEGORY_ORDER: CommandCategory[] = [
35
+ "system",
36
+ "workflow",
37
+ "session",
38
+ "config",
39
+ "auth",
40
+ "tools",
41
+ "debug",
42
+ ];
43
+
44
+ // =============================================================================
45
+ // Help Formatter
46
+ // =============================================================================
47
+
48
+ /**
49
+ * Format command list grouped by category
50
+ */
51
+ function formatCommandList(registry: CommandRegistry): string {
52
+ const lines: string[] = [];
53
+ lines.push("📚 Available Commands\n");
54
+
55
+ for (const category of CATEGORY_ORDER) {
56
+ const commands = registry.getByCategory(category);
57
+ if (commands.size === 0) continue;
58
+
59
+ lines.push(`\n${CATEGORY_NAMES[category]}:`);
60
+
61
+ // Sort commands alphabetically
62
+ const sortedCmds = Array.from(commands).sort((a, b) => a.name.localeCompare(b.name));
63
+
64
+ for (const cmd of sortedCmds) {
65
+ const aliases = cmd.aliases?.length ? ` (${cmd.aliases.join(", ")})` : "";
66
+ lines.push(` /${cmd.name}${aliases} - ${cmd.description}`);
67
+ }
68
+ }
69
+
70
+ // Add shell mode hint
71
+ lines.push("\n\n💡 Quick Tips:");
72
+ lines.push(" • Type !<command> to execute shell commands directly (e.g., !ls, !git status)");
73
+ lines.push(" • Use @file to mention files in your prompt");
74
+ lines.push(" • Press Tab for autocomplete");
75
+
76
+ lines.push("\nUse /help <command> for detailed help on a specific command.");
77
+ return lines.join("\n");
78
+ }
79
+
80
+ /**
81
+ * Format positional arguments section
82
+ */
83
+ function formatPositionalArgs(args: readonly import("../types.js").PositionalArg[]): string[] {
84
+ const lines: string[] = ["Arguments:"];
85
+ for (const arg of args) {
86
+ const required = arg.required ? "(required)" : "(optional)";
87
+ const defaultVal = arg.default !== undefined ? ` [default: ${arg.default}]` : "";
88
+ lines.push(` <${arg.name}> ${required}${defaultVal}`);
89
+ lines.push(` ${arg.description}`);
90
+ }
91
+ lines.push("");
92
+ return lines;
93
+ }
94
+
95
+ /**
96
+ * Format named arguments (flags) section
97
+ */
98
+ function formatNamedArgs(args: readonly import("../types.js").NamedArg[]): string[] {
99
+ const lines: string[] = ["Options:"];
100
+ for (const arg of args) {
101
+ const short = arg.shorthand ? `-${arg.shorthand}, ` : " ";
102
+ const required = arg.required ? "(required)" : "";
103
+ const defaultVal = arg.default !== undefined ? ` [default: ${arg.default}]` : "";
104
+ lines.push(` ${short}--${arg.name} ${required}${defaultVal}`);
105
+ lines.push(` ${arg.description}`);
106
+ }
107
+ lines.push("");
108
+ return lines;
109
+ }
110
+
111
+ /**
112
+ * Format detailed help for a single command
113
+ */
114
+ function formatCommandHelp(cmd: SlashCommand): string {
115
+ const lines: string[] = [];
116
+
117
+ // Header
118
+ lines.push(`📖 /${cmd.name}`);
119
+ lines.push(` ${cmd.description}\n`);
120
+
121
+ // Aliases
122
+ if (cmd.aliases?.length) {
123
+ lines.push(`Aliases: ${cmd.aliases.map((a) => `/${a}`).join(", ")}`);
124
+ }
125
+
126
+ // Category and Kind
127
+ lines.push(`Category: ${CATEGORY_NAMES[cmd.category]}`);
128
+ lines.push(`Kind: ${cmd.kind}\n`);
129
+
130
+ // Usage
131
+ const usage = buildUsage(cmd);
132
+ lines.push(`Usage: ${usage}\n`);
133
+
134
+ // Positional arguments
135
+ if (cmd.positionalArgs?.length) {
136
+ lines.push(...formatPositionalArgs(cmd.positionalArgs));
137
+ }
138
+
139
+ // Named arguments (flags)
140
+ if (cmd.namedArgs?.length) {
141
+ lines.push(...formatNamedArgs(cmd.namedArgs));
142
+ }
143
+
144
+ // Examples
145
+ if (cmd.examples?.length) {
146
+ lines.push("Examples:");
147
+ for (const example of cmd.examples) {
148
+ lines.push(` ${example}`);
149
+ }
150
+ }
151
+
152
+ return lines.join("\n");
153
+ }
154
+
155
+ /**
156
+ * Format help for a category
157
+ */
158
+ function formatCategoryHelp(category: CommandCategory, registry: CommandRegistry): string {
159
+ const commands = registry.getByCategory(category);
160
+ const lines: string[] = [];
161
+
162
+ lines.push(`📂 ${CATEGORY_NAMES[category]} Commands\n`);
163
+
164
+ if (commands.size === 0) {
165
+ lines.push(" No commands in this category.");
166
+ return lines.join("\n");
167
+ }
168
+
169
+ const sortedCmds = Array.from(commands).sort((a, b) => a.name.localeCompare(b.name));
170
+
171
+ for (const cmd of sortedCmds) {
172
+ const aliases = cmd.aliases?.length ? ` (${cmd.aliases.join(", ")})` : "";
173
+ lines.push(` /${cmd.name}${aliases}`);
174
+ lines.push(` ${cmd.description}`);
175
+ }
176
+
177
+ lines.push("\n\nUse /help <command> for detailed help on a specific command.");
178
+ return lines.join("\n");
179
+ }
180
+
181
+ /**
182
+ * Build usage string for a command
183
+ */
184
+ function buildUsage(cmd: SlashCommand): string {
185
+ const parts: string[] = [`/${cmd.name}`];
186
+
187
+ // Add positional args
188
+ if (cmd.positionalArgs) {
189
+ for (const arg of cmd.positionalArgs) {
190
+ if (arg.required) {
191
+ parts.push(`<${arg.name}>`);
192
+ } else {
193
+ parts.push(`[${arg.name}]`);
194
+ }
195
+ }
196
+ }
197
+
198
+ // Add named args hint
199
+ if (cmd.namedArgs?.length) {
200
+ parts.push("[options]");
201
+ }
202
+
203
+ return parts.join(" ");
204
+ }
205
+
206
+ /**
207
+ * Check if a string is a valid category
208
+ */
209
+ function isCategory(topic: string): topic is CommandCategory {
210
+ return CATEGORY_ORDER.includes(topic as CommandCategory);
211
+ }
212
+
213
+ // =============================================================================
214
+ // T027: Help Command Definition
215
+ // =============================================================================
216
+
217
+ /**
218
+ * Provides access to command registry for help command
219
+ *
220
+ * This must be set before using the help command.
221
+ * Typically set during application initialization.
222
+ */
223
+ let registryRef: CommandRegistry | null = null;
224
+
225
+ /**
226
+ * Set the command registry reference for help command
227
+ */
228
+ export function setHelpRegistry(registry: CommandRegistry): void {
229
+ registryRef = registry;
230
+ }
231
+
232
+ /**
233
+ * Get the command registry reference
234
+ */
235
+ export function getHelpRegistry(): CommandRegistry | null {
236
+ return registryRef;
237
+ }
238
+
239
+ /**
240
+ * Get dynamic subcommands for help based on registered commands.
241
+ * Returns subcommands for all registered commands plus category names.
242
+ */
243
+ export function getHelpSubcommands(): import("../types.js").SubcommandDef[] {
244
+ const subcommands: import("../types.js").SubcommandDef[] = [];
245
+
246
+ // Add category names as subcommands
247
+ for (const category of CATEGORY_ORDER) {
248
+ subcommands.push({
249
+ name: category,
250
+ description: `Show ${CATEGORY_NAMES[category]} commands`,
251
+ });
252
+ }
253
+
254
+ // Add registered commands as subcommands (if registry is available)
255
+ if (registryRef) {
256
+ const allCommands = registryRef.list();
257
+ for (const cmd of allCommands) {
258
+ // Skip if already added (category name conflict)
259
+ if (!subcommands.some((s) => s.name === cmd.name)) {
260
+ subcommands.push({
261
+ name: cmd.name,
262
+ description: cmd.description,
263
+ aliases: cmd.aliases ? [...cmd.aliases] : undefined,
264
+ });
265
+ }
266
+ }
267
+ }
268
+
269
+ return subcommands;
270
+ }
271
+
272
+ /**
273
+ * Help command - displays help information
274
+ *
275
+ * Usage:
276
+ * - /help - Display all commands grouped by category
277
+ * - /help <command> - Display detailed help for a command
278
+ * - /help <category> - Display commands in a category
279
+ */
280
+ export const helpCommand: SlashCommand = {
281
+ name: "help",
282
+ description: "Display help information for commands and categories",
283
+ kind: "builtin",
284
+ category: "system",
285
+ aliases: ["h", "?"],
286
+ positionalArgs: [
287
+ {
288
+ name: "topic",
289
+ type: "string",
290
+ description: "Command name or category to get help for",
291
+ required: false,
292
+ },
293
+ ],
294
+ examples: [
295
+ "/help - Show all commands",
296
+ "/help auth - Help for auth command",
297
+ "/help system - Show system category commands",
298
+ ],
299
+ // Subcommands are generated dynamically via getHelpSubcommands()
300
+ // The autocomplete system should call getHelpSubcommands() for fresh data
301
+ subcommands: CATEGORY_ORDER.map((category) => ({
302
+ name: category,
303
+ description: `Show ${CATEGORY_NAMES[category]} commands`,
304
+ })),
305
+
306
+ execute: async (ctx: CommandContext): Promise<CommandResult> => {
307
+ const topic = ctx.parsedArgs.positional[0] as string | undefined;
308
+
309
+ // Get registry from the reference
310
+ const registry = registryRef;
311
+ if (!registry) {
312
+ return error(
313
+ "INTERNAL_ERROR",
314
+ "Command registry not initialized. This is a configuration error."
315
+ );
316
+ }
317
+
318
+ // No topic: show all commands
319
+ if (!topic) {
320
+ const message = formatCommandList(registry);
321
+ return success(message, { type: "help-list", categories: CATEGORY_ORDER });
322
+ }
323
+
324
+ // Check if topic is a category
325
+ if (isCategory(topic)) {
326
+ const message = formatCategoryHelp(topic, registry);
327
+ return success(message, { type: "help-category", category: topic });
328
+ }
329
+
330
+ // Try to find command by name or alias
331
+ const cmd = registry.get(topic);
332
+ if (cmd) {
333
+ const message = formatCommandHelp(cmd);
334
+ return success(message, { type: "help-command", command: cmd.name });
335
+ }
336
+
337
+ // Command not found - try fuzzy search for suggestions
338
+ const allCommands = registry.list();
339
+ const suggestions = allCommands
340
+ .filter(
341
+ (c) =>
342
+ c.name.toLowerCase().includes(topic.toLowerCase()) ||
343
+ c.aliases?.some((a) => a.toLowerCase().includes(topic.toLowerCase()))
344
+ )
345
+ .map((c) => `/${c.name}`)
346
+ .slice(0, 3);
347
+
348
+ return error(
349
+ "COMMAND_NOT_FOUND",
350
+ `Unknown command or category: "${topic}"`,
351
+ suggestions.length > 0 ? suggestions : undefined
352
+ );
353
+ },
354
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Core Commands Barrel Export
3
+ *
4
+ * Exports all core builtin commands for the command system.
5
+ *
6
+ * @module cli/commands/core
7
+ */
8
+
9
+ // =============================================================================
10
+ // T030: Core Commands Exports
11
+ // =============================================================================
12
+
13
+ export { clearCommand } from "./clear.js";
14
+ export { exitCommand } from "./exit.js";
15
+ export { getHelpRegistry, getHelpSubcommands, helpCommand, setHelpRegistry } from "./help.js";
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Cost Slash Command (Phase 35)
3
+ *
4
+ * Provides the /cost command for displaying session cost information.
5
+ *
6
+ * @module cli/commands/cost
7
+ */
8
+
9
+ import type { CostService, ModelUsage, ProviderUsage } from "@vellum/core";
10
+ import { formatCost, formatCostBreakdown, formatTokenCount } from "@vellum/core";
11
+ import type { CommandContext, CommandResult, SlashCommand } from "./types.js";
12
+ import { error, success } from "./types.js";
13
+
14
+ // =============================================================================
15
+ // Module State
16
+ // =============================================================================
17
+
18
+ /**
19
+ * Reference to the active CostService instance.
20
+ * Set by the App component when initialized.
21
+ */
22
+ let costService: CostService | null = null;
23
+
24
+ /**
25
+ * Set the CostService instance for cost commands.
26
+ * Called by the App component during initialization.
27
+ *
28
+ * @param service - The CostService instance to use
29
+ */
30
+ export function setCostCommandsService(service: CostService | null): void {
31
+ costService = service;
32
+ }
33
+
34
+ /**
35
+ * Get the current CostService instance.
36
+ * Returns null if not yet initialized.
37
+ */
38
+ export function getCostCommandsService(): CostService | null {
39
+ return costService;
40
+ }
41
+
42
+ // =============================================================================
43
+ // /cost Command
44
+ // =============================================================================
45
+
46
+ /**
47
+ * /cost command - Display session cost information.
48
+ *
49
+ * Shows current session's token usage and cost breakdown.
50
+ * Without a CostService, shows a placeholder indicating
51
+ * cost tracking is not initialized.
52
+ */
53
+ export const costCommand: SlashCommand = {
54
+ name: "cost",
55
+ description: "Show session cost breakdown",
56
+ kind: "builtin",
57
+ category: "system",
58
+ aliases: ["costs", "usage"],
59
+ positionalArgs: [
60
+ {
61
+ name: "format",
62
+ type: "string",
63
+ description: "Output format: brief, full, json",
64
+ required: false,
65
+ },
66
+ ],
67
+ examples: [
68
+ "/cost - Show brief cost summary",
69
+ "/cost full - Show detailed breakdown",
70
+ "/cost json - Output as JSON",
71
+ ],
72
+
73
+ execute: async (ctx: CommandContext): Promise<CommandResult> => {
74
+ const format = (ctx.parsedArgs.positional[0] as string | undefined) ?? "brief";
75
+
76
+ if (!costService) {
77
+ return error("RESOURCE_NOT_FOUND", "Cost tracking not initialized. Start a session first.");
78
+ }
79
+
80
+ const sessionCost = costService.getSessionCost();
81
+ const inputTokens = costService.totalInputTokens;
82
+ const outputTokens = costService.totalOutputTokens;
83
+ const requestCount = costService.requestCount;
84
+
85
+ // JSON output
86
+ if (format === "json") {
87
+ const summary = costService.getSessionSummary();
88
+ return success(JSON.stringify(summary, null, 2));
89
+ }
90
+
91
+ // Brief output (default)
92
+ if (format === "brief" || format !== "full") {
93
+ const totalTokens = inputTokens + outputTokens;
94
+ const lines = [
95
+ "💰 Session Cost",
96
+ "",
97
+ ` Requests: ${requestCount}`,
98
+ ` Tokens: ${formatTokenCount(totalTokens)} (${formatTokenCount(inputTokens)} in / ${formatTokenCount(outputTokens)} out)`,
99
+ ` Cost: ${formatCost(sessionCost.total)}`,
100
+ "",
101
+ "Use /cost full for detailed breakdown.",
102
+ ];
103
+ return success(lines.join("\n"));
104
+ }
105
+
106
+ // Full output
107
+ const summary = costService.getSessionSummary();
108
+ const lines = [
109
+ "💰 Session Cost Details",
110
+ "",
111
+ "─── Token Usage ───",
112
+ ` Input: ${formatTokenCount(inputTokens)}`,
113
+ ` Output: ${formatTokenCount(outputTokens)}`,
114
+ ];
115
+
116
+ if (summary.totalCacheReadTokens > 0) {
117
+ lines.push(` Cache (R): ${formatTokenCount(summary.totalCacheReadTokens)}`);
118
+ }
119
+ if (summary.totalCacheWriteTokens > 0) {
120
+ lines.push(` Cache (W): ${formatTokenCount(summary.totalCacheWriteTokens)}`);
121
+ }
122
+ if (summary.totalReasoningTokens > 0) {
123
+ lines.push(` Reasoning: ${formatTokenCount(summary.totalReasoningTokens)}`);
124
+ }
125
+
126
+ lines.push("");
127
+ lines.push("─── Cost Breakdown ───");
128
+ lines.push(formatCostBreakdown(sessionCost));
129
+
130
+ // By provider
131
+ const providers = Object.entries(summary.byProvider) as [string, ProviderUsage][];
132
+ if (providers.length > 0) {
133
+ lines.push("");
134
+ lines.push("─── By Provider ───");
135
+ for (const [provider, usage] of providers) {
136
+ lines.push(` ${provider}: ${formatCost(usage.cost)} (${usage.requests} requests)`);
137
+ }
138
+ }
139
+
140
+ // By model
141
+ const models = Object.entries(summary.byModel) as [string, ModelUsage][];
142
+ if (models.length > 0) {
143
+ lines.push("");
144
+ lines.push("─── By Model ───");
145
+ for (const [model, usage] of models) {
146
+ lines.push(` ${model}: ${formatCost(usage.cost)} (${usage.requests} requests)`);
147
+ }
148
+ }
149
+
150
+ return success(lines.join("\n"));
151
+ },
152
+ };
153
+
154
+ /**
155
+ * /cost reset command - Reset session cost tracking.
156
+ */
157
+ export const costResetCommand: SlashCommand = {
158
+ name: "cost-reset",
159
+ description: "Reset session cost tracking",
160
+ kind: "builtin",
161
+ category: "system",
162
+ aliases: ["reset-cost"],
163
+ examples: ["/cost-reset - Clear session cost data"],
164
+
165
+ execute: async (_ctx: CommandContext): Promise<CommandResult> => {
166
+ if (!costService) {
167
+ return error("RESOURCE_NOT_FOUND", "Cost tracking not initialized.");
168
+ }
169
+
170
+ costService.reset();
171
+ return success("✅ Session cost tracking reset.");
172
+ },
173
+ };
174
+
175
+ // =============================================================================
176
+ // Export
177
+ // =============================================================================
178
+
179
+ export default costCommand;