@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
|
+
* LSP Context Provider
|
|
3
|
+
*
|
|
4
|
+
* Provides LSP (Language Server Protocol) state management for the TUI.
|
|
5
|
+
* Subscribes to LSP integration manager state updates and provides
|
|
6
|
+
* status information to UI components.
|
|
7
|
+
*
|
|
8
|
+
* @module tui/context/LspContext
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
createContext,
|
|
13
|
+
type ReactNode,
|
|
14
|
+
useCallback,
|
|
15
|
+
useContext,
|
|
16
|
+
useEffect,
|
|
17
|
+
useMemo,
|
|
18
|
+
useState,
|
|
19
|
+
} from "react";
|
|
20
|
+
|
|
21
|
+
import { getLspManager, type LspIntegrationState } from "../lsp-integration.js";
|
|
22
|
+
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// Types
|
|
25
|
+
// =============================================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* LSP Context state
|
|
29
|
+
*/
|
|
30
|
+
export interface LspContextState {
|
|
31
|
+
/** Whether LSP is initialized */
|
|
32
|
+
readonly isInitialized: boolean;
|
|
33
|
+
/** Number of running LSP servers */
|
|
34
|
+
readonly runningServers: number;
|
|
35
|
+
/** Total number of configured LSP servers */
|
|
36
|
+
readonly totalServers: number;
|
|
37
|
+
/** Currently running server IDs */
|
|
38
|
+
readonly runningServerIds: readonly string[];
|
|
39
|
+
/** Whether tools are registered */
|
|
40
|
+
readonly toolsRegistered: boolean;
|
|
41
|
+
/** Error that occurred, if any */
|
|
42
|
+
readonly error: Error | null;
|
|
43
|
+
/** Refresh LSP state */
|
|
44
|
+
readonly refresh: () => void;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* LSP Context
|
|
49
|
+
*/
|
|
50
|
+
const LspContext = createContext<LspContextState | null>(null);
|
|
51
|
+
|
|
52
|
+
// =============================================================================
|
|
53
|
+
// Provider Props
|
|
54
|
+
// =============================================================================
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Props for LspProvider
|
|
58
|
+
*/
|
|
59
|
+
export interface LspProviderProps {
|
|
60
|
+
/** Children to render */
|
|
61
|
+
readonly children: ReactNode;
|
|
62
|
+
/** Refresh interval in milliseconds (default: 2000) */
|
|
63
|
+
readonly refreshInterval?: number;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// =============================================================================
|
|
67
|
+
// Provider Component
|
|
68
|
+
// =============================================================================
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* LSP Provider component.
|
|
72
|
+
*
|
|
73
|
+
* Subscribes to LSP integration manager state and provides it to the component tree.
|
|
74
|
+
* Automatically refreshes state at the specified interval.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```tsx
|
|
78
|
+
* <LspProvider>
|
|
79
|
+
* <App />
|
|
80
|
+
* </LspProvider>
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export function LspProvider({
|
|
84
|
+
children,
|
|
85
|
+
refreshInterval = 2000,
|
|
86
|
+
}: LspProviderProps): React.JSX.Element {
|
|
87
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
88
|
+
const [runningServers, setRunningServers] = useState(0);
|
|
89
|
+
const [totalServers, setTotalServers] = useState(0);
|
|
90
|
+
const [runningServerIds, setRunningServerIds] = useState<readonly string[]>([]);
|
|
91
|
+
const [toolsRegistered, setToolsRegistered] = useState(false);
|
|
92
|
+
const [error, setError] = useState<Error | null>(null);
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Refresh LSP state from the manager
|
|
96
|
+
*/
|
|
97
|
+
const refresh = useCallback(() => {
|
|
98
|
+
try {
|
|
99
|
+
const manager = getLspManager();
|
|
100
|
+
const state: LspIntegrationState = manager.getState();
|
|
101
|
+
const hub = manager.getHub();
|
|
102
|
+
|
|
103
|
+
setIsInitialized(state.initialized);
|
|
104
|
+
setRunningServerIds(state.runningServers);
|
|
105
|
+
setRunningServers(state.runningServers.length);
|
|
106
|
+
setToolsRegistered(state.toolsRegistered);
|
|
107
|
+
|
|
108
|
+
// Get total configured servers from hub
|
|
109
|
+
if (hub) {
|
|
110
|
+
const servers = hub.getServers();
|
|
111
|
+
setTotalServers(servers.length);
|
|
112
|
+
} else {
|
|
113
|
+
setTotalServers(0);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
setError(null);
|
|
117
|
+
} catch (err) {
|
|
118
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
119
|
+
}
|
|
120
|
+
}, []);
|
|
121
|
+
|
|
122
|
+
// Initial refresh and interval
|
|
123
|
+
useEffect(() => {
|
|
124
|
+
// Immediate refresh
|
|
125
|
+
refresh();
|
|
126
|
+
|
|
127
|
+
// Set up interval for periodic refresh
|
|
128
|
+
const intervalId = setInterval(refresh, refreshInterval);
|
|
129
|
+
|
|
130
|
+
return () => {
|
|
131
|
+
clearInterval(intervalId);
|
|
132
|
+
};
|
|
133
|
+
}, [refresh, refreshInterval]);
|
|
134
|
+
|
|
135
|
+
// Create context value
|
|
136
|
+
const contextValue = useMemo<LspContextState>(
|
|
137
|
+
() => ({
|
|
138
|
+
isInitialized,
|
|
139
|
+
runningServers,
|
|
140
|
+
totalServers,
|
|
141
|
+
runningServerIds,
|
|
142
|
+
toolsRegistered,
|
|
143
|
+
error,
|
|
144
|
+
refresh,
|
|
145
|
+
}),
|
|
146
|
+
[isInitialized, runningServers, totalServers, runningServerIds, toolsRegistered, error, refresh]
|
|
147
|
+
);
|
|
148
|
+
|
|
149
|
+
return <LspContext value={contextValue}>{children}</LspContext>;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// =============================================================================
|
|
153
|
+
// Hook
|
|
154
|
+
// =============================================================================
|
|
155
|
+
|
|
156
|
+
/**
|
|
157
|
+
* Hook to access LSP context.
|
|
158
|
+
*
|
|
159
|
+
* @returns LSP context state
|
|
160
|
+
* @throws Error if used outside LspProvider
|
|
161
|
+
*
|
|
162
|
+
* @example
|
|
163
|
+
* ```tsx
|
|
164
|
+
* function MyComponent() {
|
|
165
|
+
* const { isInitialized, runningServers, totalServers } = useLsp();
|
|
166
|
+
*
|
|
167
|
+
* if (!isInitialized) {
|
|
168
|
+
* return <Text>LSP: off</Text>;
|
|
169
|
+
* }
|
|
170
|
+
*
|
|
171
|
+
* return <Text>LSP: {runningServers}/{totalServers}</Text>;
|
|
172
|
+
* }
|
|
173
|
+
* ```
|
|
174
|
+
*/
|
|
175
|
+
export function useLsp(): LspContextState {
|
|
176
|
+
const context = useContext(LspContext);
|
|
177
|
+
|
|
178
|
+
if (!context) {
|
|
179
|
+
throw new Error("useLsp must be used within a LspProvider");
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return context;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Hook to access LSP context optionally (returns null if outside provider).
|
|
187
|
+
*
|
|
188
|
+
* @returns LSP context state or null
|
|
189
|
+
*/
|
|
190
|
+
export function useLspOptional(): LspContextState | null {
|
|
191
|
+
return useContext(LspContext);
|
|
192
|
+
}
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Context Provider
|
|
3
|
+
*
|
|
4
|
+
* Provides McpHub initialization and lifecycle management for the TUI.
|
|
5
|
+
* Handles startup initialization and graceful shutdown via ProcessManager.
|
|
6
|
+
*
|
|
7
|
+
* @module tui/context/McpContext
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
import fs from "node:fs/promises";
|
|
11
|
+
import os from "node:os";
|
|
12
|
+
import path from "node:path";
|
|
13
|
+
import type { ToolExecutor, ToolRegistry } from "@vellum/core";
|
|
14
|
+
import {
|
|
15
|
+
type CoreCredentialManager,
|
|
16
|
+
createOAuthCredentialAdapter,
|
|
17
|
+
getProcessManager,
|
|
18
|
+
McpHub,
|
|
19
|
+
type McpHubOptions,
|
|
20
|
+
type OAuthCredentialManager,
|
|
21
|
+
} from "@vellum/mcp";
|
|
22
|
+
import {
|
|
23
|
+
createContext,
|
|
24
|
+
type ReactNode,
|
|
25
|
+
useCallback,
|
|
26
|
+
useContext,
|
|
27
|
+
useEffect,
|
|
28
|
+
useMemo,
|
|
29
|
+
useState,
|
|
30
|
+
} from "react";
|
|
31
|
+
|
|
32
|
+
// =============================================================================
|
|
33
|
+
// T047: MCP Context Types
|
|
34
|
+
// =============================================================================
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* MCP Context state
|
|
38
|
+
*/
|
|
39
|
+
export interface McpContextState {
|
|
40
|
+
/** McpHub instance (null until initialized) */
|
|
41
|
+
readonly hub: McpHub | null;
|
|
42
|
+
/** Whether MCP is initialized */
|
|
43
|
+
readonly isInitialized: boolean;
|
|
44
|
+
/** Whether MCP is currently initializing */
|
|
45
|
+
readonly isInitializing: boolean;
|
|
46
|
+
/** Error that occurred during initialization, if any */
|
|
47
|
+
readonly error: Error | null;
|
|
48
|
+
/** Reinitialize MCP (e.g., after config change) */
|
|
49
|
+
readonly reinitialize: () => Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* MCP Context
|
|
54
|
+
*/
|
|
55
|
+
const McpContext = createContext<McpContextState | null>(null);
|
|
56
|
+
|
|
57
|
+
// =============================================================================
|
|
58
|
+
// T047: MCP Provider Props
|
|
59
|
+
// =============================================================================
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Props for McpProvider
|
|
63
|
+
*/
|
|
64
|
+
export interface McpProviderProps {
|
|
65
|
+
/** Children to render */
|
|
66
|
+
readonly children: ReactNode;
|
|
67
|
+
/** Whether to auto-initialize on mount (default: true) */
|
|
68
|
+
readonly autoInitialize?: boolean;
|
|
69
|
+
/** Client version for MCP protocol */
|
|
70
|
+
readonly clientVersion?: string;
|
|
71
|
+
/** Optional project config path override */
|
|
72
|
+
readonly projectConfigPath?: string;
|
|
73
|
+
/**
|
|
74
|
+
* Optional credential manager for OAuth token persistence.
|
|
75
|
+
* Can be either a CoreCredentialManager (from @vellum/core) or
|
|
76
|
+
* an OAuthCredentialManager directly.
|
|
77
|
+
*/
|
|
78
|
+
readonly credentialManager?: CoreCredentialManager | OAuthCredentialManager;
|
|
79
|
+
/** Optional tool registry for MCP tool registration */
|
|
80
|
+
readonly toolRegistry?: ToolRegistry;
|
|
81
|
+
/** Optional tool executor for MCP tool execution */
|
|
82
|
+
readonly toolExecutor?: ToolExecutor;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// =============================================================================
|
|
86
|
+
// T047: Default Paths
|
|
87
|
+
// =============================================================================
|
|
88
|
+
|
|
89
|
+
/**
|
|
90
|
+
* Get the default Vellum settings directory path.
|
|
91
|
+
* On Windows: %USERPROFILE%\.vellum
|
|
92
|
+
* On Unix: ~/.vellum
|
|
93
|
+
*/
|
|
94
|
+
async function getDefaultSettingsPath(): Promise<string> {
|
|
95
|
+
const home = os.homedir();
|
|
96
|
+
const settingsDir = path.join(home, ".vellum");
|
|
97
|
+
|
|
98
|
+
// Ensure directory exists
|
|
99
|
+
await fs.mkdir(settingsDir, { recursive: true });
|
|
100
|
+
|
|
101
|
+
return settingsDir;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Get the default MCP servers config path.
|
|
106
|
+
* Returns ~/.vellum/mcp.json
|
|
107
|
+
*/
|
|
108
|
+
async function getDefaultMcpServersPath(): Promise<string> {
|
|
109
|
+
const settingsDir = await getDefaultSettingsPath();
|
|
110
|
+
return path.join(settingsDir, "mcp.json");
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// =============================================================================
|
|
114
|
+
// T047: MCP Provider Component
|
|
115
|
+
// =============================================================================
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* MCP Provider component.
|
|
119
|
+
*
|
|
120
|
+
* Initializes McpHub on mount and registers cleanup with ProcessManager
|
|
121
|
+
* for graceful shutdown handling.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* ```tsx
|
|
125
|
+
* <McpProvider clientVersion="1.0.0">
|
|
126
|
+
* <App />
|
|
127
|
+
* </McpProvider>
|
|
128
|
+
* ```
|
|
129
|
+
*/
|
|
130
|
+
export function McpProvider({
|
|
131
|
+
children,
|
|
132
|
+
autoInitialize = true,
|
|
133
|
+
clientVersion = "1.0.0",
|
|
134
|
+
projectConfigPath,
|
|
135
|
+
credentialManager,
|
|
136
|
+
toolRegistry,
|
|
137
|
+
toolExecutor,
|
|
138
|
+
}: McpProviderProps): React.JSX.Element {
|
|
139
|
+
const [hub, setHub] = useState<McpHub | null>(null);
|
|
140
|
+
const [isInitialized, setIsInitialized] = useState(false);
|
|
141
|
+
const [isInitializing, setIsInitializing] = useState(false);
|
|
142
|
+
const [error, setError] = useState<Error | null>(null);
|
|
143
|
+
|
|
144
|
+
/**
|
|
145
|
+
* Initialize McpHub and register with ProcessManager
|
|
146
|
+
*/
|
|
147
|
+
const initialize = useCallback(async () => {
|
|
148
|
+
if (isInitializing || hub) {
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
setIsInitializing(true);
|
|
153
|
+
setError(null);
|
|
154
|
+
|
|
155
|
+
try {
|
|
156
|
+
// Adapt credential manager if needed
|
|
157
|
+
// If it looks like a CoreCredentialManager (Result-based API), wrap it
|
|
158
|
+
let oauthCredentialManager: OAuthCredentialManager | undefined;
|
|
159
|
+
if (credentialManager) {
|
|
160
|
+
// Check if it's already an OAuthCredentialManager (has void-returning methods)
|
|
161
|
+
// vs a CoreCredentialManager (has Result-returning methods)
|
|
162
|
+
// We duck-type check by looking at resolve return type
|
|
163
|
+
const testResolve = credentialManager.resolve("test");
|
|
164
|
+
if (testResolve instanceof Promise) {
|
|
165
|
+
const result = await testResolve;
|
|
166
|
+
// If result has 'ok' property, it's a CoreCredentialManager
|
|
167
|
+
if (result && typeof result === "object" && "ok" in result) {
|
|
168
|
+
oauthCredentialManager = createOAuthCredentialAdapter(
|
|
169
|
+
credentialManager as CoreCredentialManager
|
|
170
|
+
);
|
|
171
|
+
} else {
|
|
172
|
+
// It's already an OAuthCredentialManager
|
|
173
|
+
oauthCredentialManager = credentialManager as OAuthCredentialManager;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Create McpHub options
|
|
179
|
+
const options: McpHubOptions = {
|
|
180
|
+
getMcpServersPath: getDefaultMcpServersPath,
|
|
181
|
+
getSettingsDirectoryPath: getDefaultSettingsPath,
|
|
182
|
+
clientVersion,
|
|
183
|
+
projectConfigPath: projectConfigPath ? () => Promise.resolve(projectConfigPath) : undefined,
|
|
184
|
+
credentialManager: oauthCredentialManager,
|
|
185
|
+
toolRegistry,
|
|
186
|
+
toolExecutor,
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Create and initialize McpHub
|
|
190
|
+
const newHub = new McpHub(options);
|
|
191
|
+
await newHub.initialize();
|
|
192
|
+
|
|
193
|
+
// Register with ProcessManager for graceful shutdown
|
|
194
|
+
const processManager = getProcessManager();
|
|
195
|
+
processManager.onCleanup(async () => {
|
|
196
|
+
await newHub.dispose();
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
setHub(newHub);
|
|
200
|
+
setIsInitialized(true);
|
|
201
|
+
} catch (err) {
|
|
202
|
+
const initError = err instanceof Error ? err : new Error(String(err));
|
|
203
|
+
setError(initError);
|
|
204
|
+
console.error("[MCP] Initialization failed:", initError.message);
|
|
205
|
+
} finally {
|
|
206
|
+
setIsInitializing(false);
|
|
207
|
+
}
|
|
208
|
+
}, [
|
|
209
|
+
clientVersion,
|
|
210
|
+
projectConfigPath,
|
|
211
|
+
hub,
|
|
212
|
+
isInitializing,
|
|
213
|
+
credentialManager,
|
|
214
|
+
toolRegistry,
|
|
215
|
+
toolExecutor,
|
|
216
|
+
]);
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Reinitialize MCP (dispose and recreate)
|
|
220
|
+
*/
|
|
221
|
+
const reinitialize = useCallback(async () => {
|
|
222
|
+
// Dispose existing hub
|
|
223
|
+
if (hub) {
|
|
224
|
+
try {
|
|
225
|
+
await hub.dispose();
|
|
226
|
+
} catch (err) {
|
|
227
|
+
console.warn("[MCP] Error disposing hub during reinitialize:", err);
|
|
228
|
+
}
|
|
229
|
+
setHub(null);
|
|
230
|
+
setIsInitialized(false);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Re-initialize
|
|
234
|
+
await initialize();
|
|
235
|
+
}, [hub, initialize]);
|
|
236
|
+
|
|
237
|
+
// Auto-initialize on mount
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
if (autoInitialize && !hub && !isInitializing) {
|
|
240
|
+
initialize();
|
|
241
|
+
}
|
|
242
|
+
}, [autoInitialize, hub, isInitializing, initialize]);
|
|
243
|
+
|
|
244
|
+
// Cleanup on unmount
|
|
245
|
+
useEffect(() => {
|
|
246
|
+
return () => {
|
|
247
|
+
if (hub) {
|
|
248
|
+
hub.dispose().catch((err) => {
|
|
249
|
+
console.warn("[MCP] Error disposing hub on unmount:", err);
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
};
|
|
253
|
+
}, [hub]);
|
|
254
|
+
|
|
255
|
+
// Create context value
|
|
256
|
+
const contextValue = useMemo<McpContextState>(
|
|
257
|
+
() => ({
|
|
258
|
+
hub,
|
|
259
|
+
isInitialized,
|
|
260
|
+
isInitializing,
|
|
261
|
+
error,
|
|
262
|
+
reinitialize,
|
|
263
|
+
}),
|
|
264
|
+
[hub, isInitialized, isInitializing, error, reinitialize]
|
|
265
|
+
);
|
|
266
|
+
|
|
267
|
+
return <McpContext value={contextValue}>{children}</McpContext>;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// =============================================================================
|
|
271
|
+
// T047: Hook
|
|
272
|
+
// =============================================================================
|
|
273
|
+
|
|
274
|
+
/**
|
|
275
|
+
* Hook to access MCP context.
|
|
276
|
+
*
|
|
277
|
+
* @returns MCP context state
|
|
278
|
+
* @throws Error if used outside McpProvider
|
|
279
|
+
*
|
|
280
|
+
* @example
|
|
281
|
+
* ```tsx
|
|
282
|
+
* function MyComponent() {
|
|
283
|
+
* const { hub, isInitialized, error } = useMcp();
|
|
284
|
+
*
|
|
285
|
+
* if (!isInitialized) {
|
|
286
|
+
* return <Text>Loading MCP...</Text>;
|
|
287
|
+
* }
|
|
288
|
+
*
|
|
289
|
+
* if (error) {
|
|
290
|
+
* return <Text color="red">MCP Error: {error.message}</Text>;
|
|
291
|
+
* }
|
|
292
|
+
*
|
|
293
|
+
* // Use hub...
|
|
294
|
+
* }
|
|
295
|
+
* ```
|
|
296
|
+
*/
|
|
297
|
+
export function useMcp(): McpContextState {
|
|
298
|
+
const context = useContext(McpContext);
|
|
299
|
+
|
|
300
|
+
if (!context) {
|
|
301
|
+
throw new Error("useMcp must be used within a McpProvider");
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
return context;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Hook to access McpHub directly (throws if not initialized).
|
|
309
|
+
*
|
|
310
|
+
* @returns McpHub instance
|
|
311
|
+
* @throws Error if MCP is not initialized or used outside provider
|
|
312
|
+
*/
|
|
313
|
+
export function useMcpHub(): McpHub {
|
|
314
|
+
const { hub, isInitialized, error } = useMcp();
|
|
315
|
+
|
|
316
|
+
if (error) {
|
|
317
|
+
throw error;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!isInitialized || !hub) {
|
|
321
|
+
throw new Error("McpHub is not initialized");
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
return hub;
|
|
325
|
+
}
|