@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,192 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Terminal UI Sizing Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized utilities for calculating terminal dimensions and responsive layouts.
|
|
5
|
+
* Ported from Gemini CLI patterns for consistent responsive behavior.
|
|
6
|
+
*
|
|
7
|
+
* @module tui/utils/ui-sizing
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Default terminal width when stdout is not a TTY */
|
|
11
|
+
const DEFAULT_TERMINAL_WIDTH = 80;
|
|
12
|
+
|
|
13
|
+
/** Default terminal height when stdout is not a TTY */
|
|
14
|
+
const DEFAULT_TERMINAL_HEIGHT = 24;
|
|
15
|
+
|
|
16
|
+
/** Minimum width for narrow terminal detection */
|
|
17
|
+
const NARROW_WIDTH_BREAKPOINT = 80;
|
|
18
|
+
|
|
19
|
+
/** Maximum width for responsive scaling (beyond this, use fixed percentage) */
|
|
20
|
+
const WIDE_WIDTH_BREAKPOINT = 132;
|
|
21
|
+
|
|
22
|
+
/** Content width percentage at narrow width (98%) */
|
|
23
|
+
const NARROW_CONTENT_RATIO = 0.98;
|
|
24
|
+
|
|
25
|
+
/** Content width percentage at wide width (90%) */
|
|
26
|
+
const WIDE_CONTENT_RATIO = 0.9;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Linear interpolation between two values.
|
|
30
|
+
*
|
|
31
|
+
* @param min - Minimum value (at t=0)
|
|
32
|
+
* @param max - Maximum value (at t=1)
|
|
33
|
+
* @param t - Interpolation factor (0-1)
|
|
34
|
+
* @returns Interpolated value
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* lerp(0, 100, 0.5) // 50
|
|
39
|
+
* lerp(10, 20, 0.25) // 12.5
|
|
40
|
+
* ```
|
|
41
|
+
*/
|
|
42
|
+
export function lerp(min: number, max: number, t: number): number {
|
|
43
|
+
return min + (max - min) * t;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Clamp a value to a specified range.
|
|
48
|
+
*
|
|
49
|
+
* @param value - Value to clamp
|
|
50
|
+
* @param min - Minimum allowed value
|
|
51
|
+
* @param max - Maximum allowed value
|
|
52
|
+
* @returns Clamped value
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```ts
|
|
56
|
+
* clamp(150, 0, 100) // 100
|
|
57
|
+
* clamp(-10, 0, 100) // 0
|
|
58
|
+
* clamp(50, 0, 100) // 50
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
export function clamp(value: number, min: number, max: number): number {
|
|
62
|
+
return Math.min(Math.max(value, min), max);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Get the current terminal width.
|
|
67
|
+
*
|
|
68
|
+
* @param fallback - Fallback width if terminal size cannot be determined
|
|
69
|
+
* @returns Terminal width in columns
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* ```ts
|
|
73
|
+
* const width = getTerminalWidth();
|
|
74
|
+
* console.log(`Terminal is ${width} columns wide`);
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export function getTerminalWidth(fallback = DEFAULT_TERMINAL_WIDTH): number {
|
|
78
|
+
return process.stdout.columns ?? fallback;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Get the current terminal height.
|
|
83
|
+
*
|
|
84
|
+
* @param fallback - Fallback height if terminal size cannot be determined
|
|
85
|
+
* @returns Terminal height in rows
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```ts
|
|
89
|
+
* const height = getTerminalHeight();
|
|
90
|
+
* console.log(`Terminal is ${height} rows tall`);
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
export function getTerminalHeight(fallback = DEFAULT_TERMINAL_HEIGHT): number {
|
|
94
|
+
return process.stdout.rows ?? fallback;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Calculate the maximum content width for responsive layouts.
|
|
99
|
+
*
|
|
100
|
+
* Uses linear interpolation between narrow and wide breakpoints:
|
|
101
|
+
* - At 80 columns: 98% width (maximize space in small terminals)
|
|
102
|
+
* - At 132 columns: 90% width (comfortable reading width)
|
|
103
|
+
* - Below 80: Use full available width minus minimal padding
|
|
104
|
+
* - Above 132: Cap at 90% of terminal width
|
|
105
|
+
*
|
|
106
|
+
* @param terminalWidth - Terminal width (defaults to current terminal)
|
|
107
|
+
* @returns Maximum content width in columns
|
|
108
|
+
*
|
|
109
|
+
* @example
|
|
110
|
+
* ```ts
|
|
111
|
+
* // In a 100-column terminal
|
|
112
|
+
* const maxWidth = getMaxContentWidth(100);
|
|
113
|
+
* // Returns ~94 columns (interpolated between 98% and 90%)
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export function getMaxContentWidth(terminalWidth?: number): number {
|
|
117
|
+
const width = terminalWidth ?? getTerminalWidth();
|
|
118
|
+
|
|
119
|
+
// Below narrow breakpoint: use almost full width
|
|
120
|
+
if (width <= NARROW_WIDTH_BREAKPOINT) {
|
|
121
|
+
return Math.floor(width * NARROW_CONTENT_RATIO);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Above wide breakpoint: cap at wide ratio
|
|
125
|
+
if (width >= WIDE_WIDTH_BREAKPOINT) {
|
|
126
|
+
return Math.floor(width * WIDE_CONTENT_RATIO);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Interpolate between breakpoints
|
|
130
|
+
const t = (width - NARROW_WIDTH_BREAKPOINT) / (WIDE_WIDTH_BREAKPOINT - NARROW_WIDTH_BREAKPOINT);
|
|
131
|
+
const ratio = lerp(NARROW_CONTENT_RATIO, WIDE_CONTENT_RATIO, t);
|
|
132
|
+
|
|
133
|
+
return Math.floor(width * ratio);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Calculate content padding for centered layouts.
|
|
138
|
+
*
|
|
139
|
+
* @param terminalWidth - Terminal width (defaults to current terminal)
|
|
140
|
+
* @returns Object with left and right padding values
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* ```ts
|
|
144
|
+
* const { left, right } = getContentPadding(100);
|
|
145
|
+
* // For centered content at 94 cols in 100 col terminal:
|
|
146
|
+
* // left = 3, right = 3
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
export function getContentPadding(terminalWidth?: number): {
|
|
150
|
+
left: number;
|
|
151
|
+
right: number;
|
|
152
|
+
} {
|
|
153
|
+
const width = terminalWidth ?? getTerminalWidth();
|
|
154
|
+
const contentWidth = getMaxContentWidth(width);
|
|
155
|
+
const totalPadding = width - contentWidth;
|
|
156
|
+
|
|
157
|
+
// Distribute padding evenly, with any remainder going to the right
|
|
158
|
+
const leftPadding = Math.floor(totalPadding / 2);
|
|
159
|
+
const rightPadding = totalPadding - leftPadding;
|
|
160
|
+
|
|
161
|
+
return {
|
|
162
|
+
left: leftPadding,
|
|
163
|
+
right: rightPadding,
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Get terminal dimensions as an object.
|
|
169
|
+
*
|
|
170
|
+
* @returns Object with width and height
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* const { width, height } = getTerminalSize();
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
export function getTerminalSize(): { width: number; height: number } {
|
|
178
|
+
return {
|
|
179
|
+
width: getTerminalWidth(),
|
|
180
|
+
height: getTerminalHeight(),
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Re-export constants for external use
|
|
185
|
+
export {
|
|
186
|
+
DEFAULT_TERMINAL_HEIGHT,
|
|
187
|
+
DEFAULT_TERMINAL_WIDTH,
|
|
188
|
+
NARROW_CONTENT_RATIO,
|
|
189
|
+
NARROW_WIDTH_BREAKPOINT,
|
|
190
|
+
WIDE_CONTENT_RATIO,
|
|
191
|
+
WIDE_WIDTH_BREAKPOINT,
|
|
192
|
+
};
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import blessed from "neo-blessed";
|
|
2
|
+
import type { AppComponents } from "./types.js";
|
|
3
|
+
|
|
4
|
+
export function createApp(): AppComponents {
|
|
5
|
+
const screen = blessed.screen({
|
|
6
|
+
smartCSR: true,
|
|
7
|
+
fullUnicode: true,
|
|
8
|
+
title: "Vellum CLI (blessed POC)",
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
// Layout constants
|
|
12
|
+
const HEADER_HEIGHT = 1;
|
|
13
|
+
const STATUS_HEIGHT = 2;
|
|
14
|
+
const INPUT_HEIGHT = 3;
|
|
15
|
+
|
|
16
|
+
const header = blessed.box({
|
|
17
|
+
parent: screen,
|
|
18
|
+
top: 0,
|
|
19
|
+
left: 0,
|
|
20
|
+
width: "100%",
|
|
21
|
+
height: HEADER_HEIGHT,
|
|
22
|
+
content: " 🐍 Vellum CLI | Model: claude-3.5-sonnet ",
|
|
23
|
+
style: { fg: "white", bg: "blue" },
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
const messageLog = blessed.log({
|
|
27
|
+
parent: screen,
|
|
28
|
+
top: HEADER_HEIGHT,
|
|
29
|
+
left: 0,
|
|
30
|
+
width: "100%",
|
|
31
|
+
height: `100%-${HEADER_HEIGHT + STATUS_HEIGHT + INPUT_HEIGHT}`,
|
|
32
|
+
tags: true, // Enable {color-fg} tags
|
|
33
|
+
keys: true,
|
|
34
|
+
vi: true,
|
|
35
|
+
mouse: true,
|
|
36
|
+
scrollable: true,
|
|
37
|
+
alwaysScroll: true,
|
|
38
|
+
scrollbar: {
|
|
39
|
+
ch: "│",
|
|
40
|
+
track: { bg: "black" },
|
|
41
|
+
style: { bg: "gray" },
|
|
42
|
+
},
|
|
43
|
+
scrollback: 3000,
|
|
44
|
+
border: { type: "line" },
|
|
45
|
+
style: { border: { fg: "gray" } },
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const statusBar = blessed.box({
|
|
49
|
+
parent: screen,
|
|
50
|
+
bottom: INPUT_HEIGHT,
|
|
51
|
+
left: 0,
|
|
52
|
+
width: "100%",
|
|
53
|
+
height: STATUS_HEIGHT,
|
|
54
|
+
content: " Status: Ready | Tokens: 0/0 ",
|
|
55
|
+
style: { fg: "gray" },
|
|
56
|
+
border: { type: "line" },
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
const input = blessed.textbox({
|
|
60
|
+
parent: screen,
|
|
61
|
+
bottom: 0,
|
|
62
|
+
left: 0,
|
|
63
|
+
width: "100%",
|
|
64
|
+
height: INPUT_HEIGHT,
|
|
65
|
+
inputOnFocus: true,
|
|
66
|
+
border: { type: "line" },
|
|
67
|
+
style: {
|
|
68
|
+
fg: "white",
|
|
69
|
+
border: { fg: "cyan" },
|
|
70
|
+
},
|
|
71
|
+
label: " Input ",
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Global keybindings
|
|
75
|
+
screen.key(["C-c", "C-q"], () => {
|
|
76
|
+
screen.destroy();
|
|
77
|
+
process.exit(0);
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
screen.key(["pageup"], () => {
|
|
81
|
+
messageLog.scroll(-Math.floor((messageLog.height as number) / 2));
|
|
82
|
+
screen.render();
|
|
83
|
+
});
|
|
84
|
+
|
|
85
|
+
screen.key(["pagedown"], () => {
|
|
86
|
+
messageLog.scroll(Math.floor((messageLog.height as number) / 2));
|
|
87
|
+
screen.render();
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
screen.key(["home"], () => {
|
|
91
|
+
messageLog.setScrollPerc(0);
|
|
92
|
+
screen.render();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
screen.key(["end"], () => {
|
|
96
|
+
messageLog.setScrollPerc(100);
|
|
97
|
+
screen.render();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
// Escape returns to input
|
|
101
|
+
screen.key(["escape"], () => {
|
|
102
|
+
input.focus();
|
|
103
|
+
screen.render();
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
// Input handling
|
|
107
|
+
input.on("submit", (value: string) => {
|
|
108
|
+
const text = String(value ?? "").trim();
|
|
109
|
+
if (text) {
|
|
110
|
+
addMessage(messageLog, { role: "user", content: text });
|
|
111
|
+
// Simulate assistant response
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
addMessage(messageLog, {
|
|
114
|
+
role: "assistant",
|
|
115
|
+
content: "This is a simulated response. 中文测试 🎉 Emoji test!",
|
|
116
|
+
});
|
|
117
|
+
screen.render();
|
|
118
|
+
}, 500);
|
|
119
|
+
}
|
|
120
|
+
input.clearValue();
|
|
121
|
+
screen.render();
|
|
122
|
+
input.focus();
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
input.focus();
|
|
126
|
+
screen.render();
|
|
127
|
+
|
|
128
|
+
return { screen, header, messageLog, input, statusBar };
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function addMessage(
|
|
132
|
+
log: ReturnType<typeof blessed.log>,
|
|
133
|
+
message: { role: string; content: string }
|
|
134
|
+
) {
|
|
135
|
+
const roleColors: Record<string, string> = {
|
|
136
|
+
user: "cyan",
|
|
137
|
+
assistant: "green",
|
|
138
|
+
system: "yellow",
|
|
139
|
+
tool: "magenta",
|
|
140
|
+
};
|
|
141
|
+
const color = roleColors[message.role] || "white";
|
|
142
|
+
const prefix = message.role === "user" ? "You" : "Assistant";
|
|
143
|
+
log.add(`{${color}-fg}${prefix}:{/${color}-fg} ${message.content}`);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function addMessageToLog(
|
|
147
|
+
log: ReturnType<typeof blessed.log>,
|
|
148
|
+
role: "user" | "assistant" | "system" | "tool",
|
|
149
|
+
content: string
|
|
150
|
+
) {
|
|
151
|
+
const roleColors: Record<string, string> = {
|
|
152
|
+
user: "cyan",
|
|
153
|
+
assistant: "green",
|
|
154
|
+
system: "yellow",
|
|
155
|
+
tool: "magenta",
|
|
156
|
+
};
|
|
157
|
+
const color = roleColors[role];
|
|
158
|
+
const prefix = role === "user" ? "You" : role.charAt(0).toUpperCase() + role.slice(1);
|
|
159
|
+
log.add(`{${color}-fg}${prefix}:{/${color}-fg} ${content}`);
|
|
160
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { createApp } from "./app.js";
|
|
2
|
+
|
|
3
|
+
const { messageLog, screen } = createApp();
|
|
4
|
+
|
|
5
|
+
// Add some test messages
|
|
6
|
+
messageLog.add("{cyan-fg}You:{/cyan-fg} Hello!");
|
|
7
|
+
messageLog.add("{green-fg}Assistant:{/green-fg} Hi! How can I help you today?");
|
|
8
|
+
messageLog.add("{magenta-fg}Tool:{/magenta-fg} search_files completed");
|
|
9
|
+
messageLog.add("{yellow-fg}System:{/yellow-fg} Connected to model");
|
|
10
|
+
|
|
11
|
+
// Test CJK and emoji
|
|
12
|
+
messageLog.add("{cyan-fg}You:{/cyan-fg} 请用中文回答 🎉");
|
|
13
|
+
messageLog.add("{green-fg}Assistant:{/green-fg} 当然可以!我会用中文回答你的问题。😊");
|
|
14
|
+
|
|
15
|
+
// Test long content
|
|
16
|
+
messageLog.add(
|
|
17
|
+
"{green-fg}Assistant:{/green-fg} " +
|
|
18
|
+
"This is a very long message that should wrap properly in the terminal. ".repeat(5)
|
|
19
|
+
);
|
|
20
|
+
|
|
21
|
+
screen.render();
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Widgets } from "blessed";
|
|
2
|
+
|
|
3
|
+
export interface AppComponents {
|
|
4
|
+
screen: Widgets.Screen;
|
|
5
|
+
header: Widgets.BoxElement;
|
|
6
|
+
messageLog: Widgets.Log;
|
|
7
|
+
input: Widgets.TextboxElement;
|
|
8
|
+
statusBar: Widgets.BoxElement;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export interface MessageOptions {
|
|
12
|
+
role: "user" | "assistant" | "system" | "tool";
|
|
13
|
+
content: string;
|
|
14
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Text-based icons to replace emojis throughout the CLI.
|
|
3
|
+
* Using bracketed text for better terminal compatibility.
|
|
4
|
+
*
|
|
5
|
+
* @module cli/utils/icons
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Unified icon system for CLI output.
|
|
10
|
+
* All values are text-based for maximum terminal compatibility.
|
|
11
|
+
*/
|
|
12
|
+
export const ICONS = {
|
|
13
|
+
// Status indicators
|
|
14
|
+
success: "[OK]",
|
|
15
|
+
error: "[ERR]",
|
|
16
|
+
warning: "[WARN]",
|
|
17
|
+
info: "[INFO]",
|
|
18
|
+
|
|
19
|
+
// Actions/hints
|
|
20
|
+
hint: "Hint:",
|
|
21
|
+
tip: "Tip:",
|
|
22
|
+
note: "Note:",
|
|
23
|
+
tools: "Tools:",
|
|
24
|
+
|
|
25
|
+
// Progress indicators
|
|
26
|
+
skip: "[SKIP]",
|
|
27
|
+
running: "[...]",
|
|
28
|
+
done: "[DONE]",
|
|
29
|
+
interrupted: "[INT]",
|
|
30
|
+
pending: "[...]",
|
|
31
|
+
|
|
32
|
+
// File types (for mentions)
|
|
33
|
+
file: {
|
|
34
|
+
code: "[Code]",
|
|
35
|
+
docs: "[Doc]",
|
|
36
|
+
config: "[Cfg]",
|
|
37
|
+
web: "[Web]",
|
|
38
|
+
style: "[Style]",
|
|
39
|
+
default: "[File]",
|
|
40
|
+
folder: "[Dir]",
|
|
41
|
+
},
|
|
42
|
+
|
|
43
|
+
// Providers (bracketed names)
|
|
44
|
+
provider: {
|
|
45
|
+
anthropic: "[Anthropic]",
|
|
46
|
+
openai: "[OpenAI]",
|
|
47
|
+
google: "[Google]",
|
|
48
|
+
copilot: "[Copilot]",
|
|
49
|
+
deepseek: "[DeepSeek]",
|
|
50
|
+
groq: "[Groq]",
|
|
51
|
+
xai: "[xAI]",
|
|
52
|
+
qwen: "[Qwen]",
|
|
53
|
+
ollama: "[Ollama]",
|
|
54
|
+
lmstudio: "[LMStudio]",
|
|
55
|
+
default: "[Provider]",
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// Modes
|
|
59
|
+
mode: {
|
|
60
|
+
vibe: "[Vibe]",
|
|
61
|
+
plan: "[Plan]",
|
|
62
|
+
spec: "[Spec]",
|
|
63
|
+
},
|
|
64
|
+
|
|
65
|
+
// Spec phases
|
|
66
|
+
phase: {
|
|
67
|
+
research: "[Research]",
|
|
68
|
+
requirements: "[Reqs]",
|
|
69
|
+
design: "[Design]",
|
|
70
|
+
tasks: "[Tasks]",
|
|
71
|
+
implementation: "[Impl]",
|
|
72
|
+
validation: "[Valid]",
|
|
73
|
+
},
|
|
74
|
+
|
|
75
|
+
// Tips/onboarding icons
|
|
76
|
+
tips: {
|
|
77
|
+
hint: "Hint:",
|
|
78
|
+
vibe: "[Vibe]",
|
|
79
|
+
edit: "[Edit]",
|
|
80
|
+
tools: "Tools:",
|
|
81
|
+
target: "[Goal]",
|
|
82
|
+
plan: "[Plan]",
|
|
83
|
+
search: "[Search]",
|
|
84
|
+
rocket: "[Start]",
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
// Misc
|
|
88
|
+
current: "*", // Mark current item
|
|
89
|
+
bullet: "-",
|
|
90
|
+
workflow: "[Flow]",
|
|
91
|
+
migrate: "[Migrate]",
|
|
92
|
+
package: "[Pkg]",
|
|
93
|
+
git: "[Git]",
|
|
94
|
+
cwd: "[CWD]",
|
|
95
|
+
checkpoint: "[Ckpt]",
|
|
96
|
+
celebration: "[Done!]",
|
|
97
|
+
reset: "[Reset]",
|
|
98
|
+
} as const;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Get provider icon text
|
|
102
|
+
*/
|
|
103
|
+
export function getProviderIcon(provider: string): string {
|
|
104
|
+
const key = provider.toLowerCase() as keyof typeof ICONS.provider;
|
|
105
|
+
return ICONS.provider[key] ?? ICONS.provider.default;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Get mode icon text
|
|
110
|
+
*/
|
|
111
|
+
export function getModeIcon(mode: string): string {
|
|
112
|
+
const key = mode.toLowerCase() as keyof typeof ICONS.mode;
|
|
113
|
+
return ICONS.mode[key] ?? `[${mode}]`;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Get phase icon text
|
|
118
|
+
*/
|
|
119
|
+
export function getPhaseIcon(phase: string): string {
|
|
120
|
+
const key = phase.toLowerCase() as keyof typeof ICONS.phase;
|
|
121
|
+
return ICONS.phase[key] ?? `[${phase}]`;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Get file type icon text
|
|
126
|
+
*/
|
|
127
|
+
export function getFileIcon(type: string): string {
|
|
128
|
+
const key = type.toLowerCase() as keyof typeof ICONS.file;
|
|
129
|
+
return ICONS.file[key] ?? ICONS.file.default;
|
|
130
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Utilities
|
|
3
|
+
*
|
|
4
|
+
* Shared utility functions for the Vellum CLI.
|
|
5
|
+
*
|
|
6
|
+
* @module cli/utils
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
// For backward compatibility, also export ModelMetadata as an alias
|
|
10
|
+
export type { ModelInfo as ModelMetadata } from "@vellum/provider";
|
|
11
|
+
|
|
12
|
+
// Re-export model utilities from @vellum/provider (Single Source of Truth)
|
|
13
|
+
export {
|
|
14
|
+
calculateCost,
|
|
15
|
+
getContextWindow,
|
|
16
|
+
getModelInfo,
|
|
17
|
+
getProviderModels,
|
|
18
|
+
getSupportedProviders,
|
|
19
|
+
type ModelInfo,
|
|
20
|
+
} from "@vellum/provider";
|
|
21
|
+
export {
|
|
22
|
+
getFileIcon,
|
|
23
|
+
getModeIcon,
|
|
24
|
+
getPhaseIcon,
|
|
25
|
+
getProviderIcon,
|
|
26
|
+
ICONS,
|
|
27
|
+
} from "./icons.js";
|
|
28
|
+
export {
|
|
29
|
+
formatResumeHint,
|
|
30
|
+
getShortId,
|
|
31
|
+
SHORT_ID_LENGTH,
|
|
32
|
+
shouldShowResumeHint,
|
|
33
|
+
} from "./resume-hint.js";
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resume Hint Utilities (T034)
|
|
3
|
+
*
|
|
4
|
+
* Provides exit resume hint formatting for the CLI.
|
|
5
|
+
* Displays a cyan-colored message with short session ID
|
|
6
|
+
* to help users resume their sessions.
|
|
7
|
+
*
|
|
8
|
+
* @module cli/utils/resume-hint
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import chalk from "chalk";
|
|
12
|
+
|
|
13
|
+
import { ICONS } from "./icons.js";
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Constants
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Number of characters in a short session ID.
|
|
21
|
+
*/
|
|
22
|
+
export const SHORT_ID_LENGTH = 8;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Horizontal separator line for the hint box.
|
|
26
|
+
*/
|
|
27
|
+
const SEPARATOR = "━".repeat(39);
|
|
28
|
+
|
|
29
|
+
// =============================================================================
|
|
30
|
+
// Functions
|
|
31
|
+
// =============================================================================
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Extract short ID from a full session UUID.
|
|
35
|
+
*
|
|
36
|
+
* Takes the first 8 characters of the UUID for easy typing.
|
|
37
|
+
*
|
|
38
|
+
* @param sessionId - Full session UUID
|
|
39
|
+
* @returns First 8 characters of the UUID
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* getShortId('a1b2c3d4-e5f6-7890-abcd-ef1234567890')
|
|
44
|
+
* // Returns: 'a1b2c3d4'
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export function getShortId(sessionId: string): string {
|
|
48
|
+
return sessionId.slice(0, SHORT_ID_LENGTH);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Format a resume hint message for display on exit.
|
|
53
|
+
*
|
|
54
|
+
* Creates a cyan-colored box with instructions for resuming
|
|
55
|
+
* the session using the short ID.
|
|
56
|
+
*
|
|
57
|
+
* @param sessionId - Full session UUID
|
|
58
|
+
* @returns Formatted cyan-colored hint message
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```typescript
|
|
62
|
+
* formatResumeHint('a1b2c3d4-e5f6-7890-abcd-ef1234567890')
|
|
63
|
+
* // Returns:
|
|
64
|
+
* // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
65
|
+
* // Hint: To resume this session, run: vellum resume a1b2c3d4
|
|
66
|
+
* // ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function formatResumeHint(sessionId: string): string {
|
|
70
|
+
const shortId = getShortId(sessionId);
|
|
71
|
+
const message = `${ICONS.hint} To resume this session, run: vellum resume ${shortId}`;
|
|
72
|
+
|
|
73
|
+
return chalk.cyan(`${SEPARATOR}\n${message}\n${SEPARATOR}`);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Check if a session should show resume hint on exit.
|
|
78
|
+
*
|
|
79
|
+
* Resume hint should only be shown for sessions with messages.
|
|
80
|
+
*
|
|
81
|
+
* @param messageCount - Number of messages in the session
|
|
82
|
+
* @returns True if resume hint should be shown
|
|
83
|
+
*/
|
|
84
|
+
export function shouldShowResumeHint(messageCount: number): boolean {
|
|
85
|
+
return messageCount > 0;
|
|
86
|
+
}
|
package/src/version.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export const version = "0.1.0";
|
package/tsconfig.json
ADDED
package/vitest.config.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Vitest Configuration for CLI Package
|
|
3
|
+
*
|
|
4
|
+
* CLI-specific test settings for command system tests.
|
|
5
|
+
* Tests for commands are located in src/commands/__tests__/
|
|
6
|
+
*/
|
|
7
|
+
import { defineConfig } from "vitest/config";
|
|
8
|
+
|
|
9
|
+
export default defineConfig({
|
|
10
|
+
test: {
|
|
11
|
+
environment: "node",
|
|
12
|
+
include: [
|
|
13
|
+
"src/**/*.test.{ts,tsx}",
|
|
14
|
+
// Explicitly include command tests
|
|
15
|
+
"src/commands/**/*.test.{ts,tsx}",
|
|
16
|
+
"src/commands/__tests__/**/*.test.{ts,tsx}",
|
|
17
|
+
// Include fixture tests
|
|
18
|
+
"src/test/fixtures/__tests__/**/*.test.{ts,tsx}",
|
|
19
|
+
],
|
|
20
|
+
coverage: {
|
|
21
|
+
provider: "v8",
|
|
22
|
+
reporter: ["text", "json", "html"],
|
|
23
|
+
},
|
|
24
|
+
env: {
|
|
25
|
+
VELLUM_FAKE_RESPONSES: "true",
|
|
26
|
+
VELLUM_ICONS: "unicode", // Force Unicode icons in tests for consistent assertions
|
|
27
|
+
},
|
|
28
|
+
// Increase timeout for MCP-related tests that involve dynamic imports with vi.mock
|
|
29
|
+
testTimeout: 10000,
|
|
30
|
+
// Ensure tests with vi.mock for @vellum/mcp run in sequence to avoid mock conflicts
|
|
31
|
+
sequence: {
|
|
32
|
+
shuffle: false,
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|