@machina.ai/cell-cli 1.11.0-rc1 → 1.13.0-rc1
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/dist/package.json +12 -10
- package/dist/src/commands/extensions/disable.d.ts +1 -1
- package/dist/src/commands/extensions/disable.js +15 -7
- package/dist/src/commands/extensions/disable.js.map +1 -1
- package/dist/src/commands/extensions/enable.d.ts +1 -1
- package/dist/src/commands/extensions/enable.js +15 -7
- package/dist/src/commands/extensions/enable.js.map +1 -1
- package/dist/src/commands/extensions/install.js +14 -3
- package/dist/src/commands/extensions/install.js.map +1 -1
- package/dist/src/commands/extensions/install.test.js +39 -19
- package/dist/src/commands/extensions/install.test.js.map +1 -1
- package/dist/src/commands/extensions/link.js +14 -3
- package/dist/src/commands/extensions/link.js.map +1 -1
- package/dist/src/commands/extensions/list.js +13 -4
- package/dist/src/commands/extensions/list.js.map +1 -1
- package/dist/src/commands/extensions/uninstall.js +13 -2
- package/dist/src/commands/extensions/uninstall.js.map +1 -1
- package/dist/src/commands/extensions/update.js +18 -13
- 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 +83 -0
- package/dist/src/commands/extensions/validate.js.map +1 -0
- package/dist/src/commands/extensions/validate.test.js +93 -0
- package/dist/src/commands/extensions/validate.test.js.map +1 -0
- package/dist/src/commands/extensions.js +3 -0
- package/dist/src/commands/extensions.js.map +1 -1
- package/dist/src/commands/mcp/add.test.js +3 -0
- package/dist/src/commands/mcp/add.test.js.map +1 -1
- package/dist/src/commands/mcp/list.js +10 -3
- package/dist/src/commands/mcp/list.js.map +1 -1
- package/dist/src/commands/mcp/list.test.js +37 -27
- package/dist/src/commands/mcp/list.test.js.map +1 -1
- package/dist/src/config/auth.js +0 -5
- package/dist/src/config/auth.js.map +1 -1
- package/dist/src/config/config.d.ts +6 -3
- package/dist/src/config/config.js +65 -80
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/config.test.js +235 -212
- package/dist/src/config/config.test.js.map +1 -1
- package/dist/src/config/extension-manager.d.ts +63 -0
- package/dist/src/config/extension-manager.js +450 -0
- package/dist/src/config/extension-manager.js.map +1 -0
- package/dist/src/config/extension.d.ts +4 -51
- package/dist/src/config/extension.js +1 -535
- package/dist/src/config/extension.js.map +1 -1
- package/dist/src/config/extension.test.js +525 -201
- package/dist/src/config/extension.test.js.map +1 -1
- package/dist/src/config/extensions/consent.d.ts +38 -0
- package/dist/src/config/extensions/consent.js +123 -0
- package/dist/src/config/extensions/consent.js.map +1 -0
- package/dist/src/config/extensions/extensionEnablement.d.ts +1 -1
- package/dist/src/config/extensions/extensionEnablement.js +4 -3
- package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
- package/dist/src/config/extensions/extensionEnablement.test.js +10 -10
- package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
- package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
- package/dist/src/config/extensions/extensionSettings.js +113 -0
- package/dist/src/config/extensions/extensionSettings.js.map +1 -0
- package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
- package/dist/src/config/extensions/extensionSettings.test.js +254 -0
- package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
- package/dist/src/config/extensions/github.d.ts +2 -2
- package/dist/src/config/extensions/github.js +5 -10
- package/dist/src/config/extensions/github.js.map +1 -1
- package/dist/src/config/extensions/github.test.js +153 -167
- package/dist/src/config/extensions/github.test.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.d.ts +1 -1
- package/dist/src/config/extensions/github_fetch.js +13 -1
- package/dist/src/config/extensions/github_fetch.js.map +1 -1
- package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
- package/dist/src/config/extensions/github_fetch.test.js +169 -0
- package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
- package/dist/src/config/extensions/storage.d.ts +14 -0
- package/dist/src/config/extensions/storage.js +32 -0
- package/dist/src/config/extensions/storage.js.map +1 -0
- package/dist/src/config/extensions/update.d.ts +4 -4
- package/dist/src/config/extensions/update.js +39 -39
- package/dist/src/config/extensions/update.js.map +1 -1
- package/dist/src/config/extensions/update.test.js +72 -74
- package/dist/src/config/extensions/update.test.js.map +1 -1
- package/dist/src/config/extensions/variableSchema.d.ts +0 -6
- package/dist/src/config/extensions/variableSchema.js.map +1 -1
- package/dist/src/config/extensions/variables.d.ts +4 -0
- package/dist/src/config/extensions/variables.js +6 -0
- package/dist/src/config/extensions/variables.js.map +1 -1
- package/dist/src/config/keyBindings.d.ts +3 -0
- package/dist/src/config/keyBindings.js +30 -8
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/keyBindings.test.js +17 -0
- package/dist/src/config/keyBindings.test.js.map +1 -1
- package/dist/src/config/policies/read-only.toml +56 -0
- package/dist/src/config/policies/write.toml +63 -0
- package/dist/src/config/policies/yolo.toml +31 -0
- package/dist/src/config/policy-engine.integration.test.js +41 -38
- package/dist/src/config/policy-engine.integration.test.js.map +1 -1
- package/dist/src/config/policy.d.ts +2 -2
- package/dist/src/config/policy.js +10 -148
- package/dist/src/config/policy.js.map +1 -1
- package/dist/src/config/sandboxConfig.d.ts +1 -1
- package/dist/src/config/sandboxConfig.js +6 -3
- package/dist/src/config/sandboxConfig.js.map +1 -1
- package/dist/src/config/settings.d.ts +2 -1
- package/dist/src/config/settings.js +58 -18
- package/dist/src/config/settings.js.map +1 -1
- package/dist/src/config/settings.test.js +128 -69
- package/dist/src/config/settings.test.js.map +1 -1
- package/dist/src/config/settingsSchema.d.ts +170 -28
- package/dist/src/config/settingsSchema.js +418 -27
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.js +42 -1
- package/dist/src/config/settingsSchema.test.js.map +1 -1
- package/dist/src/config/trustedFolders.d.ts +1 -1
- package/dist/src/config/trustedFolders.js +4 -2
- package/dist/src/config/trustedFolders.js.map +1 -1
- package/dist/src/core/initializer.js +2 -1
- package/dist/src/core/initializer.js.map +1 -1
- package/dist/src/gemini.d.ts +1 -1
- package/dist/src/gemini.js +46 -16
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +88 -30
- package/dist/src/gemini.test.js.map +1 -1
- package/dist/src/generated/git-commit.d.ts +2 -2
- package/dist/src/generated/git-commit.js +2 -2
- package/dist/src/nonInteractiveCli.d.ts +9 -1
- package/dist/src/nonInteractiveCli.js +114 -7
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/nonInteractiveCli.test.js +355 -112
- package/dist/src/nonInteractiveCli.test.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.js +4 -0
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
- package/dist/src/services/FeedbackService.js +2 -2
- package/dist/src/services/FeedbackService.js.map +1 -1
- package/dist/src/services/McpPromptLoader.js +2 -2
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.test.js +4 -2
- package/dist/src/services/McpPromptLoader.test.js.map +1 -1
- package/dist/src/test-utils/async.d.ts +9 -0
- package/dist/src/test-utils/async.js +29 -0
- package/dist/src/test-utils/async.js.map +1 -0
- package/dist/src/test-utils/createExtension.d.ts +3 -1
- package/dist/src/test-utils/createExtension.js +3 -3
- package/dist/src/test-utils/createExtension.js.map +1 -1
- package/dist/src/test-utils/render.d.ts +16 -2
- package/dist/src/test-utils/render.js +66 -4
- package/dist/src/test-utils/render.js.map +1 -1
- package/dist/src/test-utils/render.test.d.ts +6 -0
- package/dist/src/test-utils/render.test.js +79 -0
- package/dist/src/test-utils/render.test.js.map +1 -0
- package/dist/src/ui/App.test.js +1 -1
- package/dist/src/ui/App.test.js.map +1 -1
- package/dist/src/ui/AppContainer.js +181 -65
- package/dist/src/ui/AppContainer.js.map +1 -1
- package/dist/src/ui/AppContainer.test.js +505 -147
- package/dist/src/ui/AppContainer.test.js.map +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js +1 -1
- package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
- package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
- package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
- package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
- package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
- package/dist/src/ui/auth/AuthDialog.js +7 -3
- package/dist/src/ui/auth/AuthDialog.js.map +1 -1
- package/dist/src/ui/auth/useAuth.d.ts +2 -0
- package/dist/src/ui/auth/useAuth.js +31 -2
- package/dist/src/ui/auth/useAuth.js.map +1 -1
- package/dist/src/ui/colors.js +3 -0
- package/dist/src/ui/colors.js.map +1 -1
- package/dist/src/ui/commands/directoryCommand.js +1 -1
- package/dist/src/ui/commands/directoryCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.js +64 -11
- package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
- package/dist/src/ui/commands/extensionsCommand.test.js +72 -1
- package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +14 -14
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.test.js +4 -0
- package/dist/src/ui/commands/mcpCommand.test.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.js +1 -1
- package/dist/src/ui/commands/memoryCommand.js.map +1 -1
- package/dist/src/ui/commands/memoryCommand.test.js +3 -1
- package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
- package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
- package/dist/src/ui/commands/policiesCommand.js +59 -0
- package/dist/src/ui/commands/policiesCommand.js.map +1 -0
- package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/policiesCommand.test.js +83 -0
- package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
- package/dist/src/ui/components/AnsiOutput.test.js +1 -1
- package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
- package/dist/src/ui/components/AsciiArt.d.ts +3 -3
- package/dist/src/ui/components/AsciiArt.js +3 -3
- package/dist/src/ui/components/Composer.js +1 -1
- package/dist/src/ui/components/Composer.js.map +1 -1
- package/dist/src/ui/components/Composer.test.js +5 -2
- package/dist/src/ui/components/Composer.test.js.map +1 -1
- package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
- package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
- package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
- package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
- package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
- package/dist/src/ui/components/ContextSummaryDisplay.test.js +11 -6
- package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
- package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
- package/dist/src/ui/components/DialogManager.js +4 -0
- package/dist/src/ui/components/DialogManager.js.map +1 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js +2 -1
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/Footer.js +4 -3
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.test.js +83 -0
- package/dist/src/ui/components/Footer.test.js.map +1 -1
- package/dist/src/ui/components/Header.test.js +13 -5
- package/dist/src/ui/components/Header.test.js.map +1 -1
- package/dist/src/ui/components/Help.test.js +5 -4
- package/dist/src/ui/components/Help.test.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +27 -8
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.test.js +776 -727
- package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.js +2 -2
- package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
- package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
- package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
- package/dist/src/ui/components/MainContent.js +15 -4
- package/dist/src/ui/components/MainContent.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.js +1 -1
- package/dist/src/ui/components/ModelDialog.js.map +1 -1
- package/dist/src/ui/components/ModelDialog.test.js +23 -13
- package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/Notifications.js +38 -5
- package/dist/src/ui/components/Notifications.js.map +1 -1
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +2 -2
- package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
- package/dist/src/ui/components/PrepareLabel.test.js +14 -8
- package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
- package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
- package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
- package/dist/src/ui/components/QueuedMessageDisplay.test.js +11 -6
- package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js +1 -1
- package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.js +32 -25
- package/dist/src/ui/components/SettingsDialog.js.map +1 -1
- package/dist/src/ui/components/SettingsDialog.test.js +428 -532
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
- package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js +1 -1
- package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/ThemeDialog.test.js +2 -2
- package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js +1 -1
- package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -1
- package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
- package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js +1 -1
- package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.js +27 -5
- package/dist/src/ui/components/messages/Todo.js.map +1 -1
- package/dist/src/ui/components/messages/Todo.test.js +20 -8
- package/dist/src/ui/components/messages/Todo.test.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/components/messages/WarningMessage.js +2 -2
- package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js +1 -1
- package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
- package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
- package/dist/src/ui/components/shared/TextInput.js +38 -0
- package/dist/src/ui/components/shared/TextInput.js.map +1 -0
- package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
- package/dist/src/ui/components/shared/TextInput.test.js +242 -0
- package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
- package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
- package/dist/src/ui/components/shared/text-buffer.js +51 -13
- package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
- package/dist/src/ui/components/shared/text-buffer.test.js +385 -202
- package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
- package/dist/src/ui/components/views/ChatList.test.js +7 -4
- package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
- package/dist/src/ui/components/views/ExtensionsList.js +9 -11
- package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
- package/dist/src/ui/components/views/ExtensionsList.test.js +43 -22
- package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
- package/dist/src/ui/components/views/McpStatus.test.js +23 -12
- package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.d.ts +3 -2
- package/dist/src/ui/contexts/KeypressContext.js +610 -540
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
- package/dist/src/ui/contexts/KeypressContext.test.js +438 -718
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
- package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
- package/dist/src/ui/contexts/MouseContext.js +89 -0
- package/dist/src/ui/contexts/MouseContext.js.map +1 -0
- package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/MouseContext.test.js +164 -0
- package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
- package/dist/src/ui/contexts/SessionContext.test.js +35 -17
- package/dist/src/ui/contexts/SessionContext.test.js.map +1 -1
- package/dist/src/ui/contexts/UIActionsContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
- package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
- package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.js +31 -9
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.test.js +193 -165
- package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.test.js +16 -5
- package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.test.js +66 -64
- package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useConsoleMessages.test.js +26 -9
- package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -1
- package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -5
- package/dist/src/ui/hooks/useExtensionUpdates.js +18 -13
- package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
- package/dist/src/ui/hooks/useExtensionUpdates.test.js +49 -44
- package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
- package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
- package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
- package/dist/src/ui/hooks/useFocus.test.js +25 -9
- package/dist/src/ui/hooks/useFocus.test.js.map +1 -1
- package/dist/src/ui/hooks/useFolderTrust.test.js +46 -22
- package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +56 -19
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.test.js +260 -411
- package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.js +4 -0
- package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
- package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
- package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
- package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
- package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.js +103 -114
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -1
- package/dist/src/ui/hooks/useLoadingIndicator.test.js +24 -6
- package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
- package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
- package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
- package/dist/src/ui/hooks/useMessageQueue.test.js +62 -45
- package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
- package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
- package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
- package/dist/src/ui/hooks/useMouse.d.ts +17 -0
- package/dist/src/ui/hooks/useMouse.js +27 -0
- package/dist/src/ui/hooks/useMouse.js.map +1 -0
- package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
- package/dist/src/ui/hooks/useMouse.test.js +57 -0
- package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
- package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/usePhraseCycler.test.js +109 -106
- package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -1
- package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
- package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
- package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
- package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
- package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
- package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +59 -34
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
- package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.js +5 -4
- package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
- package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
- package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
- package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
- package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.js +18 -7
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useTimer.test.js +43 -14
- package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +226 -242
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/hooks/vim.test.js +235 -355
- package/dist/src/ui/hooks/vim.test.js.map +1 -1
- package/dist/src/ui/keyMatchers.test.js +30 -3
- package/dist/src/ui/keyMatchers.test.js.map +1 -1
- package/dist/src/ui/state/extensions.d.ts +1 -0
- package/dist/src/ui/state/extensions.js +1 -0
- package/dist/src/ui/state/extensions.js.map +1 -1
- package/dist/src/ui/themes/ansi-light.js +1 -0
- package/dist/src/ui/themes/ansi-light.js.map +1 -1
- package/dist/src/ui/themes/ansi.js +1 -0
- package/dist/src/ui/themes/ansi.js.map +1 -1
- package/dist/src/ui/themes/atom-one-dark.js +2 -0
- package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
- package/dist/src/ui/themes/ayu-light.js +2 -0
- package/dist/src/ui/themes/ayu-light.js.map +1 -1
- package/dist/src/ui/themes/ayu.js +2 -0
- package/dist/src/ui/themes/ayu.js.map +1 -1
- package/dist/src/ui/themes/color-utils.d.ts +1 -0
- package/dist/src/ui/themes/color-utils.js +6 -0
- package/dist/src/ui/themes/color-utils.js.map +1 -1
- package/dist/src/ui/themes/color-utils.test.js +13 -1
- package/dist/src/ui/themes/color-utils.test.js.map +1 -1
- package/dist/src/ui/themes/dracula.js +2 -0
- package/dist/src/ui/themes/dracula.js.map +1 -1
- package/dist/src/ui/themes/github-dark.js +2 -0
- package/dist/src/ui/themes/github-dark.js.map +1 -1
- package/dist/src/ui/themes/github-light.js +2 -0
- package/dist/src/ui/themes/github-light.js.map +1 -1
- package/dist/src/ui/themes/googlecode.js +2 -0
- package/dist/src/ui/themes/googlecode.js.map +1 -1
- package/dist/src/ui/themes/no-color.js +3 -0
- package/dist/src/ui/themes/no-color.js.map +1 -1
- package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
- package/dist/src/ui/themes/semantic-tokens.js +6 -0
- package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
- package/dist/src/ui/themes/shades-of-purple.js +2 -0
- package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
- package/dist/src/ui/themes/theme.d.ts +3 -0
- package/dist/src/ui/themes/theme.js +14 -3
- package/dist/src/ui/themes/theme.js.map +1 -1
- package/dist/src/ui/themes/theme.test.js +67 -1
- package/dist/src/ui/themes/theme.test.js.map +1 -1
- package/dist/src/ui/themes/xcode.js +2 -0
- package/dist/src/ui/themes/xcode.js.map +1 -1
- package/dist/src/ui/types.d.ts +3 -1
- package/dist/src/ui/types.js +2 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/CodeColorizer.js +2 -1
- package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
- package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
- package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
- package/dist/src/ui/utils/MarkdownDisplay.js +11 -9
- package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
- package/dist/src/ui/utils/clipboardUtils.js +2 -2
- package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
- package/dist/src/ui/utils/input.d.ts +17 -0
- package/dist/src/ui/utils/input.js +51 -0
- package/dist/src/ui/utils/input.js.map +1 -0
- package/dist/src/ui/utils/input.test.d.ts +6 -0
- package/dist/src/ui/utils/input.test.js +44 -0
- package/dist/src/ui/utils/input.test.js.map +1 -0
- package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
- package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
- package/dist/src/ui/utils/mouse.d.ts +31 -0
- package/dist/src/ui/utils/mouse.js +164 -0
- package/dist/src/ui/utils/mouse.js.map +1 -0
- package/dist/src/ui/utils/mouse.test.d.ts +6 -0
- package/dist/src/ui/utils/mouse.test.js +131 -0
- package/dist/src/ui/utils/mouse.test.js.map +1 -0
- package/dist/src/ui/utils/textOutput.d.ts +25 -0
- package/dist/src/ui/utils/textOutput.js +49 -0
- package/dist/src/ui/utils/textOutput.js.map +1 -0
- package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
- package/dist/src/ui/utils/textOutput.test.js +79 -0
- package/dist/src/ui/utils/textOutput.test.js.map +1 -0
- package/dist/src/ui/utils/updateCheck.d.ts +7 -1
- package/dist/src/ui/utils/updateCheck.js +33 -29
- package/dist/src/ui/utils/updateCheck.js.map +1 -1
- package/dist/src/ui/utils/updateCheck.test.js +24 -50
- package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
- package/dist/src/utils/commentJson.js +2 -2
- package/dist/src/utils/commentJson.js.map +1 -1
- package/dist/src/utils/commentJson.test.js +7 -6
- package/dist/src/utils/commentJson.test.js.map +1 -1
- package/dist/src/utils/envVarResolver.d.ts +2 -2
- package/dist/src/utils/envVarResolver.js +10 -7
- package/dist/src/utils/envVarResolver.js.map +1 -1
- package/dist/src/utils/events.d.ts +11 -2
- package/dist/src/utils/events.js +1 -0
- package/dist/src/utils/events.js.map +1 -1
- package/dist/src/utils/handleAutoUpdate.js +9 -3
- package/dist/src/utils/handleAutoUpdate.js.map +1 -1
- package/dist/src/utils/sandbox.js +16 -18
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/utils/version.js +6 -2
- package/dist/src/utils/version.js.map +1 -1
- package/dist/src/zed-integration/acp.js +2 -1
- package/dist/src/zed-integration/acp.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +4 -4
- package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
- package/dist/src/zed-integration/zedIntegration.js +12 -19
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +14 -14
- package/dist/src/config/policy.test.js +0 -360
- package/dist/src/config/policy.test.js.map +0 -1
- package/dist/src/utils/package.d.ts +0 -12
- package/dist/src/utils/package.js +0 -24
- package/dist/src/utils/package.js.map +0 -1
- /package/dist/src/{config/policy.test.d.ts → commands/extensions/validate.test.d.ts} +0 -0
|
@@ -4,12 +4,14 @@
|
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
6
|
import { describe, it, expect, vi, beforeEach } from 'vitest';
|
|
7
|
-
import {
|
|
7
|
+
import { act } from 'react';
|
|
8
|
+
import { renderHook } from '../../test-utils/render.js';
|
|
9
|
+
import { waitFor } from '../../test-utils/async.js';
|
|
8
10
|
import { useGeminiStream } from './useGeminiStream.js';
|
|
9
11
|
import { useKeypress } from './useKeypress.js';
|
|
10
12
|
import * as atCommandProcessor from './atCommandProcessor.js';
|
|
11
13
|
import { useReactToolScheduler } from './useReactToolScheduler.js';
|
|
12
|
-
import { ApprovalMode, AuthType, GeminiEventType as ServerGeminiEventType, ToolErrorType, ToolConfirmationOutcome, tokenLimit, } from '@google/gemini-cli-core';
|
|
14
|
+
import { ApprovalMode, AuthType, GeminiEventType as ServerGeminiEventType, ToolErrorType, ToolConfirmationOutcome, tokenLimit, debugLogger, } from '@google/gemini-cli-core';
|
|
13
15
|
import { MessageType, StreamingState } from '../types.js';
|
|
14
16
|
// --- MOCKS ---
|
|
15
17
|
const mockSendMessageStream = vi
|
|
@@ -175,8 +177,9 @@ describe('useGeminiStream', () => {
|
|
|
175
177
|
mockUseReactToolScheduler.mockReturnValue([
|
|
176
178
|
[], // Default to empty array for toolCalls
|
|
177
179
|
mockScheduleToolCalls,
|
|
178
|
-
mockCancelAllToolCalls,
|
|
179
180
|
mockMarkToolsAsSubmitted,
|
|
181
|
+
vi.fn(), // setToolCallsForDisplay
|
|
182
|
+
mockCancelAllToolCalls,
|
|
180
183
|
]);
|
|
181
184
|
// Reset mocks for GeminiClient instance methods (startChat and sendMessageStream)
|
|
182
185
|
// The GeminiClient constructor itself is mocked at the module level.
|
|
@@ -197,35 +200,62 @@ describe('useGeminiStream', () => {
|
|
|
197
200
|
setValue: vi.fn(),
|
|
198
201
|
};
|
|
199
202
|
const renderTestHook = (initialToolCalls = [], geminiClient) => {
|
|
200
|
-
let currentToolCalls = initialToolCalls;
|
|
201
|
-
const setToolCalls = (newToolCalls) => {
|
|
202
|
-
currentToolCalls = newToolCalls;
|
|
203
|
-
};
|
|
204
|
-
mockUseReactToolScheduler.mockImplementation(() => [
|
|
205
|
-
currentToolCalls,
|
|
206
|
-
mockScheduleToolCalls,
|
|
207
|
-
mockCancelAllToolCalls,
|
|
208
|
-
mockMarkToolsAsSubmitted,
|
|
209
|
-
]);
|
|
210
203
|
const client = geminiClient || mockConfig.getGeminiClient();
|
|
204
|
+
const initialProps = {
|
|
205
|
+
client,
|
|
206
|
+
history: [],
|
|
207
|
+
addItem: mockAddItem,
|
|
208
|
+
config: mockConfig,
|
|
209
|
+
onDebugMessage: mockOnDebugMessage,
|
|
210
|
+
handleSlashCommand: mockHandleSlashCommand,
|
|
211
|
+
shellModeActive: false,
|
|
212
|
+
loadedSettings: mockLoadedSettings,
|
|
213
|
+
toolCalls: initialToolCalls,
|
|
214
|
+
};
|
|
211
215
|
const { result, rerender } = renderHook((props) => {
|
|
212
|
-
//
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
+
// This mock needs to be stateful. When setToolCallsForDisplay is called,
|
|
217
|
+
// it should trigger a rerender with the new state.
|
|
218
|
+
const mockSetToolCallsForDisplay = vi.fn((updater) => {
|
|
219
|
+
const newToolCalls = typeof updater === 'function' ? updater(props.toolCalls) : updater;
|
|
220
|
+
rerender({ ...props, toolCalls: newToolCalls });
|
|
221
|
+
});
|
|
222
|
+
// Create a stateful mock for cancellation that updates the toolCalls state.
|
|
223
|
+
const statefulCancelAllToolCalls = vi.fn((...args) => {
|
|
224
|
+
// Call the original spy so `toHaveBeenCalled` checks still work.
|
|
225
|
+
mockCancelAllToolCalls(...args);
|
|
226
|
+
const newToolCalls = props.toolCalls.map((tc) => {
|
|
227
|
+
// Only cancel tools that are in a cancellable state.
|
|
228
|
+
if (tc.status === 'awaiting_approval' ||
|
|
229
|
+
tc.status === 'executing' ||
|
|
230
|
+
tc.status === 'scheduled' ||
|
|
231
|
+
tc.status === 'validating') {
|
|
232
|
+
// A real cancelled tool call has a response object.
|
|
233
|
+
// We need to simulate this to avoid type errors downstream.
|
|
234
|
+
return {
|
|
235
|
+
...tc,
|
|
236
|
+
status: 'cancelled',
|
|
237
|
+
response: {
|
|
238
|
+
callId: tc.request.callId,
|
|
239
|
+
responseParts: [],
|
|
240
|
+
resultDisplay: 'Request cancelled.',
|
|
241
|
+
},
|
|
242
|
+
responseSubmittedToGemini: true, // Mark as "processed"
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
return tc;
|
|
246
|
+
});
|
|
247
|
+
rerender({ ...props, toolCalls: newToolCalls });
|
|
248
|
+
});
|
|
249
|
+
mockUseReactToolScheduler.mockImplementation(() => [
|
|
250
|
+
props.toolCalls,
|
|
251
|
+
mockScheduleToolCalls,
|
|
252
|
+
mockMarkToolsAsSubmitted,
|
|
253
|
+
mockSetToolCallsForDisplay,
|
|
254
|
+
statefulCancelAllToolCalls, // Use the stateful mock
|
|
255
|
+
]);
|
|
216
256
|
return useGeminiStream(props.client, props.history, props.addItem, props.config, props.loadedSettings, props.onDebugMessage, props.handleSlashCommand, props.shellModeActive, () => 'vscode', () => { }, () => Promise.resolve(), false, () => { }, () => { }, () => { }, () => { }, 80, 24);
|
|
217
257
|
}, {
|
|
218
|
-
initialProps
|
|
219
|
-
client,
|
|
220
|
-
history: [],
|
|
221
|
-
addItem: mockAddItem,
|
|
222
|
-
config: mockConfig,
|
|
223
|
-
onDebugMessage: mockOnDebugMessage,
|
|
224
|
-
handleSlashCommand: mockHandleSlashCommand,
|
|
225
|
-
shellModeActive: false,
|
|
226
|
-
loadedSettings: mockLoadedSettings,
|
|
227
|
-
toolCalls: initialToolCalls,
|
|
228
|
-
},
|
|
258
|
+
initialProps,
|
|
229
259
|
});
|
|
230
260
|
return {
|
|
231
261
|
result,
|
|
@@ -235,6 +265,49 @@ describe('useGeminiStream', () => {
|
|
|
235
265
|
client,
|
|
236
266
|
};
|
|
237
267
|
};
|
|
268
|
+
// Helper to create mock tool calls - reduces boilerplate
|
|
269
|
+
const createMockToolCall = (toolName, callId, confirmationType, mockOnConfirm, status = 'awaiting_approval') => ({
|
|
270
|
+
request: {
|
|
271
|
+
callId,
|
|
272
|
+
name: toolName,
|
|
273
|
+
args: {},
|
|
274
|
+
isClientInitiated: false,
|
|
275
|
+
prompt_id: 'prompt-id-1',
|
|
276
|
+
},
|
|
277
|
+
status: status,
|
|
278
|
+
responseSubmittedToGemini: false,
|
|
279
|
+
confirmationDetails: confirmationType === 'edit'
|
|
280
|
+
? {
|
|
281
|
+
type: 'edit',
|
|
282
|
+
title: 'Confirm Edit',
|
|
283
|
+
onConfirm: mockOnConfirm,
|
|
284
|
+
fileName: 'file.txt',
|
|
285
|
+
filePath: '/test/file.txt',
|
|
286
|
+
fileDiff: 'fake diff',
|
|
287
|
+
originalContent: 'old',
|
|
288
|
+
newContent: 'new',
|
|
289
|
+
}
|
|
290
|
+
: {
|
|
291
|
+
type: 'info',
|
|
292
|
+
title: `${toolName} confirmation`,
|
|
293
|
+
onConfirm: mockOnConfirm,
|
|
294
|
+
prompt: `Execute ${toolName}?`,
|
|
295
|
+
},
|
|
296
|
+
tool: {
|
|
297
|
+
name: toolName,
|
|
298
|
+
displayName: toolName,
|
|
299
|
+
description: `${toolName} description`,
|
|
300
|
+
build: vi.fn(),
|
|
301
|
+
},
|
|
302
|
+
invocation: {
|
|
303
|
+
getDescription: () => 'Mock description',
|
|
304
|
+
},
|
|
305
|
+
});
|
|
306
|
+
// Helper to render hook with default parameters - reduces boilerplate
|
|
307
|
+
const renderHookWithDefaults = (options = {}) => {
|
|
308
|
+
const { shellModeActive = false, onCancelSubmit = () => { }, setShellInputFocused = () => { }, performMemoryRefresh = () => Promise.resolve(), onAuthError = () => { }, onEditorClose = () => { }, setModelSwitched = vi.fn(), modelSwitched = false, } = options;
|
|
309
|
+
return renderHook(() => useGeminiStream(new MockedGeminiClientClass(mockConfig), [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, shellModeActive, () => 'vscode', onAuthError, performMemoryRefresh, modelSwitched, setModelSwitched, onEditorClose, onCancelSubmit, setShellInputFocused, 80, 24));
|
|
310
|
+
};
|
|
238
311
|
it('should not submit tool responses if not all tool calls are completed', () => {
|
|
239
312
|
const toolCalls = [
|
|
240
313
|
{
|
|
@@ -341,7 +414,7 @@ describe('useGeminiStream', () => {
|
|
|
341
414
|
let capturedOnComplete = null;
|
|
342
415
|
mockUseReactToolScheduler.mockImplementation((onComplete) => {
|
|
343
416
|
capturedOnComplete = onComplete;
|
|
344
|
-
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted];
|
|
417
|
+
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted, vi.fn()];
|
|
345
418
|
});
|
|
346
419
|
renderHook(() => useGeminiStream(new MockedGeminiClientClass(mockConfig), [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, () => Promise.resolve(), false, () => { }, () => { }, () => { }, () => { }, 80, 24));
|
|
347
420
|
// Trigger the onComplete callback with completed tools
|
|
@@ -390,7 +463,7 @@ describe('useGeminiStream', () => {
|
|
|
390
463
|
let capturedOnComplete = null;
|
|
391
464
|
mockUseReactToolScheduler.mockImplementation((onComplete) => {
|
|
392
465
|
capturedOnComplete = onComplete;
|
|
393
|
-
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted];
|
|
466
|
+
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted, vi.fn()];
|
|
394
467
|
});
|
|
395
468
|
renderHook(() => useGeminiStream(client, [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, () => Promise.resolve(), false, () => { }, () => { }, () => { }, () => { }, 80, 24));
|
|
396
469
|
// Trigger the onComplete callback with cancelled tools
|
|
@@ -473,7 +546,7 @@ describe('useGeminiStream', () => {
|
|
|
473
546
|
let capturedOnComplete = null;
|
|
474
547
|
mockUseReactToolScheduler.mockImplementation((onComplete) => {
|
|
475
548
|
capturedOnComplete = onComplete;
|
|
476
|
-
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted];
|
|
549
|
+
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted, vi.fn()];
|
|
477
550
|
});
|
|
478
551
|
renderHook(() => useGeminiStream(client, [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, () => Promise.resolve(), false, () => { }, () => { }, () => { }, () => { }, 80, 24));
|
|
479
552
|
// Trigger the onComplete callback with multiple cancelled tools
|
|
@@ -552,6 +625,7 @@ describe('useGeminiStream', () => {
|
|
|
552
625
|
currentToolCalls,
|
|
553
626
|
mockScheduleToolCalls,
|
|
554
627
|
mockMarkToolsAsSubmitted,
|
|
628
|
+
vi.fn(), // setToolCallsForDisplay
|
|
555
629
|
];
|
|
556
630
|
});
|
|
557
631
|
const { result, rerender } = renderHook(() => useGeminiStream(new MockedGeminiClientClass(mockConfig), [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, () => Promise.resolve(), false, () => { }, () => { }, () => { }, () => { }, 80, 24));
|
|
@@ -565,6 +639,7 @@ describe('useGeminiStream', () => {
|
|
|
565
639
|
completedToolCalls,
|
|
566
640
|
mockScheduleToolCalls,
|
|
567
641
|
mockMarkToolsAsSubmitted,
|
|
642
|
+
vi.fn(), // setToolCallsForDisplay
|
|
568
643
|
];
|
|
569
644
|
});
|
|
570
645
|
act(() => {
|
|
@@ -696,18 +771,18 @@ describe('useGeminiStream', () => {
|
|
|
696
771
|
// Cancel the request
|
|
697
772
|
simulateEscapeKeyPress();
|
|
698
773
|
// Allow the stream to continue
|
|
699
|
-
act(() => {
|
|
774
|
+
await act(async () => {
|
|
700
775
|
continueStream();
|
|
776
|
+
// Wait a bit to see if the second part is processed
|
|
777
|
+
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
701
778
|
});
|
|
702
|
-
// Wait a bit to see if the second part is processed
|
|
703
|
-
await new Promise((resolve) => setTimeout(resolve, 50));
|
|
704
779
|
// The text should not have been updated with " Canceled"
|
|
705
780
|
const lastCall = mockAddItem.mock.calls.find((call) => call[0].type === 'gemini');
|
|
706
781
|
expect(lastCall?.[0].text).toBe('Initial');
|
|
707
782
|
// The final state should be idle after cancellation
|
|
708
783
|
expect(result.current.streamingState).toBe(StreamingState.Idle);
|
|
709
784
|
});
|
|
710
|
-
it('should
|
|
785
|
+
it('should cancel if a tool call is in progress', async () => {
|
|
711
786
|
const toolCalls = [
|
|
712
787
|
{
|
|
713
788
|
request: { callId: 'call1', name: 'tool1', args: {} },
|
|
@@ -727,14 +802,64 @@ describe('useGeminiStream', () => {
|
|
|
727
802
|
liveOutput: '...',
|
|
728
803
|
},
|
|
729
804
|
];
|
|
730
|
-
const abortSpy = vi.spyOn(AbortController.prototype, 'abort');
|
|
731
805
|
const { result } = renderTestHook(toolCalls);
|
|
732
806
|
// State is `Responding` because a tool is running
|
|
733
807
|
expect(result.current.streamingState).toBe(StreamingState.Responding);
|
|
734
808
|
// Try to cancel
|
|
735
809
|
simulateEscapeKeyPress();
|
|
736
|
-
//
|
|
737
|
-
expect(
|
|
810
|
+
// The cancel function should be called
|
|
811
|
+
expect(mockCancelAllToolCalls).toHaveBeenCalled();
|
|
812
|
+
});
|
|
813
|
+
it('should cancel a request when a tool is awaiting confirmation', async () => {
|
|
814
|
+
const mockOnConfirm = vi.fn().mockResolvedValue(undefined);
|
|
815
|
+
const toolCalls = [
|
|
816
|
+
{
|
|
817
|
+
request: {
|
|
818
|
+
callId: 'confirm-call',
|
|
819
|
+
name: 'some_tool',
|
|
820
|
+
args: {},
|
|
821
|
+
isClientInitiated: false,
|
|
822
|
+
prompt_id: 'prompt-id-1',
|
|
823
|
+
},
|
|
824
|
+
status: 'awaiting_approval',
|
|
825
|
+
responseSubmittedToGemini: false,
|
|
826
|
+
tool: {
|
|
827
|
+
name: 'some_tool',
|
|
828
|
+
description: 'a tool',
|
|
829
|
+
build: vi.fn().mockImplementation((_) => ({
|
|
830
|
+
getDescription: () => `Mock description`,
|
|
831
|
+
})),
|
|
832
|
+
},
|
|
833
|
+
invocation: {
|
|
834
|
+
getDescription: () => `Mock description`,
|
|
835
|
+
},
|
|
836
|
+
confirmationDetails: {
|
|
837
|
+
type: 'edit',
|
|
838
|
+
title: 'Confirm Edit',
|
|
839
|
+
onConfirm: mockOnConfirm,
|
|
840
|
+
fileName: 'file.txt',
|
|
841
|
+
filePath: '/test/file.txt',
|
|
842
|
+
fileDiff: 'fake diff',
|
|
843
|
+
originalContent: 'old',
|
|
844
|
+
newContent: 'new',
|
|
845
|
+
},
|
|
846
|
+
},
|
|
847
|
+
];
|
|
848
|
+
const { result } = renderTestHook(toolCalls);
|
|
849
|
+
// State is `WaitingForConfirmation` because a tool is awaiting approval
|
|
850
|
+
expect(result.current.streamingState).toBe(StreamingState.WaitingForConfirmation);
|
|
851
|
+
// Try to cancel
|
|
852
|
+
simulateEscapeKeyPress();
|
|
853
|
+
// The imperative cancel function should be called on the scheduler
|
|
854
|
+
expect(mockCancelAllToolCalls).toHaveBeenCalled();
|
|
855
|
+
// A cancellation message should be added to history
|
|
856
|
+
await waitFor(() => {
|
|
857
|
+
expect(mockAddItem).toHaveBeenCalledWith(expect.objectContaining({
|
|
858
|
+
text: 'Request cancelled.',
|
|
859
|
+
}), expect.any(Number));
|
|
860
|
+
});
|
|
861
|
+
// The final state should be idle
|
|
862
|
+
expect(result.current.streamingState).toBe(StreamingState.Idle);
|
|
738
863
|
});
|
|
739
864
|
});
|
|
740
865
|
describe('Slash Command Handling', () => {
|
|
@@ -871,7 +996,7 @@ describe('useGeminiStream', () => {
|
|
|
871
996
|
let capturedOnComplete = null;
|
|
872
997
|
mockUseReactToolScheduler.mockImplementation((onComplete) => {
|
|
873
998
|
capturedOnComplete = onComplete;
|
|
874
|
-
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted];
|
|
999
|
+
return [[], mockScheduleToolCalls, mockMarkToolsAsSubmitted, vi.fn()];
|
|
875
1000
|
});
|
|
876
1001
|
renderHook(() => useGeminiStream(new MockedGeminiClientClass(mockConfig), [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, mockPerformMemoryRefresh, false, () => { }, () => { }, () => { }, () => { }, 80, 24));
|
|
877
1002
|
// Trigger the onComplete callback with the completed save_memory tool
|
|
@@ -917,62 +1042,8 @@ describe('useGeminiStream', () => {
|
|
|
917
1042
|
it('should auto-approve all pending tool calls when switching to YOLO mode', async () => {
|
|
918
1043
|
const mockOnConfirm = vi.fn().mockResolvedValue(undefined);
|
|
919
1044
|
const awaitingApprovalToolCalls = [
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
callId: 'call1',
|
|
923
|
-
name: 'replace',
|
|
924
|
-
args: { old_string: 'old', new_string: 'new' },
|
|
925
|
-
isClientInitiated: false,
|
|
926
|
-
prompt_id: 'prompt-id-1',
|
|
927
|
-
},
|
|
928
|
-
status: 'awaiting_approval',
|
|
929
|
-
responseSubmittedToGemini: false,
|
|
930
|
-
confirmationDetails: {
|
|
931
|
-
type: 'edit',
|
|
932
|
-
title: 'Confirm Edit',
|
|
933
|
-
onConfirm: mockOnConfirm,
|
|
934
|
-
fileName: 'file.txt',
|
|
935
|
-
filePath: '/test/file.txt',
|
|
936
|
-
fileDiff: 'fake diff',
|
|
937
|
-
originalContent: 'old',
|
|
938
|
-
newContent: 'new',
|
|
939
|
-
},
|
|
940
|
-
tool: {
|
|
941
|
-
name: 'replace',
|
|
942
|
-
displayName: 'replace',
|
|
943
|
-
description: 'Replace text',
|
|
944
|
-
build: vi.fn(),
|
|
945
|
-
},
|
|
946
|
-
invocation: {
|
|
947
|
-
getDescription: () => 'Mock description',
|
|
948
|
-
},
|
|
949
|
-
},
|
|
950
|
-
{
|
|
951
|
-
request: {
|
|
952
|
-
callId: 'call2',
|
|
953
|
-
name: 'read_file',
|
|
954
|
-
args: { path: '/test/file.txt' },
|
|
955
|
-
isClientInitiated: false,
|
|
956
|
-
prompt_id: 'prompt-id-1',
|
|
957
|
-
},
|
|
958
|
-
status: 'awaiting_approval',
|
|
959
|
-
responseSubmittedToGemini: false,
|
|
960
|
-
confirmationDetails: {
|
|
961
|
-
type: 'info',
|
|
962
|
-
title: 'Read File',
|
|
963
|
-
onConfirm: mockOnConfirm,
|
|
964
|
-
prompt: 'Read /test/file.txt?',
|
|
965
|
-
},
|
|
966
|
-
tool: {
|
|
967
|
-
name: 'read_file',
|
|
968
|
-
displayName: 'read_file',
|
|
969
|
-
description: 'Read file',
|
|
970
|
-
build: vi.fn(),
|
|
971
|
-
},
|
|
972
|
-
invocation: {
|
|
973
|
-
getDescription: () => 'Mock description',
|
|
974
|
-
},
|
|
975
|
-
},
|
|
1045
|
+
createMockToolCall('replace', 'call1', 'edit', mockOnConfirm),
|
|
1046
|
+
createMockToolCall('read_file', 'call2', 'info', mockOnConfirm),
|
|
976
1047
|
];
|
|
977
1048
|
const { result } = renderTestHook(awaitingApprovalToolCalls);
|
|
978
1049
|
await act(async () => {
|
|
@@ -980,109 +1051,23 @@ describe('useGeminiStream', () => {
|
|
|
980
1051
|
});
|
|
981
1052
|
// Both tool calls should be auto-approved
|
|
982
1053
|
expect(mockOnConfirm).toHaveBeenCalledTimes(2);
|
|
983
|
-
expect(mockOnConfirm).
|
|
984
|
-
expect(mockOnConfirm).toHaveBeenNthCalledWith(2, ToolConfirmationOutcome.ProceedOnce);
|
|
1054
|
+
expect(mockOnConfirm).toHaveBeenCalledWith(ToolConfirmationOutcome.ProceedOnce);
|
|
985
1055
|
});
|
|
986
1056
|
it('should only auto-approve edit tools when switching to AUTO_EDIT mode', async () => {
|
|
987
1057
|
const mockOnConfirmReplace = vi.fn().mockResolvedValue(undefined);
|
|
988
1058
|
const mockOnConfirmWrite = vi.fn().mockResolvedValue(undefined);
|
|
989
1059
|
const mockOnConfirmRead = vi.fn().mockResolvedValue(undefined);
|
|
990
1060
|
const awaitingApprovalToolCalls = [
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
name: 'replace',
|
|
995
|
-
args: { old_string: 'old', new_string: 'new' },
|
|
996
|
-
isClientInitiated: false,
|
|
997
|
-
prompt_id: 'prompt-id-1',
|
|
998
|
-
},
|
|
999
|
-
status: 'awaiting_approval',
|
|
1000
|
-
responseSubmittedToGemini: false,
|
|
1001
|
-
confirmationDetails: {
|
|
1002
|
-
type: 'edit',
|
|
1003
|
-
title: 'Confirm Edit',
|
|
1004
|
-
onConfirm: mockOnConfirmReplace,
|
|
1005
|
-
fileName: 'file.txt',
|
|
1006
|
-
filePath: '/test/file.txt',
|
|
1007
|
-
fileDiff: 'fake diff',
|
|
1008
|
-
originalContent: 'old',
|
|
1009
|
-
newContent: 'new',
|
|
1010
|
-
},
|
|
1011
|
-
tool: {
|
|
1012
|
-
name: 'replace',
|
|
1013
|
-
displayName: 'replace',
|
|
1014
|
-
description: 'Replace text',
|
|
1015
|
-
build: vi.fn(),
|
|
1016
|
-
},
|
|
1017
|
-
invocation: {
|
|
1018
|
-
getDescription: () => 'Mock description',
|
|
1019
|
-
},
|
|
1020
|
-
},
|
|
1021
|
-
{
|
|
1022
|
-
request: {
|
|
1023
|
-
callId: 'call2',
|
|
1024
|
-
name: 'write_file',
|
|
1025
|
-
args: { path: '/test/new.txt', content: 'content' },
|
|
1026
|
-
isClientInitiated: false,
|
|
1027
|
-
prompt_id: 'prompt-id-1',
|
|
1028
|
-
},
|
|
1029
|
-
status: 'awaiting_approval',
|
|
1030
|
-
responseSubmittedToGemini: false,
|
|
1031
|
-
confirmationDetails: {
|
|
1032
|
-
type: 'edit',
|
|
1033
|
-
title: 'Confirm Edit',
|
|
1034
|
-
onConfirm: mockOnConfirmWrite,
|
|
1035
|
-
fileName: 'new.txt',
|
|
1036
|
-
filePath: '/test/new.txt',
|
|
1037
|
-
fileDiff: 'fake diff',
|
|
1038
|
-
originalContent: null,
|
|
1039
|
-
newContent: 'content',
|
|
1040
|
-
},
|
|
1041
|
-
tool: {
|
|
1042
|
-
name: 'write_file',
|
|
1043
|
-
displayName: 'write_file',
|
|
1044
|
-
description: 'Write file',
|
|
1045
|
-
build: vi.fn(),
|
|
1046
|
-
},
|
|
1047
|
-
invocation: {
|
|
1048
|
-
getDescription: () => 'Mock description',
|
|
1049
|
-
},
|
|
1050
|
-
},
|
|
1051
|
-
{
|
|
1052
|
-
request: {
|
|
1053
|
-
callId: 'call3',
|
|
1054
|
-
name: 'read_file',
|
|
1055
|
-
args: { path: '/test/file.txt' },
|
|
1056
|
-
isClientInitiated: false,
|
|
1057
|
-
prompt_id: 'prompt-id-1',
|
|
1058
|
-
},
|
|
1059
|
-
status: 'awaiting_approval',
|
|
1060
|
-
responseSubmittedToGemini: false,
|
|
1061
|
-
confirmationDetails: {
|
|
1062
|
-
type: 'info',
|
|
1063
|
-
title: 'Read File',
|
|
1064
|
-
onConfirm: mockOnConfirmRead,
|
|
1065
|
-
prompt: 'Read /test/file.txt?',
|
|
1066
|
-
},
|
|
1067
|
-
tool: {
|
|
1068
|
-
name: 'read_file',
|
|
1069
|
-
displayName: 'read_file',
|
|
1070
|
-
description: 'Read file',
|
|
1071
|
-
build: vi.fn(),
|
|
1072
|
-
},
|
|
1073
|
-
invocation: {
|
|
1074
|
-
getDescription: () => 'Mock description',
|
|
1075
|
-
},
|
|
1076
|
-
},
|
|
1061
|
+
createMockToolCall('replace', 'call1', 'edit', mockOnConfirmReplace),
|
|
1062
|
+
createMockToolCall('write_file', 'call2', 'edit', mockOnConfirmWrite),
|
|
1063
|
+
createMockToolCall('read_file', 'call3', 'info', mockOnConfirmRead),
|
|
1077
1064
|
];
|
|
1078
1065
|
const { result } = renderTestHook(awaitingApprovalToolCalls);
|
|
1079
1066
|
await act(async () => {
|
|
1080
1067
|
await result.current.handleApprovalModeChange(ApprovalMode.AUTO_EDIT);
|
|
1081
1068
|
});
|
|
1082
1069
|
// Only replace and write_file should be auto-approved
|
|
1083
|
-
expect(mockOnConfirmReplace).toHaveBeenCalledTimes(1);
|
|
1084
1070
|
expect(mockOnConfirmReplace).toHaveBeenCalledWith(ToolConfirmationOutcome.ProceedOnce);
|
|
1085
|
-
expect(mockOnConfirmWrite).toHaveBeenCalledTimes(1);
|
|
1086
1071
|
expect(mockOnConfirmWrite).toHaveBeenCalledWith(ToolConfirmationOutcome.ProceedOnce);
|
|
1087
1072
|
// read_file should not be auto-approved
|
|
1088
1073
|
expect(mockOnConfirmRead).not.toHaveBeenCalled();
|
|
@@ -1090,36 +1075,7 @@ describe('useGeminiStream', () => {
|
|
|
1090
1075
|
it('should not auto-approve any tools when switching to REQUIRE_CONFIRMATION mode', async () => {
|
|
1091
1076
|
const mockOnConfirm = vi.fn().mockResolvedValue(undefined);
|
|
1092
1077
|
const awaitingApprovalToolCalls = [
|
|
1093
|
-
|
|
1094
|
-
request: {
|
|
1095
|
-
callId: 'call1',
|
|
1096
|
-
name: 'replace',
|
|
1097
|
-
args: { old_string: 'old', new_string: 'new' },
|
|
1098
|
-
isClientInitiated: false,
|
|
1099
|
-
prompt_id: 'prompt-id-1',
|
|
1100
|
-
},
|
|
1101
|
-
status: 'awaiting_approval',
|
|
1102
|
-
responseSubmittedToGemini: false,
|
|
1103
|
-
confirmationDetails: {
|
|
1104
|
-
type: 'edit',
|
|
1105
|
-
title: 'Confirm Edit',
|
|
1106
|
-
onConfirm: mockOnConfirm,
|
|
1107
|
-
fileName: 'file.txt',
|
|
1108
|
-
filePath: '/test/file.txt',
|
|
1109
|
-
fileDiff: 'fake diff',
|
|
1110
|
-
originalContent: 'old',
|
|
1111
|
-
newContent: 'new',
|
|
1112
|
-
},
|
|
1113
|
-
tool: {
|
|
1114
|
-
name: 'replace',
|
|
1115
|
-
displayName: 'replace',
|
|
1116
|
-
description: 'Replace text',
|
|
1117
|
-
build: vi.fn(),
|
|
1118
|
-
},
|
|
1119
|
-
invocation: {
|
|
1120
|
-
getDescription: () => 'Mock description',
|
|
1121
|
-
},
|
|
1122
|
-
},
|
|
1078
|
+
createMockToolCall('replace', 'call1', 'edit', mockOnConfirm),
|
|
1123
1079
|
];
|
|
1124
1080
|
const { result } = renderTestHook(awaitingApprovalToolCalls);
|
|
1125
1081
|
await act(async () => {
|
|
@@ -1129,85 +1085,27 @@ describe('useGeminiStream', () => {
|
|
|
1129
1085
|
expect(mockOnConfirm).not.toHaveBeenCalled();
|
|
1130
1086
|
});
|
|
1131
1087
|
it('should handle errors gracefully when auto-approving tool calls', async () => {
|
|
1132
|
-
const
|
|
1133
|
-
.spyOn(
|
|
1088
|
+
const debuggerSpy = vi
|
|
1089
|
+
.spyOn(debugLogger, 'warn')
|
|
1134
1090
|
.mockImplementation(() => { });
|
|
1135
1091
|
const mockOnConfirmSuccess = vi.fn().mockResolvedValue(undefined);
|
|
1136
1092
|
const mockOnConfirmError = vi
|
|
1137
1093
|
.fn()
|
|
1138
1094
|
.mockRejectedValue(new Error('Approval failed'));
|
|
1139
1095
|
const awaitingApprovalToolCalls = [
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
callId: 'call1',
|
|
1143
|
-
name: 'replace',
|
|
1144
|
-
args: { old_string: 'old', new_string: 'new' },
|
|
1145
|
-
isClientInitiated: false,
|
|
1146
|
-
prompt_id: 'prompt-id-1',
|
|
1147
|
-
},
|
|
1148
|
-
status: 'awaiting_approval',
|
|
1149
|
-
responseSubmittedToGemini: false,
|
|
1150
|
-
confirmationDetails: {
|
|
1151
|
-
type: 'edit',
|
|
1152
|
-
title: 'Confirm Edit',
|
|
1153
|
-
onConfirm: mockOnConfirmSuccess,
|
|
1154
|
-
fileName: 'file.txt',
|
|
1155
|
-
filePath: '/test/file.txt',
|
|
1156
|
-
fileDiff: 'fake diff',
|
|
1157
|
-
originalContent: 'old',
|
|
1158
|
-
newContent: 'new',
|
|
1159
|
-
},
|
|
1160
|
-
tool: {
|
|
1161
|
-
name: 'replace',
|
|
1162
|
-
displayName: 'replace',
|
|
1163
|
-
description: 'Replace text',
|
|
1164
|
-
build: vi.fn(),
|
|
1165
|
-
},
|
|
1166
|
-
invocation: {
|
|
1167
|
-
getDescription: () => 'Mock description',
|
|
1168
|
-
},
|
|
1169
|
-
},
|
|
1170
|
-
{
|
|
1171
|
-
request: {
|
|
1172
|
-
callId: 'call2',
|
|
1173
|
-
name: 'write_file',
|
|
1174
|
-
args: { path: '/test/file.txt', content: 'content' },
|
|
1175
|
-
isClientInitiated: false,
|
|
1176
|
-
prompt_id: 'prompt-id-1',
|
|
1177
|
-
},
|
|
1178
|
-
status: 'awaiting_approval',
|
|
1179
|
-
responseSubmittedToGemini: false,
|
|
1180
|
-
confirmationDetails: {
|
|
1181
|
-
type: 'edit',
|
|
1182
|
-
title: 'Confirm Edit',
|
|
1183
|
-
onConfirm: mockOnConfirmError,
|
|
1184
|
-
fileName: 'file.txt',
|
|
1185
|
-
filePath: '/test/file.txt',
|
|
1186
|
-
fileDiff: 'fake diff',
|
|
1187
|
-
originalContent: null,
|
|
1188
|
-
newContent: 'content',
|
|
1189
|
-
},
|
|
1190
|
-
tool: {
|
|
1191
|
-
name: 'write_file',
|
|
1192
|
-
displayName: 'write_file',
|
|
1193
|
-
description: 'Write file',
|
|
1194
|
-
build: vi.fn(),
|
|
1195
|
-
},
|
|
1196
|
-
invocation: {
|
|
1197
|
-
getDescription: () => 'Mock description',
|
|
1198
|
-
},
|
|
1199
|
-
},
|
|
1096
|
+
createMockToolCall('replace', 'call1', 'edit', mockOnConfirmSuccess),
|
|
1097
|
+
createMockToolCall('write_file', 'call2', 'edit', mockOnConfirmError),
|
|
1200
1098
|
];
|
|
1201
1099
|
const { result } = renderTestHook(awaitingApprovalToolCalls);
|
|
1202
1100
|
await act(async () => {
|
|
1203
1101
|
await result.current.handleApprovalModeChange(ApprovalMode.YOLO);
|
|
1204
1102
|
});
|
|
1205
1103
|
// Both confirmation methods should be called
|
|
1206
|
-
expect(mockOnConfirmSuccess).
|
|
1207
|
-
expect(mockOnConfirmError).
|
|
1104
|
+
expect(mockOnConfirmSuccess).toHaveBeenCalled();
|
|
1105
|
+
expect(mockOnConfirmError).toHaveBeenCalled();
|
|
1208
1106
|
// Error should be logged
|
|
1209
|
-
expect(
|
|
1210
|
-
|
|
1107
|
+
expect(debuggerSpy).toHaveBeenCalledWith('Failed to auto-approve tool call call2:', expect.any(Error));
|
|
1108
|
+
debuggerSpy.mockRestore();
|
|
1211
1109
|
});
|
|
1212
1110
|
it('should skip tool calls without confirmationDetails', async () => {
|
|
1213
1111
|
const awaitingApprovalToolCalls = [
|
|
@@ -1374,53 +1272,37 @@ describe('useGeminiStream', () => {
|
|
|
1374
1272
|
beforeEach(() => {
|
|
1375
1273
|
vi.mocked(tokenLimit).mockReturnValue(100);
|
|
1376
1274
|
});
|
|
1377
|
-
it(
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
await act(async () => {
|
|
1392
|
-
await result.current.submitQuery('Test overflow');
|
|
1393
|
-
});
|
|
1394
|
-
// Check that the message was added without suggestion
|
|
1395
|
-
await waitFor(() => {
|
|
1396
|
-
expect(mockAddItem).toHaveBeenCalledWith({
|
|
1397
|
-
type: 'info',
|
|
1398
|
-
text: `Sending this message (20 tokens) might exceed the remaining context window limit (80 tokens).`,
|
|
1399
|
-
}, expect.any(Number));
|
|
1400
|
-
});
|
|
1401
|
-
});
|
|
1402
|
-
it('should add message with suggestion when remaining tokens are < 75% of limit', async () => {
|
|
1403
|
-
// Setup mock to return a stream with ContextWindowWillOverflow event
|
|
1404
|
-
// Limit is 100, remaining is 70 (< 75)
|
|
1275
|
+
it.each([
|
|
1276
|
+
{
|
|
1277
|
+
name: 'without suggestion when remaining tokens are > 75% of limit',
|
|
1278
|
+
requestTokens: 20,
|
|
1279
|
+
remainingTokens: 80,
|
|
1280
|
+
expectedMessage: 'Sending this message (20 tokens) might exceed the remaining context window limit (80 tokens).',
|
|
1281
|
+
},
|
|
1282
|
+
{
|
|
1283
|
+
name: 'with suggestion when remaining tokens are < 75% of limit',
|
|
1284
|
+
requestTokens: 30,
|
|
1285
|
+
remainingTokens: 70,
|
|
1286
|
+
expectedMessage: 'Sending this message (30 tokens) might exceed the remaining context window limit (70 tokens). Please try reducing the size of your message or use the `/compress` command to compress the chat history.',
|
|
1287
|
+
},
|
|
1288
|
+
])('should add message $name', async ({ requestTokens, remainingTokens, expectedMessage }) => {
|
|
1405
1289
|
mockSendMessageStream.mockReturnValue((async function* () {
|
|
1406
1290
|
yield {
|
|
1407
1291
|
type: ServerGeminiEventType.ContextWindowWillOverflow,
|
|
1408
1292
|
value: {
|
|
1409
|
-
estimatedRequestTokenCount:
|
|
1410
|
-
remainingTokenCount:
|
|
1293
|
+
estimatedRequestTokenCount: requestTokens,
|
|
1294
|
+
remainingTokenCount: remainingTokens,
|
|
1411
1295
|
},
|
|
1412
1296
|
};
|
|
1413
1297
|
})());
|
|
1414
|
-
const { result } =
|
|
1415
|
-
// Submit a query
|
|
1298
|
+
const { result } = renderHookWithDefaults();
|
|
1416
1299
|
await act(async () => {
|
|
1417
1300
|
await result.current.submitQuery('Test overflow');
|
|
1418
1301
|
});
|
|
1419
|
-
// Check that the message was added with suggestion
|
|
1420
1302
|
await waitFor(() => {
|
|
1421
1303
|
expect(mockAddItem).toHaveBeenCalledWith({
|
|
1422
1304
|
type: 'info',
|
|
1423
|
-
text:
|
|
1305
|
+
text: expectedMessage,
|
|
1424
1306
|
}, expect.any(Number));
|
|
1425
1307
|
});
|
|
1426
1308
|
});
|
|
@@ -1447,112 +1329,71 @@ describe('useGeminiStream', () => {
|
|
|
1447
1329
|
expect(onCancelSubmitSpy).toHaveBeenCalled();
|
|
1448
1330
|
});
|
|
1449
1331
|
});
|
|
1450
|
-
it(
|
|
1451
|
-
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1332
|
+
it.each([
|
|
1333
|
+
{
|
|
1334
|
+
reason: 'STOP',
|
|
1335
|
+
shouldAddMessage: false,
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
reason: 'FINISH_REASON_UNSPECIFIED',
|
|
1339
|
+
shouldAddMessage: false,
|
|
1340
|
+
},
|
|
1341
|
+
{
|
|
1342
|
+
reason: 'SAFETY',
|
|
1343
|
+
message: '⚠️ Response stopped due to safety reasons.',
|
|
1344
|
+
},
|
|
1345
|
+
{
|
|
1346
|
+
reason: 'RECITATION',
|
|
1347
|
+
message: '⚠️ Response stopped due to recitation policy.',
|
|
1348
|
+
},
|
|
1349
|
+
{
|
|
1350
|
+
reason: 'LANGUAGE',
|
|
1351
|
+
message: '⚠️ Response stopped due to unsupported language.',
|
|
1352
|
+
},
|
|
1353
|
+
{
|
|
1354
|
+
reason: 'BLOCKLIST',
|
|
1355
|
+
message: '⚠️ Response stopped due to forbidden terms.',
|
|
1356
|
+
},
|
|
1357
|
+
{
|
|
1358
|
+
reason: 'PROHIBITED_CONTENT',
|
|
1359
|
+
message: '⚠️ Response stopped due to prohibited content.',
|
|
1360
|
+
},
|
|
1361
|
+
{
|
|
1362
|
+
reason: 'SPII',
|
|
1363
|
+
message: '⚠️ Response stopped due to sensitive personally identifiable information.',
|
|
1364
|
+
},
|
|
1365
|
+
{
|
|
1366
|
+
reason: 'OTHER',
|
|
1367
|
+
message: '⚠️ Response stopped for other reasons.',
|
|
1368
|
+
},
|
|
1369
|
+
{
|
|
1370
|
+
reason: 'MALFORMED_FUNCTION_CALL',
|
|
1371
|
+
message: '⚠️ Response stopped due to malformed function call.',
|
|
1372
|
+
},
|
|
1373
|
+
{
|
|
1374
|
+
reason: 'IMAGE_SAFETY',
|
|
1375
|
+
message: '⚠️ Response stopped due to image safety violations.',
|
|
1376
|
+
},
|
|
1377
|
+
{
|
|
1378
|
+
reason: 'UNEXPECTED_TOOL_CALL',
|
|
1379
|
+
message: '⚠️ Response stopped due to unexpected tool call.',
|
|
1380
|
+
},
|
|
1381
|
+
])('should handle $reason finish reason correctly', async ({ reason, shouldAddMessage = true, message }) => {
|
|
1475
1382
|
mockSendMessageStream.mockReturnValue((async function* () {
|
|
1476
1383
|
yield {
|
|
1477
1384
|
type: ServerGeminiEventType.Content,
|
|
1478
|
-
value:
|
|
1385
|
+
value: `Response for ${reason}`,
|
|
1479
1386
|
};
|
|
1480
1387
|
yield {
|
|
1481
1388
|
type: ServerGeminiEventType.Finished,
|
|
1482
|
-
value: {
|
|
1483
|
-
reason: 'FINISH_REASON_UNSPECIFIED',
|
|
1484
|
-
usageMetadata: undefined,
|
|
1485
|
-
},
|
|
1389
|
+
value: { reason, usageMetadata: undefined },
|
|
1486
1390
|
};
|
|
1487
1391
|
})());
|
|
1488
|
-
const { result } =
|
|
1489
|
-
// Submit a query
|
|
1392
|
+
const { result } = renderHookWithDefaults();
|
|
1490
1393
|
await act(async () => {
|
|
1491
|
-
await result.current.submitQuery(
|
|
1394
|
+
await result.current.submitQuery(`Test ${reason}`);
|
|
1492
1395
|
});
|
|
1493
|
-
|
|
1494
|
-
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
1495
|
-
// Check that no info message was added
|
|
1496
|
-
const infoMessages = mockAddItem.mock.calls.filter((call) => call[0].type === 'info');
|
|
1497
|
-
expect(infoMessages).toHaveLength(0);
|
|
1498
|
-
});
|
|
1499
|
-
it('should add appropriate messages for other finish reasons', async () => {
|
|
1500
|
-
const testCases = [
|
|
1501
|
-
{
|
|
1502
|
-
reason: 'SAFETY',
|
|
1503
|
-
message: '⚠️ Response stopped due to safety reasons.',
|
|
1504
|
-
},
|
|
1505
|
-
{
|
|
1506
|
-
reason: 'RECITATION',
|
|
1507
|
-
message: '⚠️ Response stopped due to recitation policy.',
|
|
1508
|
-
},
|
|
1509
|
-
{
|
|
1510
|
-
reason: 'LANGUAGE',
|
|
1511
|
-
message: '⚠️ Response stopped due to unsupported language.',
|
|
1512
|
-
},
|
|
1513
|
-
{
|
|
1514
|
-
reason: 'BLOCKLIST',
|
|
1515
|
-
message: '⚠️ Response stopped due to forbidden terms.',
|
|
1516
|
-
},
|
|
1517
|
-
{
|
|
1518
|
-
reason: 'PROHIBITED_CONTENT',
|
|
1519
|
-
message: '⚠️ Response stopped due to prohibited content.',
|
|
1520
|
-
},
|
|
1521
|
-
{
|
|
1522
|
-
reason: 'SPII',
|
|
1523
|
-
message: '⚠️ Response stopped due to sensitive personally identifiable information.',
|
|
1524
|
-
},
|
|
1525
|
-
{ reason: 'OTHER', message: '⚠️ Response stopped for other reasons.' },
|
|
1526
|
-
{
|
|
1527
|
-
reason: 'MALFORMED_FUNCTION_CALL',
|
|
1528
|
-
message: '⚠️ Response stopped due to malformed function call.',
|
|
1529
|
-
},
|
|
1530
|
-
{
|
|
1531
|
-
reason: 'IMAGE_SAFETY',
|
|
1532
|
-
message: '⚠️ Response stopped due to image safety violations.',
|
|
1533
|
-
},
|
|
1534
|
-
{
|
|
1535
|
-
reason: 'UNEXPECTED_TOOL_CALL',
|
|
1536
|
-
message: '⚠️ Response stopped due to unexpected tool call.',
|
|
1537
|
-
},
|
|
1538
|
-
];
|
|
1539
|
-
for (const { reason, message } of testCases) {
|
|
1540
|
-
// Reset mocks for each test case
|
|
1541
|
-
mockAddItem.mockClear();
|
|
1542
|
-
mockSendMessageStream.mockReturnValue((async function* () {
|
|
1543
|
-
yield {
|
|
1544
|
-
type: ServerGeminiEventType.Content,
|
|
1545
|
-
value: `Response for ${reason}`,
|
|
1546
|
-
};
|
|
1547
|
-
yield {
|
|
1548
|
-
type: ServerGeminiEventType.Finished,
|
|
1549
|
-
value: { reason, usageMetadata: undefined },
|
|
1550
|
-
};
|
|
1551
|
-
})());
|
|
1552
|
-
const { result } = renderHook(() => useGeminiStream(new MockedGeminiClientClass(mockConfig), [], mockAddItem, mockConfig, mockLoadedSettings, mockOnDebugMessage, mockHandleSlashCommand, false, () => 'vscode', () => { }, () => Promise.resolve(), false, () => { }, () => { }, () => { }, vi.fn(), 80, 24));
|
|
1553
|
-
await act(async () => {
|
|
1554
|
-
await result.current.submitQuery(`Test ${reason}`);
|
|
1555
|
-
});
|
|
1396
|
+
if (shouldAddMessage) {
|
|
1556
1397
|
await waitFor(() => {
|
|
1557
1398
|
expect(mockAddItem).toHaveBeenCalledWith({
|
|
1558
1399
|
type: 'info',
|
|
@@ -1560,6 +1401,14 @@ describe('useGeminiStream', () => {
|
|
|
1560
1401
|
}, expect.any(Number));
|
|
1561
1402
|
});
|
|
1562
1403
|
}
|
|
1404
|
+
else {
|
|
1405
|
+
// Verify state returns to idle without any info messages
|
|
1406
|
+
await waitFor(() => {
|
|
1407
|
+
expect(result.current.streamingState).toBe(StreamingState.Idle);
|
|
1408
|
+
});
|
|
1409
|
+
const infoMessages = mockAddItem.mock.calls.filter((call) => call[0].type === 'info');
|
|
1410
|
+
expect(infoMessages).toHaveLength(0);
|
|
1411
|
+
}
|
|
1563
1412
|
});
|
|
1564
1413
|
});
|
|
1565
1414
|
it('should process @include commands, adding user turn after processing to prevent race conditions', async () => {
|