@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,267 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Command System Adapters
|
|
3
|
+
*
|
|
4
|
+
* Provides adapter functions for backward compatibility between:
|
|
5
|
+
* - Legacy SlashCommandResult format (auth.ts original)
|
|
6
|
+
* - New CommandResult discriminated union (types.ts)
|
|
7
|
+
*
|
|
8
|
+
* Enables gradual migration of existing commands to the new interface.
|
|
9
|
+
*
|
|
10
|
+
* @module cli/commands/adapters
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
import type { CommandContext, CommandError, CommandResult, InteractivePrompt } from "./types.js";
|
|
14
|
+
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// T032/T033: Legacy Type Definition
|
|
17
|
+
// =============================================================================
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Legacy SlashCommandResult format
|
|
21
|
+
*
|
|
22
|
+
* Used by existing auth commands before migration to enhanced interface.
|
|
23
|
+
*/
|
|
24
|
+
export interface LegacySlashCommandResult {
|
|
25
|
+
/** Whether the command succeeded */
|
|
26
|
+
success: boolean;
|
|
27
|
+
/** Message to display to user */
|
|
28
|
+
message: string;
|
|
29
|
+
/** Additional data (for programmatic use) */
|
|
30
|
+
data?: Record<string, unknown>;
|
|
31
|
+
/** Whether to prompt for input */
|
|
32
|
+
promptForInput?: {
|
|
33
|
+
type: "api_key";
|
|
34
|
+
provider: string;
|
|
35
|
+
placeholder: string;
|
|
36
|
+
onSubmit: (value: string) => Promise<LegacySlashCommandResult>;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// =============================================================================
|
|
41
|
+
// T032: toSlashCommandResult - New → Legacy Adapter
|
|
42
|
+
// =============================================================================
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Convert new CommandResult to legacy SlashCommandResult format
|
|
46
|
+
*
|
|
47
|
+
* Maps the discriminated union result to the legacy format:
|
|
48
|
+
* - success: kind === 'success'
|
|
49
|
+
* - error: kind === 'error'
|
|
50
|
+
* - interactive: converted to promptForInput if password type
|
|
51
|
+
*
|
|
52
|
+
* @param result - New CommandResult to convert
|
|
53
|
+
* @returns Legacy SlashCommandResult format
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* ```typescript
|
|
57
|
+
* const newResult: CommandResult = { kind: 'success', message: 'Done' };
|
|
58
|
+
* const legacy = toSlashCommandResult(newResult);
|
|
59
|
+
* // { success: true, message: 'Done' }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export function toSlashCommandResult(result: CommandResult): LegacySlashCommandResult {
|
|
63
|
+
switch (result.kind) {
|
|
64
|
+
case "success":
|
|
65
|
+
return {
|
|
66
|
+
success: true,
|
|
67
|
+
message: result.message ?? "",
|
|
68
|
+
data: result.data as Record<string, unknown> | undefined,
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
case "error":
|
|
72
|
+
return {
|
|
73
|
+
success: false,
|
|
74
|
+
message: result.message,
|
|
75
|
+
data: {
|
|
76
|
+
code: result.code,
|
|
77
|
+
suggestions: result.suggestions,
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
case "interactive": {
|
|
82
|
+
const { prompt } = result;
|
|
83
|
+
|
|
84
|
+
// Convert interactive prompt to legacy promptForInput if applicable
|
|
85
|
+
if (prompt.inputType === "password" || prompt.inputType === "text") {
|
|
86
|
+
return {
|
|
87
|
+
success: true,
|
|
88
|
+
message: prompt.message,
|
|
89
|
+
promptForInput: {
|
|
90
|
+
type: "api_key",
|
|
91
|
+
provider: prompt.provider ?? "",
|
|
92
|
+
placeholder: prompt.placeholder ?? "",
|
|
93
|
+
onSubmit: async (value: string): Promise<LegacySlashCommandResult> => {
|
|
94
|
+
const handlerResult = await prompt.handler(value);
|
|
95
|
+
return toSlashCommandResult(handlerResult);
|
|
96
|
+
},
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
// For confirm/select, return message only
|
|
102
|
+
return {
|
|
103
|
+
success: true,
|
|
104
|
+
message: prompt.message,
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
case "pending":
|
|
109
|
+
return {
|
|
110
|
+
success: true,
|
|
111
|
+
message: result.operation.message,
|
|
112
|
+
data: {
|
|
113
|
+
pending: true,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
default: {
|
|
118
|
+
// Exhaustive check - result should never reach here
|
|
119
|
+
result satisfies never;
|
|
120
|
+
return {
|
|
121
|
+
success: false,
|
|
122
|
+
message: "Unknown result type",
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// =============================================================================
|
|
129
|
+
// T033: fromSlashCommandResult - Legacy → New Adapter
|
|
130
|
+
// =============================================================================
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Convert legacy SlashCommandResult to new CommandResult format
|
|
134
|
+
*
|
|
135
|
+
* Maps the legacy result to the discriminated union:
|
|
136
|
+
* - success: true → CommandSuccess
|
|
137
|
+
* - success: false → CommandError
|
|
138
|
+
* - promptForInput → CommandInteractive
|
|
139
|
+
*
|
|
140
|
+
* @param legacy - Legacy SlashCommandResult to convert
|
|
141
|
+
* @returns New CommandResult discriminated union
|
|
142
|
+
*
|
|
143
|
+
* @example
|
|
144
|
+
* ```typescript
|
|
145
|
+
* const legacy = { success: true, message: 'Done' };
|
|
146
|
+
* const result = fromSlashCommandResult(legacy);
|
|
147
|
+
* // { kind: 'success', message: 'Done' }
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
export function fromSlashCommandResult(legacy: LegacySlashCommandResult): CommandResult {
|
|
151
|
+
// Handle interactive prompts
|
|
152
|
+
if (legacy.promptForInput) {
|
|
153
|
+
const { promptForInput } = legacy;
|
|
154
|
+
|
|
155
|
+
const prompt: InteractivePrompt = {
|
|
156
|
+
inputType: "password",
|
|
157
|
+
message: legacy.message,
|
|
158
|
+
placeholder: promptForInput.placeholder,
|
|
159
|
+
provider: promptForInput.provider,
|
|
160
|
+
handler: async (value: string): Promise<CommandResult> => {
|
|
161
|
+
const legacyResult = await promptForInput.onSubmit(value);
|
|
162
|
+
return fromSlashCommandResult(legacyResult);
|
|
163
|
+
},
|
|
164
|
+
onCancel: () => ({
|
|
165
|
+
kind: "error" as const,
|
|
166
|
+
code: "COMMAND_ABORTED" as const,
|
|
167
|
+
message: "Operation cancelled",
|
|
168
|
+
}),
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
return {
|
|
172
|
+
kind: "interactive",
|
|
173
|
+
prompt,
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Handle success
|
|
178
|
+
if (legacy.success) {
|
|
179
|
+
return {
|
|
180
|
+
kind: "success",
|
|
181
|
+
message: legacy.message || undefined,
|
|
182
|
+
data: legacy.data,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// Handle error
|
|
187
|
+
return {
|
|
188
|
+
kind: "error",
|
|
189
|
+
code: (legacy.data?.code as CommandError["code"]) ?? "UNKNOWN_ERROR",
|
|
190
|
+
message: legacy.message,
|
|
191
|
+
suggestions: legacy.data?.suggestions as readonly string[] | undefined,
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// =============================================================================
|
|
196
|
+
// T034A: wrapLegacyHandler - Legacy Handler Wrapper
|
|
197
|
+
// =============================================================================
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Legacy command handler function signature
|
|
201
|
+
*/
|
|
202
|
+
export type LegacyHandler = (
|
|
203
|
+
args: string[],
|
|
204
|
+
context: { currentProvider?: string; credentialManager: CommandContext["credentials"] }
|
|
205
|
+
) => Promise<LegacySlashCommandResult>;
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Wrap a legacy handler to work with the new command system
|
|
209
|
+
*
|
|
210
|
+
* Converts CommandContext to legacy context format,
|
|
211
|
+
* calls the legacy handler, then converts the result.
|
|
212
|
+
*
|
|
213
|
+
* @param legacyHandler - Legacy handler function
|
|
214
|
+
* @returns New-style command handler
|
|
215
|
+
*
|
|
216
|
+
* @example
|
|
217
|
+
* ```typescript
|
|
218
|
+
* const newHandler = wrapLegacyHandler(handleLogin);
|
|
219
|
+
*
|
|
220
|
+
* const command: SlashCommand = {
|
|
221
|
+
* name: 'login',
|
|
222
|
+
* execute: newHandler,
|
|
223
|
+
* };
|
|
224
|
+
* ```
|
|
225
|
+
*/
|
|
226
|
+
export function wrapLegacyHandler(
|
|
227
|
+
legacyHandler: LegacyHandler
|
|
228
|
+
): (ctx: CommandContext) => Promise<CommandResult> {
|
|
229
|
+
return async (ctx: CommandContext): Promise<CommandResult> => {
|
|
230
|
+
// Extract positional args as string array
|
|
231
|
+
const args = ctx.parsedArgs.positional.map((arg) => String(arg));
|
|
232
|
+
|
|
233
|
+
// Build legacy context
|
|
234
|
+
const legacyContext = {
|
|
235
|
+
currentProvider: ctx.session.provider,
|
|
236
|
+
credentialManager: ctx.credentials,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
// Call legacy handler
|
|
240
|
+
const legacyResult = await legacyHandler(args, legacyContext);
|
|
241
|
+
|
|
242
|
+
// Convert to new result format
|
|
243
|
+
return fromSlashCommandResult(legacyResult);
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// =============================================================================
|
|
248
|
+
// Utility: Create Legacy Context from CommandContext
|
|
249
|
+
// =============================================================================
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Extract legacy context from CommandContext
|
|
253
|
+
*
|
|
254
|
+
* Useful when calling legacy handlers directly within new commands.
|
|
255
|
+
*
|
|
256
|
+
* @param ctx - New CommandContext
|
|
257
|
+
* @returns Legacy context object
|
|
258
|
+
*/
|
|
259
|
+
export function toLegacyContext(ctx: CommandContext): {
|
|
260
|
+
currentProvider?: string;
|
|
261
|
+
credentialManager: CommandContext["credentials"];
|
|
262
|
+
} {
|
|
263
|
+
return {
|
|
264
|
+
currentProvider: ctx.session.provider,
|
|
265
|
+
credentialManager: ctx.credentials,
|
|
266
|
+
};
|
|
267
|
+
}
|
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Agent Level Slash Commands (T046c)
|
|
3
|
+
*
|
|
4
|
+
* Provides slash commands for agent level management:
|
|
5
|
+
* - /agent - Show current agent level and options
|
|
6
|
+
* - /agent l0 - Switch to orchestrator level
|
|
7
|
+
* - /agent l1 - Switch to workflow level
|
|
8
|
+
* - /agent l2 - Switch to worker level
|
|
9
|
+
* - /agent clear - Clear level override
|
|
10
|
+
* - /agent list - List registered agents
|
|
11
|
+
*
|
|
12
|
+
* @module cli/commands/agent
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { AgentLevel, type ModeManager } from "@vellum/core";
|
|
16
|
+
import type { CommandContext, CommandResult, SlashCommand } from "./types.js";
|
|
17
|
+
import { error, success } from "./types.js";
|
|
18
|
+
|
|
19
|
+
// =============================================================================
|
|
20
|
+
// Module State
|
|
21
|
+
// =============================================================================
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Reference to the active ModeManager instance.
|
|
25
|
+
* Set by the App component when initialized.
|
|
26
|
+
*/
|
|
27
|
+
let modeManager: ModeManager | null = null;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Set the ModeManager instance for agent commands.
|
|
31
|
+
* Called by the App component during initialization.
|
|
32
|
+
*
|
|
33
|
+
* @param manager - The ModeManager instance to use
|
|
34
|
+
*/
|
|
35
|
+
export function setAgentCommandsManager(manager: ModeManager | null): void {
|
|
36
|
+
modeManager = manager;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Get the current ModeManager instance.
|
|
41
|
+
* Returns null if not yet initialized.
|
|
42
|
+
*/
|
|
43
|
+
export function getAgentCommandsManager(): ModeManager | null {
|
|
44
|
+
return modeManager;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// =============================================================================
|
|
48
|
+
// Agent Level Constants
|
|
49
|
+
// =============================================================================
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Agent level names for display.
|
|
53
|
+
*/
|
|
54
|
+
const AGENT_LEVEL_NAMES: Record<AgentLevel, string> = {
|
|
55
|
+
[AgentLevel.orchestrator]: "Orchestrator",
|
|
56
|
+
[AgentLevel.workflow]: "Workflow",
|
|
57
|
+
[AgentLevel.worker]: "Worker",
|
|
58
|
+
} as const;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Agent level descriptions.
|
|
62
|
+
*/
|
|
63
|
+
const AGENT_LEVEL_DESCRIPTIONS: Record<AgentLevel, string> = {
|
|
64
|
+
[AgentLevel.orchestrator]: "Top-level coordinator, spawns workflow agents",
|
|
65
|
+
[AgentLevel.workflow]: "Mid-level manager, spawns worker agents",
|
|
66
|
+
[AgentLevel.worker]: "Leaf-level executor, cannot spawn agents",
|
|
67
|
+
} as const;
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Agent level icons.
|
|
71
|
+
*/
|
|
72
|
+
const AGENT_LEVEL_ICONS: Record<AgentLevel, string> = {
|
|
73
|
+
[AgentLevel.orchestrator]: "[L0]",
|
|
74
|
+
[AgentLevel.workflow]: "[L1]",
|
|
75
|
+
[AgentLevel.worker]: "[L2]",
|
|
76
|
+
} as const;
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Subcommand to AgentLevel mapping.
|
|
80
|
+
*/
|
|
81
|
+
const SUBCOMMAND_TO_LEVEL: Record<string, AgentLevel> = {
|
|
82
|
+
l0: AgentLevel.orchestrator,
|
|
83
|
+
l1: AgentLevel.workflow,
|
|
84
|
+
l2: AgentLevel.worker,
|
|
85
|
+
orchestrator: AgentLevel.orchestrator,
|
|
86
|
+
workflow: AgentLevel.workflow,
|
|
87
|
+
worker: AgentLevel.worker,
|
|
88
|
+
} as const;
|
|
89
|
+
|
|
90
|
+
// =============================================================================
|
|
91
|
+
// Helper Functions
|
|
92
|
+
// =============================================================================
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Format agent level info for display.
|
|
96
|
+
*/
|
|
97
|
+
function formatLevelInfo(level: AgentLevel, isCurrent: boolean): string {
|
|
98
|
+
const icon = AGENT_LEVEL_ICONS[level];
|
|
99
|
+
const name = AGENT_LEVEL_NAMES[level];
|
|
100
|
+
const desc = AGENT_LEVEL_DESCRIPTIONS[level];
|
|
101
|
+
const marker = isCurrent ? " (current)" : "";
|
|
102
|
+
return ` ${icon} ${name}${marker} - ${desc}`;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Get numeric level from AgentLevel.
|
|
107
|
+
*/
|
|
108
|
+
function getLevelNumber(level: AgentLevel): number {
|
|
109
|
+
return level; // AgentLevel enum values are 0, 1, 2
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
// =============================================================================
|
|
113
|
+
// /agent Command - Show Current Level and Options
|
|
114
|
+
// =============================================================================
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* /agent command - Display current agent level and available options.
|
|
118
|
+
*
|
|
119
|
+
* Shows the current agent level and lists all available levels
|
|
120
|
+
* with their descriptions. Supports subcommands for switching levels.
|
|
121
|
+
*/
|
|
122
|
+
export const agentCommand: SlashCommand = {
|
|
123
|
+
name: "agent",
|
|
124
|
+
description: "Switch agent level or show current level",
|
|
125
|
+
kind: "builtin",
|
|
126
|
+
category: "workflow",
|
|
127
|
+
aliases: ["ag"],
|
|
128
|
+
positionalArgs: [
|
|
129
|
+
{
|
|
130
|
+
name: "subcommand",
|
|
131
|
+
type: "string",
|
|
132
|
+
description: "Subcommand: l0, l1, l2, clear, or list",
|
|
133
|
+
required: false,
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
examples: [
|
|
137
|
+
"/agent - Show current agent level and options",
|
|
138
|
+
"/agent l0 - Switch to orchestrator level (L0)",
|
|
139
|
+
"/agent l1 - Switch to workflow level (L1)",
|
|
140
|
+
"/agent l2 - Switch to worker level (L2)",
|
|
141
|
+
"/agent clear - Clear level override, restore mode default",
|
|
142
|
+
"/agent list - List registered agents",
|
|
143
|
+
],
|
|
144
|
+
subcommands: [
|
|
145
|
+
{ name: "l0", description: "Switch to orchestrator level" },
|
|
146
|
+
{ name: "l1", description: "Switch to workflow level" },
|
|
147
|
+
{ name: "l2", description: "Switch to worker level" },
|
|
148
|
+
{ name: "clear", description: "Clear level override" },
|
|
149
|
+
{ name: "list", description: "List registered agents" },
|
|
150
|
+
],
|
|
151
|
+
|
|
152
|
+
execute: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
153
|
+
const subcommand = ctx.parsedArgs.positional[0] as string | undefined;
|
|
154
|
+
|
|
155
|
+
// Handle subcommands
|
|
156
|
+
if (subcommand) {
|
|
157
|
+
const normalized = subcommand.toLowerCase();
|
|
158
|
+
|
|
159
|
+
// Check for level switch commands
|
|
160
|
+
const level = SUBCOMMAND_TO_LEVEL[normalized as keyof typeof SUBCOMMAND_TO_LEVEL];
|
|
161
|
+
if (level !== undefined) {
|
|
162
|
+
return switchToLevel(level);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Handle clear command
|
|
166
|
+
if (normalized === "clear") {
|
|
167
|
+
return clearLevelOverride();
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// Handle list command
|
|
171
|
+
if (normalized === "list") {
|
|
172
|
+
return listAgents();
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Unknown subcommand
|
|
176
|
+
return error("INVALID_ARGUMENT", `Unknown subcommand: ${subcommand}`, [
|
|
177
|
+
"Valid subcommands: l0, l1, l2, clear, list",
|
|
178
|
+
]);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// No subcommand - show current level and options
|
|
182
|
+
return showCurrentLevel();
|
|
183
|
+
},
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// =============================================================================
|
|
187
|
+
// Subcommand Handlers
|
|
188
|
+
// =============================================================================
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Show current agent level and available options.
|
|
192
|
+
*/
|
|
193
|
+
function showCurrentLevel(): CommandResult {
|
|
194
|
+
if (!modeManager) {
|
|
195
|
+
const lines = [
|
|
196
|
+
"Agent Levels",
|
|
197
|
+
"",
|
|
198
|
+
"Available levels:",
|
|
199
|
+
formatLevelInfo(AgentLevel.orchestrator, false),
|
|
200
|
+
formatLevelInfo(AgentLevel.workflow, false),
|
|
201
|
+
formatLevelInfo(AgentLevel.worker, true), // Default
|
|
202
|
+
"",
|
|
203
|
+
"Mode system not initialized. Using default: L2 (Worker)",
|
|
204
|
+
"",
|
|
205
|
+
"Use /agent l0, /agent l1, or /agent l2 to switch levels.",
|
|
206
|
+
];
|
|
207
|
+
return success(lines.join("\n"));
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
const effectiveLevel = modeManager.getEffectiveAgentLevel();
|
|
211
|
+
const override = modeManager.getAgentLevelOverride();
|
|
212
|
+
const hasOverride = modeManager.hasAgentLevelOverride();
|
|
213
|
+
|
|
214
|
+
const levelIcon = AGENT_LEVEL_ICONS[effectiveLevel];
|
|
215
|
+
const levelName = AGENT_LEVEL_NAMES[effectiveLevel];
|
|
216
|
+
|
|
217
|
+
const lines = [
|
|
218
|
+
"Agent Levels",
|
|
219
|
+
"",
|
|
220
|
+
`Current level: ${levelIcon} ${levelName} (L${getLevelNumber(effectiveLevel)})`,
|
|
221
|
+
];
|
|
222
|
+
|
|
223
|
+
if (hasOverride && override) {
|
|
224
|
+
lines.push(`Override source: ${override.source}`);
|
|
225
|
+
lines.push("");
|
|
226
|
+
lines.push("[INFO] Use /agent clear to restore mode default.");
|
|
227
|
+
} else {
|
|
228
|
+
lines.push("(Mode-derived, no override active)");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
lines.push("");
|
|
232
|
+
lines.push("Available levels:");
|
|
233
|
+
lines.push(formatLevelInfo(AgentLevel.orchestrator, effectiveLevel === AgentLevel.orchestrator));
|
|
234
|
+
lines.push(formatLevelInfo(AgentLevel.workflow, effectiveLevel === AgentLevel.workflow));
|
|
235
|
+
lines.push(formatLevelInfo(AgentLevel.worker, effectiveLevel === AgentLevel.worker));
|
|
236
|
+
lines.push("");
|
|
237
|
+
lines.push("Use /agent l0, /agent l1, or /agent l2 to switch levels.");
|
|
238
|
+
|
|
239
|
+
return success(lines.join("\n"));
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Switch to a specific agent level.
|
|
244
|
+
*/
|
|
245
|
+
function switchToLevel(level: AgentLevel): CommandResult {
|
|
246
|
+
if (!modeManager) {
|
|
247
|
+
return error("OPERATION_NOT_ALLOWED", "Mode system not initialized", [
|
|
248
|
+
"Cannot set agent level override without ModeManager.",
|
|
249
|
+
]);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
const currentLevel = modeManager.getEffectiveAgentLevel();
|
|
253
|
+
|
|
254
|
+
// Check if already at this level with override
|
|
255
|
+
if (modeManager.hasAgentLevelOverride()) {
|
|
256
|
+
const override = modeManager.getAgentLevelOverride();
|
|
257
|
+
if (override?.level === level) {
|
|
258
|
+
const icon = AGENT_LEVEL_ICONS[level];
|
|
259
|
+
const name = AGENT_LEVEL_NAMES[level];
|
|
260
|
+
return success(`Already at ${icon} ${name} level (L${getLevelNumber(level)}).`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// Set the override
|
|
265
|
+
modeManager.setAgentLevelOverride(level, "command");
|
|
266
|
+
|
|
267
|
+
const icon = AGENT_LEVEL_ICONS[level];
|
|
268
|
+
const name = AGENT_LEVEL_NAMES[level];
|
|
269
|
+
const prevIcon = AGENT_LEVEL_ICONS[currentLevel];
|
|
270
|
+
const prevName = AGENT_LEVEL_NAMES[currentLevel];
|
|
271
|
+
|
|
272
|
+
return success(
|
|
273
|
+
`${icon} Switched to ${name} level (L${getLevelNumber(level)}).\n` +
|
|
274
|
+
`Previous: ${prevIcon} ${prevName} (L${getLevelNumber(currentLevel)})`
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Clear agent level override.
|
|
280
|
+
*/
|
|
281
|
+
function clearLevelOverride(): CommandResult {
|
|
282
|
+
if (!modeManager) {
|
|
283
|
+
return error("OPERATION_NOT_ALLOWED", "Mode system not initialized", [
|
|
284
|
+
"Cannot clear agent level override without ModeManager.",
|
|
285
|
+
]);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!modeManager.hasAgentLevelOverride()) {
|
|
289
|
+
const effectiveLevel = modeManager.getEffectiveAgentLevel();
|
|
290
|
+
const icon = AGENT_LEVEL_ICONS[effectiveLevel];
|
|
291
|
+
const name = AGENT_LEVEL_NAMES[effectiveLevel];
|
|
292
|
+
return success(
|
|
293
|
+
`No override active. Current level: ${icon} ${name} (L${getLevelNumber(effectiveLevel)})`
|
|
294
|
+
);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const previousOverride = modeManager.getAgentLevelOverride();
|
|
298
|
+
const prevLevel: AgentLevel = previousOverride?.level ?? AgentLevel.worker;
|
|
299
|
+
modeManager.clearAgentLevelOverride();
|
|
300
|
+
|
|
301
|
+
const newLevel = modeManager.getEffectiveAgentLevel();
|
|
302
|
+
const newIcon = AGENT_LEVEL_ICONS[newLevel];
|
|
303
|
+
const newName = AGENT_LEVEL_NAMES[newLevel];
|
|
304
|
+
|
|
305
|
+
const prevIcon = AGENT_LEVEL_ICONS[prevLevel];
|
|
306
|
+
const prevName = AGENT_LEVEL_NAMES[prevLevel];
|
|
307
|
+
|
|
308
|
+
return success(
|
|
309
|
+
`Override cleared.\n` +
|
|
310
|
+
`Previous: ${prevIcon} ${prevName} (L${getLevelNumber(prevLevel)})\n` +
|
|
311
|
+
`Now: ${newIcon} ${newName} (L${getLevelNumber(newLevel)}) (mode-derived)`
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
/**
|
|
316
|
+
* List registered agents.
|
|
317
|
+
*
|
|
318
|
+
* Currently returns a placeholder as agent registry is not yet implemented.
|
|
319
|
+
*/
|
|
320
|
+
function listAgents(): CommandResult {
|
|
321
|
+
// TODO: Once agent registry is implemented, list actual agents
|
|
322
|
+
const lines = [
|
|
323
|
+
"Registered Agents",
|
|
324
|
+
"",
|
|
325
|
+
"Built-in agent configurations:",
|
|
326
|
+
" [L2] Vibe Agent - Fast autonomous worker",
|
|
327
|
+
" [L1] Plan Agent - Plan-then-execute workflow",
|
|
328
|
+
" [L0] Spec Orchestrator - 6-phase structured workflow",
|
|
329
|
+
"",
|
|
330
|
+
"Use /mode to switch between agent configurations.",
|
|
331
|
+
"Use /agent l0|l1|l2 to manually override agent level.",
|
|
332
|
+
];
|
|
333
|
+
return success(lines.join("\n"));
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// =============================================================================
|
|
337
|
+
// Shortcut Commands
|
|
338
|
+
// =============================================================================
|
|
339
|
+
|
|
340
|
+
/**
|
|
341
|
+
* /l0 command - Quick switch to orchestrator level.
|
|
342
|
+
*/
|
|
343
|
+
export const l0Command: SlashCommand = {
|
|
344
|
+
name: "l0",
|
|
345
|
+
description: "Switch to orchestrator level (L0)",
|
|
346
|
+
kind: "builtin",
|
|
347
|
+
category: "workflow",
|
|
348
|
+
aliases: ["orchestrator"],
|
|
349
|
+
examples: ["/l0 - Switch to orchestrator level"],
|
|
350
|
+
|
|
351
|
+
execute: async (_ctx: CommandContext): Promise<CommandResult> => {
|
|
352
|
+
return switchToLevel(AgentLevel.orchestrator);
|
|
353
|
+
},
|
|
354
|
+
};
|
|
355
|
+
|
|
356
|
+
/**
|
|
357
|
+
* /l1 command - Quick switch to workflow level.
|
|
358
|
+
*/
|
|
359
|
+
export const l1Command: SlashCommand = {
|
|
360
|
+
name: "l1",
|
|
361
|
+
description: "Switch to workflow level (L1)",
|
|
362
|
+
kind: "builtin",
|
|
363
|
+
category: "workflow",
|
|
364
|
+
aliases: ["workflow"],
|
|
365
|
+
examples: ["/l1 - Switch to workflow level"],
|
|
366
|
+
|
|
367
|
+
execute: async (_ctx: CommandContext): Promise<CommandResult> => {
|
|
368
|
+
return switchToLevel(AgentLevel.workflow);
|
|
369
|
+
},
|
|
370
|
+
};
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* /l2 command - Quick switch to worker level.
|
|
374
|
+
*/
|
|
375
|
+
export const l2Command: SlashCommand = {
|
|
376
|
+
name: "l2",
|
|
377
|
+
description: "Switch to worker level (L2)",
|
|
378
|
+
kind: "builtin",
|
|
379
|
+
category: "workflow",
|
|
380
|
+
aliases: ["worker"],
|
|
381
|
+
examples: ["/l2 - Switch to worker level"],
|
|
382
|
+
|
|
383
|
+
execute: async (_ctx: CommandContext): Promise<CommandResult> => {
|
|
384
|
+
return switchToLevel(AgentLevel.worker);
|
|
385
|
+
},
|
|
386
|
+
};
|
|
387
|
+
|
|
388
|
+
// =============================================================================
|
|
389
|
+
// Export All Agent Commands
|
|
390
|
+
// =============================================================================
|
|
391
|
+
|
|
392
|
+
/**
|
|
393
|
+
* All agent-related slash commands for registration.
|
|
394
|
+
*/
|
|
395
|
+
export const agentSlashCommands: SlashCommand[] = [agentCommand, l0Command, l1Command, l2Command];
|