@vybestack/llxprt-code 0.1.20 → 0.1.22
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 +31 -0
- package/dist/package.json +3 -3
- package/dist/src/commands/mcp/add.js +11 -0
- package/dist/src/commands/mcp/add.js.map +1 -1
- package/dist/src/config/auth.test.d.ts +6 -0
- package/dist/src/config/auth.test.js +57 -0
- package/dist/src/config/auth.test.js.map +1 -0
- package/dist/src/config/config.d.ts +1 -1
- package/dist/src/config/config.js +27 -14
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/keyBindings.js +3 -2
- package/dist/src/config/keyBindings.js.map +1 -1
- package/dist/src/config/keyBindings.test.d.ts +6 -0
- package/dist/src/config/keyBindings.test.js +51 -0
- package/dist/src/config/keyBindings.test.js.map +1 -0
- package/dist/src/config/logging/loggingConfig.test.d.ts +6 -0
- package/dist/src/config/logging/loggingConfig.test.js +363 -0
- package/dist/src/config/logging/loggingConfig.test.js.map +1 -0
- package/dist/src/config/settingsSchema.d.ts +0 -9
- package/dist/src/config/settingsSchema.js +0 -9
- package/dist/src/config/settingsSchema.js.map +1 -1
- package/dist/src/config/settingsSchema.test.d.ts +6 -0
- package/dist/src/config/settingsSchema.test.js +195 -0
- package/dist/src/config/settingsSchema.test.js.map +1 -0
- package/dist/src/config/trustedFolders.test.d.ts +6 -0
- package/dist/src/config/trustedFolders.test.js +156 -0
- package/dist/src/config/trustedFolders.test.js.map +1 -0
- package/dist/src/gemini.js +14 -4
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.d.ts +6 -0
- package/dist/src/gemini.test.js +199 -0
- package/dist/src/gemini.test.js.map +1 -0
- package/dist/src/generated/git-commit.d.ts +1 -1
- package/dist/src/generated/git-commit.js +1 -1
- package/dist/src/integration-tests/base-url-behavior.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/base-url-behavior.integration.test.js +492 -0
- package/dist/src/integration-tests/base-url-behavior.integration.test.js.map +1 -0
- package/dist/src/integration-tests/cli-args.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/cli-args.integration.test.js +398 -0
- package/dist/src/integration-tests/cli-args.integration.test.js.map +1 -0
- package/dist/src/integration-tests/compression-settings-apply.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/compression-settings-apply.integration.test.js +436 -0
- package/dist/src/integration-tests/compression-settings-apply.integration.test.js.map +1 -0
- package/dist/src/integration-tests/ephemeral-settings.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/ephemeral-settings.integration.test.js +318 -0
- package/dist/src/integration-tests/ephemeral-settings.integration.test.js.map +1 -0
- package/dist/src/integration-tests/model-params-isolation.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/model-params-isolation.integration.test.js +564 -0
- package/dist/src/integration-tests/model-params-isolation.integration.test.js.map +1 -0
- package/dist/src/integration-tests/modelParams.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/modelParams.integration.test.js +784 -0
- package/dist/src/integration-tests/modelParams.integration.test.js.map +1 -0
- package/dist/src/integration-tests/profile-keyfile.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/profile-keyfile.integration.test.js +429 -0
- package/dist/src/integration-tests/profile-keyfile.integration.test.js.map +1 -0
- package/dist/src/integration-tests/profile-system.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/profile-system.integration.test.js +364 -0
- package/dist/src/integration-tests/profile-system.integration.test.js.map +1 -0
- package/dist/src/integration-tests/provider-switching.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/provider-switching.integration.test.js +207 -0
- package/dist/src/integration-tests/provider-switching.integration.test.js.map +1 -0
- package/dist/src/integration-tests/security.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/security.integration.test.js +319 -0
- package/dist/src/integration-tests/security.integration.test.js.map +1 -0
- package/dist/src/integration-tests/test-utils.test.d.ts +6 -0
- package/dist/src/integration-tests/test-utils.test.js +221 -0
- package/dist/src/integration-tests/test-utils.test.js.map +1 -0
- package/dist/src/integration-tests/todo-continuation.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/todo-continuation.integration.test.js +559 -0
- package/dist/src/integration-tests/todo-continuation.integration.test.js.map +1 -0
- package/dist/src/nonInteractiveCli.js +2 -5
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/providers/logging/LoggingProviderWrapper.test.d.ts +6 -0
- package/dist/src/providers/logging/LoggingProviderWrapper.test.js +305 -0
- package/dist/src/providers/logging/LoggingProviderWrapper.test.js.map +1 -0
- package/dist/src/providers/logging/git-stats.integration.test.d.ts +6 -0
- package/dist/src/providers/logging/git-stats.integration.test.js +245 -0
- package/dist/src/providers/logging/git-stats.integration.test.js.map +1 -0
- package/dist/src/providers/logging/git-stats.test.d.ts +6 -0
- package/dist/src/providers/logging/git-stats.test.js +432 -0
- package/dist/src/providers/logging/git-stats.test.js.map +1 -0
- package/dist/src/providers/logging/multi-provider-logging.integration.test.d.ts +6 -0
- package/dist/src/providers/logging/multi-provider-logging.integration.test.js +531 -0
- package/dist/src/providers/logging/multi-provider-logging.integration.test.js.map +1 -0
- package/dist/src/providers/logging/performance.test.d.ts +6 -0
- package/dist/src/providers/logging/performance.test.js +465 -0
- package/dist/src/providers/logging/performance.test.js.map +1 -0
- package/dist/src/providers/provider-gemini-switching.test.d.ts +6 -0
- package/dist/src/providers/provider-gemini-switching.test.js +129 -0
- package/dist/src/providers/provider-gemini-switching.test.js.map +1 -0
- package/dist/src/providers/provider-switching.integration.test.d.ts +6 -0
- package/dist/src/providers/provider-switching.integration.test.js +113 -0
- package/dist/src/providers/provider-switching.integration.test.js.map +1 -0
- package/dist/src/providers/providerManagerInstance.test.d.ts +6 -0
- package/dist/src/providers/providerManagerInstance.test.js +104 -0
- package/dist/src/providers/providerManagerInstance.test.js.map +1 -0
- package/dist/src/services/BuiltinCommandLoader.test.d.ts +6 -0
- package/dist/src/services/BuiltinCommandLoader.test.js +118 -0
- package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -0
- package/dist/src/services/CommandService.test.d.ts +6 -0
- package/dist/src/services/CommandService.test.js +232 -0
- package/dist/src/services/CommandService.test.js.map +1 -0
- package/dist/src/services/FileCommandLoader.js +10 -8
- package/dist/src/services/FileCommandLoader.js.map +1 -1
- package/dist/src/services/prompt-processors/argumentProcessor.d.ts +2 -7
- package/dist/src/services/prompt-processors/argumentProcessor.js +2 -10
- package/dist/src/services/prompt-processors/argumentProcessor.js.map +1 -1
- package/dist/src/services/prompt-processors/shellProcessor.d.ts +16 -13
- package/dist/src/services/prompt-processors/shellProcessor.js +133 -40
- package/dist/src/services/prompt-processors/shellProcessor.js.map +1 -1
- package/dist/src/services/prompt-processors/types.d.ts +2 -0
- package/dist/src/services/prompt-processors/types.js +2 -0
- package/dist/src/services/prompt-processors/types.js.map +1 -1
- package/dist/src/storage/ConversationStorage.test.d.ts +6 -0
- package/dist/src/storage/ConversationStorage.test.js +379 -0
- package/dist/src/storage/ConversationStorage.test.js.map +1 -0
- package/dist/src/test-utils/customMatchers.d.ts +14 -0
- package/dist/src/test-utils/customMatchers.js +46 -0
- package/dist/src/test-utils/customMatchers.js.map +1 -0
- package/dist/src/test-utils/mockCommandContext.d.ts +18 -0
- package/dist/src/test-utils/mockCommandContext.js +86 -0
- package/dist/src/test-utils/mockCommandContext.js.map +1 -0
- package/dist/src/test-utils/mockCommandContext.test.d.ts +6 -0
- package/dist/src/test-utils/mockCommandContext.test.js +51 -0
- package/dist/src/test-utils/mockCommandContext.test.js.map +1 -0
- package/dist/src/test-utils/render.d.ts +8 -0
- package/dist/src/test-utils/render.js +10 -0
- package/dist/src/test-utils/render.js.map +1 -0
- package/dist/src/test-utils/responsive-testing.d.ts +14 -0
- package/dist/src/test-utils/responsive-testing.js +35 -0
- package/dist/src/test-utils/responsive-testing.js.map +1 -0
- package/dist/src/test-utils/responsive-testing.test.d.ts +6 -0
- package/dist/src/test-utils/responsive-testing.test.js +89 -0
- package/dist/src/test-utils/responsive-testing.test.js.map +1 -0
- package/dist/src/test-utils/testProviderConfig.d.ts +18 -0
- package/dist/src/test-utils/testProviderConfig.js +19 -0
- package/dist/src/test-utils/testProviderConfig.js.map +1 -0
- package/dist/src/ui/App.js +7 -6
- package/dist/src/ui/App.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/colors.js +25 -2
- package/dist/src/ui/colors.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.js +3 -0
- package/dist/src/ui/commands/aboutCommand.js.map +1 -1
- package/dist/src/ui/commands/chatCommand.js +8 -6
- package/dist/src/ui/commands/chatCommand.js.map +1 -1
- package/dist/src/ui/commands/diagnosticsCommand.js +0 -1
- package/dist/src/ui/commands/diagnosticsCommand.js.map +1 -1
- package/dist/src/ui/commands/ideCommand.js +3 -3
- package/dist/src/ui/commands/ideCommand.js.map +1 -1
- package/dist/src/ui/commands/keyCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/keyCommand.test.js +128 -0
- package/dist/src/ui/commands/keyCommand.test.js.map +1 -0
- package/dist/src/ui/commands/profileCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/profileCommand.test.js +343 -0
- package/dist/src/ui/commands/profileCommand.test.js.map +1 -0
- package/dist/src/ui/commands/setCommand.js +41 -0
- package/dist/src/ui/commands/setCommand.js.map +1 -1
- package/dist/src/ui/commands/setCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/setCommand.test.js +431 -0
- package/dist/src/ui/commands/setCommand.test.js.map +1 -0
- package/dist/src/ui/commands/setupGithubCommand.test.d.ts +6 -0
- package/dist/src/ui/commands/setupGithubCommand.test.js +69 -0
- package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -0
- package/dist/src/ui/commands/toolformatCommand.test.d.ts +1 -0
- package/dist/src/ui/commands/toolformatCommand.test.js +145 -0
- package/dist/src/ui/commands/toolformatCommand.test.js.map +1 -0
- package/dist/src/ui/components/AboutBox.d.ts +1 -0
- package/dist/src/ui/components/AboutBox.js +1 -1
- package/dist/src/ui/components/AboutBox.js.map +1 -1
- package/dist/src/ui/components/AuthDialog.js +1 -1
- package/dist/src/ui/components/AuthDialog.js.map +1 -1
- package/dist/src/ui/components/AuthDialog.test.d.ts +6 -0
- package/dist/src/ui/components/AuthDialog.test.js +252 -0
- package/dist/src/ui/components/AuthDialog.test.js.map +1 -0
- package/dist/src/ui/components/ContextIndicator.ui.test.d.ts +1 -0
- package/dist/src/ui/components/ContextIndicator.ui.test.js +89 -0
- package/dist/src/ui/components/ContextIndicator.ui.test.js.map +1 -0
- package/dist/src/ui/components/ContextSummaryDisplay.js +1 -1
- package/dist/src/ui/components/ContextUsageDisplay.semantic.test.d.ts +6 -0
- package/dist/src/ui/components/ContextUsageDisplay.semantic.test.js +75 -0
- package/dist/src/ui/components/ContextUsageDisplay.semantic.test.js.map +1 -0
- package/dist/src/ui/components/FolderTrustDialog.test.d.ts +6 -0
- package/dist/src/ui/components/FolderTrustDialog.test.js +26 -0
- package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -0
- package/dist/src/ui/components/Footer.d.ts +1 -0
- package/dist/src/ui/components/Footer.js +2 -2
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/Footer.responsive.test.d.ts +6 -0
- package/dist/src/ui/components/Footer.responsive.test.js +262 -0
- package/dist/src/ui/components/Footer.responsive.test.js.map +1 -0
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.test.d.ts +6 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.js +93 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -0
- package/dist/src/ui/components/InputPrompt.js +0 -4
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.paste.test.d.ts +6 -0
- package/dist/src/ui/components/InputPrompt.paste.test.js +263 -0
- package/dist/src/ui/components/InputPrompt.paste.test.js.map +1 -0
- package/dist/src/ui/components/LoadingIndicator.test.d.ts +6 -0
- package/dist/src/ui/components/LoadingIndicator.test.js +149 -0
- package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -0
- package/dist/src/ui/components/MemoryUsageDisplay.semantic.test.d.ts +6 -0
- package/dist/src/ui/components/MemoryUsageDisplay.semantic.test.js +127 -0
- package/dist/src/ui/components/MemoryUsageDisplay.semantic.test.js.map +1 -0
- package/dist/src/ui/components/ProviderDialog.responsive.test.d.ts +6 -0
- package/dist/src/ui/components/ProviderDialog.responsive.test.js +153 -0
- package/dist/src/ui/components/ProviderDialog.responsive.test.js.map +1 -0
- package/dist/src/ui/components/ProviderModelDialog.responsive.test.d.ts +6 -0
- package/dist/src/ui/components/ProviderModelDialog.responsive.test.js +252 -0
- package/dist/src/ui/components/ProviderModelDialog.responsive.test.js.map +1 -0
- package/dist/src/ui/components/ProviderModelDialog.test.d.ts +6 -0
- package/dist/src/ui/components/ProviderModelDialog.test.js +197 -0
- package/dist/src/ui/components/ProviderModelDialog.test.js.map +1 -0
- package/dist/src/ui/components/SettingsDialog.test.d.ts +6 -0
- package/dist/src/ui/components/SettingsDialog.test.js +555 -0
- package/dist/src/ui/components/SettingsDialog.test.js.map +1 -0
- package/dist/src/ui/components/ShellConfirmationDialog.js +2 -1
- package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
- package/dist/src/ui/components/ShellConfirmationDialog.test.d.ts +6 -0
- package/dist/src/ui/components/ShellConfirmationDialog.test.js +40 -0
- package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -0
- package/dist/src/ui/components/TodoPanel.responsive.test.d.ts +6 -0
- package/dist/src/ui/components/TodoPanel.responsive.test.js +221 -0
- package/dist/src/ui/components/TodoPanel.responsive.test.js.map +1 -0
- package/dist/src/ui/components/TodoPanel.semantic.test.d.ts +6 -0
- package/dist/src/ui/components/TodoPanel.semantic.test.js +137 -0
- package/dist/src/ui/components/TodoPanel.semantic.test.js.map +1 -0
- package/dist/src/ui/components/__tests__/LayoutManager.test.d.ts +6 -0
- package/dist/src/ui/components/__tests__/LayoutManager.test.js +94 -0
- package/dist/src/ui/components/__tests__/LayoutManager.test.js.map +1 -0
- package/dist/src/ui/components/messages/DiffRenderer.js +9 -3
- package/dist/src/ui/components/messages/DiffRenderer.js.map +1 -1
- package/dist/src/ui/components/messages/DiffRenderer.test.d.ts +6 -0
- package/dist/src/ui/components/messages/DiffRenderer.test.js +266 -0
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -0
- package/dist/src/ui/components/messages/InfoMessage.js +2 -1
- package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +15 -5
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolConfirmationMessage.responsive.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.responsive.test.js +173 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.responsive.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +37 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolMessage.test.d.ts +6 -0
- package/dist/src/ui/components/messages/ToolMessage.test.js +118 -0
- package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -0
- package/dist/src/ui/components/shared/MaxSizedBox.test.d.ts +6 -0
- package/dist/src/ui/components/shared/MaxSizedBox.test.js +154 -0
- package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -0
- package/dist/src/ui/components/shared/RadioButtonSelect.js +1 -1
- package/dist/src/ui/components/shared/RadioButtonSelect.js.map +1 -1
- package/dist/src/ui/components/shared/RadioButtonSelect.test.d.ts +6 -0
- package/dist/src/ui/components/shared/RadioButtonSelect.test.js +113 -0
- package/dist/src/ui/components/shared/RadioButtonSelect.test.js.map +1 -0
- package/dist/src/ui/containers/SessionController.test.d.ts +6 -0
- package/dist/src/ui/containers/SessionController.test.js +440 -0
- package/dist/src/ui/containers/SessionController.test.js.map +1 -0
- package/dist/src/ui/contexts/KeypressContext.d.ts +30 -0
- package/dist/src/ui/contexts/KeypressContext.js +314 -0
- package/dist/src/ui/contexts/KeypressContext.js.map +1 -0
- package/dist/src/ui/contexts/KeypressContext.test.d.ts +6 -0
- package/dist/src/ui/contexts/KeypressContext.test.js +220 -0
- package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -0
- package/dist/src/ui/hooks/atCommandProcessor.test.d.ts +6 -0
- package/dist/src/ui/hooks/atCommandProcessor.test.js +830 -0
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -0
- package/dist/src/ui/hooks/index.d.ts +1 -0
- package/dist/src/ui/hooks/index.js +1 -0
- package/dist/src/ui/hooks/index.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.d.ts +6 -0
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +328 -0
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -0
- package/dist/src/ui/hooks/slashCommandProcessor.js +13 -7
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useAtCompletion.js +3 -5
- package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.d.ts +6 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +191 -0
- package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -0
- package/dist/src/ui/hooks/useEditorSettings.test.d.ts +6 -0
- package/dist/src/ui/hooks/useEditorSettings.test.js +221 -0
- package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -0
- package/dist/src/ui/hooks/useGeminiStream.integration.test.d.ts +6 -0
- package/dist/src/ui/hooks/useGeminiStream.integration.test.js +800 -0
- package/dist/src/ui/hooks/useGeminiStream.integration.test.js.map +1 -0
- package/dist/src/ui/hooks/useGeminiStream.js +12 -47
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGitBranchName.test.d.ts +6 -0
- package/dist/src/ui/hooks/useGitBranchName.test.js +170 -0
- package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -0
- package/dist/src/ui/hooks/useHistoryManager.test.d.ts +6 -0
- package/dist/src/ui/hooks/useHistoryManager.test.js +171 -0
- package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -0
- package/dist/src/ui/hooks/useInputHistory.test.d.ts +6 -0
- package/dist/src/ui/hooks/useInputHistory.test.js +207 -0
- package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -0
- package/dist/src/ui/hooks/useKeypress.d.ts +4 -24
- package/dist/src/ui/hooks/useKeypress.js +9 -330
- package/dist/src/ui/hooks/useKeypress.js.map +1 -1
- package/dist/src/ui/hooks/useKeypress.test.d.ts +6 -0
- package/dist/src/ui/hooks/useKeypress.test.js +176 -0
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
- package/dist/src/ui/hooks/usePhraseCycler.js +1 -0
- package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
- package/dist/src/ui/hooks/useResponsive.test.d.ts +6 -0
- package/dist/src/ui/hooks/useResponsive.test.js +124 -0
- package/dist/src/ui/hooks/useResponsive.test.js.map +1 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.d.ts +6 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +163 -0
- package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -0
- package/dist/src/ui/hooks/useShellHistory.test.d.ts +6 -0
- package/dist/src/ui/hooks/useShellHistory.test.js +162 -0
- package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -0
- package/dist/src/ui/hooks/useSlashCompletion.test.d.ts +6 -0
- package/dist/src/ui/hooks/useSlashCompletion.test.js +929 -0
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -0
- package/dist/src/ui/hooks/useStableCallback.test.d.ts +6 -0
- package/dist/src/ui/hooks/useStableCallback.test.js +57 -0
- package/dist/src/ui/hooks/useStableCallback.test.js.map +1 -0
- package/dist/src/ui/hooks/useToolScheduler.test.d.ts +6 -0
- package/dist/src/ui/hooks/useToolScheduler.test.js +841 -0
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -0
- package/dist/src/ui/keyMatchers.test.d.ts +6 -0
- package/dist/src/ui/keyMatchers.test.js +276 -0
- package/dist/src/ui/keyMatchers.test.js.map +1 -0
- package/dist/src/ui/reducers/appReducer.test.d.ts +6 -0
- package/dist/src/ui/reducers/appReducer.test.js +519 -0
- package/dist/src/ui/reducers/appReducer.test.js.map +1 -0
- package/dist/src/ui/themes/color-utils.test.d.ts +6 -0
- package/dist/src/ui/themes/color-utils.test.js +197 -0
- package/dist/src/ui/themes/color-utils.test.js.map +1 -0
- package/dist/src/ui/themes/semantic-resolver.js +16 -7
- package/dist/src/ui/themes/semantic-resolver.js.map +1 -1
- package/dist/src/ui/themes/semantic-resolver.test.d.ts +6 -0
- package/dist/src/ui/themes/semantic-resolver.test.js +246 -0
- package/dist/src/ui/themes/semantic-resolver.test.js.map +1 -0
- package/dist/src/ui/themes/semantic-tokens.d.ts +18 -33
- package/dist/src/ui/themes/semantic-tokens.js +88 -1
- package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
- package/dist/src/ui/themes/semantic-tokens.test.d.ts +6 -0
- package/dist/src/ui/themes/semantic-tokens.test.js +289 -0
- package/dist/src/ui/themes/semantic-tokens.test.js.map +1 -0
- package/dist/src/ui/themes/theme-compat.d.ts +1 -1
- package/dist/src/ui/themes/theme-compat.js +7 -2
- package/dist/src/ui/themes/theme-compat.js.map +1 -1
- package/dist/src/ui/themes/theme-manager.test.d.ts +6 -0
- package/dist/src/ui/themes/theme-manager.test.js +160 -0
- package/dist/src/ui/themes/theme-manager.test.js.map +1 -0
- package/dist/src/ui/types.d.ts +12 -1
- package/dist/src/ui/types.js +1 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.js +8 -1
- package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
- package/dist/src/ui/utils/MarkdownDisplay.test.d.ts +6 -0
- package/dist/src/ui/utils/MarkdownDisplay.test.js +151 -0
- package/dist/src/ui/utils/MarkdownDisplay.test.js.map +1 -0
- package/dist/src/ui/utils/clipboardUtils.test.d.ts +6 -0
- package/dist/src/ui/utils/clipboardUtils.test.js +65 -0
- package/dist/src/ui/utils/clipboardUtils.test.js.map +1 -0
- package/dist/src/ui/utils/commandUtils.test.d.ts +6 -0
- package/dist/src/ui/utils/commandUtils.test.js +294 -0
- package/dist/src/ui/utils/commandUtils.test.js.map +1 -0
- package/dist/src/ui/utils/displayUtils.test.d.ts +6 -0
- package/dist/src/ui/utils/displayUtils.test.js +42 -0
- package/dist/src/ui/utils/displayUtils.test.js.map +1 -0
- package/dist/src/ui/utils/formatters.test.d.ts +6 -0
- package/dist/src/ui/utils/formatters.test.js +56 -0
- package/dist/src/ui/utils/formatters.test.js.map +1 -0
- package/dist/src/ui/utils/markdownUtilities.test.d.ts +6 -0
- package/dist/src/ui/utils/markdownUtilities.test.js +42 -0
- package/dist/src/ui/utils/markdownUtilities.test.js.map +1 -0
- package/dist/src/ui/utils/platformConstants.d.ts +5 -0
- package/dist/src/ui/utils/platformConstants.js +5 -0
- package/dist/src/ui/utils/platformConstants.js.map +1 -1
- package/dist/src/ui/utils/responsive.test.d.ts +6 -0
- package/dist/src/ui/utils/responsive.test.js +107 -0
- package/dist/src/ui/utils/responsive.test.js.map +1 -0
- package/dist/src/ui/utils/secureInputHandler.test.d.ts +6 -0
- package/dist/src/ui/utils/secureInputHandler.test.js +274 -0
- package/dist/src/ui/utils/secureInputHandler.test.js.map +1 -0
- package/dist/src/ui/utils/updateCheck.test.d.ts +6 -0
- package/dist/src/ui/utils/updateCheck.test.js +202 -0
- package/dist/src/ui/utils/updateCheck.test.js.map +1 -0
- package/dist/src/utils/ConversationContext.test.d.ts +6 -0
- package/dist/src/utils/ConversationContext.test.js +64 -0
- package/dist/src/utils/ConversationContext.test.js.map +1 -0
- package/dist/src/utils/gitUtils.test.d.ts +6 -0
- package/dist/src/utils/gitUtils.test.js +113 -0
- package/dist/src/utils/gitUtils.test.js.map +1 -0
- package/dist/src/utils/installationInfo.test.d.ts +6 -0
- package/dist/src/utils/installationInfo.test.js +242 -0
- package/dist/src/utils/installationInfo.test.js.map +1 -0
- package/dist/src/utils/privacy/ConversationDataRedactor.test.d.ts +6 -0
- package/dist/src/utils/privacy/ConversationDataRedactor.test.js +463 -0
- package/dist/src/utils/privacy/ConversationDataRedactor.test.js.map +1 -0
- package/dist/src/utils/readStdin.js +10 -0
- package/dist/src/utils/readStdin.js.map +1 -1
- package/dist/src/utils/sandbox.js +2 -2
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/utils/settingsUtils.test.d.ts +6 -0
- package/dist/src/utils/settingsUtils.test.js +514 -0
- package/dist/src/utils/settingsUtils.test.js.map +1 -0
- package/dist/src/utils/userStartupWarnings.js +2 -2
- package/dist/src/utils/userStartupWarnings.test.d.ts +6 -0
- package/dist/src/utils/userStartupWarnings.test.js +67 -0
- package/dist/src/utils/userStartupWarnings.test.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +3 -3
@@ -0,0 +1,379 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Vybestack LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { describe, it, expect, beforeEach, afterEach } from 'vitest';
|
7
|
+
import * as path from 'path';
|
8
|
+
import { ContentGeneratorRole } from '@vybestack/llxprt-code-core';
|
9
|
+
// Mock implementation for behavioral testing
|
10
|
+
class MockConversationStorage {
|
11
|
+
config;
|
12
|
+
currentLogFile;
|
13
|
+
currentLogSize = 0;
|
14
|
+
logFiles = new Map();
|
15
|
+
logEntries = [];
|
16
|
+
constructor(config) {
|
17
|
+
this.config = config;
|
18
|
+
this.currentLogFile = path.join(config.logPath, 'conversations.log');
|
19
|
+
}
|
20
|
+
async writeConversationEntry(entry) {
|
21
|
+
await this.ensureLogDirectory();
|
22
|
+
const entrySize = JSON.stringify(entry).length;
|
23
|
+
// Check if rotation is needed before writing
|
24
|
+
if (this.currentLogSize + entrySize >
|
25
|
+
this.config.maxLogSizeMB * 1024 * 1024) {
|
26
|
+
await this.rotateLogIfNeeded();
|
27
|
+
}
|
28
|
+
// Write entry (simulated)
|
29
|
+
this.logEntries.push(entry);
|
30
|
+
this.currentLogSize += entrySize;
|
31
|
+
// Update file metadata
|
32
|
+
const now = new Date();
|
33
|
+
const currentFile = this.getCurrentLogPath();
|
34
|
+
if (!this.logFiles.has(currentFile)) {
|
35
|
+
this.logFiles.set(currentFile, {
|
36
|
+
size: 0,
|
37
|
+
created: now,
|
38
|
+
lastModified: now,
|
39
|
+
});
|
40
|
+
}
|
41
|
+
const fileInfo = this.logFiles.get(currentFile);
|
42
|
+
fileInfo.size = this.currentLogSize;
|
43
|
+
fileInfo.lastModified = now;
|
44
|
+
}
|
45
|
+
async rotateLogIfNeeded() {
|
46
|
+
// Always rotate when called (since we already checked the condition)
|
47
|
+
// Generate new log file name with timestamp
|
48
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
49
|
+
const newLogFile = path.join(this.config.logPath, `conversations-${timestamp}.log`);
|
50
|
+
// Archive current log
|
51
|
+
const currentFile = this.getCurrentLogPath();
|
52
|
+
const fileInfo = this.logFiles.get(currentFile);
|
53
|
+
if (fileInfo) {
|
54
|
+
this.logFiles.set(newLogFile, { ...fileInfo });
|
55
|
+
}
|
56
|
+
// Create new current log
|
57
|
+
this.currentLogFile = path.join(this.config.logPath, 'conversations.log');
|
58
|
+
this.currentLogSize = 0;
|
59
|
+
// Remove excess log files if needed
|
60
|
+
await this.enforceMaxLogFiles();
|
61
|
+
}
|
62
|
+
async enforceMaxLogFiles() {
|
63
|
+
const files = await this.getLogFiles();
|
64
|
+
if (files.length > this.config.maxLogFiles) {
|
65
|
+
// Sort by creation date, keep newest files
|
66
|
+
const sortedFiles = files.sort((a, b) => b.created.getTime() - a.created.getTime());
|
67
|
+
const filesToDelete = sortedFiles.slice(this.config.maxLogFiles);
|
68
|
+
for (const file of filesToDelete) {
|
69
|
+
this.logFiles.delete(file.path);
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
async cleanupOldLogs() {
|
74
|
+
const cutoffDate = new Date();
|
75
|
+
cutoffDate.setDate(cutoffDate.getDate() - this.config.retentionDays);
|
76
|
+
const files = await this.getLogFiles();
|
77
|
+
for (const file of files) {
|
78
|
+
if (file.created < cutoffDate) {
|
79
|
+
this.logFiles.delete(file.path);
|
80
|
+
}
|
81
|
+
}
|
82
|
+
}
|
83
|
+
async getLogFiles() {
|
84
|
+
return Array.from(this.logFiles.entries()).map(([filePath, info]) => ({
|
85
|
+
path: filePath,
|
86
|
+
size: info.size,
|
87
|
+
created: info.created,
|
88
|
+
lastModified: info.lastModified,
|
89
|
+
}));
|
90
|
+
}
|
91
|
+
async getCurrentLogSize() {
|
92
|
+
return this.currentLogSize;
|
93
|
+
}
|
94
|
+
getCurrentLogPath() {
|
95
|
+
return this.currentLogFile;
|
96
|
+
}
|
97
|
+
async ensureLogDirectory() {
|
98
|
+
// Simulate directory creation
|
99
|
+
// In real implementation, would create directories recursively
|
100
|
+
}
|
101
|
+
async createLogFileWithDate(filename, date) {
|
102
|
+
const filePath = path.join(this.config.logPath, filename);
|
103
|
+
this.logFiles.set(filePath, {
|
104
|
+
size: 1024, // Simulate some content
|
105
|
+
created: date,
|
106
|
+
lastModified: date,
|
107
|
+
});
|
108
|
+
}
|
109
|
+
}
|
110
|
+
// Test helper functions
|
111
|
+
function createLargeConversationEntry(sizeBytes) {
|
112
|
+
const largeContent = 'x'.repeat(Math.max(sizeBytes - 200, 0)); // Reserve space for JSON overhead
|
113
|
+
return {
|
114
|
+
timestamp: new Date().toISOString(),
|
115
|
+
conversation_id: 'conv_123',
|
116
|
+
provider_name: 'openai',
|
117
|
+
messages: [{ role: ContentGeneratorRole.USER, content: largeContent }],
|
118
|
+
};
|
119
|
+
}
|
120
|
+
function createTypicalConversationEntry() {
|
121
|
+
return {
|
122
|
+
timestamp: new Date().toISOString(),
|
123
|
+
conversation_id: 'conv_456',
|
124
|
+
provider_name: 'anthropic',
|
125
|
+
messages: [
|
126
|
+
{
|
127
|
+
role: ContentGeneratorRole.USER,
|
128
|
+
content: 'Hello, how can you help me?',
|
129
|
+
},
|
130
|
+
{
|
131
|
+
role: ContentGeneratorRole.ASSISTANT,
|
132
|
+
content: 'I can help you with various tasks...',
|
133
|
+
},
|
134
|
+
],
|
135
|
+
session_id: 'session_789',
|
136
|
+
};
|
137
|
+
}
|
138
|
+
describe('Conversation Log Storage Management', () => {
|
139
|
+
let storage;
|
140
|
+
let testLogPath;
|
141
|
+
beforeEach(() => {
|
142
|
+
testLogPath = '/tmp/test-logs-' + Date.now();
|
143
|
+
storage = new MockConversationStorage({
|
144
|
+
logPath: testLogPath,
|
145
|
+
maxLogSizeMB: 1,
|
146
|
+
maxLogFiles: 3,
|
147
|
+
retentionDays: 7,
|
148
|
+
});
|
149
|
+
});
|
150
|
+
afterEach(() => {
|
151
|
+
// Cleanup would happen here in real implementation
|
152
|
+
});
|
153
|
+
/**
|
154
|
+
* @requirement STORAGE-001: Log file rotation
|
155
|
+
* @scenario Log file exceeds maximum size
|
156
|
+
* @given ConversationStorage with maxLogSizeMB: 1
|
157
|
+
* @when writeConversationEntry() is called with large entry
|
158
|
+
* @then New log file is created and old file is rotated
|
159
|
+
* @and Total log files does not exceed maxLogFiles
|
160
|
+
*/
|
161
|
+
it('should rotate log files when size limit is exceeded', async () => {
|
162
|
+
// First, add a medium-sized entry to partially fill the log
|
163
|
+
const mediumEntry = createLargeConversationEntry(600 * 1024); // 600KB
|
164
|
+
await storage.writeConversationEntry(mediumEntry);
|
165
|
+
expect(await storage.getCurrentLogSize()).toBeLessThan(1024 * 1024);
|
166
|
+
// Now add another entry that would exceed the 1MB limit (600KB + 600KB > 1MB)
|
167
|
+
const anotherEntry = createLargeConversationEntry(600 * 1024); // 600KB
|
168
|
+
await storage.writeConversationEntry(anotherEntry);
|
169
|
+
// After rotation, we should have multiple log files and the current size should be just the new entry
|
170
|
+
const logFiles = await storage.getLogFiles();
|
171
|
+
expect(logFiles.length).toBeGreaterThan(1); // Rotation should have occurred
|
172
|
+
expect(logFiles.length).toBeLessThanOrEqual(3);
|
173
|
+
expect(await storage.getCurrentLogSize()).toBeLessThan(1024 * 1024); // Current file should have just the new entry
|
174
|
+
});
|
175
|
+
/**
|
176
|
+
* @requirement STORAGE-002: Retention policy
|
177
|
+
* @scenario Old log files exceed retention period
|
178
|
+
* @given Log files older than retentionDays
|
179
|
+
* @when cleanupOldLogs() is called
|
180
|
+
* @then Files older than retention period are deleted
|
181
|
+
*/
|
182
|
+
it('should clean up log files beyond retention period', async () => {
|
183
|
+
const oldDate = new Date(Date.now() - 10 * 24 * 60 * 60 * 1000); // 10 days ago
|
184
|
+
await storage.createLogFileWithDate('old-conversation.log', oldDate);
|
185
|
+
// Add a recent file to ensure we don't delete everything
|
186
|
+
const recentDate = new Date(Date.now() - 1 * 24 * 60 * 60 * 1000); // 1 day ago
|
187
|
+
await storage.createLogFileWithDate('recent-conversation.log', recentDate);
|
188
|
+
await storage.cleanupOldLogs();
|
189
|
+
const remainingFiles = await storage.getLogFiles();
|
190
|
+
expect(remainingFiles.some((f) => f.path.includes('old-conversation'))).toBe(false);
|
191
|
+
expect(remainingFiles.some((f) => f.path.includes('recent-conversation'))).toBe(true);
|
192
|
+
});
|
193
|
+
/**
|
194
|
+
* @requirement STORAGE-003: Multiple small entries
|
195
|
+
* @scenario Multiple small conversation entries within size limit
|
196
|
+
* @given ConversationStorage with sufficient capacity
|
197
|
+
* @when multiple writeConversationEntry() calls are made
|
198
|
+
* @then All entries are written to same log file
|
199
|
+
* @and No rotation occurs
|
200
|
+
*/
|
201
|
+
it('should handle multiple small conversation entries without rotation', async () => {
|
202
|
+
const entries = [
|
203
|
+
createTypicalConversationEntry(),
|
204
|
+
createTypicalConversationEntry(),
|
205
|
+
createTypicalConversationEntry(),
|
206
|
+
];
|
207
|
+
for (const entry of entries) {
|
208
|
+
await storage.writeConversationEntry(entry);
|
209
|
+
}
|
210
|
+
const logFiles = await storage.getLogFiles();
|
211
|
+
expect(logFiles.length).toBe(1); // All in one file
|
212
|
+
expect(await storage.getCurrentLogSize()).toBeLessThan(1024 * 1024); // Under 1MB limit
|
213
|
+
});
|
214
|
+
/**
|
215
|
+
* @requirement STORAGE-004: Concurrent write handling
|
216
|
+
* @scenario Multiple simultaneous write operations
|
217
|
+
* @given ConversationStorage with concurrent write operations
|
218
|
+
* @when multiple writeConversationEntry() calls are made simultaneously
|
219
|
+
* @then All entries are written successfully
|
220
|
+
* @and File rotation is handled correctly
|
221
|
+
*/
|
222
|
+
it('should handle concurrent conversation entry writes', async () => {
|
223
|
+
const entries = Array.from({ length: 5 }, () => createTypicalConversationEntry());
|
224
|
+
// Write all entries concurrently
|
225
|
+
await Promise.all(entries.map((entry) => storage.writeConversationEntry(entry)));
|
226
|
+
const logFiles = await storage.getLogFiles();
|
227
|
+
expect(logFiles.length).toBeGreaterThan(0);
|
228
|
+
// Verify total size is reasonable
|
229
|
+
const totalSize = logFiles.reduce((sum, file) => sum + file.size, 0);
|
230
|
+
expect(totalSize).toBeGreaterThan(0);
|
231
|
+
});
|
232
|
+
/**
|
233
|
+
* @requirement STORAGE-005: Log directory creation
|
234
|
+
* @scenario Log directory does not exist
|
235
|
+
* @given ConversationStorage with non-existent log directory
|
236
|
+
* @when writeConversationEntry() is called
|
237
|
+
* @then Log directory is created automatically
|
238
|
+
* @and Entry is written successfully
|
239
|
+
*/
|
240
|
+
it('should create log directory if it does not exist', async () => {
|
241
|
+
const nonExistentPath = '/tmp/non-existent-' + Date.now();
|
242
|
+
const storageWithNewPath = new MockConversationStorage({
|
243
|
+
logPath: nonExistentPath,
|
244
|
+
maxLogSizeMB: 1,
|
245
|
+
maxLogFiles: 3,
|
246
|
+
retentionDays: 7,
|
247
|
+
});
|
248
|
+
const entry = createTypicalConversationEntry();
|
249
|
+
// Should not throw error even if directory doesn't exist
|
250
|
+
await expect(storageWithNewPath.writeConversationEntry(entry)).resolves.not.toThrow();
|
251
|
+
expect(await storageWithNewPath.getCurrentLogSize()).toBeGreaterThan(0);
|
252
|
+
});
|
253
|
+
/**
|
254
|
+
* @requirement STORAGE-006: Max log files enforcement
|
255
|
+
* @scenario More log files than maxLogFiles limit
|
256
|
+
* @given ConversationStorage with maxLogFiles: 3
|
257
|
+
* @when rotation creates more than 3 log files
|
258
|
+
* @then Oldest log files are deleted to maintain limit
|
259
|
+
*/
|
260
|
+
it('should enforce maximum log files limit', async () => {
|
261
|
+
// Create multiple large entries to force multiple rotations
|
262
|
+
for (let i = 0; i < 5; i++) {
|
263
|
+
const largeEntry = createLargeConversationEntry(1.5 * 1024 * 1024); // 1.5MB each
|
264
|
+
await storage.writeConversationEntry(largeEntry);
|
265
|
+
// Small delay to ensure different timestamps
|
266
|
+
await new Promise((resolve) => setTimeout(resolve, 10));
|
267
|
+
}
|
268
|
+
const logFiles = await storage.getLogFiles();
|
269
|
+
expect(logFiles.length).toBeLessThanOrEqual(3);
|
270
|
+
});
|
271
|
+
/**
|
272
|
+
* @requirement STORAGE-007: Log file metadata tracking
|
273
|
+
* @scenario Log file information retrieval
|
274
|
+
* @given ConversationStorage with written log files
|
275
|
+
* @when getLogFiles() is called
|
276
|
+
* @then Returns accurate file metadata including size and dates
|
277
|
+
*/
|
278
|
+
it('should track accurate log file metadata', async () => {
|
279
|
+
const entry1 = createTypicalConversationEntry();
|
280
|
+
await storage.writeConversationEntry(entry1);
|
281
|
+
// Force rotation with large entry
|
282
|
+
const largeEntry = createLargeConversationEntry(2 * 1024 * 1024);
|
283
|
+
await storage.writeConversationEntry(largeEntry);
|
284
|
+
const logFiles = await storage.getLogFiles();
|
285
|
+
for (const file of logFiles) {
|
286
|
+
expect(file.path).toBeTruthy();
|
287
|
+
expect(file.size).toBeGreaterThan(0);
|
288
|
+
expect(file.created).toBeInstanceOf(Date);
|
289
|
+
expect(file.lastModified).toBeInstanceOf(Date);
|
290
|
+
expect(file.lastModified.getTime()).toBeGreaterThanOrEqual(file.created.getTime());
|
291
|
+
}
|
292
|
+
});
|
293
|
+
/**
|
294
|
+
* @requirement STORAGE-008: Storage error handling
|
295
|
+
* @scenario Storage operation failures
|
296
|
+
* @given ConversationStorage with simulated write errors
|
297
|
+
* @when writeConversationEntry() encounters errors
|
298
|
+
* @then Errors are handled gracefully without corrupting state
|
299
|
+
*/
|
300
|
+
it('should handle storage errors gracefully', async () => {
|
301
|
+
// Create a storage instance that will simulate errors
|
302
|
+
const errorProneStorage = new MockConversationStorage({
|
303
|
+
logPath: '/invalid/path/that/cannot/be/created',
|
304
|
+
maxLogSizeMB: 1,
|
305
|
+
maxLogFiles: 3,
|
306
|
+
retentionDays: 7,
|
307
|
+
});
|
308
|
+
// In real implementation, this would test actual filesystem errors
|
309
|
+
// For now, we verify the storage instance handles the invalid path gracefully
|
310
|
+
await expect(errorProneStorage.ensureLogDirectory()).resolves.not.toThrow();
|
311
|
+
});
|
312
|
+
/**
|
313
|
+
* @requirement STORAGE-009: Log rotation timing
|
314
|
+
* @scenario Rotation happens at correct size threshold
|
315
|
+
* @given ConversationStorage with 1MB limit
|
316
|
+
* @when entries are written approaching the limit
|
317
|
+
* @then Rotation occurs at or before limit is exceeded
|
318
|
+
*/
|
319
|
+
it('should rotate logs at correct size threshold', async () => {
|
320
|
+
const mediumEntry = createLargeConversationEntry(600 * 1024); // 600KB
|
321
|
+
// Write first entry (should not rotate)
|
322
|
+
await storage.writeConversationEntry(mediumEntry);
|
323
|
+
expect(await storage.getCurrentLogSize()).toBeLessThan(1024 * 1024);
|
324
|
+
// Write second entry (should trigger rotation due to combined size > 1MB)
|
325
|
+
await storage.writeConversationEntry(mediumEntry);
|
326
|
+
expect(await storage.getCurrentLogSize()).toBeLessThan(1024 * 1024); // New file should be smaller
|
327
|
+
const logFiles = await storage.getLogFiles();
|
328
|
+
expect(logFiles.length).toBeGreaterThan(1); // Rotation should have occurred
|
329
|
+
});
|
330
|
+
/**
|
331
|
+
* @requirement STORAGE-010: Empty entry handling
|
332
|
+
* @scenario Conversation entry with minimal content
|
333
|
+
* @given ConversationStorage with empty or minimal entries
|
334
|
+
* @when writeConversationEntry() is called with empty messages
|
335
|
+
* @then Entry is handled correctly without errors
|
336
|
+
*/
|
337
|
+
it('should handle empty or minimal conversation entries', async () => {
|
338
|
+
const emptyEntry = {
|
339
|
+
timestamp: new Date().toISOString(),
|
340
|
+
conversation_id: 'empty_conv',
|
341
|
+
provider_name: 'test',
|
342
|
+
messages: [],
|
343
|
+
};
|
344
|
+
const minimalEntry = {
|
345
|
+
timestamp: new Date().toISOString(),
|
346
|
+
conversation_id: 'minimal_conv',
|
347
|
+
provider_name: 'test',
|
348
|
+
messages: [{ role: ContentGeneratorRole.USER, content: '' }],
|
349
|
+
};
|
350
|
+
await expect(storage.writeConversationEntry(emptyEntry)).resolves.not.toThrow();
|
351
|
+
await expect(storage.writeConversationEntry(minimalEntry)).resolves.not.toThrow();
|
352
|
+
expect(await storage.getCurrentLogSize()).toBeGreaterThan(0);
|
353
|
+
});
|
354
|
+
/**
|
355
|
+
* @requirement STORAGE-011: Retention cleanup precision
|
356
|
+
* @scenario Files created exactly at retention boundary
|
357
|
+
* @given Log files created exactly retentionDays ago
|
358
|
+
* @when cleanupOldLogs() is called
|
359
|
+
* @then Boundary cases are handled correctly (files exactly at limit are kept/deleted consistently)
|
360
|
+
*/
|
361
|
+
it('should handle retention boundary cases correctly', async () => {
|
362
|
+
const exactBoundaryDate = new Date();
|
363
|
+
exactBoundaryDate.setDate(exactBoundaryDate.getDate() - 7); // Exactly 7 days ago
|
364
|
+
const justInsideBoundaryDate = new Date();
|
365
|
+
justInsideBoundaryDate.setDate(justInsideBoundaryDate.getDate() - 6); // 6 days ago
|
366
|
+
const justOutsideBoundaryDate = new Date();
|
367
|
+
justOutsideBoundaryDate.setDate(justOutsideBoundaryDate.getDate() - 8); // 8 days ago
|
368
|
+
await storage.createLogFileWithDate('exact-boundary.log', exactBoundaryDate);
|
369
|
+
await storage.createLogFileWithDate('just-inside.log', justInsideBoundaryDate);
|
370
|
+
await storage.createLogFileWithDate('just-outside.log', justOutsideBoundaryDate);
|
371
|
+
await storage.cleanupOldLogs();
|
372
|
+
const remainingFiles = await storage.getLogFiles();
|
373
|
+
const filenames = remainingFiles.map((f) => path.basename(f.path));
|
374
|
+
expect(filenames).toContain('just-inside.log'); // 6 days ago should remain
|
375
|
+
expect(filenames).not.toContain('just-outside.log'); // 8 days ago should be deleted
|
376
|
+
// Boundary case (exactly 7 days) behavior should be consistent
|
377
|
+
});
|
378
|
+
});
|
379
|
+
//# sourceMappingURL=ConversationStorage.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"ConversationStorage.test.js","sourceRoot":"","sources":["../../../src/storage/ConversationStorage.test.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
declare module 'vitest' {
|
7
|
+
interface Assertion<T> {
|
8
|
+
toHaveOnlyValidCharacters(): T;
|
9
|
+
}
|
10
|
+
interface AsymmetricMatchersContaining {
|
11
|
+
toHaveOnlyValidCharacters(): void;
|
12
|
+
}
|
13
|
+
}
|
14
|
+
export {};
|
@@ -0,0 +1,46 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
/// <reference types="vitest/globals" />
|
7
|
+
/**
|
8
|
+
* @license
|
9
|
+
* Copyright 2025 Google LLC
|
10
|
+
* SPDX-License-Identifier: Apache-2.0
|
11
|
+
*/
|
12
|
+
import { expect } from 'vitest';
|
13
|
+
// RegExp to detect invalid characters: backspace, and ANSI escape codes
|
14
|
+
// eslint-disable-next-line no-control-regex
|
15
|
+
const invalidCharsRegex = /[\b\x1b]/;
|
16
|
+
function toHaveOnlyValidCharacters(buffer) {
|
17
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
18
|
+
const { isNot } = this;
|
19
|
+
let pass = true;
|
20
|
+
const invalidLines = [];
|
21
|
+
for (let i = 0; i < buffer.lines.length; i++) {
|
22
|
+
const line = buffer.lines[i];
|
23
|
+
if (line.includes('\n')) {
|
24
|
+
pass = false;
|
25
|
+
invalidLines.push({ line: i, content: line });
|
26
|
+
break; // Fail fast on newlines
|
27
|
+
}
|
28
|
+
if (invalidCharsRegex.test(line)) {
|
29
|
+
pass = false;
|
30
|
+
invalidLines.push({ line: i, content: line });
|
31
|
+
}
|
32
|
+
}
|
33
|
+
return {
|
34
|
+
pass,
|
35
|
+
message: () => `Expected buffer ${isNot ? 'not ' : ''}to have only valid characters, but found invalid characters in lines:\n${invalidLines
|
36
|
+
.map((l) => ` [${l.line}]: "${l.content}"`) /* This line was changed */
|
37
|
+
.join('\n')}`,
|
38
|
+
actual: buffer.lines,
|
39
|
+
expected: 'Lines with no line breaks, backspaces, or escape codes.',
|
40
|
+
};
|
41
|
+
}
|
42
|
+
expect.extend({
|
43
|
+
toHaveOnlyValidCharacters,
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
45
|
+
});
|
46
|
+
//# sourceMappingURL=customMatchers.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"customMatchers.js","sourceRoot":"","sources":["../../../src/test-utils/customMatchers.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,wCAAwC;AAExC;;;;GAIG;AAEH,OAAO,EAAa,MAAM,EAAE,MAAM,QAAQ,CAAC;AAG3C,wEAAwE;AACxE,4CAA4C;AAC5C,MAAM,iBAAiB,GAAG,UAAU,CAAC;AAErC,SAAS,yBAAyB,CAAkB,MAAkB;IACpE,8DAA8D;IAC9D,MAAM,EAAE,KAAK,EAAE,GAAG,IAAW,CAAC;IAC9B,IAAI,IAAI,GAAG,IAAI,CAAC;IAChB,MAAM,YAAY,GAA6C,EAAE,CAAC;IAElE,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7C,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;QAC7B,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,IAAI,GAAG,KAAK,CAAC;YACb,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC9C,MAAM,CAAC,wBAAwB;QACjC,CAAC;QACD,IAAI,iBAAiB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACjC,IAAI,GAAG,KAAK,CAAC;YACb,YAAY,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI;QACJ,OAAO,EAAE,GAAG,EAAE,CACZ,mBAAmB,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,0EAA0E,YAAY;aACzH,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,2BAA2B;aACvE,IAAI,CAAC,IAAI,CAAC,EAAE;QACjB,MAAM,EAAE,MAAM,CAAC,KAAK;QACpB,QAAQ,EAAE,yDAAyD;KACpE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,MAAM,CAAC;IACZ,yBAAyB;IACzB,8DAA8D;CACxD,CAAC,CAAC"}
|
@@ -0,0 +1,18 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { CommandContext } from '../ui/commands/types.js';
|
7
|
+
type DeepPartial<T> = T extends object ? {
|
8
|
+
[P in keyof T]?: DeepPartial<T[P]>;
|
9
|
+
} : T;
|
10
|
+
/**
|
11
|
+
* Creates a deep, fully-typed mock of the CommandContext for use in tests.
|
12
|
+
* All functions are pre-mocked with `vi.fn()`.
|
13
|
+
*
|
14
|
+
* @param overrides - A deep partial object to override any default mock values.
|
15
|
+
* @returns A complete, mocked CommandContext object.
|
16
|
+
*/
|
17
|
+
export declare const createMockCommandContext: (overrides?: DeepPartial<CommandContext>) => CommandContext;
|
18
|
+
export {};
|
@@ -0,0 +1,86 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { vi } from 'vitest';
|
7
|
+
/**
|
8
|
+
* Creates a deep, fully-typed mock of the CommandContext for use in tests.
|
9
|
+
* All functions are pre-mocked with `vi.fn()`.
|
10
|
+
*
|
11
|
+
* @param overrides - A deep partial object to override any default mock values.
|
12
|
+
* @returns A complete, mocked CommandContext object.
|
13
|
+
*/
|
14
|
+
export const createMockCommandContext = (overrides = {}) => {
|
15
|
+
const defaultMocks = {
|
16
|
+
invocation: {
|
17
|
+
raw: '',
|
18
|
+
name: '',
|
19
|
+
args: '',
|
20
|
+
},
|
21
|
+
services: {
|
22
|
+
config: null,
|
23
|
+
settings: { merged: {} },
|
24
|
+
git: undefined,
|
25
|
+
logger: {
|
26
|
+
log: vi.fn(),
|
27
|
+
logMessage: vi.fn(),
|
28
|
+
saveCheckpoint: vi.fn(),
|
29
|
+
loadCheckpoint: vi.fn().mockResolvedValue([]),
|
30
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
31
|
+
}, // Cast because Logger is a class.
|
32
|
+
},
|
33
|
+
ui: {
|
34
|
+
addItem: vi.fn(),
|
35
|
+
clear: vi.fn(),
|
36
|
+
setDebugMessage: vi.fn(),
|
37
|
+
pendingItem: null,
|
38
|
+
setPendingItem: vi.fn(),
|
39
|
+
loadHistory: vi.fn(),
|
40
|
+
toggleCorgiMode: vi.fn(),
|
41
|
+
toggleVimEnabled: vi.fn(),
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
43
|
+
},
|
44
|
+
session: {
|
45
|
+
sessionShellAllowlist: new Set(),
|
46
|
+
stats: {
|
47
|
+
sessionStartTime: new Date(),
|
48
|
+
lastPromptTokenCount: 0,
|
49
|
+
metrics: {
|
50
|
+
models: {},
|
51
|
+
tools: {
|
52
|
+
totalCalls: 0,
|
53
|
+
totalSuccess: 0,
|
54
|
+
totalFail: 0,
|
55
|
+
totalDurationMs: 0,
|
56
|
+
totalDecisions: { accept: 0, reject: 0, modify: 0 },
|
57
|
+
byName: {},
|
58
|
+
},
|
59
|
+
},
|
60
|
+
},
|
61
|
+
},
|
62
|
+
};
|
63
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
64
|
+
const merge = (target, source) => {
|
65
|
+
const output = { ...target };
|
66
|
+
for (const key in source) {
|
67
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
68
|
+
const sourceValue = source[key];
|
69
|
+
const targetValue = output[key];
|
70
|
+
if (
|
71
|
+
// We only want to recursivlty merge plain objects
|
72
|
+
Object.prototype.toString.call(sourceValue) === '[object Object]' &&
|
73
|
+
Object.prototype.toString.call(targetValue) === '[object Object]') {
|
74
|
+
output[key] = merge(targetValue, sourceValue);
|
75
|
+
}
|
76
|
+
else {
|
77
|
+
// If not, we do a direct assignment. This preserves Date objects and others.
|
78
|
+
output[key] = sourceValue;
|
79
|
+
}
|
80
|
+
}
|
81
|
+
}
|
82
|
+
return output;
|
83
|
+
};
|
84
|
+
return merge(defaultMocks, overrides);
|
85
|
+
};
|
86
|
+
//# sourceMappingURL=mockCommandContext.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mockCommandContext.js","sourceRoot":"","sources":["../../../src/test-utils/mockCommandContext.ts"],"names":[],"mappings":"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"}
|
@@ -0,0 +1,51 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { vi, describe, it, expect } from 'vitest';
|
7
|
+
import { createMockCommandContext } from './mockCommandContext.js';
|
8
|
+
describe('createMockCommandContext', () => {
|
9
|
+
it('should return a valid CommandContext object with default mocks', () => {
|
10
|
+
const context = createMockCommandContext();
|
11
|
+
// Just a few spot checks to ensure the structure is correct
|
12
|
+
// and functions are mocks.
|
13
|
+
expect(context).toBeDefined();
|
14
|
+
expect(context.ui.addItem).toBeInstanceOf(Function);
|
15
|
+
expect(vi.isMockFunction(context.ui.addItem)).toBe(true);
|
16
|
+
});
|
17
|
+
it('should apply top-level overrides correctly', () => {
|
18
|
+
const mockClear = vi.fn();
|
19
|
+
const overrides = {
|
20
|
+
ui: {
|
21
|
+
clear: mockClear,
|
22
|
+
},
|
23
|
+
};
|
24
|
+
const context = createMockCommandContext(overrides);
|
25
|
+
// Call the function to see if the override was used
|
26
|
+
context.ui.clear();
|
27
|
+
// Assert that our specific mock was called, not the default
|
28
|
+
expect(mockClear).toHaveBeenCalled();
|
29
|
+
// And that other defaults are still in place
|
30
|
+
expect(vi.isMockFunction(context.ui.addItem)).toBe(true);
|
31
|
+
});
|
32
|
+
it('should apply deeply nested overrides correctly', () => {
|
33
|
+
// This is the most important test for factory's logic.
|
34
|
+
const mockConfig = {
|
35
|
+
getProjectRoot: () => '/test/project',
|
36
|
+
getModel: () => 'gemini-pro',
|
37
|
+
};
|
38
|
+
const overrides = {
|
39
|
+
services: {
|
40
|
+
config: mockConfig,
|
41
|
+
},
|
42
|
+
};
|
43
|
+
const context = createMockCommandContext(overrides);
|
44
|
+
expect(context.services.config).toBeDefined();
|
45
|
+
expect(context.services.config?.getModel()).toBe('gemini-pro');
|
46
|
+
expect(context.services.config?.getProjectRoot()).toBe('/test/project');
|
47
|
+
// Verify a default property on the same nested object is still there
|
48
|
+
expect(context.services.logger).toBeDefined();
|
49
|
+
});
|
50
|
+
});
|
51
|
+
//# sourceMappingURL=mockCommandContext.test.js.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"mockCommandContext.test.js","sourceRoot":"","sources":["../../../src/test-utils/mockCommandContext.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAClD,OAAO,EAAE,wBAAwB,EAAE,MAAM,yBAAyB,CAAC;AAEnE,QAAQ,CAAC,0BAA0B,EAAE,GAAG,EAAE;IACxC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,OAAO,GAAG,wBAAwB,EAAE,CAAC;QAE3C,4DAA4D;QAC5D,2BAA2B;QAC3B,MAAM,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9B,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,4CAA4C,EAAE,GAAG,EAAE;QACpD,MAAM,SAAS,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC1B,MAAM,SAAS,GAAG;YAChB,EAAE,EAAE;gBACF,KAAK,EAAE,SAAS;aACjB;SACF,CAAC;QAEF,MAAM,OAAO,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;QAEpD,oDAAoD;QACpD,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;QAEnB,4DAA4D;QAC5D,MAAM,CAAC,SAAS,CAAC,CAAC,gBAAgB,EAAE,CAAC;QACrC,6CAA6C;QAC7C,MAAM,CAAC,EAAE,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,uDAAuD;QACvD,MAAM,UAAU,GAAG;YACjB,cAAc,EAAE,GAAG,EAAE,CAAC,eAAe;YACrC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY;SAC7B,CAAC;QAEF,MAAM,SAAS,GAAG;YAChB,QAAQ,EAAE;gBACR,MAAM,EAAE,UAAU;aACnB;SACF,CAAC;QAEF,MAAM,OAAO,GAAG,wBAAwB,CAAC,SAAS,CAAC,CAAC;QAEpD,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAC9C,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC/D,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,cAAc,EAAE,CAAC,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;QAExE,qEAAqE;QACrE,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;IAChD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
@@ -0,0 +1,8 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Google LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { render } from 'ink-testing-library';
|
7
|
+
import React from 'react';
|
8
|
+
export declare const renderWithProviders: (component: React.ReactElement) => ReturnType<typeof render>;
|