@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,424 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AgentProgress Component (T046)
|
|
3
|
+
*
|
|
4
|
+
* TUI component for displaying agent task progress with a visual task tree
|
|
5
|
+
* and progress bar. Shows task status with icons and completion percentage.
|
|
6
|
+
*
|
|
7
|
+
* @module tui/components/AgentProgress
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import type { TaskChain, TaskChainNode } from "@vellum/core";
|
|
11
|
+
import { Box, Text } from "ink";
|
|
12
|
+
import type React from "react";
|
|
13
|
+
import { useMemo } from "react";
|
|
14
|
+
import { useTheme } from "../theme/index.js";
|
|
15
|
+
|
|
16
|
+
// =============================================================================
|
|
17
|
+
// Types
|
|
18
|
+
// =============================================================================
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Props for the AgentProgress component.
|
|
22
|
+
*/
|
|
23
|
+
export interface AgentProgressProps {
|
|
24
|
+
/** The task chain to display */
|
|
25
|
+
readonly chain: TaskChain;
|
|
26
|
+
/** ID of the currently executing task (for highlighting) */
|
|
27
|
+
readonly currentTaskId?: string;
|
|
28
|
+
/** Whether to show detailed task information */
|
|
29
|
+
readonly showDetails?: boolean;
|
|
30
|
+
/** Width of the progress bar in characters (default: 20) */
|
|
31
|
+
readonly progressBarWidth?: number;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// =============================================================================
|
|
35
|
+
// Constants
|
|
36
|
+
// =============================================================================
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Status icons for task states.
|
|
40
|
+
* Using ASCII symbols for terminal display.
|
|
41
|
+
*/
|
|
42
|
+
const STATUS_ICONS: Record<TaskChainNode["status"], string> = {
|
|
43
|
+
pending: "o",
|
|
44
|
+
running: "~",
|
|
45
|
+
completed: "+",
|
|
46
|
+
failed: "x",
|
|
47
|
+
} as const;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Tree line characters for visual hierarchy.
|
|
51
|
+
*/
|
|
52
|
+
const TREE_CHARS = {
|
|
53
|
+
branch: "├──",
|
|
54
|
+
last: "└──",
|
|
55
|
+
vertical: "│ ",
|
|
56
|
+
space: " ",
|
|
57
|
+
} as const;
|
|
58
|
+
|
|
59
|
+
/** Default progress bar width */
|
|
60
|
+
const DEFAULT_PROGRESS_BAR_WIDTH = 20;
|
|
61
|
+
|
|
62
|
+
/** Progress bar characters */
|
|
63
|
+
const PROGRESS_FILLED = "█";
|
|
64
|
+
const PROGRESS_EMPTY = "░";
|
|
65
|
+
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// Helper Functions
|
|
68
|
+
// =============================================================================
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Get the color for a task status.
|
|
72
|
+
*/
|
|
73
|
+
function getStatusColor(
|
|
74
|
+
status: TaskChainNode["status"],
|
|
75
|
+
isCurrent: boolean,
|
|
76
|
+
theme: ReturnType<typeof useTheme>["theme"]
|
|
77
|
+
): string {
|
|
78
|
+
if (isCurrent) {
|
|
79
|
+
return theme.semantic.status.running;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
switch (status) {
|
|
83
|
+
case "completed":
|
|
84
|
+
return theme.semantic.status.complete;
|
|
85
|
+
case "failed":
|
|
86
|
+
return theme.semantic.status.error;
|
|
87
|
+
case "running":
|
|
88
|
+
return theme.semantic.status.running;
|
|
89
|
+
default:
|
|
90
|
+
return theme.semantic.text.muted;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Build a hierarchical tree structure from task chain nodes.
|
|
96
|
+
* Returns nodes organized by parent-child relationships.
|
|
97
|
+
*/
|
|
98
|
+
interface TreeNode {
|
|
99
|
+
node: TaskChainNode;
|
|
100
|
+
children: TreeNode[];
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function buildTree(chain: TaskChain): TreeNode[] {
|
|
104
|
+
const nodeMap = new Map<string, TreeNode>();
|
|
105
|
+
const roots: TreeNode[] = [];
|
|
106
|
+
|
|
107
|
+
// Create TreeNode wrappers
|
|
108
|
+
for (const [, node] of chain.nodes) {
|
|
109
|
+
nodeMap.set(node.taskId, { node, children: [] });
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// Build parent-child relationships
|
|
113
|
+
for (const [, treeNode] of nodeMap) {
|
|
114
|
+
const parentId = treeNode.node.parentTaskId;
|
|
115
|
+
if (parentId && nodeMap.has(parentId)) {
|
|
116
|
+
nodeMap.get(parentId)?.children.push(treeNode);
|
|
117
|
+
} else {
|
|
118
|
+
// Root node (no parent)
|
|
119
|
+
roots.push(treeNode);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Sort children by creation time
|
|
124
|
+
for (const treeNode of nodeMap.values()) {
|
|
125
|
+
treeNode.children.sort((a, b) => a.node.createdAt.getTime() - b.node.createdAt.getTime());
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// Sort roots by creation time
|
|
129
|
+
roots.sort((a, b) => a.node.createdAt.getTime() - b.node.createdAt.getTime());
|
|
130
|
+
|
|
131
|
+
return roots;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Flatten tree into display order with depth info for rendering.
|
|
136
|
+
*/
|
|
137
|
+
interface FlattenedNode {
|
|
138
|
+
node: TaskChainNode;
|
|
139
|
+
depth: number;
|
|
140
|
+
isLast: boolean;
|
|
141
|
+
parentIsLast: boolean[];
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function flattenTree(
|
|
145
|
+
roots: TreeNode[],
|
|
146
|
+
depth: number = 0,
|
|
147
|
+
parentIsLast: boolean[] = []
|
|
148
|
+
): FlattenedNode[] {
|
|
149
|
+
const result: FlattenedNode[] = [];
|
|
150
|
+
|
|
151
|
+
for (let i = 0; i < roots.length; i++) {
|
|
152
|
+
const treeNode = roots[i];
|
|
153
|
+
if (!treeNode) continue;
|
|
154
|
+
const isLast = i === roots.length - 1;
|
|
155
|
+
|
|
156
|
+
result.push({
|
|
157
|
+
node: treeNode.node,
|
|
158
|
+
depth,
|
|
159
|
+
isLast,
|
|
160
|
+
parentIsLast: [...parentIsLast],
|
|
161
|
+
});
|
|
162
|
+
|
|
163
|
+
if (treeNode.children.length > 0) {
|
|
164
|
+
result.push(...flattenTree(treeNode.children, depth + 1, [...parentIsLast, isLast]));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
return result;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
/**
|
|
172
|
+
* Calculate progress statistics from the task chain.
|
|
173
|
+
*/
|
|
174
|
+
interface ProgressStats {
|
|
175
|
+
total: number;
|
|
176
|
+
completed: number;
|
|
177
|
+
failed: number;
|
|
178
|
+
running: number;
|
|
179
|
+
pending: number;
|
|
180
|
+
percentage: number;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function calculateProgress(chain: TaskChain): ProgressStats {
|
|
184
|
+
const stats: ProgressStats = {
|
|
185
|
+
total: chain.nodes.size,
|
|
186
|
+
completed: 0,
|
|
187
|
+
failed: 0,
|
|
188
|
+
running: 0,
|
|
189
|
+
pending: 0,
|
|
190
|
+
percentage: 0,
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
for (const node of chain.nodes.values()) {
|
|
194
|
+
switch (node.status) {
|
|
195
|
+
case "completed":
|
|
196
|
+
stats.completed++;
|
|
197
|
+
break;
|
|
198
|
+
case "failed":
|
|
199
|
+
stats.failed++;
|
|
200
|
+
break;
|
|
201
|
+
case "running":
|
|
202
|
+
stats.running++;
|
|
203
|
+
break;
|
|
204
|
+
case "pending":
|
|
205
|
+
stats.pending++;
|
|
206
|
+
break;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
if (stats.total > 0) {
|
|
211
|
+
stats.percentage = Math.round((stats.completed / stats.total) * 100);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return stats;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Generate ASCII progress bar.
|
|
219
|
+
*/
|
|
220
|
+
function generateProgressBar(percentage: number, width: number): string {
|
|
221
|
+
const filledCount = Math.round((percentage / 100) * width);
|
|
222
|
+
const emptyCount = width - filledCount;
|
|
223
|
+
|
|
224
|
+
return PROGRESS_FILLED.repeat(filledCount) + PROGRESS_EMPTY.repeat(emptyCount);
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Format task ID for display (truncate if needed).
|
|
229
|
+
*/
|
|
230
|
+
function formatTaskId(taskId: string, maxLength: number = 20): string {
|
|
231
|
+
if (taskId.length <= maxLength) {
|
|
232
|
+
return taskId;
|
|
233
|
+
}
|
|
234
|
+
return `${taskId.substring(0, maxLength - 3)}...`;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// =============================================================================
|
|
238
|
+
// Sub-Components
|
|
239
|
+
// =============================================================================
|
|
240
|
+
|
|
241
|
+
interface TaskTreeItemProps {
|
|
242
|
+
readonly flatNode: FlattenedNode;
|
|
243
|
+
readonly isCurrent: boolean;
|
|
244
|
+
readonly showDetails: boolean;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/**
|
|
248
|
+
* Single task item in the tree view.
|
|
249
|
+
*/
|
|
250
|
+
function TaskTreeItem({ flatNode, isCurrent, showDetails }: TaskTreeItemProps): React.JSX.Element {
|
|
251
|
+
const { theme } = useTheme();
|
|
252
|
+
const { node, depth, isLast, parentIsLast } = flatNode;
|
|
253
|
+
|
|
254
|
+
const statusIcon = STATUS_ICONS[node.status];
|
|
255
|
+
const statusColor = getStatusColor(node.status, isCurrent, theme);
|
|
256
|
+
|
|
257
|
+
// Build prefix for tree structure
|
|
258
|
+
let prefix = "";
|
|
259
|
+
for (let i = 0; i < depth; i++) {
|
|
260
|
+
const parentLast = parentIsLast[i];
|
|
261
|
+
prefix += parentLast ? TREE_CHARS.space : TREE_CHARS.vertical;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Add branch character for non-root nodes
|
|
265
|
+
if (depth > 0) {
|
|
266
|
+
prefix = prefix.slice(0, -3) + (isLast ? TREE_CHARS.last : TREE_CHARS.branch);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// Format task display
|
|
270
|
+
const taskDisplay = showDetails
|
|
271
|
+
? `${formatTaskId(node.taskId)} [${node.agentSlug}]`
|
|
272
|
+
: formatTaskId(node.taskId);
|
|
273
|
+
|
|
274
|
+
const currentMarker = isCurrent ? " (current)" : "";
|
|
275
|
+
|
|
276
|
+
return (
|
|
277
|
+
<Box>
|
|
278
|
+
<Text color={theme.semantic.text.muted}>{prefix}</Text>
|
|
279
|
+
<Text color={statusColor}>{statusIcon}</Text>
|
|
280
|
+
<Text> </Text>
|
|
281
|
+
<Text color={isCurrent ? theme.semantic.status.running : theme.semantic.text.primary}>
|
|
282
|
+
{taskDisplay}
|
|
283
|
+
</Text>
|
|
284
|
+
{isCurrent && (
|
|
285
|
+
<Text color={theme.semantic.status.running} italic>
|
|
286
|
+
{currentMarker}
|
|
287
|
+
</Text>
|
|
288
|
+
)}
|
|
289
|
+
</Box>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
interface ProgressBarDisplayProps {
|
|
294
|
+
readonly stats: ProgressStats;
|
|
295
|
+
readonly width: number;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/**
|
|
299
|
+
* Progress bar with completion percentage.
|
|
300
|
+
*/
|
|
301
|
+
function ProgressBarDisplay({ stats, width }: ProgressBarDisplayProps): React.JSX.Element {
|
|
302
|
+
const { theme } = useTheme();
|
|
303
|
+
|
|
304
|
+
const progressBar = generateProgressBar(stats.percentage, width);
|
|
305
|
+
|
|
306
|
+
// Determine progress bar color based on completion
|
|
307
|
+
let barColor = theme.semantic.status.running;
|
|
308
|
+
if (stats.failed > 0) {
|
|
309
|
+
barColor = theme.semantic.status.error;
|
|
310
|
+
} else if (stats.percentage === 100) {
|
|
311
|
+
barColor = theme.semantic.status.complete;
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
return (
|
|
315
|
+
<Box marginTop={1}>
|
|
316
|
+
<Text color={theme.semantic.text.muted}>Progress: </Text>
|
|
317
|
+
<Text color={theme.semantic.text.primary}>
|
|
318
|
+
{stats.completed}/{stats.total}
|
|
319
|
+
</Text>
|
|
320
|
+
<Text color={theme.semantic.text.muted}> ({stats.percentage}%) </Text>
|
|
321
|
+
<Text color={barColor}>{progressBar}</Text>
|
|
322
|
+
</Box>
|
|
323
|
+
);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// =============================================================================
|
|
327
|
+
// Main Component
|
|
328
|
+
// =============================================================================
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* AgentProgress displays a visual task tree with progress tracking.
|
|
332
|
+
*
|
|
333
|
+
* Features:
|
|
334
|
+
* - Hierarchical task tree visualization
|
|
335
|
+
* - Status icons (○ pending, ◐ running, ● completed, ✗ failed)
|
|
336
|
+
* - ASCII progress bar with percentage
|
|
337
|
+
* - Current task highlighting
|
|
338
|
+
* - Optional detailed view with agent slugs
|
|
339
|
+
*
|
|
340
|
+
* @example
|
|
341
|
+
* ```tsx
|
|
342
|
+
* // Basic usage
|
|
343
|
+
* <AgentProgress chain={taskChain} />
|
|
344
|
+
*
|
|
345
|
+
* // With current task highlighting
|
|
346
|
+
* <AgentProgress
|
|
347
|
+
* chain={taskChain}
|
|
348
|
+
* currentTaskId="task-123"
|
|
349
|
+
* />
|
|
350
|
+
*
|
|
351
|
+
* // With details and custom progress bar width
|
|
352
|
+
* <AgentProgress
|
|
353
|
+
* chain={taskChain}
|
|
354
|
+
* currentTaskId="task-123"
|
|
355
|
+
* showDetails={true}
|
|
356
|
+
* progressBarWidth={30}
|
|
357
|
+
* />
|
|
358
|
+
* ```
|
|
359
|
+
*
|
|
360
|
+
* Display format:
|
|
361
|
+
* ```
|
|
362
|
+
* Task Chain: abc123
|
|
363
|
+
* ├── ● T001 - Create schema
|
|
364
|
+
* ├── ● T002 - Implement handler
|
|
365
|
+
* ├── ◐ T003 - Write tests (current)
|
|
366
|
+
* ├── ○ T004 - Documentation
|
|
367
|
+
* └── ○ T005 - Integration
|
|
368
|
+
*
|
|
369
|
+
* Progress: 2/5 (40%) ████████░░░░░░░░░░░░
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
export function AgentProgress({
|
|
373
|
+
chain,
|
|
374
|
+
currentTaskId,
|
|
375
|
+
showDetails = false,
|
|
376
|
+
progressBarWidth = DEFAULT_PROGRESS_BAR_WIDTH,
|
|
377
|
+
}: AgentProgressProps): React.JSX.Element {
|
|
378
|
+
const { theme } = useTheme();
|
|
379
|
+
|
|
380
|
+
// Build tree structure and flatten for rendering
|
|
381
|
+
const flattenedNodes = useMemo(() => {
|
|
382
|
+
const tree = buildTree(chain);
|
|
383
|
+
return flattenTree(tree);
|
|
384
|
+
}, [chain]);
|
|
385
|
+
|
|
386
|
+
// Calculate progress statistics
|
|
387
|
+
const stats = useMemo(() => calculateProgress(chain), [chain]);
|
|
388
|
+
|
|
389
|
+
// Empty state
|
|
390
|
+
if (chain.nodes.size === 0) {
|
|
391
|
+
return (
|
|
392
|
+
<Box flexDirection="column">
|
|
393
|
+
<Text color={theme.semantic.text.muted}>No tasks in chain</Text>
|
|
394
|
+
</Box>
|
|
395
|
+
);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
return (
|
|
399
|
+
<Box flexDirection="column">
|
|
400
|
+
{/* Chain header */}
|
|
401
|
+
<Box marginBottom={1}>
|
|
402
|
+
<Text color={theme.semantic.text.muted}>Task Chain: </Text>
|
|
403
|
+
<Text color={theme.semantic.text.primary} bold>
|
|
404
|
+
{formatTaskId(chain.chainId, 30)}
|
|
405
|
+
</Text>
|
|
406
|
+
</Box>
|
|
407
|
+
|
|
408
|
+
{/* Task tree */}
|
|
409
|
+
<Box flexDirection="column">
|
|
410
|
+
{flattenedNodes.map((flatNode) => (
|
|
411
|
+
<TaskTreeItem
|
|
412
|
+
key={flatNode.node.taskId}
|
|
413
|
+
flatNode={flatNode}
|
|
414
|
+
isCurrent={flatNode.node.taskId === currentTaskId}
|
|
415
|
+
showDetails={showDetails}
|
|
416
|
+
/>
|
|
417
|
+
))}
|
|
418
|
+
</Box>
|
|
419
|
+
|
|
420
|
+
{/* Progress bar */}
|
|
421
|
+
<ProgressBarDisplay stats={stats} width={progressBarWidth} />
|
|
422
|
+
</Box>
|
|
423
|
+
);
|
|
424
|
+
}
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ASCII Art Definitions for Vellum Banner
|
|
3
|
+
*
|
|
4
|
+
* Block-style ASCII art with ancient parchment/scroll styling.
|
|
5
|
+
* Multiple sizes for responsive terminal width adaptation.
|
|
6
|
+
*
|
|
7
|
+
* @module tui/components/Banner/AsciiArt
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// =============================================================================
|
|
11
|
+
// Large ASCII Art (80+ columns)
|
|
12
|
+
// =============================================================================
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Large VELLUM ASCII Art with scroll decorations.
|
|
16
|
+
* Designed for terminals 80+ columns wide.
|
|
17
|
+
* Features: scroll rod decorations (◊), worn edges (·~·), parchment corners (╔╗╚╝)
|
|
18
|
+
*/
|
|
19
|
+
export const VELLUM_LARGE = trimAscii(`
|
|
20
|
+
════◊╠═══════════════════════════════════════════════════════════════════════╣◊════
|
|
21
|
+
╔ ┌───────────────────────────────────────────────────────────────────┐ ╗
|
|
22
|
+
║ │ │ ║
|
|
23
|
+
║ │ ██╗ ██╗ ███████╗ ██╗ ██╗ ██╗ ██╗ ███╗ ███╗ │ ║
|
|
24
|
+
║ │ ██║ ██║ ██╔════╝ ██║ ██║ ██║ ██║ ████╗ ████║ │ ║
|
|
25
|
+
║ │ ██║ ██║ █████╗ ██║ ██║ ██║ ██║ ██╔████╔██║ │ ║
|
|
26
|
+
║ │ ╚██╗ ██╔╝ ██╔══╝ ██║ ██║ ██║ ██║ ██║╚██╔╝██║ │ ║
|
|
27
|
+
║ │ ╚████╔╝ ███████╗ ███████╗ ███████╗ ╚██████╔╝ ██║ ╚═╝ ██║ │ ║
|
|
28
|
+
║ │ ╚═══╝ ╚══════╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚═╝ ╚═╝ │ ║
|
|
29
|
+
║ │ │ ║
|
|
30
|
+
║ │ ·~· Ancient Wisdom for Modern Code ·~· │ ║
|
|
31
|
+
║ │ │ ║
|
|
32
|
+
╚ └───────────────────────────────────────────────────────────────────┘ ╝
|
|
33
|
+
════◊╠═══════════════════════════════════════════════════════════════════════╣◊════
|
|
34
|
+
`);
|
|
35
|
+
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// Medium ASCII Art (60-79 columns)
|
|
38
|
+
// =============================================================================
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Medium VELLUM ASCII Art.
|
|
42
|
+
* Designed for terminals 60-79 columns wide.
|
|
43
|
+
* Features: scroll rod decorations (◊), worn edges (·~·)
|
|
44
|
+
* Note: Uses ASCII-compatible characters for consistent terminal alignment.
|
|
45
|
+
*/
|
|
46
|
+
export const VELLUM_MEDIUM = trimAscii(`
|
|
47
|
+
══╣ ◊ ╠═══════════════════════════════════════════╣ ◊ ╠══
|
|
48
|
+
║ ┌─────────────────────────────────────────────────┐ ║
|
|
49
|
+
║ │ │ ║
|
|
50
|
+
║ │ ██╗ ██╗ ███████╗ ██╗ ██╗ ██╗ ██╗ │ ║
|
|
51
|
+
║ │ ██║ ██║ ██╔════╝ ██║ ██║ ██║ ██║ │ ║
|
|
52
|
+
║ │ ██║ ██║ █████╗ ██║ ██║ ██║ ██║ │ ║
|
|
53
|
+
║ │ ╚██╗ ██╔╝ ██╔══╝ ██║ ██║ ██║ ██║ │ ║
|
|
54
|
+
║ │ ╚████╔╝ ███████╗ ███████╗███████╗╚██████╔╝ │ ║
|
|
55
|
+
║ │ ╚═══╝ ╚══════╝ ╚══════╝╚══════╝ ╚═════╝ │ ║
|
|
56
|
+
║ │ │ ║
|
|
57
|
+
║ │ ·~· Ancient Wisdom for Modern Code ·~· │ ║
|
|
58
|
+
║ └─────────────────────────────────────────────────┘ ║
|
|
59
|
+
══╣ ◊ ╠═══════════════════════════════════════════╣ ◊ ╠══
|
|
60
|
+
`);
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// Small ASCII Art (40-59 columns)
|
|
64
|
+
// =============================================================================
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Small VELLUM ASCII Art.
|
|
68
|
+
* Designed for terminals 40-59 columns wide.
|
|
69
|
+
* Features: worn edges (·~·)
|
|
70
|
+
*/
|
|
71
|
+
export const VELLUM_SMALL = trimAscii(`
|
|
72
|
+
╭──◊────────────────────────────◊──╮
|
|
73
|
+
│ ╔══════════════════════════════╗ │
|
|
74
|
+
│ ║ ╦ ╦╔═╗╦ ╦ ╦ ╦╔╦╗ ║ │
|
|
75
|
+
│ ║ ╚╗╔╝║╣ ║ ║ ║ ║║║║ ║ │
|
|
76
|
+
│ ║ ╚╝ ╚═╝╩═╝╩═╝╚═╝╩ ╩ ║ │
|
|
77
|
+
│ ║ ║ │
|
|
78
|
+
│ ║ ·~· Ancient Wisdom ·~· ║ │
|
|
79
|
+
│ ╚══════════════════════════════╝ │
|
|
80
|
+
╰──◊────────────────────────────◊──╯
|
|
81
|
+
`);
|
|
82
|
+
|
|
83
|
+
// =============================================================================
|
|
84
|
+
// Minimal ASCII Art (<40 columns)
|
|
85
|
+
// =============================================================================
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Minimal VELLUM display.
|
|
89
|
+
* For very narrow terminals.
|
|
90
|
+
* Features: subtle scroll rod decoration (◊)
|
|
91
|
+
*/
|
|
92
|
+
export const VELLUM_MINIMAL = trimAscii(`
|
|
93
|
+
╭───◊──────────◊───╮
|
|
94
|
+
│ ╔══════════════╗ │
|
|
95
|
+
│ ║ V E L L U M ║ │
|
|
96
|
+
│ ╚══════════════╝ │
|
|
97
|
+
╰───◊──────────◊───╯
|
|
98
|
+
`);
|
|
99
|
+
|
|
100
|
+
// =============================================================================
|
|
101
|
+
// Scroll Decorations
|
|
102
|
+
// =============================================================================
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Top scroll decoration for parchment effect.
|
|
106
|
+
*/
|
|
107
|
+
export const SCROLL_TOP = trimAscii(`
|
|
108
|
+
════╣ ◊ ╠═══════════════════════════════════════════════════════════╣ ◊ ╠════
|
|
109
|
+
╔═══════════════════════════════════════════════════════════════════════════╗
|
|
110
|
+
`);
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Bottom scroll decoration for parchment effect.
|
|
114
|
+
*/
|
|
115
|
+
export const SCROLL_BOTTOM = trimAscii(`
|
|
116
|
+
╚═══════════════════════════════════════════════════════════════════════════╝
|
|
117
|
+
════╣ ◊ ╠═══════════════════════════════════════════════════════════╣ ◊ ╠════
|
|
118
|
+
`);
|
|
119
|
+
|
|
120
|
+
// =============================================================================
|
|
121
|
+
// Utility Functions
|
|
122
|
+
// =============================================================================
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Select appropriate ASCII art size based on terminal width.
|
|
126
|
+
*
|
|
127
|
+
* @param terminalWidth - Current terminal width in columns
|
|
128
|
+
* @returns Appropriate ASCII art string
|
|
129
|
+
*/
|
|
130
|
+
export function selectAsciiArt(terminalWidth: number): string {
|
|
131
|
+
if (terminalWidth >= 80) {
|
|
132
|
+
return VELLUM_LARGE;
|
|
133
|
+
} else if (terminalWidth >= 60) {
|
|
134
|
+
return VELLUM_MEDIUM;
|
|
135
|
+
} else if (terminalWidth >= 40) {
|
|
136
|
+
return VELLUM_SMALL;
|
|
137
|
+
} else {
|
|
138
|
+
return VELLUM_MINIMAL;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Get all ASCII art variants.
|
|
144
|
+
*/
|
|
145
|
+
export const ASCII_VARIANTS = {
|
|
146
|
+
large: VELLUM_LARGE,
|
|
147
|
+
medium: VELLUM_MEDIUM,
|
|
148
|
+
small: VELLUM_SMALL,
|
|
149
|
+
minimal: VELLUM_MINIMAL,
|
|
150
|
+
} as const;
|
|
151
|
+
|
|
152
|
+
export type AsciiVariant = keyof typeof ASCII_VARIANTS;
|
|
153
|
+
|
|
154
|
+
// =============================================================================
|
|
155
|
+
// Internal Helpers
|
|
156
|
+
// =============================================================================
|
|
157
|
+
|
|
158
|
+
function trimAscii(value: string): string {
|
|
159
|
+
return value.replace(/^\n/, "").trimEnd();
|
|
160
|
+
}
|