@blackbox_ai/blackbox-cli 0.0.7 → 0.8.1
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/README.md +11 -183
- package/dist/index.js +8 -1
- package/dist/index.js.map +1 -1
- package/dist/package.json +13 -3
- package/dist/src/built-in-extensions/conductor/README.md +242 -0
- package/dist/src/built-in-extensions/conductor/blackbox-extension.json +5 -0
- package/dist/src/built-in-extensions/conductor/commands/conductor/implement.toml +170 -0
- package/dist/src/built-in-extensions/conductor/commands/conductor/newTrack.toml +142 -0
- package/dist/src/built-in-extensions/conductor/commands/conductor/revert.toml +122 -0
- package/dist/src/built-in-extensions/conductor/commands/conductor/setup.toml +424 -0
- package/dist/src/built-in-extensions/conductor/commands/conductor/status.toml +57 -0
- package/dist/src/built-in-extensions/conductor/templates/code_styleguides/general.md +23 -0
- package/dist/src/built-in-extensions/conductor/templates/code_styleguides/go.md +48 -0
- package/dist/src/built-in-extensions/conductor/templates/code_styleguides/html-css.md +49 -0
- package/dist/src/built-in-extensions/conductor/templates/code_styleguides/javascript.md +51 -0
- package/dist/src/built-in-extensions/conductor/templates/code_styleguides/python.md +37 -0
- package/dist/src/built-in-extensions/conductor/templates/code_styleguides/typescript.md +43 -0
- package/dist/src/built-in-extensions/conductor/templates/workflow.md +333 -0
- package/dist/src/built-in-extensions-data.d.ts +15 -0
- package/dist/src/built-in-extensions-data.js +61 -0
- package/dist/src/built-in-extensions-data.js.map +1 -0
- package/dist/src/commands/configure/ConfigureUI.d.ts +14 -0
- package/dist/src/commands/configure/ConfigureUI.js +556 -0
- package/dist/src/commands/configure/ConfigureUI.js.map +1 -0
- package/dist/src/commands/configure/index.d.ts +7 -0
- package/dist/src/commands/configure/index.js +62 -0
- package/dist/src/commands/configure/index.js.map +1 -0
- package/dist/src/commands/configure.d.ts +7 -0
- package/dist/src/commands/configure.js +276 -0
- package/dist/src/commands/configure.js.map +1 -0
- package/dist/src/commands/configure.test.d.ts +6 -0
- package/dist/src/commands/configure.test.js +32 -0
- package/dist/src/commands/configure.test.js.map +1 -0
- package/dist/src/commands/extensions/enable.js +1 -1
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/examples/context/CONTEXT.md +16 -0
- package/dist/src/commands/extensions/examples/context/blackbox-extension.json +5 -0
- package/dist/src/commands/extensions/examples/custom-commands/blackbox-extension.json +4 -0
- package/dist/src/commands/extensions/examples/custom-commands/commands/deploy.toml +12 -0
- package/dist/src/commands/extensions/examples/exclude-tools/README.md +28 -0
- package/dist/src/commands/extensions/examples/exclude-tools/blackbox-extension.json +5 -0
- package/dist/src/commands/extensions/install.d.ts +6 -2
- package/dist/src/commands/extensions/install.js +109 -15
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/link.d.ts +12 -0
- package/dist/src/commands/extensions/link.js +53 -0
- package/dist/src/commands/extensions/link.js.map +1 -0
- package/dist/src/commands/extensions/list.js +2 -2
- package/dist/src/commands/extensions/list.js.map +1 -1
- package/dist/src/commands/extensions/new.d.ts +13 -0
- package/dist/src/commands/extensions/new.js +145 -0
- package/dist/src/commands/extensions/new.js.map +1 -0
- package/dist/src/commands/extensions/settings.d.ts +18 -0
- package/dist/src/commands/extensions/settings.js +98 -0
- package/dist/src/commands/extensions/settings.js.map +1 -0
- package/dist/src/commands/extensions/update.d.ts +2 -1
- package/dist/src/commands/extensions/update.js +59 -10
- package/dist/src/commands/extensions/update.js.map +1 -1
- package/dist/src/commands/extensions/validate.d.ts +12 -0
- package/dist/src/commands/extensions/validate.js +72 -0
- package/dist/src/commands/extensions/validate.js.map +1 -0
- package/dist/src/commands/extensions.js +10 -1
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.d.ts +11 -0
- package/dist/src/commands/mcp/add.js +61 -7
- package/dist/src/commands/mcp/add.js.map +1 -1
- package/dist/src/commands/update.d.ts +7 -0
- package/dist/src/commands/update.js +103 -0
- package/dist/src/commands/update.js.map +1 -0
- package/dist/src/commands/voice.d.ts +7 -0
- package/dist/src/commands/voice.js +510 -0
- package/dist/src/commands/voice.js.map +1 -0
- package/dist/src/config/auth.d.ts +32 -1
- package/dist/src/config/auth.js +317 -2
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config.d.ts +7 -1
- package/dist/src/config/config.js +71 -10
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/extension.d.ts +6 -1
- package/dist/src/config/extension.js +137 -11
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extensions/github.d.ts +48 -0
- package/dist/src/config/extensions/github.js +308 -0
- package/dist/src/config/extensions/github.js.map +1 -0
- package/dist/src/config/keyBindings.d.ts +1 -0
- package/dist/src/config/keyBindings.js +3 -0
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/modelFetcher.d.ts +21 -0
- package/dist/src/config/modelFetcher.js +226 -0
- package/dist/src/config/modelFetcher.js.map +1 -0
- package/dist/src/config/settings.js +101 -0
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +626 -0
- package/dist/src/config/settingsSchema.js +626 -0
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/voice.d.ts +31 -0
- package/dist/src/config/voice.js +82 -0
- package/dist/src/config/voice.js.map +1 -0
- package/dist/src/encrypt/attestation.d.ts +5 -0
- package/dist/src/encrypt/attestation.js +100 -0
- package/dist/src/encrypt/attestation.js.map +1 -0
- package/dist/src/encrypt/bridge.d.ts +30 -0
- package/dist/src/encrypt/bridge.js +32 -0
- package/dist/src/encrypt/bridge.js.map +1 -0
- package/dist/src/encrypt/client.d.ts +14 -0
- package/dist/src/encrypt/client.js +133 -0
- package/dist/src/encrypt/client.js.map +1 -0
- package/dist/src/encrypt/config.d.ts +26 -0
- package/dist/src/encrypt/config.js +51 -0
- package/dist/src/encrypt/config.js.map +1 -0
- package/dist/src/encrypt/crypto-utils.d.ts +57 -0
- package/dist/src/encrypt/crypto-utils.js +257 -0
- package/dist/src/encrypt/crypto-utils.js.map +1 -0
- package/dist/src/encrypt/index.d.ts +12 -0
- package/dist/src/encrypt/index.js +13 -0
- package/dist/src/encrypt/index.js.map +1 -0
- package/dist/src/encrypt/retry-utils.d.ts +20 -0
- package/dist/src/encrypt/retry-utils.js +60 -0
- package/dist/src/encrypt/retry-utils.js.map +1 -0
- package/dist/src/encrypt/sessions.d.ts +17 -0
- package/dist/src/encrypt/sessions.js +221 -0
- package/dist/src/encrypt/sessions.js.map +1 -0
- package/dist/src/encrypt/streaming-client.d.ts +29 -0
- package/dist/src/encrypt/streaming-client.js +226 -0
- package/dist/src/encrypt/streaming-client.js.map +1 -0
- package/dist/src/encrypt/types.d.ts +81 -0
- package/dist/src/encrypt/types.js +2 -0
- package/dist/src/encrypt/types.js.map +1 -0
- package/dist/src/gemini.d.ts +1 -1
- package/dist/src/gemini.js +61 -28
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +3 -3
- package/dist/src/generated/git-commit.js +3 -3
- package/dist/src/nonInteractiveCli.d.ts +4 -0
- package/dist/src/nonInteractiveCli.js +563 -6
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/on-demand-extensions/README.md +266 -0
- package/dist/src/on-demand-extensions/git-helper/README.md +16 -0
- package/dist/src/on-demand-extensions/git-helper/blackbox-extension.json +5 -0
- package/dist/src/on-demand-extensions/git-helper/commands/git/branch-cleanup.toml +18 -0
- package/dist/src/on-demand-extensions/git-helper/commands/git/smart-commit.toml +22 -0
- package/dist/src/on-demand-extensions/greet/README.md +76 -0
- package/dist/src/on-demand-extensions/greet/blackbox-extension.json +5 -0
- package/dist/src/on-demand-extensions/greet/commands/greet/hello.toml +9 -0
- package/dist/src/on-demand-extensions/registry.json +251 -0
- package/dist/src/services/BuiltinCommandLoader.js +20 -2
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/EncryptedContentGenerator.d.ts +63 -0
- package/dist/src/services/EncryptedContentGenerator.js +426 -0
- package/dist/src/services/EncryptedContentGenerator.js.map +1 -0
- package/dist/src/services/McpCommandLoader.d.ts +24 -0
- package/dist/src/services/McpCommandLoader.js +50 -0
- package/dist/src/services/McpCommandLoader.js.map +1 -0
- package/dist/src/services/McpPromptLoader.js +17 -2
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/ReleaseNotesCache.d.ts +57 -0
- package/dist/src/services/ReleaseNotesCache.js +186 -0
- package/dist/src/services/ReleaseNotesCache.js.map +1 -0
- package/dist/src/services/elevenLabsErrors.d.ts +65 -0
- package/dist/src/services/elevenLabsErrors.js +233 -0
- package/dist/src/services/elevenLabsErrors.js.map +1 -0
- package/dist/src/services/elevenLabsService.d.ts +62 -0
- package/dist/src/services/elevenLabsService.js +186 -0
- package/dist/src/services/elevenLabsService.js.map +1 -0
- package/dist/src/services/elevenLabsStreamingService.d.ts +59 -0
- package/dist/src/services/elevenLabsStreamingService.js +202 -0
- package/dist/src/services/elevenLabsStreamingService.js.map +1 -0
- package/dist/src/services/elevenLabsTokenService.d.ts +21 -0
- package/dist/src/services/elevenLabsTokenService.js +42 -0
- package/dist/src/services/elevenLabsTokenService.js.map +1 -0
- package/dist/src/services/voiceInputHandler.d.ts +26 -0
- package/dist/src/services/voiceInputHandler.js +209 -0
- package/dist/src/services/voiceInputHandler.js.map +1 -0
- package/dist/src/services/voiceRecordingService.d.ts +69 -0
- package/dist/src/services/voiceRecordingService.js +397 -0
- package/dist/src/services/voiceRecordingService.js.map +1 -0
- package/dist/src/ui/App.d.ts +1 -0
- package/dist/src/ui/App.js +412 -63
- package/dist/src/ui/App.js.map +1 -1
- package/dist/src/ui/commands/browseExtensionsCommand.d.ts +7 -0
- package/dist/src/ui/commands/browseExtensionsCommand.js +16 -0
- package/dist/src/ui/commands/browseExtensionsCommand.js.map +1 -0
- package/dist/src/ui/commands/chatCommand.js +356 -16
- package/dist/src/ui/commands/chatCommand.js.map +1 -1
- package/dist/src/ui/commands/dbCommand.d.ts +7 -0
- package/dist/src/ui/commands/dbCommand.js +37 -0
- package/dist/src/ui/commands/dbCommand.js.map +1 -0
- package/dist/src/ui/commands/docsCommand.js +1 -1
- package/dist/src/ui/commands/docsCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +3 -2
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpInvokeCommand.d.ts +16 -0
- package/dist/src/ui/commands/mcpInvokeCommand.js +263 -0
- package/dist/src/ui/commands/mcpInvokeCommand.js.map +1 -0
- package/dist/src/ui/commands/modelCommand.js +79 -5
- package/dist/src/ui/commands/modelCommand.js.map +1 -1
- package/dist/src/ui/commands/multiAgentCommand.d.ts +7 -0
- package/dist/src/ui/commands/multiAgentCommand.js +833 -0
- package/dist/src/ui/commands/multiAgentCommand.js.map +1 -0
- package/dist/src/ui/commands/multiAgentConfigureCommand.d.ts +7 -0
- package/dist/src/ui/commands/multiAgentConfigureCommand.js +17 -0
- package/dist/src/ui/commands/multiAgentConfigureCommand.js.map +1 -0
- package/dist/src/ui/commands/quitCommand.js +71 -2
- package/dist/src/ui/commands/quitCommand.js.map +1 -1
- package/dist/src/ui/commands/releasesCommand.d.ts +7 -0
- package/dist/src/ui/commands/releasesCommand.js +16 -0
- package/dist/src/ui/commands/releasesCommand.js.map +1 -0
- package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
- package/dist/src/ui/commands/shellPermissionsCommand.d.ts +7 -0
- package/dist/src/ui/commands/shellPermissionsCommand.js +109 -0
- package/dist/src/ui/commands/shellPermissionsCommand.js.map +1 -0
- package/dist/src/ui/commands/skillCommand.d.ts +7 -0
- package/dist/src/ui/commands/skillCommand.js +240 -0
- package/dist/src/ui/commands/skillCommand.js.map +1 -0
- package/dist/src/ui/commands/statsCommand.js +243 -1
- package/dist/src/ui/commands/statsCommand.js.map +1 -1
- package/dist/src/ui/commands/tasksCommand.d.ts +7 -0
- package/dist/src/ui/commands/tasksCommand.js +535 -0
- package/dist/src/ui/commands/tasksCommand.js.map +1 -0
- package/dist/src/ui/commands/toolPermissionsCommand.d.ts +7 -0
- package/dist/src/ui/commands/toolPermissionsCommand.js +408 -0
- package/dist/src/ui/commands/toolPermissionsCommand.js.map +1 -0
- package/dist/src/ui/commands/types.d.ts +10 -2
- package/dist/src/ui/commands/types.js.map +1 -1
- package/dist/src/ui/commands/voiceCommand.d.ts +7 -0
- package/dist/src/ui/commands/voiceCommand.js +525 -0
- package/dist/src/ui/commands/voiceCommand.js.map +1 -0
- package/dist/src/ui/components/AuthDialog.d.ts +4 -2
- package/dist/src/ui/components/AuthDialog.js +349 -64
- package/dist/src/ui/components/AuthDialog.js.map +1 -1
- package/dist/src/ui/components/AuthInProgress.js +3 -1
- package/dist/src/ui/components/AuthInProgress.js.map +1 -1
- package/dist/src/ui/components/ExtensionsDialog.d.ts +11 -0
- package/dist/src/ui/components/ExtensionsDialog.js +303 -0
- package/dist/src/ui/components/ExtensionsDialog.js.map +1 -0
- package/dist/src/ui/components/GenericProviderKeyPrompt.d.ts +24 -0
- package/dist/src/ui/components/GenericProviderKeyPrompt.js +99 -0
- package/dist/src/ui/components/GenericProviderKeyPrompt.js.map +1 -0
- package/dist/src/ui/components/Header.js +10 -1
- package/dist/src/ui/components/Header.js.map +1 -1
- package/dist/src/ui/components/HistoryBrowserDialog.d.ts +15 -0
- package/dist/src/ui/components/HistoryBrowserDialog.js +166 -0
- package/dist/src/ui/components/HistoryBrowserDialog.js.map +1 -0
- package/dist/src/ui/components/HistoryItemDisplay.js +13 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +22 -8
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.d.ts +4 -0
- package/dist/src/ui/components/LoadingIndicator.js +16 -4
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +108 -16
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/ModelSelectionDialog.d.ts +2 -0
- package/dist/src/ui/components/ModelSelectionDialog.js +33 -4
- package/dist/src/ui/components/ModelSelectionDialog.js.map +1 -1
- package/dist/src/ui/components/ModelSelectionDialog.test.js +41 -4
- package/dist/src/ui/components/ModelSelectionDialog.test.js.map +1 -1
- package/dist/src/ui/components/ReleaseNotesDialog.d.ts +23 -0
- package/dist/src/ui/components/ReleaseNotesDialog.js +150 -0
- package/dist/src/ui/components/ReleaseNotesDialog.js.map +1 -0
- package/dist/src/ui/components/ReleaseNotesDisplay.d.ts +18 -0
- package/dist/src/ui/components/ReleaseNotesDisplay.js +14 -0
- package/dist/src/ui/components/ReleaseNotesDisplay.js.map +1 -0
- package/dist/src/ui/components/SessionSummaryDisplay.d.ts +2 -0
- package/dist/src/ui/components/SessionSummaryDisplay.js +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.d.ts +3 -1
- package/dist/src/ui/components/SettingsDialog.js +17 -7
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.d.ts +2 -0
- package/dist/src/ui/components/ShellConfirmationDialog.js +7 -3
- package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.d.ts +2 -0
- package/dist/src/ui/components/StatsDisplay.js +92 -7
- package/dist/src/ui/components/StatsDisplay.js.map +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js +6 -1
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.d.ts +3 -1
- package/dist/src/ui/components/ThemeDialog.js +5 -2
- package/dist/src/ui/components/ThemeDialog.js.map +1 -1
- package/dist/src/ui/components/Tips.js +1 -4
- package/dist/src/ui/components/Tips.js.map +1 -1
- package/dist/src/ui/components/TodoListDialog.d.ts +13 -0
- package/dist/src/ui/components/TodoListDialog.js +29 -0
- package/dist/src/ui/components/TodoListDialog.js.map +1 -0
- package/dist/src/ui/components/TodoListDialog.test.d.ts +6 -0
- package/dist/src/ui/components/TodoListDialog.test.js +60 -0
- package/dist/src/ui/components/TodoListDialog.test.js.map +1 -0
- package/dist/src/ui/components/VoiceConfigDialog.d.ts +17 -0
- package/dist/src/ui/components/VoiceConfigDialog.js +47 -0
- package/dist/src/ui/components/VoiceConfigDialog.js.map +1 -0
- package/dist/src/ui/components/messages/GeminiMessage.js +4 -0
- package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
- package/dist/src/ui/components/messages/GeminiMessageContent.js +4 -0
- package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.d.ts +2 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +96 -9
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +3 -3
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolMessage.test.js +9 -12
- package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
- package/dist/src/ui/components/multiagent/MultiAgentConfigDialog.d.ts +25 -0
- package/dist/src/ui/components/multiagent/MultiAgentConfigDialog.js +179 -0
- package/dist/src/ui/components/multiagent/MultiAgentConfigDialog.js.map +1 -0
- package/dist/src/ui/components/shared/RadioButtonSelect.d.ts +3 -1
- package/dist/src/ui/components/shared/RadioButtonSelect.js +57 -18
- package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
- package/dist/src/ui/components/shared/TextInput.d.ts +2 -1
- package/dist/src/ui/components/shared/TextInput.js +5 -2
- package/dist/src/ui/components/shared/TextInput.js.map +1 -1
- package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.js +3 -3
- package/dist/src/ui/components/subagents/runtime/AgentExecutionDisplay.js.map +1 -1
- package/dist/src/ui/constants.d.ts +3 -3
- package/dist/src/ui/constants.js +3 -3
- package/dist/src/ui/constants.js.map +1 -1
- package/dist/src/ui/contexts/SessionContext.d.ts +6 -0
- package/dist/src/ui/contexts/SessionContext.js +24 -2
- package/dist/src/ui/contexts/SessionContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +139 -57
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.d.ts +2 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +189 -17
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useAdaptiveStream.d.ts +42 -0
- package/dist/src/ui/hooks/useAdaptiveStream.js +31 -0
- package/dist/src/ui/hooks/useAdaptiveStream.js.map +1 -0
- package/dist/src/ui/hooks/useAtCompletion.js +20 -4
- package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useAuthCommand.d.ts +2 -2
- package/dist/src/ui/hooks/useAuthCommand.js +99 -5
- package/dist/src/ui/hooks/useAuthCommand.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.js +14 -10
- package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useDialogClose.d.ts +10 -0
- package/dist/src/ui/hooks/useDialogClose.js +25 -0
- package/dist/src/ui/hooks/useDialogClose.js.map +1 -1
- package/dist/src/ui/hooks/useDialogCloseAnimation.d.ts +22 -0
- package/dist/src/ui/hooks/useDialogCloseAnimation.js +68 -0
- package/dist/src/ui/hooks/useDialogCloseAnimation.js.map +1 -0
- package/dist/src/ui/hooks/useEncryptedStream.d.ts +22 -0
- package/dist/src/ui/hooks/useEncryptedStream.js +378 -0
- package/dist/src/ui/hooks/useEncryptedStream.js.map +1 -0
- package/dist/src/ui/hooks/useExtensionsDialog.d.ts +10 -0
- package/dist/src/ui/hooks/useExtensionsDialog.js +21 -0
- package/dist/src/ui/hooks/useExtensionsDialog.js.map +1 -0
- package/dist/src/ui/hooks/useGeminiStream.js +6 -2
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.d.ts +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.js +3 -2
- package/dist/src/ui/hooks/useLoadingIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +27 -5
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useMultiAgentConfigCommand.d.ts +10 -0
- package/dist/src/ui/hooks/useMultiAgentConfigCommand.js +21 -0
- package/dist/src/ui/hooks/useMultiAgentConfigCommand.js.map +1 -0
- package/dist/src/ui/hooks/useReleasesDialog.d.ts +20 -0
- package/dist/src/ui/hooks/useReleasesDialog.js +214 -0
- package/dist/src/ui/hooks/useReleasesDialog.js.map +1 -0
- package/dist/src/ui/hooks/useSlashCompletion.js +10 -8
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useTodoList.d.ts +17 -0
- package/dist/src/ui/hooks/useTodoList.js +51 -0
- package/dist/src/ui/hooks/useTodoList.js.map +1 -0
- package/dist/src/ui/keyMatchers.test.js +6 -0
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/themes/blackbox-dark.js +1 -1
- package/dist/src/ui/themes/blackbox-dark.js.map +1 -1
- package/dist/src/ui/themes/blackbox-light.js +1 -1
- package/dist/src/ui/themes/blackbox-light.js.map +1 -1
- package/dist/src/ui/types.d.ts +15 -2
- package/dist/src/ui/types.js +1 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/computeStats.d.ts +25 -1
- package/dist/src/ui/utils/computeStats.js +58 -1
- package/dist/src/ui/utils/computeStats.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.js +37 -54
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/utils/backgroundUpdateCheck.d.ts +15 -0
- package/dist/src/utils/backgroundUpdateCheck.js +48 -0
- package/dist/src/utils/backgroundUpdateCheck.js.map +1 -0
- package/dist/src/utils/gitAutoDetect.d.ts +16 -0
- package/dist/src/utils/gitAutoDetect.js +45 -0
- package/dist/src/utils/gitAutoDetect.js.map +1 -0
- package/dist/src/utils/installationInfo.d.ts +1 -0
- package/dist/src/utils/installationInfo.js +24 -4
- package/dist/src/utils/installationInfo.js.map +1 -1
- package/dist/src/utils/preLaunchUpdateCheck.d.ts +17 -0
- package/dist/src/utils/preLaunchUpdateCheck.js +75 -0
- package/dist/src/utils/preLaunchUpdateCheck.js.map +1 -0
- package/dist/src/utils/version.js +12 -1
- package/dist/src/utils/version.js.map +1 -1
- package/dist/src/utils/versionStorage.d.ts +50 -0
- package/dist/src/utils/versionStorage.js +224 -0
- package/dist/src/utils/versionStorage.js.map +1 -0
- package/dist/src/validateNonInterActiveAuth.js +10 -3
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/src/virtual-extensions.d.ts +14 -0
- package/dist/src/virtual-extensions.js +56 -0
- package/dist/src/virtual-extensions.js.map +1 -0
- package/dist/src/zed-integration/fileSystemService.d.ts +3 -3
- package/dist/src/zed-integration/fileSystemService.js +5 -7
- package/dist/src/zed-integration/fileSystemService.js.map +1 -1
- package/dist/src/zed-integration/zedIntegration.js +62 -17
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +13 -3
- package/dist/src/utils/handleAutoUpdate.d.ts +0 -11
- package/dist/src/utils/handleAutoUpdate.js +0 -102
- package/dist/src/utils/handleAutoUpdate.js.map +0 -1
- package/dist/src/utils/updateEventEmitter.d.ts +0 -11
- package/dist/src/utils/updateEventEmitter.js +0 -12
- package/dist/src/utils/updateEventEmitter.js.map +0 -1
- package/dist/src/zed-integration/acp.d.ts +0 -63
- package/dist/src/zed-integration/acp.js +0 -226
- package/dist/src/zed-integration/acp.js.map +0 -1
- package/dist/src/zed-integration/schema.d.ts +0 -11782
- package/dist/src/zed-integration/schema.js +0 -311
- package/dist/src/zed-integration/schema.js.map +0 -1
|
@@ -3,10 +3,420 @@
|
|
|
3
3
|
* Copyright 2025 Google LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import { executeToolCall, shutdownTelemetry, isTelemetrySdkInitialized, GeminiEventType, parseAndFormatApiError, FatalInputError, FatalTurnLimitedError, } from '@blackbox_ai/blackbox-cli-core';
|
|
6
|
+
import { executeToolCall, shutdownTelemetry, isTelemetrySdkInitialized, GeminiEventType, parseAndFormatApiError, FatalInputError, FatalTurnLimitedError, Logger, decodeTagName, CheckpointApiService, } from '@blackbox_ai/blackbox-cli-core';
|
|
7
|
+
import { FinishReason } from '@google/genai';
|
|
8
|
+
import * as fsPromises from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
7
10
|
import { ConsolePatcher } from './ui/utils/ConsolePatcher.js';
|
|
8
11
|
import { handleAtCommand } from './ui/hooks/atCommandProcessor.js';
|
|
12
|
+
// Minimal ANSI color helpers (avoid extra deps; disable when not a TTY or NO_COLOR=1)
|
|
13
|
+
const USE_COLOR = Boolean(process.stdout.isTTY) && process.env['NO_COLOR'] !== '1';
|
|
14
|
+
const ansi = (open, close) => (s) => USE_COLOR ? `\u001b[${open}m${s}\u001b[${close}m` : s;
|
|
15
|
+
const bold = ansi(1, 22);
|
|
16
|
+
const dim = ansi(2, 22);
|
|
17
|
+
const red = ansi(31, 39);
|
|
18
|
+
const green = ansi(32, 39);
|
|
19
|
+
const yellow = ansi(33, 39);
|
|
20
|
+
const blue = ansi(34, 39);
|
|
21
|
+
const magenta = ansi(35, 39);
|
|
22
|
+
const cyan = ansi(36, 39);
|
|
23
|
+
const gray = ansi(90, 39);
|
|
24
|
+
function printInfoToStderr(prefix, message) {
|
|
25
|
+
console.error(`${prefix} ${message}`);
|
|
26
|
+
}
|
|
27
|
+
function printToolSectionToStdout(toolName, content) {
|
|
28
|
+
const columns = Math.max(30, Math.min(100, process.stdout.columns || 80));
|
|
29
|
+
const horizontal = '─'.repeat(columns - 2);
|
|
30
|
+
const top = USE_COLOR
|
|
31
|
+
? cyan(`┌${horizontal}┐`)
|
|
32
|
+
: `┌${horizontal}┐`;
|
|
33
|
+
const bottom = USE_COLOR
|
|
34
|
+
? cyan(`└${horizontal}┘`)
|
|
35
|
+
: `└${horizontal}┘`;
|
|
36
|
+
const title = `${bold(cyan('Tool'))} ${bold(magenta(toolName))}`;
|
|
37
|
+
const titleLine = `│ ${title}${' '.repeat(Math.max(0, columns - 3 - title.length))}│`;
|
|
38
|
+
const lines = content.split(/\r?\n/);
|
|
39
|
+
const body = lines
|
|
40
|
+
.map((line) => {
|
|
41
|
+
const safe = line.replace(/\t/g, ' ');
|
|
42
|
+
const visibleLen = safe.length; // best-effort; we avoid nested ANSI here
|
|
43
|
+
const padding = Math.max(0, columns - 3 - visibleLen);
|
|
44
|
+
return `│ ${safe}${' '.repeat(padding)}│`;
|
|
45
|
+
})
|
|
46
|
+
.join('\n');
|
|
47
|
+
process.stdout.write(`\n${top}\n${titleLine}\n${gray(`│${' '.repeat(columns - 2)}│`)}\n${body}\n${bottom}\n`);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Formats tool result display for clean, user-friendly output.
|
|
51
|
+
* Handles different result types similar to the interactive mode.
|
|
52
|
+
*/
|
|
53
|
+
function formatToolResultDisplay(resultDisplay) {
|
|
54
|
+
if (!resultDisplay) {
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
// Handle string results with truncation for very long outputs
|
|
58
|
+
if (typeof resultDisplay === 'string') {
|
|
59
|
+
const MAX_STRING_LENGTH = 2000;
|
|
60
|
+
if (resultDisplay.length > MAX_STRING_LENGTH) {
|
|
61
|
+
const truncated = resultDisplay.substring(0, MAX_STRING_LENGTH);
|
|
62
|
+
const remaining = resultDisplay.length - MAX_STRING_LENGTH;
|
|
63
|
+
return `${truncated}\n\n${dim(`... (${remaining} more characters truncated)`)}`;
|
|
64
|
+
}
|
|
65
|
+
return resultDisplay;
|
|
66
|
+
}
|
|
67
|
+
// Handle object results
|
|
68
|
+
if (typeof resultDisplay === 'object' && resultDisplay !== null) {
|
|
69
|
+
// Check for FileDiff (write_file, edit_file results)
|
|
70
|
+
if ('fileDiff' in resultDisplay && 'fileName' in resultDisplay) {
|
|
71
|
+
const result = resultDisplay;
|
|
72
|
+
let summary = `${bold('File:')} ${result.fileName}\n`;
|
|
73
|
+
// Parse the diff to show visual changes
|
|
74
|
+
const diffLines = result.fileDiff.split('\n');
|
|
75
|
+
const addedLines = [];
|
|
76
|
+
const removedLines = [];
|
|
77
|
+
for (const line of diffLines) {
|
|
78
|
+
if (line.startsWith('+') && !line.startsWith('+++')) {
|
|
79
|
+
const content = line.substring(1);
|
|
80
|
+
// Skip empty lines that are just formatting
|
|
81
|
+
if (content.trim().length > 0) {
|
|
82
|
+
addedLines.push(content);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
else if (line.startsWith('-') && !line.startsWith('---')) {
|
|
86
|
+
const content = line.substring(1);
|
|
87
|
+
// Skip empty lines that are just formatting
|
|
88
|
+
if (content.trim().length > 0) {
|
|
89
|
+
removedLines.push(content);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
// Show change statistics - use actual parsed lines, not diffStat which includes markers
|
|
94
|
+
const totalAdded = addedLines.length;
|
|
95
|
+
const totalRemoved = removedLines.length;
|
|
96
|
+
if (totalAdded > 0 || totalRemoved > 0) {
|
|
97
|
+
summary += `${bold('Changes:')} `;
|
|
98
|
+
if (totalRemoved > 0)
|
|
99
|
+
summary += `${red(`-${totalRemoved} lines`)} `;
|
|
100
|
+
if (totalAdded > 0)
|
|
101
|
+
summary += `${green(`+${totalAdded} lines`)}`;
|
|
102
|
+
summary += '\n\n';
|
|
103
|
+
}
|
|
104
|
+
// Show visual diff (deletions and additions)
|
|
105
|
+
const MAX_DIFF_LINES = 15;
|
|
106
|
+
let diffDisplay = '';
|
|
107
|
+
if (removedLines.length > 0) {
|
|
108
|
+
diffDisplay += `${bold(red('Removed:'))}\n`;
|
|
109
|
+
const linesToShow = removedLines.slice(0, MAX_DIFF_LINES);
|
|
110
|
+
for (const line of linesToShow) {
|
|
111
|
+
diffDisplay += `${red('- ' + line)}\n`;
|
|
112
|
+
}
|
|
113
|
+
if (removedLines.length > MAX_DIFF_LINES) {
|
|
114
|
+
diffDisplay += `${dim(`... (${removedLines.length - MAX_DIFF_LINES} more lines removed)`)}\n`;
|
|
115
|
+
}
|
|
116
|
+
diffDisplay += '\n';
|
|
117
|
+
}
|
|
118
|
+
if (addedLines.length > 0) {
|
|
119
|
+
diffDisplay += `${bold(green('Added:'))}\n`;
|
|
120
|
+
const linesToShow = addedLines.slice(0, MAX_DIFF_LINES);
|
|
121
|
+
for (const line of linesToShow) {
|
|
122
|
+
diffDisplay += `${green('+ ' + line)}\n`;
|
|
123
|
+
}
|
|
124
|
+
if (addedLines.length > MAX_DIFF_LINES) {
|
|
125
|
+
diffDisplay += `${dim(`... (${addedLines.length - MAX_DIFF_LINES} more lines added)`)}\n`;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
if (diffDisplay) {
|
|
129
|
+
summary += diffDisplay;
|
|
130
|
+
}
|
|
131
|
+
else if (result.newContent) {
|
|
132
|
+
// Fallback: show content preview if no diff lines parsed
|
|
133
|
+
const MAX_CONTENT_PREVIEW = 300;
|
|
134
|
+
if (result.newContent.length < MAX_CONTENT_PREVIEW) {
|
|
135
|
+
summary += `${bold('Content:')}\n${dim(result.newContent)}`;
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
const preview = result.newContent.substring(0, MAX_CONTENT_PREVIEW);
|
|
139
|
+
const remaining = result.newContent.length - MAX_CONTENT_PREVIEW;
|
|
140
|
+
summary += `${bold('Content preview:')}\n${dim(preview)}\n${dim(`... (${remaining} more characters)`)}`;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return summary.trim();
|
|
144
|
+
}
|
|
145
|
+
// Check for todo_list results
|
|
146
|
+
if ('type' in resultDisplay && resultDisplay.type === 'todo_list') {
|
|
147
|
+
const todoResult = resultDisplay;
|
|
148
|
+
let output = `${bold('TODO List:')}\n`;
|
|
149
|
+
if (Array.isArray(todoResult.todos)) {
|
|
150
|
+
const MAX_TODOS = 20;
|
|
151
|
+
const todosToShow = todoResult.todos.slice(0, MAX_TODOS);
|
|
152
|
+
todosToShow.forEach((todo) => {
|
|
153
|
+
// Use status icons matching the UI
|
|
154
|
+
const statusIcon = {
|
|
155
|
+
pending: '○',
|
|
156
|
+
in_progress: '◐',
|
|
157
|
+
completed: '●',
|
|
158
|
+
}[todo.status] || '○';
|
|
159
|
+
const checkbox = todo.status === 'completed' ? '[✓]' : '[ ]';
|
|
160
|
+
output += `${checkbox} ${statusIcon} ${todo.content}\n`;
|
|
161
|
+
});
|
|
162
|
+
if (todoResult.todos.length > MAX_TODOS) {
|
|
163
|
+
output += `${dim(`... (${todoResult.todos.length - MAX_TODOS} more todos)`)}`;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return output.trim();
|
|
167
|
+
}
|
|
168
|
+
// Check for task_execution (subagent) results
|
|
169
|
+
if ('type' in resultDisplay && resultDisplay.type === 'task_execution') {
|
|
170
|
+
const taskResult = resultDisplay;
|
|
171
|
+
let output = `${bold(cyan('Subagent:'))} ${magenta(taskResult.subagentName)}\n`;
|
|
172
|
+
output += `${bold('Task:')} ${taskResult.taskDescription}\n`;
|
|
173
|
+
output += `${bold('Status:')} ${taskResult.status}\n`;
|
|
174
|
+
if (taskResult.result) {
|
|
175
|
+
const MAX_RESULT_LENGTH = 1000;
|
|
176
|
+
if (taskResult.result.length > MAX_RESULT_LENGTH) {
|
|
177
|
+
const truncated = taskResult.result.substring(0, MAX_RESULT_LENGTH);
|
|
178
|
+
const remaining = taskResult.result.length - MAX_RESULT_LENGTH;
|
|
179
|
+
output += `${bold('Result:')}\n${truncated}\n${dim(`... (${remaining} more characters)`)}`;
|
|
180
|
+
}
|
|
181
|
+
else {
|
|
182
|
+
output += `${bold('Result:')}\n${taskResult.result}`;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return output;
|
|
186
|
+
}
|
|
187
|
+
// Check for plan_summary results
|
|
188
|
+
if ('type' in resultDisplay && resultDisplay.type === 'plan_summary') {
|
|
189
|
+
const planResult = resultDisplay;
|
|
190
|
+
return `${bold(planResult.message)}\n\n${planResult.plan}`;
|
|
191
|
+
}
|
|
192
|
+
// For other objects, show a clean summary instead of raw JSON
|
|
193
|
+
// Extract key information if available
|
|
194
|
+
const obj = resultDisplay;
|
|
195
|
+
if ('message' in obj && typeof obj['message'] === 'string') {
|
|
196
|
+
const msg = obj['message'];
|
|
197
|
+
if (msg.length > 1000) {
|
|
198
|
+
return msg.substring(0, 1000) + dim('\n... (truncated)');
|
|
199
|
+
}
|
|
200
|
+
return msg;
|
|
201
|
+
}
|
|
202
|
+
if ('result' in obj && typeof obj['result'] === 'string') {
|
|
203
|
+
const res = obj['result'];
|
|
204
|
+
if (res.length > 1000) {
|
|
205
|
+
return res.substring(0, 1000) + dim('\n... (truncated)');
|
|
206
|
+
}
|
|
207
|
+
return res;
|
|
208
|
+
}
|
|
209
|
+
if ('output' in obj && typeof obj['output'] === 'string') {
|
|
210
|
+
const out = obj['output'];
|
|
211
|
+
if (out.length > 1000) {
|
|
212
|
+
return out.substring(0, 1000) + dim('\n... (truncated)');
|
|
213
|
+
}
|
|
214
|
+
return out;
|
|
215
|
+
}
|
|
216
|
+
// Last resort: show formatted JSON but only for small objects
|
|
217
|
+
const jsonStr = JSON.stringify(resultDisplay, null, 2);
|
|
218
|
+
const MAX_JSON_LENGTH = 500;
|
|
219
|
+
if (jsonStr.length < MAX_JSON_LENGTH) {
|
|
220
|
+
return jsonStr;
|
|
221
|
+
}
|
|
222
|
+
// For large objects, show a summary
|
|
223
|
+
return `${bold('Result:')} ${dim('[Complex object with ' + Object.keys(obj).length + ' properties - output truncated]')}`;
|
|
224
|
+
}
|
|
225
|
+
return String(resultDisplay);
|
|
226
|
+
}
|
|
227
|
+
function printPlanSectionToStderr(toolName, planDescription, argsJsonPretty) {
|
|
228
|
+
const columns = Math.max(30, Math.min(100, process.stderr.columns || process.stdout.columns || 80));
|
|
229
|
+
const horizontal = '─'.repeat(columns - 2);
|
|
230
|
+
const top = USE_COLOR ? yellow(`┌${horizontal}┐`) : `┌${horizontal}┐`;
|
|
231
|
+
const bottom = USE_COLOR ? yellow(`└${horizontal}┘`) : `└${horizontal}┘`;
|
|
232
|
+
const title = `${bold(yellow('Tool'))} ${bold(magenta(toolName))}`;
|
|
233
|
+
const titleLine = `│ ${title}${' '.repeat(Math.max(0, columns - 3 - title.length))}│`;
|
|
234
|
+
const bodyLines = [`${bold('Description:')}`, planDescription || '(none)', '', `${bold('Invocation payload:')}`, argsJsonPretty];
|
|
235
|
+
const body = bodyLines
|
|
236
|
+
.flatMap((line) => (line.includes('\n') ? line.split(/\r?\n/) : [line]))
|
|
237
|
+
.map((line) => {
|
|
238
|
+
const safe = line.replace(/\t/g, ' ');
|
|
239
|
+
const visibleLen = safe.length;
|
|
240
|
+
const padding = Math.max(0, columns - 3 - visibleLen);
|
|
241
|
+
return `│ ${safe}${' '.repeat(padding)}│`;
|
|
242
|
+
})
|
|
243
|
+
.join('\n');
|
|
244
|
+
process.stderr.write(`\n${top}\n${titleLine}\n${gray(`│${' '.repeat(columns - 2)}│`)}\n${body}\n${bottom}\n`);
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Lists all available checkpoints and exits
|
|
248
|
+
*/
|
|
249
|
+
export async function listCheckpoints(config) {
|
|
250
|
+
try {
|
|
251
|
+
const geminiDir = config.storage?.getProjectTempDir();
|
|
252
|
+
if (!geminiDir) {
|
|
253
|
+
printInfoToStderr(red('✖ Error'), 'Could not determine the .blackboxcli directory path.');
|
|
254
|
+
process.exit(1);
|
|
255
|
+
}
|
|
256
|
+
const file_head = 'checkpoint-';
|
|
257
|
+
const file_tail = '.json';
|
|
258
|
+
const files = await fsPromises.readdir(geminiDir);
|
|
259
|
+
const checkpoints = [];
|
|
260
|
+
for (const file of files) {
|
|
261
|
+
if (file.startsWith(file_head) && file.endsWith(file_tail)) {
|
|
262
|
+
const filePath = path.join(geminiDir, file);
|
|
263
|
+
const stats = await fsPromises.stat(filePath);
|
|
264
|
+
const tagName = file.slice(file_head.length, -file_tail.length);
|
|
265
|
+
checkpoints.push({
|
|
266
|
+
name: decodeTagName(tagName),
|
|
267
|
+
mtime: stats.mtime,
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
if (checkpoints.length === 0) {
|
|
272
|
+
console.log('No saved conversation checkpoints found.');
|
|
273
|
+
process.exit(0);
|
|
274
|
+
}
|
|
275
|
+
// Sort by modification time (newest first)
|
|
276
|
+
checkpoints.sort((a, b) => b.mtime.getTime() - a.mtime.getTime());
|
|
277
|
+
const maxNameLength = Math.max(...checkpoints.map((cp) => cp.name.length));
|
|
278
|
+
console.log('Available conversation checkpoints:\n');
|
|
279
|
+
for (const checkpoint of checkpoints) {
|
|
280
|
+
const paddedName = checkpoint.name.padEnd(maxNameLength, ' ');
|
|
281
|
+
const isoString = checkpoint.mtime.toISOString();
|
|
282
|
+
const match = isoString.match(/(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})/);
|
|
283
|
+
const formattedDate = match ? `${match[1]} ${match[2]}` : 'Invalid Date';
|
|
284
|
+
console.log(` ${cyan(paddedName)} ${gray(`(saved on ${formattedDate})`)}`);
|
|
285
|
+
}
|
|
286
|
+
console.log(`\n${gray('Resume with:')} ${cyan('blackbox --resume-checkpoint "<tag>" --prompt "<new-task>"')}`);
|
|
287
|
+
process.exit(0);
|
|
288
|
+
}
|
|
289
|
+
catch (error) {
|
|
290
|
+
printInfoToStderr(red('✖ Error'), `Failed to list checkpoints: ${error instanceof Error ? error.message : String(error)}`);
|
|
291
|
+
process.exit(1);
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Resumes conversation from a checkpoint
|
|
296
|
+
* Supports both local and cloud checkpoints (from Supabase database)
|
|
297
|
+
*/
|
|
298
|
+
async function resumeFromCheckpoint(config, tag) {
|
|
299
|
+
try {
|
|
300
|
+
const logger = new Logger(config.getSessionId(), config.storage);
|
|
301
|
+
await logger.initialize();
|
|
302
|
+
// Try loading from local storage first
|
|
303
|
+
let conversation = await logger.loadCheckpoint(tag);
|
|
304
|
+
// If not found locally and should check cloud (starts with "cloud-" or is a 21-char ID), try fetching from database
|
|
305
|
+
if (conversation.length === 0 && (tag.startsWith('cloud-') || (tag.length === 21 && /^[a-zA-Z0-9_-]+$/.test(tag)))) {
|
|
306
|
+
try {
|
|
307
|
+
const apiService = new CheckpointApiService();
|
|
308
|
+
// Check if API key is configured
|
|
309
|
+
if (!apiService.isConfigured()) {
|
|
310
|
+
printInfoToStderr(yellow('⚠ Warning'), 'Blackbox API key not configured. Set BLACKBOX_API_KEY environment variable to restore checkpoints.');
|
|
311
|
+
printInfoToStderr(red('✖ Error'), `No saved checkpoint found with tag: ${decodeTagName(tag)}`);
|
|
312
|
+
process.exit(1);
|
|
313
|
+
}
|
|
314
|
+
// Fetch checkpoint from API
|
|
315
|
+
printInfoToStderr(dim('→ Restoring'), 'checkpoint from database...');
|
|
316
|
+
const checkpoint = await apiService.fetchCheckpointByTag(tag);
|
|
317
|
+
if (!checkpoint || !checkpoint.content) {
|
|
318
|
+
printInfoToStderr(yellow('⚠ Warning'), `Checkpoint not found: ${decodeTagName(tag)}`);
|
|
319
|
+
printInfoToStderr(red('✖ Error'), `No saved checkpoint found with tag: ${decodeTagName(tag)}`);
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
// Save the fetched checkpoint to local filesystem
|
|
323
|
+
await logger.saveCheckpointFromDatabase(tag, checkpoint.content);
|
|
324
|
+
// Load the checkpoint from local filesystem
|
|
325
|
+
conversation = await logger.loadCheckpoint(tag);
|
|
326
|
+
if (conversation.length === 0) {
|
|
327
|
+
printInfoToStderr(red('✖ Error'), 'Failed to load checkpoint');
|
|
328
|
+
process.exit(1);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
catch (apiError) {
|
|
332
|
+
// Log API error but don't expose sensitive details
|
|
333
|
+
if (config.getDebugMode()) {
|
|
334
|
+
console.error('API error details:', apiError);
|
|
335
|
+
}
|
|
336
|
+
printInfoToStderr(red('✖ Error'), `Failed to fetch checkpoint: ${apiError instanceof Error ? apiError.message : 'Unknown error'}`);
|
|
337
|
+
process.exit(1);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
// Final check if checkpoint was found
|
|
341
|
+
if (conversation.length === 0) {
|
|
342
|
+
printInfoToStderr(red('✖ Error'), `No saved checkpoint found with tag: ${decodeTagName(tag)}`);
|
|
343
|
+
process.exit(1);
|
|
344
|
+
}
|
|
345
|
+
// Restore the conversation history to the Gemini client
|
|
346
|
+
const geminiClient = config.getGeminiClient();
|
|
347
|
+
if (geminiClient && geminiClient.isInitialized()) {
|
|
348
|
+
geminiClient.setHistory(conversation);
|
|
349
|
+
printInfoToStderr(green('✓ Checkpoint restored:'), `${bold(decodeTagName(tag))} ${dim('(continuing conversation)')}`);
|
|
350
|
+
}
|
|
351
|
+
else {
|
|
352
|
+
printInfoToStderr(red('✖ Error'), 'Gemini client not initialized');
|
|
353
|
+
process.exit(1);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
catch (error) {
|
|
357
|
+
printInfoToStderr(red('✖ Error'), `Failed to resume checkpoint: ${error instanceof Error ? error.message : String(error)}`);
|
|
358
|
+
process.exit(1);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
/**
|
|
362
|
+
* Generates a safe, unique checkpoint name using UUID and timestamp
|
|
363
|
+
*/
|
|
364
|
+
function generateCheckpointName() {
|
|
365
|
+
// Generate a simple UUID-like string (8 characters)
|
|
366
|
+
const uuid = Math.random().toString(36).substring(2, 10);
|
|
367
|
+
// Generate timestamp
|
|
368
|
+
const now = new Date();
|
|
369
|
+
const timestamp = now.toISOString()
|
|
370
|
+
.replace(/[:.]/g, '-')
|
|
371
|
+
.replace('T', '-')
|
|
372
|
+
.substring(0, 19); // YYYY-MM-DD-HH-MM-SS
|
|
373
|
+
return `task-${uuid}-${timestamp}`;
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Saves conversation checkpoint after successful task completion in non-interactive mode
|
|
377
|
+
*/
|
|
378
|
+
async function saveConversationCheckpoint(config, originalInput, customTag) {
|
|
379
|
+
try {
|
|
380
|
+
const chat = config.getGeminiClient()?.getChat();
|
|
381
|
+
if (!chat)
|
|
382
|
+
return;
|
|
383
|
+
const history = chat.getHistory();
|
|
384
|
+
if (history.length <= 2)
|
|
385
|
+
return; // No meaningful conversation
|
|
386
|
+
const logger = new Logger(config.getSessionId(), config.storage);
|
|
387
|
+
await logger.initialize();
|
|
388
|
+
let tag;
|
|
389
|
+
if (customTag) {
|
|
390
|
+
tag = customTag;
|
|
391
|
+
}
|
|
392
|
+
else {
|
|
393
|
+
// Generate safe, unique tag
|
|
394
|
+
tag = generateCheckpointName();
|
|
395
|
+
}
|
|
396
|
+
await logger.saveCheckpoint(history, tag);
|
|
397
|
+
// Get the full path to the checkpoint file
|
|
398
|
+
const checkpointDir = config.storage?.getProjectTempDir();
|
|
399
|
+
const checkpointPath = checkpointDir ? path.join(checkpointDir, `checkpoint-${tag}.json`) : `checkpoint-${tag}.json`;
|
|
400
|
+
printInfoToStderr(green('✓ Checkpoint saved:'), `${bold(tag)}\n ${dim('- Path:')} ${checkpointPath}\n ${dim('- Resume with:')} ${cyan(`blackbox`)} ${dim('then')} ${cyan(`/chat resume "${tag}"`)}`);
|
|
401
|
+
}
|
|
402
|
+
catch (error) {
|
|
403
|
+
// Don't fail the main task if checkpoint saving fails
|
|
404
|
+
if (config.getDebugMode()) {
|
|
405
|
+
printInfoToStderr(yellow('⚠ Checkpoint save failed:'), error instanceof Error ? error.message : String(error));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
9
409
|
export async function runNonInteractive(config, input, prompt_id) {
|
|
410
|
+
// Handle list checkpoints command
|
|
411
|
+
if (config.getListCheckpoints()) {
|
|
412
|
+
await listCheckpoints(config);
|
|
413
|
+
return;
|
|
414
|
+
}
|
|
415
|
+
// Handle resume checkpoint
|
|
416
|
+
const resumeTag = config.getResumeCheckpoint();
|
|
417
|
+
if (resumeTag) {
|
|
418
|
+
await resumeFromCheckpoint(config, resumeTag);
|
|
419
|
+
}
|
|
10
420
|
const consolePatcher = new ConsolePatcher({
|
|
11
421
|
stderr: true,
|
|
12
422
|
debugMode: config.getDebugMode(),
|
|
@@ -52,21 +462,164 @@ export async function runNonInteractive(config, input, prompt_id) {
|
|
|
52
462
|
console.error('Operation cancelled.');
|
|
53
463
|
return;
|
|
54
464
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
465
|
+
switch (event.type) {
|
|
466
|
+
case GeminiEventType.Content: {
|
|
467
|
+
process.stdout.write(event.value);
|
|
468
|
+
break;
|
|
469
|
+
}
|
|
470
|
+
case GeminiEventType.ToolCallRequest: {
|
|
471
|
+
toolCallRequests.push(event.value);
|
|
472
|
+
break;
|
|
473
|
+
}
|
|
474
|
+
case GeminiEventType.Thought: {
|
|
475
|
+
// Keep agent "thoughts" off stdout so piping remains clean
|
|
476
|
+
printInfoToStderr(cyan('ℹ Thought:'), `${bold(event.value.subject)} ${dim('-')} ${event.value.description}`);
|
|
477
|
+
break;
|
|
478
|
+
}
|
|
479
|
+
case GeminiEventType.Retry: {
|
|
480
|
+
printInfoToStderr(yellow('↻ Retrying'), dim('request...'));
|
|
481
|
+
break;
|
|
482
|
+
}
|
|
483
|
+
case GeminiEventType.ChatCompressed: {
|
|
484
|
+
printInfoToStderr(blue('ℹ Compression'), `Using compressed context (${event.value?.originalTokenCount ?? 'unknown'} → ${event.value?.newTokenCount ?? 'unknown'} tokens).`);
|
|
485
|
+
break;
|
|
486
|
+
}
|
|
487
|
+
case GeminiEventType.MaxSessionTurns: {
|
|
488
|
+
printInfoToStderr(yellow('⚠ Max turns'), 'Reached max session turns.');
|
|
489
|
+
return;
|
|
490
|
+
}
|
|
491
|
+
case GeminiEventType.SessionTokenLimitExceeded: {
|
|
492
|
+
printInfoToStderr(red('🚫 Token limit'), `${event.value.message}\n` +
|
|
493
|
+
`${dim('Tips:')}\n` +
|
|
494
|
+
` ${dim('•')} Start a new session.\n` +
|
|
495
|
+
` ${dim('•')} Increase limit via settings.json (sessionTokenLimit).\n` +
|
|
496
|
+
` ${dim('•')} Compress history using /compress in interactive mode.`);
|
|
497
|
+
return;
|
|
498
|
+
}
|
|
499
|
+
case GeminiEventType.Finished: {
|
|
500
|
+
const finishReason = event.value;
|
|
501
|
+
const finishReasonMessages = {
|
|
502
|
+
[FinishReason.MAX_TOKENS]: 'Response truncated due to token limits.',
|
|
503
|
+
[FinishReason.SAFETY]: 'Response stopped due to safety reasons.',
|
|
504
|
+
[FinishReason.RECITATION]: 'Response stopped due to recitation policy.',
|
|
505
|
+
[FinishReason.LANGUAGE]: 'Response stopped due to unsupported language.',
|
|
506
|
+
[FinishReason.BLOCKLIST]: 'Response stopped due to forbidden terms.',
|
|
507
|
+
[FinishReason.PROHIBITED_CONTENT]: 'Response stopped due to prohibited content.',
|
|
508
|
+
[FinishReason.SPII]: 'Response stopped due to sensitive personally identifiable information.',
|
|
509
|
+
[FinishReason.OTHER]: 'Response stopped for other reasons.',
|
|
510
|
+
[FinishReason.MALFORMED_FUNCTION_CALL]: 'Response stopped due to malformed function call.',
|
|
511
|
+
[FinishReason.IMAGE_SAFETY]: 'Response stopped due to image safety violations.',
|
|
512
|
+
[FinishReason.UNEXPECTED_TOOL_CALL]: 'Response stopped due to unexpected tool call.',
|
|
513
|
+
[FinishReason.IMAGE_PROHIBITED_CONTENT]: 'Response stopped due to prohibited image content.',
|
|
514
|
+
[FinishReason.NO_IMAGE]: 'Response stopped because no image was provided.',
|
|
515
|
+
};
|
|
516
|
+
const message = finishReasonMessages[finishReason];
|
|
517
|
+
if (message) {
|
|
518
|
+
printInfoToStderr(yellow('⚠ Finished'), message);
|
|
519
|
+
}
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
case GeminiEventType.LoopDetected: {
|
|
523
|
+
printInfoToStderr(magenta('⚠ Loop detected'), 'A potential loop was detected. The request has been halted.');
|
|
524
|
+
return;
|
|
525
|
+
}
|
|
526
|
+
case GeminiEventType.Error: {
|
|
527
|
+
printInfoToStderr(red('✖ Error'), event.value.error.message);
|
|
528
|
+
return;
|
|
529
|
+
}
|
|
530
|
+
default: {
|
|
531
|
+
// Ignore other event types in non-interactive mode
|
|
532
|
+
break;
|
|
533
|
+
}
|
|
60
534
|
}
|
|
61
535
|
}
|
|
62
536
|
if (toolCallRequests.length > 0) {
|
|
63
537
|
const toolResponseParts = [];
|
|
64
538
|
for (const requestInfo of toolCallRequests) {
|
|
539
|
+
// Build a plan preview using ToolRegistry if available
|
|
540
|
+
try {
|
|
541
|
+
const tool = config.getToolRegistry().getTool(requestInfo.name);
|
|
542
|
+
if (tool) {
|
|
543
|
+
const invocation = tool.build(requestInfo.args);
|
|
544
|
+
const description = invocation.getDescription() || '';
|
|
545
|
+
// For edit_file, edit, and write_file, hide long content in the payload
|
|
546
|
+
let argsToShow = requestInfo.args;
|
|
547
|
+
const MAX_CONTENT_DISPLAY = 200;
|
|
548
|
+
// Hide edit_file SEARCH/REPLACE content
|
|
549
|
+
if (requestInfo.name === 'edit_file' && requestInfo.args && typeof requestInfo.args === 'object') {
|
|
550
|
+
const args = requestInfo.args;
|
|
551
|
+
if ('content' in args && typeof args['content'] === 'string') {
|
|
552
|
+
const content = args['content'];
|
|
553
|
+
// Show a summary instead of the full SEARCH/REPLACE blocks
|
|
554
|
+
const searchBlocks = (content.match(/<<<<<<< SEARCH/g) || []).length;
|
|
555
|
+
argsToShow = {
|
|
556
|
+
...args,
|
|
557
|
+
content: `[${searchBlocks} edit block${searchBlocks !== 1 ? 's' : ''} - content hidden for clarity]`
|
|
558
|
+
};
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
// Hide edit tool old_string and new_string if they're long
|
|
562
|
+
if (requestInfo.name === 'edit' && requestInfo.args && typeof requestInfo.args === 'object') {
|
|
563
|
+
const args = requestInfo.args;
|
|
564
|
+
const updatedArgs = { ...args };
|
|
565
|
+
if ('old_string' in args && typeof args['old_string'] === 'string') {
|
|
566
|
+
const oldString = args['old_string'];
|
|
567
|
+
if (oldString.length > MAX_CONTENT_DISPLAY) {
|
|
568
|
+
const lines = oldString.split('\n').length;
|
|
569
|
+
const chars = oldString.length;
|
|
570
|
+
updatedArgs['old_string'] = `[Content hidden - ${lines} lines, ${chars} characters]`;
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
if ('new_string' in args && typeof args['new_string'] === 'string') {
|
|
574
|
+
const newString = args['new_string'];
|
|
575
|
+
if (newString.length > MAX_CONTENT_DISPLAY) {
|
|
576
|
+
const lines = newString.split('\n').length;
|
|
577
|
+
const chars = newString.length;
|
|
578
|
+
updatedArgs['new_string'] = `[Content hidden - ${lines} lines, ${chars} characters]`;
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
argsToShow = updatedArgs;
|
|
582
|
+
}
|
|
583
|
+
// Hide write_file content if it's long
|
|
584
|
+
if (requestInfo.name === 'write_file' && requestInfo.args && typeof requestInfo.args === 'object') {
|
|
585
|
+
const args = requestInfo.args;
|
|
586
|
+
if ('content' in args && typeof args['content'] === 'string') {
|
|
587
|
+
const content = args['content'];
|
|
588
|
+
if (content.length > MAX_CONTENT_DISPLAY) {
|
|
589
|
+
const lines = content.split('\n').length;
|
|
590
|
+
const chars = content.length;
|
|
591
|
+
argsToShow = {
|
|
592
|
+
...args,
|
|
593
|
+
content: `[Content hidden - ${lines} lines, ${chars} characters]`
|
|
594
|
+
};
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
}
|
|
598
|
+
const prettyArgs = JSON.stringify(argsToShow, null, 2);
|
|
599
|
+
printPlanSectionToStderr(requestInfo.name, description, prettyArgs);
|
|
600
|
+
}
|
|
601
|
+
else {
|
|
602
|
+
const prettyArgs = JSON.stringify(requestInfo.args, null, 2);
|
|
603
|
+
printPlanSectionToStderr(requestInfo.name, '(tool not found in registry)', prettyArgs);
|
|
604
|
+
}
|
|
605
|
+
}
|
|
606
|
+
catch (_e) {
|
|
607
|
+
// If plan building fails, still show the raw args so users see payload
|
|
608
|
+
const prettyArgs = JSON.stringify(requestInfo.args, null, 2);
|
|
609
|
+
printPlanSectionToStderr(requestInfo.name, '(failed to build plan; showing raw payload)', prettyArgs);
|
|
610
|
+
}
|
|
65
611
|
const toolResponse = await executeToolCall(config, requestInfo, abortController.signal);
|
|
66
612
|
if (toolResponse.error &&
|
|
67
613
|
!config.getSupressToolIterationErrors()) {
|
|
68
614
|
console.error(`Error executing tool ${requestInfo.name}: ${toolResponse.resultDisplay || toolResponse.error.message}`);
|
|
69
615
|
}
|
|
616
|
+
// Print tool results to stdout with a styled section
|
|
617
|
+
if (toolResponse.resultDisplay) {
|
|
618
|
+
const displayContent = formatToolResultDisplay(toolResponse.resultDisplay);
|
|
619
|
+
if (displayContent) {
|
|
620
|
+
printToolSectionToStdout(requestInfo.name, displayContent);
|
|
621
|
+
}
|
|
622
|
+
}
|
|
70
623
|
if (toolResponse.responseParts) {
|
|
71
624
|
toolResponseParts.push(...toolResponse.responseParts);
|
|
72
625
|
}
|
|
@@ -75,6 +628,10 @@ export async function runNonInteractive(config, input, prompt_id) {
|
|
|
75
628
|
}
|
|
76
629
|
else {
|
|
77
630
|
process.stdout.write('\n'); // Ensure a final newline
|
|
631
|
+
// Save checkpoint if requested
|
|
632
|
+
if (config.getSaveCheckpoint() || config.getAutoSave()) {
|
|
633
|
+
await saveConversationCheckpoint(config, input, config.getSaveCheckpoint());
|
|
634
|
+
}
|
|
78
635
|
return;
|
|
79
636
|
}
|
|
80
637
|
}
|