@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.
- package/LICENSE +21 -0
- package/README.md +411 -0
- package/__fixtures__/responses/code-generation.json +42 -0
- package/__fixtures__/responses/error-response.json +20 -0
- package/__fixtures__/responses/hello-world.json +32 -0
- package/dist/auth-6MCXESOH.js +26 -0
- package/dist/chunk-SECXJGWA.js +597 -0
- package/dist/index.js +34023 -0
- package/package.json +67 -0
- package/src/__tests__/commands.e2e.test.ts +728 -0
- package/src/__tests__/credentials.test.ts +713 -0
- package/src/__tests__/mode-e2e.test.ts +391 -0
- package/src/__tests__/tui-integration.test.tsx +1271 -0
- package/src/agents/__tests__/task-persistence.test.ts +235 -0
- package/src/agents/commands/delegate.ts +240 -0
- package/src/agents/commands/index.ts +10 -0
- package/src/agents/commands/resume.ts +335 -0
- package/src/agents/index.ts +29 -0
- package/src/agents/task-persistence.ts +272 -0
- package/src/agents/task-resumption.ts +242 -0
- package/src/app.tsx +4737 -0
- package/src/commands/__tests__/.gitkeep +1 -0
- package/src/commands/__tests__/agents.test.ts +606 -0
- package/src/commands/__tests__/auth.test.ts +626 -0
- package/src/commands/__tests__/autocomplete.test.ts +683 -0
- package/src/commands/__tests__/batch.test.ts +287 -0
- package/src/commands/__tests__/chain-pipe-parser.test.ts +654 -0
- package/src/commands/__tests__/completion.test.ts +238 -0
- package/src/commands/__tests__/core.test.ts +363 -0
- package/src/commands/__tests__/executor.test.ts +496 -0
- package/src/commands/__tests__/exit-codes.test.ts +220 -0
- package/src/commands/__tests__/init.test.ts +243 -0
- package/src/commands/__tests__/language.test.ts +353 -0
- package/src/commands/__tests__/mode-cli.test.ts +667 -0
- package/src/commands/__tests__/model.test.ts +277 -0
- package/src/commands/__tests__/parser.test.ts +493 -0
- package/src/commands/__tests__/performance.bench.ts +380 -0
- package/src/commands/__tests__/registry.test.ts +534 -0
- package/src/commands/__tests__/resume.test.ts +449 -0
- package/src/commands/__tests__/security.test.ts +845 -0
- package/src/commands/__tests__/stream-json.test.ts +372 -0
- package/src/commands/__tests__/user-commands.test.ts +597 -0
- package/src/commands/adapters.ts +267 -0
- package/src/commands/agent.ts +395 -0
- package/src/commands/agents/generate.ts +506 -0
- package/src/commands/agents/index.ts +272 -0
- package/src/commands/agents/show.ts +271 -0
- package/src/commands/agents/validate.ts +387 -0
- package/src/commands/auth.ts +883 -0
- package/src/commands/autocomplete.ts +480 -0
- package/src/commands/batch/command.ts +388 -0
- package/src/commands/batch/executor.ts +361 -0
- package/src/commands/batch/index.ts +12 -0
- package/src/commands/commit.ts +235 -0
- package/src/commands/completion/index.ts +371 -0
- package/src/commands/condense.ts +191 -0
- package/src/commands/config.ts +344 -0
- package/src/commands/context-provider.ts +173 -0
- package/src/commands/copy.ts +329 -0
- package/src/commands/core/clear.ts +38 -0
- package/src/commands/core/exit.ts +43 -0
- package/src/commands/core/help.ts +354 -0
- package/src/commands/core/index.ts +15 -0
- package/src/commands/cost.ts +179 -0
- package/src/commands/credentials.tsx +618 -0
- package/src/commands/custom-agents/__tests__/custom-agents.test.ts +709 -0
- package/src/commands/custom-agents/create.ts +377 -0
- package/src/commands/custom-agents/export.ts +135 -0
- package/src/commands/custom-agents/import.ts +199 -0
- package/src/commands/custom-agents/index.ts +372 -0
- package/src/commands/custom-agents/info.ts +318 -0
- package/src/commands/custom-agents/list.ts +267 -0
- package/src/commands/custom-agents/validate.ts +388 -0
- package/src/commands/diff-mode.ts +241 -0
- package/src/commands/env.ts +53 -0
- package/src/commands/executor.ts +579 -0
- package/src/commands/exit-codes.ts +202 -0
- package/src/commands/index.ts +701 -0
- package/src/commands/init/index.ts +15 -0
- package/src/commands/init/prompts.ts +366 -0
- package/src/commands/init/templates/commands-readme.md +80 -0
- package/src/commands/init/templates/example-command.md +79 -0
- package/src/commands/init/templates/example-skill.md +168 -0
- package/src/commands/init/templates/example-workflow.md +101 -0
- package/src/commands/init/templates/prompts-readme.md +52 -0
- package/src/commands/init/templates/rules-readme.md +63 -0
- package/src/commands/init/templates/skills-readme.md +83 -0
- package/src/commands/init/templates/workflows-readme.md +94 -0
- package/src/commands/init.ts +391 -0
- package/src/commands/install.ts +90 -0
- package/src/commands/language.ts +191 -0
- package/src/commands/loaders/.gitkeep +1 -0
- package/src/commands/lsp.ts +199 -0
- package/src/commands/markdown-commands.ts +253 -0
- package/src/commands/mcp.ts +588 -0
- package/src/commands/memory/export.ts +341 -0
- package/src/commands/memory/index.ts +148 -0
- package/src/commands/memory/list.ts +261 -0
- package/src/commands/memory/search.ts +346 -0
- package/src/commands/memory/utils.ts +15 -0
- package/src/commands/metrics.ts +75 -0
- package/src/commands/migrate/index.ts +16 -0
- package/src/commands/migrate/prompts.ts +477 -0
- package/src/commands/mode.ts +331 -0
- package/src/commands/model.ts +298 -0
- package/src/commands/onboard.ts +205 -0
- package/src/commands/open.ts +169 -0
- package/src/commands/output/stream-json.ts +373 -0
- package/src/commands/parser/chain-parser.ts +370 -0
- package/src/commands/parser/index.ts +29 -0
- package/src/commands/parser/pipe-parser.ts +480 -0
- package/src/commands/parser.ts +588 -0
- package/src/commands/persistence.ts +355 -0
- package/src/commands/progress.ts +18 -0
- package/src/commands/prompt/index.ts +17 -0
- package/src/commands/prompt/validate.ts +621 -0
- package/src/commands/prompt-priority.ts +401 -0
- package/src/commands/registry.ts +374 -0
- package/src/commands/sandbox/index.ts +131 -0
- package/src/commands/security/index.ts +21 -0
- package/src/commands/security/input-sanitizer.ts +168 -0
- package/src/commands/security/permission-checker.ts +456 -0
- package/src/commands/security/sensitive-data.ts +350 -0
- package/src/commands/session/delete.ts +38 -0
- package/src/commands/session/export.ts +39 -0
- package/src/commands/session/index.ts +26 -0
- package/src/commands/session/list.ts +26 -0
- package/src/commands/session/resume.ts +562 -0
- package/src/commands/session/search.ts +434 -0
- package/src/commands/session/show.ts +26 -0
- package/src/commands/settings.ts +368 -0
- package/src/commands/setup.ts +23 -0
- package/src/commands/shell/index.ts +16 -0
- package/src/commands/shell/setup.ts +422 -0
- package/src/commands/shell-init.ts +50 -0
- package/src/commands/shell-integration/index.ts +194 -0
- package/src/commands/skill.ts +1220 -0
- package/src/commands/spec.ts +558 -0
- package/src/commands/status.ts +246 -0
- package/src/commands/theme.ts +211 -0
- package/src/commands/think.ts +551 -0
- package/src/commands/trust.ts +211 -0
- package/src/commands/tutorial.ts +522 -0
- package/src/commands/types.ts +512 -0
- package/src/commands/update.ts +274 -0
- package/src/commands/usage.ts +213 -0
- package/src/commands/user-commands.ts +630 -0
- package/src/commands/utils.ts +142 -0
- package/src/commands/vim.ts +152 -0
- package/src/commands/workflow.ts +257 -0
- package/src/components/header.tsx +25 -0
- package/src/components/input.tsx +25 -0
- package/src/components/message-list.tsx +32 -0
- package/src/components/status-bar.tsx +23 -0
- package/src/index.tsx +614 -0
- package/src/onboarding/__tests__/tutorial.test.ts +740 -0
- package/src/onboarding/index.ts +69 -0
- package/src/onboarding/tips/index.ts +9 -0
- package/src/onboarding/tips/tip-engine.ts +459 -0
- package/src/onboarding/tutorial/index.ts +88 -0
- package/src/onboarding/tutorial/lessons/basics.ts +151 -0
- package/src/onboarding/tutorial/lessons/index.ts +151 -0
- package/src/onboarding/tutorial/lessons/modes.ts +230 -0
- package/src/onboarding/tutorial/lessons/tools.ts +172 -0
- package/src/onboarding/tutorial/progress-tracker.ts +350 -0
- package/src/onboarding/tutorial/storage.ts +249 -0
- package/src/onboarding/tutorial/tutorial-system.ts +462 -0
- package/src/onboarding/tutorial/types.ts +310 -0
- package/src/orchestrator-singleton.ts +129 -0
- package/src/shutdown.ts +33 -0
- package/src/test/e2e/assertions.ts +267 -0
- package/src/test/e2e/fixtures.ts +204 -0
- package/src/test/e2e/harness.ts +575 -0
- package/src/test/e2e/index.ts +57 -0
- package/src/test/e2e/types.ts +228 -0
- package/src/test/fixtures/__tests__/fake-response-loader.test.ts +314 -0
- package/src/test/fixtures/fake-response-loader.ts +314 -0
- package/src/test/fixtures/index.ts +20 -0
- package/src/tui/__tests__/mcp-panel.test.tsx +82 -0
- package/src/tui/__tests__/mcp-wiring.test.tsx +78 -0
- package/src/tui/__tests__/mode-components.test.tsx +395 -0
- package/src/tui/__tests__/permission-ask-flow.test.tsx +138 -0
- package/src/tui/__tests__/sidebar-panel-data.test.tsx +148 -0
- package/src/tui/__tests__/tools-panel-hotkeys.test.tsx +41 -0
- package/src/tui/adapters/agent-adapter.ts +1008 -0
- package/src/tui/adapters/index.ts +48 -0
- package/src/tui/adapters/message-adapter.ts +315 -0
- package/src/tui/adapters/persistence-bridge.ts +331 -0
- package/src/tui/adapters/session-adapter.ts +419 -0
- package/src/tui/buffered-stdout.ts +223 -0
- package/src/tui/components/AgentProgress.tsx +424 -0
- package/src/tui/components/Banner/AsciiArt.ts +160 -0
- package/src/tui/components/Banner/Banner.tsx +355 -0
- package/src/tui/components/Banner/ShimmerContext.tsx +131 -0
- package/src/tui/components/Banner/ShimmerText.tsx +193 -0
- package/src/tui/components/Banner/TypeWriterGradient.tsx +321 -0
- package/src/tui/components/Banner/index.ts +61 -0
- package/src/tui/components/Banner/useShimmer.ts +241 -0
- package/src/tui/components/ChatView.tsx +11 -0
- package/src/tui/components/Checkpoint/CheckpointDiffView.tsx +371 -0
- package/src/tui/components/Checkpoint/SnapshotCheckpointPanel.tsx +440 -0
- package/src/tui/components/Checkpoint/index.ts +19 -0
- package/src/tui/components/CostDisplay.tsx +226 -0
- package/src/tui/components/InitErrorBanner.tsx +122 -0
- package/src/tui/components/Input/Autocomplete.tsx +603 -0
- package/src/tui/components/Input/EnhancedCommandInput.tsx +471 -0
- package/src/tui/components/Input/HighlightedText.tsx +236 -0
- package/src/tui/components/Input/MentionAutocomplete.tsx +375 -0
- package/src/tui/components/Input/TextInput.tsx +1002 -0
- package/src/tui/components/Input/__tests__/Autocomplete.test.tsx +374 -0
- package/src/tui/components/Input/__tests__/TextInput.test.tsx +241 -0
- package/src/tui/components/Input/__tests__/highlight.test.ts +219 -0
- package/src/tui/components/Input/__tests__/slash-command-utils.test.ts +104 -0
- package/src/tui/components/Input/highlight.ts +362 -0
- package/src/tui/components/Input/index.ts +36 -0
- package/src/tui/components/Input/slash-command-utils.ts +135 -0
- package/src/tui/components/Layout.tsx +432 -0
- package/src/tui/components/McpPanel.tsx +137 -0
- package/src/tui/components/MemoryPanel.tsx +448 -0
- package/src/tui/components/Messages/CodeBlock.tsx +527 -0
- package/src/tui/components/Messages/DiffView.tsx +679 -0
- package/src/tui/components/Messages/ImageReference.tsx +89 -0
- package/src/tui/components/Messages/MarkdownBlock.tsx +228 -0
- package/src/tui/components/Messages/MarkdownRenderer.tsx +498 -0
- package/src/tui/components/Messages/MessageBubble.tsx +270 -0
- package/src/tui/components/Messages/MessageList.tsx +1719 -0
- package/src/tui/components/Messages/StreamingText.tsx +216 -0
- package/src/tui/components/Messages/ThinkingBlock.tsx +408 -0
- package/src/tui/components/Messages/ToolResultPreview.tsx +243 -0
- package/src/tui/components/Messages/__tests__/CodeBlock.test.tsx +296 -0
- package/src/tui/components/Messages/__tests__/DiffView.test.tsx +239 -0
- package/src/tui/components/Messages/__tests__/MarkdownRenderer.test.tsx +303 -0
- package/src/tui/components/Messages/__tests__/MessageBubble.test.tsx +268 -0
- package/src/tui/components/Messages/__tests__/MessageList.test.tsx +324 -0
- package/src/tui/components/Messages/__tests__/StreamingText.test.tsx +215 -0
- package/src/tui/components/Messages/index.ts +25 -0
- package/src/tui/components/ModeIndicator.tsx +177 -0
- package/src/tui/components/ModeSelector.tsx +216 -0
- package/src/tui/components/ModelSelector.tsx +339 -0
- package/src/tui/components/OnboardingWizard.tsx +670 -0
- package/src/tui/components/PhaseProgressIndicator.tsx +270 -0
- package/src/tui/components/RateLimitIndicator.tsx +82 -0
- package/src/tui/components/ScreenReaderLayout.tsx +295 -0
- package/src/tui/components/SettingsPanel.tsx +643 -0
- package/src/tui/components/Sidebar/SystemStatusPanel.tsx +284 -0
- package/src/tui/components/Sidebar/index.ts +9 -0
- package/src/tui/components/Status/ModelStatusBar.tsx +270 -0
- package/src/tui/components/Status/index.ts +12 -0
- package/src/tui/components/StatusBar/AgentModeIndicator.tsx +257 -0
- package/src/tui/components/StatusBar/ContextProgress.tsx +167 -0
- package/src/tui/components/StatusBar/FileChangesIndicator.tsx +62 -0
- package/src/tui/components/StatusBar/GitIndicator.tsx +89 -0
- package/src/tui/components/StatusBar/HeaderBar.tsx +126 -0
- package/src/tui/components/StatusBar/ModelIndicator.tsx +157 -0
- package/src/tui/components/StatusBar/PersistenceStatusIndicator.tsx +210 -0
- package/src/tui/components/StatusBar/ResilienceIndicator.tsx +106 -0
- package/src/tui/components/StatusBar/SandboxIndicator.tsx +167 -0
- package/src/tui/components/StatusBar/StatusBar.tsx +368 -0
- package/src/tui/components/StatusBar/ThinkingModeIndicator.tsx +170 -0
- package/src/tui/components/StatusBar/TokenBreakdown.tsx +246 -0
- package/src/tui/components/StatusBar/TokenCounter.tsx +135 -0
- package/src/tui/components/StatusBar/TrustModeIndicator.tsx +130 -0
- package/src/tui/components/StatusBar/WorkspaceIndicator.tsx +86 -0
- package/src/tui/components/StatusBar/__tests__/AgentModeIndicator.test.tsx +193 -0
- package/src/tui/components/StatusBar/__tests__/StatusBar.test.tsx +729 -0
- package/src/tui/components/StatusBar/index.ts +60 -0
- package/src/tui/components/TipBanner.tsx +115 -0
- package/src/tui/components/TodoItem.tsx +208 -0
- package/src/tui/components/TodoPanel.tsx +455 -0
- package/src/tui/components/Tools/ApprovalQueue.tsx +407 -0
- package/src/tui/components/Tools/OptionSelector.tsx +160 -0
- package/src/tui/components/Tools/PermissionDialog.tsx +286 -0
- package/src/tui/components/Tools/ToolParams.tsx +483 -0
- package/src/tui/components/Tools/ToolsPanel.tsx +178 -0
- package/src/tui/components/Tools/__tests__/PermissionDialog.test.tsx +510 -0
- package/src/tui/components/Tools/__tests__/ToolParams.test.tsx +432 -0
- package/src/tui/components/Tools/index.ts +21 -0
- package/src/tui/components/TrustPrompt.tsx +279 -0
- package/src/tui/components/UpdateBanner.tsx +166 -0
- package/src/tui/components/VimModeIndicator.tsx +112 -0
- package/src/tui/components/backtrack/BacktrackControls.tsx +402 -0
- package/src/tui/components/backtrack/index.ts +13 -0
- package/src/tui/components/common/AutoApprovalStatus.tsx +251 -0
- package/src/tui/components/common/CostWarning.tsx +294 -0
- package/src/tui/components/common/DynamicShortcutHints.tsx +209 -0
- package/src/tui/components/common/EnhancedLoadingIndicator.tsx +305 -0
- package/src/tui/components/common/ErrorBoundary.tsx +140 -0
- package/src/tui/components/common/GradientText.tsx +224 -0
- package/src/tui/components/common/HotkeyHelpModal.tsx +193 -0
- package/src/tui/components/common/HotkeyHints.tsx +70 -0
- package/src/tui/components/common/MaxSizedBox.tsx +354 -0
- package/src/tui/components/common/NewMessagesBadge.tsx +65 -0
- package/src/tui/components/common/ProtectedFileLegend.tsx +89 -0
- package/src/tui/components/common/ScrollIndicator.tsx +160 -0
- package/src/tui/components/common/Spinner.tsx +342 -0
- package/src/tui/components/common/StreamingIndicator.tsx +316 -0
- package/src/tui/components/common/VirtualizedList/VirtualizedList.tsx +428 -0
- package/src/tui/components/common/VirtualizedList/hooks/index.ts +19 -0
- package/src/tui/components/common/VirtualizedList/hooks/useBatchedScroll.ts +64 -0
- package/src/tui/components/common/VirtualizedList/hooks/useScrollAnchor.ts +290 -0
- package/src/tui/components/common/VirtualizedList/hooks/useVirtualization.ts +340 -0
- package/src/tui/components/common/VirtualizedList/index.ts +30 -0
- package/src/tui/components/common/VirtualizedList/types.ts +107 -0
- package/src/tui/components/common/__tests__/NewMessagesBadge.test.tsx +74 -0
- package/src/tui/components/common/__tests__/ScrollIndicator.test.tsx +193 -0
- package/src/tui/components/common/index.ts +110 -0
- package/src/tui/components/index.ts +79 -0
- package/src/tui/components/session/CheckpointPanel.tsx +323 -0
- package/src/tui/components/session/RollbackDialog.tsx +169 -0
- package/src/tui/components/session/SessionItem.tsx +136 -0
- package/src/tui/components/session/SessionListPanel.tsx +252 -0
- package/src/tui/components/session/SessionPicker.tsx +449 -0
- package/src/tui/components/session/SessionPreview.tsx +240 -0
- package/src/tui/components/session/__tests__/session.test.tsx +408 -0
- package/src/tui/components/session/index.ts +28 -0
- package/src/tui/components/session/types.ts +116 -0
- package/src/tui/components/theme/__tests__/tokens.test.ts +471 -0
- package/src/tui/components/theme/index.ts +227 -0
- package/src/tui/components/theme/tokens.ts +484 -0
- package/src/tui/config/defaults.ts +134 -0
- package/src/tui/config/index.ts +17 -0
- package/src/tui/context/AnimationContext.tsx +284 -0
- package/src/tui/context/AppContext.tsx +349 -0
- package/src/tui/context/BracketedPasteContext.tsx +372 -0
- package/src/tui/context/LspContext.tsx +192 -0
- package/src/tui/context/McpContext.tsx +325 -0
- package/src/tui/context/MessagesContext.tsx +870 -0
- package/src/tui/context/OverflowContext.tsx +213 -0
- package/src/tui/context/RateLimitContext.tsx +108 -0
- package/src/tui/context/ResilienceContext.tsx +275 -0
- package/src/tui/context/RootProvider.tsx +136 -0
- package/src/tui/context/ScrollContext.tsx +331 -0
- package/src/tui/context/ToolsContext.tsx +702 -0
- package/src/tui/context/__tests__/BracketedPasteContext.test.tsx +416 -0
- package/src/tui/context/index.ts +140 -0
- package/src/tui/enterprise-integration.ts +282 -0
- package/src/tui/hooks/__tests__/useBacktrack.test.tsx +138 -0
- package/src/tui/hooks/__tests__/useBracketedPaste.test.tsx +222 -0
- package/src/tui/hooks/__tests__/useCopyMode.test.tsx +336 -0
- package/src/tui/hooks/__tests__/useHotkeys.ctrl-input.test.tsx +96 -0
- package/src/tui/hooks/__tests__/useHotkeys.test.tsx +454 -0
- package/src/tui/hooks/__tests__/useInputHistory.test.tsx +660 -0
- package/src/tui/hooks/__tests__/useLineBuffer.test.ts +295 -0
- package/src/tui/hooks/__tests__/useModeController.test.ts +137 -0
- package/src/tui/hooks/__tests__/useModeShortcuts.test.tsx +142 -0
- package/src/tui/hooks/__tests__/useScrollController.test.ts +464 -0
- package/src/tui/hooks/__tests__/useVim.test.tsx +531 -0
- package/src/tui/hooks/index.ts +252 -0
- package/src/tui/hooks/useAgentLoop.ts +712 -0
- package/src/tui/hooks/useAlternateBuffer.ts +398 -0
- package/src/tui/hooks/useAnimatedScrollbar.ts +241 -0
- package/src/tui/hooks/useBacktrack.ts +443 -0
- package/src/tui/hooks/useBracketedPaste.ts +104 -0
- package/src/tui/hooks/useCollapsible.ts +240 -0
- package/src/tui/hooks/useCopyMode.ts +382 -0
- package/src/tui/hooks/useCostSummary.ts +75 -0
- package/src/tui/hooks/useDesktopNotification.ts +414 -0
- package/src/tui/hooks/useDiffMode.ts +44 -0
- package/src/tui/hooks/useFileChangeStats.ts +110 -0
- package/src/tui/hooks/useFileSuggestions.ts +284 -0
- package/src/tui/hooks/useFlickerDetector.ts +250 -0
- package/src/tui/hooks/useGitStatus.ts +200 -0
- package/src/tui/hooks/useHotkeys.ts +579 -0
- package/src/tui/hooks/useImagePaste.ts +114 -0
- package/src/tui/hooks/useInputHighlight.ts +145 -0
- package/src/tui/hooks/useInputHistory.ts +246 -0
- package/src/tui/hooks/useKeyboardScroll.ts +209 -0
- package/src/tui/hooks/useLineBuffer.ts +356 -0
- package/src/tui/hooks/useMentionAutocomplete.ts +235 -0
- package/src/tui/hooks/useModeController.ts +167 -0
- package/src/tui/hooks/useModeShortcuts.ts +196 -0
- package/src/tui/hooks/usePermissionHandler.ts +146 -0
- package/src/tui/hooks/usePersistence.ts +480 -0
- package/src/tui/hooks/usePersistenceShortcuts.ts +225 -0
- package/src/tui/hooks/usePlaceholderRotation.ts +143 -0
- package/src/tui/hooks/useProviderStatus.ts +270 -0
- package/src/tui/hooks/useRateLimitStatus.ts +90 -0
- package/src/tui/hooks/useScreenReader.ts +315 -0
- package/src/tui/hooks/useScrollController.ts +450 -0
- package/src/tui/hooks/useScrollEventBatcher.ts +185 -0
- package/src/tui/hooks/useSidebarPanelData.ts +115 -0
- package/src/tui/hooks/useSmoothScroll.ts +202 -0
- package/src/tui/hooks/useSnapshots.ts +300 -0
- package/src/tui/hooks/useStateAndRef.ts +50 -0
- package/src/tui/hooks/useTerminalSize.ts +206 -0
- package/src/tui/hooks/useToolApprovalController.ts +91 -0
- package/src/tui/hooks/useVim.ts +334 -0
- package/src/tui/hooks/useWorkspace.ts +56 -0
- package/src/tui/i18n/__tests__/init.test.ts +278 -0
- package/src/tui/i18n/__tests__/language-config.test.ts +199 -0
- package/src/tui/i18n/__tests__/locale-detection.test.ts +250 -0
- package/src/tui/i18n/__tests__/settings-integration.test.ts +262 -0
- package/src/tui/i18n/index.ts +72 -0
- package/src/tui/i18n/init.ts +131 -0
- package/src/tui/i18n/language-config.ts +106 -0
- package/src/tui/i18n/locale-detection.ts +173 -0
- package/src/tui/i18n/settings-integration.ts +557 -0
- package/src/tui/i18n/tui-namespace.ts +538 -0
- package/src/tui/i18n/types.ts +312 -0
- package/src/tui/index.ts +43 -0
- package/src/tui/lsp-integration.ts +409 -0
- package/src/tui/metrics-integration.ts +366 -0
- package/src/tui/plugins.ts +383 -0
- package/src/tui/resilience.ts +342 -0
- package/src/tui/sandbox-integration.ts +317 -0
- package/src/tui/services/clipboard.ts +348 -0
- package/src/tui/services/fuzzy-search.ts +441 -0
- package/src/tui/services/index.ts +72 -0
- package/src/tui/services/markdown-renderer.ts +565 -0
- package/src/tui/services/open-external.ts +247 -0
- package/src/tui/services/syntax-highlighter.ts +483 -0
- package/src/tui/slash-commands.ts +12 -0
- package/src/tui/theme/index.ts +15 -0
- package/src/tui/theme/provider.tsx +206 -0
- package/src/tui/tip-integration.ts +300 -0
- package/src/tui/types/__tests__/ink-extended.test.ts +121 -0
- package/src/tui/types/ink-extended.ts +87 -0
- package/src/tui/utils/__tests__/bracketedPaste.test.ts +231 -0
- package/src/tui/utils/__tests__/heightEstimator.test.ts +157 -0
- package/src/tui/utils/__tests__/text-width.test.ts +158 -0
- package/src/tui/utils/__tests__/textSanitizer.test.ts +266 -0
- package/src/tui/utils/__tests__/ui-sizing.test.ts +169 -0
- package/src/tui/utils/bracketedPaste.ts +107 -0
- package/src/tui/utils/cursor-manager.ts +131 -0
- package/src/tui/utils/detectTerminal.ts +596 -0
- package/src/tui/utils/findLastSafeSplitPoint.ts +92 -0
- package/src/tui/utils/heightEstimator.ts +198 -0
- package/src/tui/utils/index.ts +91 -0
- package/src/tui/utils/isNarrowWidth.ts +52 -0
- package/src/tui/utils/stdoutGuard.ts +90 -0
- package/src/tui/utils/synchronized-update.ts +70 -0
- package/src/tui/utils/text-width.ts +225 -0
- package/src/tui/utils/textSanitizer.ts +225 -0
- package/src/tui/utils/textUtils.ts +114 -0
- package/src/tui/utils/ui-sizing.ts +192 -0
- package/src/tui-blessed/app.ts +160 -0
- package/src/tui-blessed/index.ts +2 -0
- package/src/tui-blessed/neo-blessed.d.ts +6 -0
- package/src/tui-blessed/test.ts +21 -0
- package/src/tui-blessed/types.ts +14 -0
- package/src/utils/icons.ts +130 -0
- package/src/utils/index.ts +33 -0
- package/src/utils/resume-hint.ts +86 -0
- package/src/version.ts +1 -0
- package/tsconfig.json +8 -0
- 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;
|