@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,551 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Think Slash Command (Thinking Mode Toggle)
|
|
3
|
+
*
|
|
4
|
+
* Provides slash command for managing extended thinking/reasoning mode:
|
|
5
|
+
* - /think [on|off] - Toggle or set thinking mode
|
|
6
|
+
* - /think [on] --budget <tokens> - Set thinking budget
|
|
7
|
+
*
|
|
8
|
+
* @module cli/commands/think
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { loadConfig } from "@vellum/core";
|
|
12
|
+
import {
|
|
13
|
+
getThinkingDisplayMode,
|
|
14
|
+
getThinkingSettings,
|
|
15
|
+
setThinkingDisplayMode,
|
|
16
|
+
setThinkingSettings,
|
|
17
|
+
type ThinkingDisplayMode,
|
|
18
|
+
type ThinkingSettings,
|
|
19
|
+
} from "../tui/i18n/index.js";
|
|
20
|
+
import type { CommandContext, CommandResult, SlashCommand } from "./types.js";
|
|
21
|
+
import { error, success } from "./types.js";
|
|
22
|
+
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// Types
|
|
25
|
+
// =============================================================================
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Priority for merging thinking configuration.
|
|
29
|
+
* - "global": Global /think state takes precedence
|
|
30
|
+
* - "mode": Mode's extendedThinking setting takes precedence
|
|
31
|
+
* - "merge": Either enabled means thinking is enabled
|
|
32
|
+
*/
|
|
33
|
+
export type ThinkingPriority = "global" | "mode" | "merge";
|
|
34
|
+
|
|
35
|
+
/** Re-export ThinkingDisplayMode for consumers */
|
|
36
|
+
export type { ThinkingDisplayMode };
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Effective thinking configuration for LLM calls.
|
|
40
|
+
*/
|
|
41
|
+
export interface EffectiveThinkingConfig {
|
|
42
|
+
enabled: boolean;
|
|
43
|
+
budgetTokens?: number;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// =============================================================================
|
|
47
|
+
// Module State
|
|
48
|
+
// =============================================================================
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Current thinking configuration state.
|
|
52
|
+
* This is a simple in-memory state for now.
|
|
53
|
+
* In a full implementation, this would be persisted to config.
|
|
54
|
+
*/
|
|
55
|
+
interface ThinkingState {
|
|
56
|
+
enabled: boolean;
|
|
57
|
+
budgetTokens: number;
|
|
58
|
+
priority: ThinkingPriority;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Default thinking state
|
|
63
|
+
*/
|
|
64
|
+
const defaultThinkingState: ThinkingState = {
|
|
65
|
+
enabled: false,
|
|
66
|
+
budgetTokens: 10000,
|
|
67
|
+
priority: "merge",
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Load initial thinking state from settings file first, then config file.
|
|
72
|
+
* Settings file takes precedence (user-modified via /think command).
|
|
73
|
+
* Falls back to config, then defaults if neither is available.
|
|
74
|
+
*/
|
|
75
|
+
function loadInitialThinkingState(): ThinkingState {
|
|
76
|
+
// First try to load from persisted settings (user preference)
|
|
77
|
+
const savedSettings = getThinkingSettings();
|
|
78
|
+
if (savedSettings) {
|
|
79
|
+
return {
|
|
80
|
+
enabled: savedSettings.enabled ?? defaultThinkingState.enabled,
|
|
81
|
+
budgetTokens: savedSettings.budgetTokens ?? defaultThinkingState.budgetTokens,
|
|
82
|
+
priority: savedSettings.priority ?? defaultThinkingState.priority,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// Fall back to config file
|
|
87
|
+
const result = loadConfig({ suppressDeprecationWarnings: true });
|
|
88
|
+
if (!result.ok || !result.value.thinking) {
|
|
89
|
+
return { ...defaultThinkingState };
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const { enabled, budgetTokens, priority } = result.value.thinking;
|
|
93
|
+
return {
|
|
94
|
+
enabled: enabled ?? defaultThinkingState.enabled,
|
|
95
|
+
budgetTokens: budgetTokens ?? defaultThinkingState.budgetTokens,
|
|
96
|
+
priority: priority ?? defaultThinkingState.priority,
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Current thinking state (initialized from config, managed in memory at runtime)
|
|
102
|
+
*/
|
|
103
|
+
let thinkingState: ThinkingState = loadInitialThinkingState();
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Listeners for thinking state changes
|
|
107
|
+
*/
|
|
108
|
+
type ThinkingStateListener = (state: ThinkingState) => void;
|
|
109
|
+
const listeners: Set<ThinkingStateListener> = new Set();
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Persist current thinking state to settings file.
|
|
113
|
+
* Called async to avoid blocking UI.
|
|
114
|
+
*/
|
|
115
|
+
function persistThinkingState(): void {
|
|
116
|
+
const settings: ThinkingSettings = {
|
|
117
|
+
enabled: thinkingState.enabled,
|
|
118
|
+
budgetTokens: thinkingState.budgetTokens,
|
|
119
|
+
priority: thinkingState.priority,
|
|
120
|
+
};
|
|
121
|
+
// Fire-and-forget - don't block UI for settings persistence
|
|
122
|
+
setThinkingSettings(settings);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// =============================================================================
|
|
126
|
+
// Public API for State Management
|
|
127
|
+
// =============================================================================
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Get the current thinking state.
|
|
131
|
+
*
|
|
132
|
+
* @returns Current thinking configuration
|
|
133
|
+
*/
|
|
134
|
+
export function getThinkingState(): Readonly<ThinkingState> {
|
|
135
|
+
return { ...thinkingState };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Set the thinking enabled state.
|
|
140
|
+
*
|
|
141
|
+
* @param enabled - Whether thinking is enabled
|
|
142
|
+
*/
|
|
143
|
+
export function setThinkingEnabled(enabled: boolean): void {
|
|
144
|
+
thinkingState = { ...thinkingState, enabled };
|
|
145
|
+
notifyListeners();
|
|
146
|
+
persistThinkingState();
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Set the thinking budget tokens.
|
|
151
|
+
*
|
|
152
|
+
* @param budgetTokens - Number of tokens for thinking budget
|
|
153
|
+
*/
|
|
154
|
+
export function setThinkingBudget(budgetTokens: number): void {
|
|
155
|
+
thinkingState = { ...thinkingState, budgetTokens };
|
|
156
|
+
notifyListeners();
|
|
157
|
+
persistThinkingState();
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* Toggle thinking mode on/off.
|
|
162
|
+
*
|
|
163
|
+
* @returns New enabled state
|
|
164
|
+
*/
|
|
165
|
+
export function toggleThinking(): boolean {
|
|
166
|
+
thinkingState = { ...thinkingState, enabled: !thinkingState.enabled };
|
|
167
|
+
notifyListeners();
|
|
168
|
+
persistThinkingState();
|
|
169
|
+
return thinkingState.enabled;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Subscribe to thinking state changes.
|
|
174
|
+
*
|
|
175
|
+
* @param listener - Callback function for state changes
|
|
176
|
+
* @returns Unsubscribe function
|
|
177
|
+
*/
|
|
178
|
+
export function subscribeToThinkingState(listener: ThinkingStateListener): () => void {
|
|
179
|
+
listeners.add(listener);
|
|
180
|
+
return () => {
|
|
181
|
+
listeners.delete(listener);
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Notify all listeners of state change.
|
|
187
|
+
*/
|
|
188
|
+
function notifyListeners(): void {
|
|
189
|
+
const state = getThinkingState();
|
|
190
|
+
for (const listener of listeners) {
|
|
191
|
+
listener(state);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Reset thinking state to defaults.
|
|
197
|
+
*/
|
|
198
|
+
export function resetThinkingState(): void {
|
|
199
|
+
thinkingState = { ...defaultThinkingState };
|
|
200
|
+
notifyListeners();
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Set the thinking priority.
|
|
205
|
+
*
|
|
206
|
+
* @param priority - Priority for merging thinking config
|
|
207
|
+
*/
|
|
208
|
+
export function setThinkingPriority(priority: ThinkingPriority): void {
|
|
209
|
+
thinkingState = { ...thinkingState, priority };
|
|
210
|
+
notifyListeners();
|
|
211
|
+
persistThinkingState();
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// =============================================================================
|
|
215
|
+
// Display Mode State (Separate from thinking state)
|
|
216
|
+
// =============================================================================
|
|
217
|
+
|
|
218
|
+
/**
|
|
219
|
+
* Listeners for display mode changes
|
|
220
|
+
*/
|
|
221
|
+
type DisplayModeListener = (mode: ThinkingDisplayMode) => void;
|
|
222
|
+
const displayModeListeners: Set<DisplayModeListener> = new Set();
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Get the current thinking display mode.
|
|
226
|
+
*
|
|
227
|
+
* @returns Current display mode ("full" or "compact")
|
|
228
|
+
*/
|
|
229
|
+
export { getThinkingDisplayMode };
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Set the thinking display mode.
|
|
233
|
+
*
|
|
234
|
+
* @param mode - Display mode ("full" or "compact")
|
|
235
|
+
*/
|
|
236
|
+
export function setDisplayMode(mode: ThinkingDisplayMode): void {
|
|
237
|
+
setThinkingDisplayMode(mode);
|
|
238
|
+
notifyDisplayModeListeners(mode);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
/**
|
|
242
|
+
* Subscribe to display mode changes.
|
|
243
|
+
*
|
|
244
|
+
* @param listener - Callback function for mode changes
|
|
245
|
+
* @returns Unsubscribe function
|
|
246
|
+
*/
|
|
247
|
+
export function subscribeToDisplayMode(listener: DisplayModeListener): () => void {
|
|
248
|
+
displayModeListeners.add(listener);
|
|
249
|
+
return () => {
|
|
250
|
+
displayModeListeners.delete(listener);
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Notify all display mode listeners.
|
|
256
|
+
*/
|
|
257
|
+
function notifyDisplayModeListeners(mode: ThinkingDisplayMode): void {
|
|
258
|
+
for (const listener of displayModeListeners) {
|
|
259
|
+
listener(mode);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Get the effective thinking configuration for LLM calls.
|
|
265
|
+
*
|
|
266
|
+
* This function merges the global thinking state (from /think command)
|
|
267
|
+
* with the mode's extendedThinking setting based on the priority setting.
|
|
268
|
+
*
|
|
269
|
+
* @param modeExtendedThinking - Mode's extendedThinking setting (optional)
|
|
270
|
+
* @returns Effective thinking config for LLM.stream()
|
|
271
|
+
*
|
|
272
|
+
* @example
|
|
273
|
+
* ```typescript
|
|
274
|
+
* // Get effective config using mode's extendedThinking
|
|
275
|
+
* const thinkingConfig = getEffectiveThinkingConfig(mode.extendedThinking);
|
|
276
|
+
*
|
|
277
|
+
* // Use in LLM.stream()
|
|
278
|
+
* LLM.stream({
|
|
279
|
+
* ...otherParams,
|
|
280
|
+
* thinking: thinkingConfig,
|
|
281
|
+
* });
|
|
282
|
+
* ```
|
|
283
|
+
*/
|
|
284
|
+
export function getEffectiveThinkingConfig(
|
|
285
|
+
modeExtendedThinking?: boolean
|
|
286
|
+
): EffectiveThinkingConfig {
|
|
287
|
+
const { enabled: globalEnabled, budgetTokens, priority } = thinkingState;
|
|
288
|
+
const modeEnabled = modeExtendedThinking ?? false;
|
|
289
|
+
|
|
290
|
+
let effectiveEnabled: boolean;
|
|
291
|
+
|
|
292
|
+
switch (priority) {
|
|
293
|
+
case "global":
|
|
294
|
+
// Global /think state takes precedence
|
|
295
|
+
effectiveEnabled = globalEnabled;
|
|
296
|
+
break;
|
|
297
|
+
case "mode":
|
|
298
|
+
// Mode's extendedThinking takes precedence
|
|
299
|
+
effectiveEnabled = modeEnabled;
|
|
300
|
+
break;
|
|
301
|
+
default:
|
|
302
|
+
// Either enabled means thinking is enabled
|
|
303
|
+
effectiveEnabled = globalEnabled || modeEnabled;
|
|
304
|
+
break;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
enabled: effectiveEnabled,
|
|
309
|
+
budgetTokens: effectiveEnabled ? budgetTokens : undefined,
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// =============================================================================
|
|
314
|
+
// Constants
|
|
315
|
+
// =============================================================================
|
|
316
|
+
|
|
317
|
+
/** Minimum budget tokens */
|
|
318
|
+
const MIN_BUDGET_TOKENS = 1000;
|
|
319
|
+
|
|
320
|
+
/** Maximum budget tokens */
|
|
321
|
+
const MAX_BUDGET_TOKENS = 128000;
|
|
322
|
+
|
|
323
|
+
/** Default budget tokens */
|
|
324
|
+
const DEFAULT_BUDGET_TOKENS = 10000;
|
|
325
|
+
|
|
326
|
+
// =============================================================================
|
|
327
|
+
// Helper Functions
|
|
328
|
+
// =============================================================================
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Parse budget value from string.
|
|
332
|
+
*
|
|
333
|
+
* @param value - String value to parse (e.g., "20000", "20k", "20K")
|
|
334
|
+
* @returns Parsed number or null if invalid
|
|
335
|
+
*/
|
|
336
|
+
function parseBudget(value: string): number | null {
|
|
337
|
+
// Handle k/K suffix for thousands
|
|
338
|
+
const normalized = value.toLowerCase().trim();
|
|
339
|
+
let multiplier = 1;
|
|
340
|
+
let numStr = normalized;
|
|
341
|
+
|
|
342
|
+
if (normalized.endsWith("k")) {
|
|
343
|
+
multiplier = 1000;
|
|
344
|
+
numStr = normalized.slice(0, -1);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const num = Number.parseFloat(numStr);
|
|
348
|
+
if (Number.isNaN(num) || !Number.isFinite(num)) {
|
|
349
|
+
return null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return Math.round(num * multiplier);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Format budget for display.
|
|
357
|
+
*
|
|
358
|
+
* @param tokens - Number of tokens
|
|
359
|
+
* @returns Formatted string (e.g., "10K", "128K")
|
|
360
|
+
*/
|
|
361
|
+
function formatBudget(tokens: number): string {
|
|
362
|
+
if (tokens >= 1000) {
|
|
363
|
+
return `${(tokens / 1000).toFixed(0)}K`;
|
|
364
|
+
}
|
|
365
|
+
return `${tokens}`;
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
// =============================================================================
|
|
369
|
+
// /think Command
|
|
370
|
+
// =============================================================================
|
|
371
|
+
|
|
372
|
+
/**
|
|
373
|
+
* /think command - Toggle or configure extended thinking mode.
|
|
374
|
+
*
|
|
375
|
+
* Usage:
|
|
376
|
+
* /think - Show current status and toggle
|
|
377
|
+
* /think on - Enable thinking mode
|
|
378
|
+
* /think off - Disable thinking mode
|
|
379
|
+
* /think on --budget 20000 - Enable with custom budget
|
|
380
|
+
* /think --budget 20k - Set budget (keeps current on/off state)
|
|
381
|
+
*/
|
|
382
|
+
export const thinkCommand: SlashCommand = {
|
|
383
|
+
name: "think",
|
|
384
|
+
description: "Toggle extended thinking/reasoning mode",
|
|
385
|
+
kind: "builtin",
|
|
386
|
+
category: "workflow",
|
|
387
|
+
aliases: ["thinking"],
|
|
388
|
+
subcommands: [
|
|
389
|
+
{ name: "on", description: "Enable extended thinking" },
|
|
390
|
+
{ name: "off", description: "Disable extended thinking" },
|
|
391
|
+
{ name: "mode", description: "Set display mode (full/compact)" },
|
|
392
|
+
],
|
|
393
|
+
positionalArgs: [
|
|
394
|
+
{
|
|
395
|
+
name: "state",
|
|
396
|
+
type: "string",
|
|
397
|
+
description: "Enable or disable thinking (on/off) or set display mode",
|
|
398
|
+
required: false,
|
|
399
|
+
},
|
|
400
|
+
],
|
|
401
|
+
namedArgs: [
|
|
402
|
+
{
|
|
403
|
+
name: "budget",
|
|
404
|
+
shorthand: "b",
|
|
405
|
+
type: "number",
|
|
406
|
+
description: `Token budget for thinking (${MIN_BUDGET_TOKENS}-${MAX_BUDGET_TOKENS})`,
|
|
407
|
+
required: false,
|
|
408
|
+
default: DEFAULT_BUDGET_TOKENS,
|
|
409
|
+
},
|
|
410
|
+
],
|
|
411
|
+
examples: [
|
|
412
|
+
"/think - Show current thinking status",
|
|
413
|
+
"/think on - Enable thinking mode",
|
|
414
|
+
"/think off - Disable thinking mode",
|
|
415
|
+
"/think on --budget 20000 - Enable with 20K token budget",
|
|
416
|
+
"/think -b 50k - Set budget to 50K tokens",
|
|
417
|
+
"/think mode full - Show full thinking content",
|
|
418
|
+
"/think mode compact - Show compact thinking header only",
|
|
419
|
+
],
|
|
420
|
+
|
|
421
|
+
// biome-ignore lint/complexity/noExcessiveCognitiveComplexity: Command handler with multiple state transitions
|
|
422
|
+
execute: async (ctx: CommandContext): Promise<CommandResult> => {
|
|
423
|
+
const stateArg = ctx.parsedArgs.positional[0] as string | undefined;
|
|
424
|
+
const budgetArg = ctx.parsedArgs.named.budget as string | number | undefined;
|
|
425
|
+
|
|
426
|
+
// Handle budget argument if provided
|
|
427
|
+
let newBudget: number | undefined;
|
|
428
|
+
if (budgetArg !== undefined) {
|
|
429
|
+
const budgetValue =
|
|
430
|
+
typeof budgetArg === "number" ? budgetArg : parseBudget(String(budgetArg));
|
|
431
|
+
|
|
432
|
+
if (budgetValue === null) {
|
|
433
|
+
return error("INVALID_ARGUMENT", `Invalid budget value: ${budgetArg}`, [
|
|
434
|
+
`Budget must be a number between ${formatBudget(MIN_BUDGET_TOKENS)} and ${formatBudget(MAX_BUDGET_TOKENS)}.`,
|
|
435
|
+
"Examples: 10000, 20k, 50K, 128000",
|
|
436
|
+
]);
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (budgetValue < MIN_BUDGET_TOKENS || budgetValue > MAX_BUDGET_TOKENS) {
|
|
440
|
+
return error("INVALID_ARGUMENT", `Budget out of range: ${formatBudget(budgetValue)}`, [
|
|
441
|
+
`Budget must be between ${formatBudget(MIN_BUDGET_TOKENS)} and ${formatBudget(MAX_BUDGET_TOKENS)}.`,
|
|
442
|
+
]);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
newBudget = budgetValue;
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
// If no state argument, show current status or toggle
|
|
449
|
+
if (!stateArg) {
|
|
450
|
+
// If budget was provided, just update budget
|
|
451
|
+
if (newBudget !== undefined) {
|
|
452
|
+
setThinkingBudget(newBudget);
|
|
453
|
+
const state = getThinkingState();
|
|
454
|
+
return success(
|
|
455
|
+
`🧠Thinking budget set to ${formatBudget(state.budgetTokens)} tokens.\n` +
|
|
456
|
+
` Status: ${state.enabled ? "â—† On" : "â—‡ Off"}`
|
|
457
|
+
);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
// Show current status
|
|
461
|
+
const state = getThinkingState();
|
|
462
|
+
const displayMode = getThinkingDisplayMode();
|
|
463
|
+
const statusIcon = state.enabled ? "â—†" : "â—‡";
|
|
464
|
+
const statusText = state.enabled ? "On" : "Off";
|
|
465
|
+
|
|
466
|
+
const lines = [
|
|
467
|
+
"🧠Extended Thinking Mode",
|
|
468
|
+
"",
|
|
469
|
+
` Status: ${statusIcon} ${statusText}`,
|
|
470
|
+
` Budget: ${formatBudget(state.budgetTokens)} tokens`,
|
|
471
|
+
` Display: ${displayMode}`,
|
|
472
|
+
"",
|
|
473
|
+
"Commands:",
|
|
474
|
+
" /think on - Enable thinking",
|
|
475
|
+
" /think off - Disable thinking",
|
|
476
|
+
" /think -b 20k - Set budget to 20K tokens",
|
|
477
|
+
" /think mode full|compact - Set display mode",
|
|
478
|
+
"",
|
|
479
|
+
"Shortcuts:",
|
|
480
|
+
" Ctrl+T - Toggle thinking on/off",
|
|
481
|
+
" T (in /model) - Toggle in model selector",
|
|
482
|
+
];
|
|
483
|
+
|
|
484
|
+
return success(lines.join("\n"));
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Parse state argument
|
|
488
|
+
const normalizedState = stateArg.toLowerCase().trim();
|
|
489
|
+
|
|
490
|
+
// Handle "mode" subcommand
|
|
491
|
+
if (normalizedState === "mode") {
|
|
492
|
+
const modeArg = ctx.parsedArgs.positional[1] as string | undefined;
|
|
493
|
+
const currentMode = getThinkingDisplayMode();
|
|
494
|
+
|
|
495
|
+
if (!modeArg) {
|
|
496
|
+
// Show current display mode
|
|
497
|
+
return success(
|
|
498
|
+
`🧠Thinking display mode: ${currentMode}\n` +
|
|
499
|
+
" /think mode full - Show full content\n" +
|
|
500
|
+
" /think mode compact - Show header only"
|
|
501
|
+
);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const normalizedMode = modeArg.toLowerCase().trim();
|
|
505
|
+
if (normalizedMode === "full" || normalizedMode === "compact") {
|
|
506
|
+
setDisplayMode(normalizedMode);
|
|
507
|
+
return success(`🧠Thinking display mode set to: ${normalizedMode}`);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
return error("INVALID_ARGUMENT", `Invalid display mode: ${modeArg}`, [
|
|
511
|
+
"Valid modes: full, compact",
|
|
512
|
+
"Example: /think mode compact",
|
|
513
|
+
]);
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
if (normalizedState === "on" || normalizedState === "1" || normalizedState === "true") {
|
|
517
|
+
setThinkingEnabled(true);
|
|
518
|
+
if (newBudget !== undefined) {
|
|
519
|
+
setThinkingBudget(newBudget);
|
|
520
|
+
}
|
|
521
|
+
const state = getThinkingState();
|
|
522
|
+
return success(
|
|
523
|
+
`🧠◆ Thinking mode enabled.\n Budget: ${formatBudget(state.budgetTokens)} tokens`
|
|
524
|
+
);
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
if (normalizedState === "off" || normalizedState === "0" || normalizedState === "false") {
|
|
528
|
+
setThinkingEnabled(false);
|
|
529
|
+
if (newBudget !== undefined) {
|
|
530
|
+
setThinkingBudget(newBudget);
|
|
531
|
+
}
|
|
532
|
+
return success("🧠◇ Thinking mode disabled.");
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
// Invalid state argument
|
|
536
|
+
return error("INVALID_ARGUMENT", `Invalid state: ${stateArg}`, [
|
|
537
|
+
"Valid states: on, off, mode",
|
|
538
|
+
"Example: /think on --budget 20000",
|
|
539
|
+
"Example: /think mode compact",
|
|
540
|
+
]);
|
|
541
|
+
},
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
// =============================================================================
|
|
545
|
+
// Export All Think Commands
|
|
546
|
+
// =============================================================================
|
|
547
|
+
|
|
548
|
+
/**
|
|
549
|
+
* All think-related slash commands for registration.
|
|
550
|
+
*/
|
|
551
|
+
export const thinkSlashCommands: SlashCommand[] = [thinkCommand];
|