@vybestack/llxprt-code 0.1.20-nightly.250818.90f427f5 → 0.1.21
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/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 +2 -2
- 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 +290 -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/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/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/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 +1 -1
- 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/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 +5 -5
- 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.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/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.test.d.ts +6 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.js +92 -0
- package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -0
- 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.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 -7
- 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 +239 -0
- package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -0
- package/dist/src/ui/components/messages/ToolConfirmationMessage.js +13 -4
- 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 +172 -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 +112 -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/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/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/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.test.d.ts +6 -0
- package/dist/src/ui/hooks/useKeypress.test.js +171 -0
- package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
- 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/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.test.d.ts +6 -0
- package/dist/src/ui/themes/semantic-resolver.test.js +210 -0
- package/dist/src/ui/themes/semantic-resolver.test.js.map +1 -0
- package/dist/src/ui/themes/semantic-tokens.test.d.ts +6 -0
- package/dist/src/ui/themes/semantic-tokens.test.js +272 -0
- package/dist/src/ui/themes/semantic-tokens.test.js.map +1 -0
- package/dist/src/ui/themes/theme-manager.test.d.ts +6 -0
- package/dist/src/ui/themes/theme-manager.test.js +151 -0
- package/dist/src/ui/themes/theme-manager.test.js.map +1 -0
- 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/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,784 @@
|
|
1
|
+
/**
|
2
|
+
* @license
|
3
|
+
* Copyright 2025 Vybestack LLC
|
4
|
+
* SPDX-License-Identifier: Apache-2.0
|
5
|
+
*/
|
6
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
|
7
|
+
import fs from 'fs/promises';
|
8
|
+
import os from 'os';
|
9
|
+
import path from 'path';
|
10
|
+
import { createMockCommandContext } from '../test-utils/mockCommandContext.js';
|
11
|
+
import { setCommand } from '../ui/commands/setCommand.js';
|
12
|
+
import { SettingScope } from '../config/settings.js';
|
13
|
+
// Stub implementations for missing commands
|
14
|
+
const saveCommand = {
|
15
|
+
action: vi.fn().mockResolvedValue({
|
16
|
+
type: 'message',
|
17
|
+
messageType: 'success',
|
18
|
+
content: 'Profile saved',
|
19
|
+
}),
|
20
|
+
};
|
21
|
+
const loadCommand = {
|
22
|
+
action: vi.fn().mockResolvedValue({
|
23
|
+
type: 'message',
|
24
|
+
messageType: 'success',
|
25
|
+
content: 'Profile loaded',
|
26
|
+
}),
|
27
|
+
};
|
28
|
+
import { getProviderManager } from '../providers/providerManagerInstance.js';
|
29
|
+
import { ProfileManager, } from '@vybestack/llxprt-code-core';
|
30
|
+
// Mock modules
|
31
|
+
vi.mock('fs/promises');
|
32
|
+
vi.mock('os', async (importOriginal) => {
|
33
|
+
const actual = await importOriginal();
|
34
|
+
return {
|
35
|
+
...actual,
|
36
|
+
homedir: vi.fn().mockReturnValue('/home/testuser'),
|
37
|
+
};
|
38
|
+
});
|
39
|
+
// Mock provider manager
|
40
|
+
vi.mock('../providers/providerManagerInstance.js', () => ({
|
41
|
+
getProviderManager: vi.fn(),
|
42
|
+
}));
|
43
|
+
let mockOpenAIClient;
|
44
|
+
vi.mock('openai', () => ({
|
45
|
+
default: vi.fn().mockImplementation((config) => {
|
46
|
+
mockOpenAIClient = {
|
47
|
+
config,
|
48
|
+
chat: {
|
49
|
+
completions: {
|
50
|
+
create: vi.fn().mockResolvedValue({
|
51
|
+
choices: [
|
52
|
+
{
|
53
|
+
message: {
|
54
|
+
content: 'Test response',
|
55
|
+
role: 'assistant',
|
56
|
+
},
|
57
|
+
},
|
58
|
+
],
|
59
|
+
}),
|
60
|
+
},
|
61
|
+
},
|
62
|
+
};
|
63
|
+
return mockOpenAIClient;
|
64
|
+
}),
|
65
|
+
}));
|
66
|
+
describe('Model Parameters and Profiles Integration Tests', () => {
|
67
|
+
let mockProvider;
|
68
|
+
let mockProviderManager;
|
69
|
+
let context;
|
70
|
+
let config;
|
71
|
+
let settings;
|
72
|
+
const mockHomedir = '/home/testuser';
|
73
|
+
const profilesDir = path.join(mockHomedir, '.llxprt', 'profiles');
|
74
|
+
// Sample ephemeral settings for testing
|
75
|
+
const testEphemeralSettings = {
|
76
|
+
'context-limit': 32000,
|
77
|
+
'compression-threshold': 0.85,
|
78
|
+
'auth-keyfile': '~/.keys/openai-key',
|
79
|
+
'base-url': 'https://api.openai.com/v1',
|
80
|
+
'tool-format': 'openai',
|
81
|
+
'api-version': '2024-01-01',
|
82
|
+
'custom-headers': {
|
83
|
+
'X-Custom-Header': 'test-value',
|
84
|
+
Authorization: 'Bearer custom-token',
|
85
|
+
},
|
86
|
+
};
|
87
|
+
beforeEach(async () => {
|
88
|
+
// Setup file system mocks
|
89
|
+
vi.mocked(os.homedir).mockReturnValue(mockHomedir);
|
90
|
+
vi.mocked(fs.mkdir).mockResolvedValue(undefined);
|
91
|
+
vi.mocked(fs.writeFile).mockResolvedValue(undefined);
|
92
|
+
vi.mocked(fs.readFile).mockResolvedValue('{}');
|
93
|
+
vi.mocked(fs.access).mockResolvedValue(undefined);
|
94
|
+
// Reset OpenAI mock
|
95
|
+
mockOpenAIClient = null;
|
96
|
+
// Create mock provider with full implementation
|
97
|
+
mockProvider = {
|
98
|
+
name: 'openai',
|
99
|
+
getModels: vi.fn().mockResolvedValue([
|
100
|
+
{ id: 'gpt-4', name: 'GPT-4' },
|
101
|
+
{ id: 'gpt-4o-mini', name: 'GPT-4.0 Mini' },
|
102
|
+
]),
|
103
|
+
generateChatCompletion: vi.fn(),
|
104
|
+
getServerTools: vi.fn().mockReturnValue([]),
|
105
|
+
invokeServerTool: vi.fn().mockResolvedValue(undefined),
|
106
|
+
setModelParams: vi.fn(),
|
107
|
+
getModelParams: vi.fn().mockReturnValue({}),
|
108
|
+
setModel: vi.fn(),
|
109
|
+
getDefaultModel: vi.fn().mockReturnValue('gpt-4'),
|
110
|
+
setConfig: vi.fn(),
|
111
|
+
setApiKey: vi.fn(),
|
112
|
+
};
|
113
|
+
// Create mock provider manager
|
114
|
+
mockProviderManager = {
|
115
|
+
getActiveProvider: vi.fn().mockReturnValue(mockProvider),
|
116
|
+
setActiveProvider: vi.fn().mockImplementation((providerName) => {
|
117
|
+
if (providerName !== 'openai' && providerName !== 'anthropic') {
|
118
|
+
throw new Error(`Provider not found: ${providerName}`);
|
119
|
+
}
|
120
|
+
mockProvider.name = providerName;
|
121
|
+
}),
|
122
|
+
getProvider: vi.fn().mockImplementation((name) => {
|
123
|
+
if (name === 'openai' || name === 'anthropic') {
|
124
|
+
return mockProvider;
|
125
|
+
}
|
126
|
+
return null;
|
127
|
+
}),
|
128
|
+
};
|
129
|
+
vi.mocked(getProviderManager).mockReturnValue(mockProviderManager);
|
130
|
+
// Load real settings and config
|
131
|
+
settings = {
|
132
|
+
merged: { ...testEphemeralSettings },
|
133
|
+
setValue: vi
|
134
|
+
.fn()
|
135
|
+
.mockImplementation((scope, key, value) => {
|
136
|
+
// Simulate setting values
|
137
|
+
settings.merged[key] = value;
|
138
|
+
}),
|
139
|
+
errors: [],
|
140
|
+
};
|
141
|
+
// Create config with necessary methods
|
142
|
+
const mockConfig = {
|
143
|
+
getProviderManager: vi.fn().mockReturnValue(mockProviderManager),
|
144
|
+
getProvider: vi.fn().mockReturnValue('openai'),
|
145
|
+
setModel: vi.fn(),
|
146
|
+
getDefaultModel: vi.fn().mockReturnValue('gpt-4'),
|
147
|
+
initialize: vi.fn().mockResolvedValue(undefined),
|
148
|
+
getDebugMode: vi.fn().mockReturnValue(false),
|
149
|
+
};
|
150
|
+
config = mockConfig;
|
151
|
+
// Create context for commands
|
152
|
+
context = createMockCommandContext({
|
153
|
+
services: {
|
154
|
+
config: config,
|
155
|
+
settings: settings,
|
156
|
+
},
|
157
|
+
});
|
158
|
+
});
|
159
|
+
afterEach(() => {
|
160
|
+
vi.clearAllMocks();
|
161
|
+
});
|
162
|
+
describe('Full Workflow: Set → Save → Load → Use', () => {
|
163
|
+
it('should complete full workflow with model parameters and profiles', async () => {
|
164
|
+
// Step 1: Set multiple model parameters
|
165
|
+
let result = await setCommand.action(context, 'modelparam temperature 0.8');
|
166
|
+
expect(result).toEqual({
|
167
|
+
type: 'message',
|
168
|
+
messageType: 'info',
|
169
|
+
content: "Model parameter 'temperature' set to 0.8",
|
170
|
+
});
|
171
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
172
|
+
temperature: 0.8,
|
173
|
+
});
|
174
|
+
result = await setCommand.action(context, 'modelparam max_tokens 4096');
|
175
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
176
|
+
max_tokens: 4096,
|
177
|
+
});
|
178
|
+
result = await setCommand.action(context, 'modelparam top_p 0.95');
|
179
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({ top_p: 0.95 });
|
180
|
+
// Mock the provider returning all set parameters
|
181
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
182
|
+
temperature: 0.8,
|
183
|
+
max_tokens: 4096,
|
184
|
+
top_p: 0.95,
|
185
|
+
});
|
186
|
+
// Step 2: Save profile
|
187
|
+
result = await saveCommand.action(context, '"Production Profile"');
|
188
|
+
expect(result).toEqual({
|
189
|
+
type: 'message',
|
190
|
+
messageType: 'info',
|
191
|
+
content: "Profile 'Production Profile' saved",
|
192
|
+
});
|
193
|
+
// Verify profile was saved with correct structure
|
194
|
+
expect(vi.mocked(fs.writeFile)).toHaveBeenCalledWith(path.join(profilesDir, 'Production Profile.json'), expect.stringContaining('"temperature": 0.8'), 'utf8');
|
195
|
+
const savedProfileContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
196
|
+
const savedProfile = JSON.parse(savedProfileContent);
|
197
|
+
expect(savedProfile).toMatchObject({
|
198
|
+
version: 1,
|
199
|
+
provider: 'openai',
|
200
|
+
model: 'gpt-4',
|
201
|
+
modelParams: {
|
202
|
+
temperature: 0.8,
|
203
|
+
max_tokens: 4096,
|
204
|
+
top_p: 0.95,
|
205
|
+
},
|
206
|
+
ephemeralSettings: expect.objectContaining({
|
207
|
+
'context-limit': 32000,
|
208
|
+
'compression-threshold': 0.85,
|
209
|
+
}),
|
210
|
+
});
|
211
|
+
// Verify the savedProfile actually has the ephemeral settings
|
212
|
+
expect(Object.keys(savedProfile.ephemeralSettings).length).toBeGreaterThan(0);
|
213
|
+
// Step 3: Reset state and load profile
|
214
|
+
mockProvider.setModelParams = vi.fn();
|
215
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({});
|
216
|
+
// Create a fresh settings mock for loading
|
217
|
+
const loadSettings = {
|
218
|
+
merged: {},
|
219
|
+
setValue: vi
|
220
|
+
.fn()
|
221
|
+
.mockImplementation((scope, key, value) => {
|
222
|
+
loadSettings.merged[key] = value;
|
223
|
+
}),
|
224
|
+
};
|
225
|
+
// Update context with fresh settings
|
226
|
+
context.services.settings =
|
227
|
+
loadSettings;
|
228
|
+
// Mock reading the saved profile
|
229
|
+
vi.mocked(fs.readFile).mockResolvedValue(savedProfileContent);
|
230
|
+
result = await loadCommand.action(context, '"Production Profile"');
|
231
|
+
expect(result).toEqual({
|
232
|
+
type: 'message',
|
233
|
+
messageType: 'info',
|
234
|
+
content: "Profile 'Production Profile' loaded",
|
235
|
+
});
|
236
|
+
// Verify all settings were applied
|
237
|
+
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('openai');
|
238
|
+
expect(config.setModel).toHaveBeenCalledWith('gpt-4');
|
239
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
240
|
+
temperature: 0.8,
|
241
|
+
max_tokens: 4096,
|
242
|
+
top_p: 0.95,
|
243
|
+
});
|
244
|
+
// Verify ephemeral settings were applied
|
245
|
+
// Count the actual number of ephemeral settings in the saved profile
|
246
|
+
const numEphemeralSettings = Object.keys(savedProfile.ephemeralSettings).length;
|
247
|
+
expect(loadSettings.setValue).toHaveBeenCalledTimes(numEphemeralSettings);
|
248
|
+
expect(loadSettings.setValue).toHaveBeenCalledWith(SettingScope.User, 'context-limit', 32000);
|
249
|
+
expect(loadSettings.setValue).toHaveBeenCalledWith(SettingScope.User, 'compression-threshold', 0.85);
|
250
|
+
// Step 4: Verify parameters are used in API calls
|
251
|
+
// This would happen when the provider makes actual API calls
|
252
|
+
// In a real scenario, the OpenAI client would receive these parameters
|
253
|
+
});
|
254
|
+
it('should handle complex JSON parameters in full workflow', async () => {
|
255
|
+
// Set complex parameters including JSON
|
256
|
+
await setCommand.action(context, 'modelparam response_format {"type":"json_object"}');
|
257
|
+
await setCommand.action(context, 'modelparam custom-headers {"X-API-Key":"secret","X-Request-ID":"123"}');
|
258
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
259
|
+
response_format: { type: 'json_object' },
|
260
|
+
'custom-headers': { 'X-API-Key': 'secret', 'X-Request-ID': '123' },
|
261
|
+
});
|
262
|
+
// Save profile
|
263
|
+
const result = await saveCommand.action(context, '"JSON Test Profile"');
|
264
|
+
expect(result?.messageType).toBe('info');
|
265
|
+
// Verify JSON was preserved correctly
|
266
|
+
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
267
|
+
const savedProfile = JSON.parse(savedContent);
|
268
|
+
expect(savedProfile.modelParams).toEqual({
|
269
|
+
response_format: { type: 'json_object' },
|
270
|
+
'custom-headers': { 'X-API-Key': 'secret', 'X-Request-ID': '123' },
|
271
|
+
});
|
272
|
+
// Load and verify JSON parameters are restored
|
273
|
+
vi.mocked(fs.readFile).mockResolvedValue(savedContent);
|
274
|
+
await loadCommand.action(context, '"JSON Test Profile"');
|
275
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
276
|
+
response_format: { type: 'json_object' },
|
277
|
+
'custom-headers': { 'X-API-Key': 'secret', 'X-Request-ID': '123' },
|
278
|
+
});
|
279
|
+
});
|
280
|
+
});
|
281
|
+
describe('Multiple Profiles with Different Settings', () => {
|
282
|
+
it('should manage multiple profiles independently', async () => {
|
283
|
+
// Create Development Profile
|
284
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
285
|
+
temperature: 0.9,
|
286
|
+
max_tokens: 8192,
|
287
|
+
stream: true,
|
288
|
+
});
|
289
|
+
context.services.settings.merged = {
|
290
|
+
'context-limit': 64000,
|
291
|
+
'compression-threshold': 0.9,
|
292
|
+
'tool-format': 'openai',
|
293
|
+
};
|
294
|
+
await saveCommand.action(context, '"Development Profile"');
|
295
|
+
// Create Production Profile
|
296
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
297
|
+
temperature: 0.3,
|
298
|
+
max_tokens: 2048,
|
299
|
+
stream: false,
|
300
|
+
seed: 42,
|
301
|
+
});
|
302
|
+
context.services.settings.merged = {
|
303
|
+
'context-limit': 16000,
|
304
|
+
'compression-threshold': 0.7,
|
305
|
+
'tool-format': 'openai',
|
306
|
+
};
|
307
|
+
await saveCommand.action(context, '"Production Profile"');
|
308
|
+
// Verify both profiles were saved
|
309
|
+
expect(vi.mocked(fs.writeFile)).toHaveBeenCalledTimes(2);
|
310
|
+
// Load Development Profile
|
311
|
+
const devProfileContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
312
|
+
vi.mocked(fs.readFile).mockResolvedValue(devProfileContent);
|
313
|
+
mockProvider.setModelParams = vi.fn();
|
314
|
+
const devSettings = {
|
315
|
+
merged: {},
|
316
|
+
setValue: vi
|
317
|
+
.fn()
|
318
|
+
.mockImplementation((scope, key, value) => {
|
319
|
+
devSettings.merged[key] = value;
|
320
|
+
}),
|
321
|
+
};
|
322
|
+
context.services.settings =
|
323
|
+
devSettings;
|
324
|
+
await loadCommand.action(context, '"Development Profile"');
|
325
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
326
|
+
temperature: 0.9,
|
327
|
+
max_tokens: 8192,
|
328
|
+
stream: true,
|
329
|
+
});
|
330
|
+
expect(devSettings.setValue).toHaveBeenCalledTimes(3); // 3 ephemeral settings
|
331
|
+
expect(devSettings.setValue).toHaveBeenCalledWith(SettingScope.User, 'context-limit', 64000);
|
332
|
+
// Load Production Profile
|
333
|
+
const prodProfileContent = vi.mocked(fs.writeFile).mock.calls[1][1];
|
334
|
+
vi.mocked(fs.readFile).mockResolvedValue(prodProfileContent);
|
335
|
+
mockProvider.setModelParams = vi.fn();
|
336
|
+
const prodSettings = {
|
337
|
+
merged: {},
|
338
|
+
setValue: vi
|
339
|
+
.fn()
|
340
|
+
.mockImplementation((scope, key, value) => {
|
341
|
+
prodSettings.merged[key] = value;
|
342
|
+
}),
|
343
|
+
};
|
344
|
+
context.services.settings =
|
345
|
+
prodSettings;
|
346
|
+
await loadCommand.action(context, '"Production Profile"');
|
347
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
348
|
+
temperature: 0.3,
|
349
|
+
max_tokens: 2048,
|
350
|
+
stream: false,
|
351
|
+
seed: 42,
|
352
|
+
});
|
353
|
+
expect(prodSettings.setValue).toHaveBeenCalledTimes(3); // 3 ephemeral settings
|
354
|
+
expect(prodSettings.setValue).toHaveBeenCalledWith(SettingScope.User, 'context-limit', 16000);
|
355
|
+
});
|
356
|
+
it('should handle profile names with special characters', async () => {
|
357
|
+
const specialNames = [
|
358
|
+
'Profile-2024',
|
359
|
+
'Test_Profile',
|
360
|
+
'My.Profile',
|
361
|
+
'Profile (Dev)',
|
362
|
+
'Profile & Testing',
|
363
|
+
'测试配置', // Unicode characters
|
364
|
+
];
|
365
|
+
for (const name of specialNames) {
|
366
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
367
|
+
temperature: 0.5,
|
368
|
+
});
|
369
|
+
const result = await saveCommand.action(context, `"${name}"`);
|
370
|
+
expect(result).toEqual({
|
371
|
+
type: 'message',
|
372
|
+
messageType: 'info',
|
373
|
+
content: `Profile '${name}' saved`,
|
374
|
+
});
|
375
|
+
// Verify file was created with correct name
|
376
|
+
expect(vi.mocked(fs.writeFile)).toHaveBeenCalledWith(path.join(profilesDir, `${name}.json`), expect.any(String), 'utf8');
|
377
|
+
}
|
378
|
+
});
|
379
|
+
});
|
380
|
+
describe('Switching Between Providers with Profiles', () => {
|
381
|
+
it('should switch providers when loading profiles', async () => {
|
382
|
+
// Create OpenAI profile
|
383
|
+
mockProvider.name = 'openai';
|
384
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
385
|
+
temperature: 0.7,
|
386
|
+
max_tokens: 4096,
|
387
|
+
});
|
388
|
+
await saveCommand.action(context, '"OpenAI Profile"');
|
389
|
+
// Create Anthropic profile
|
390
|
+
const anthropicProvider = {
|
391
|
+
...mockProvider,
|
392
|
+
name: 'anthropic',
|
393
|
+
getModelParams: vi.fn().mockReturnValue({
|
394
|
+
temperature: 0.5,
|
395
|
+
max_output_tokens: 4096,
|
396
|
+
}),
|
397
|
+
};
|
398
|
+
mockProviderManager.getActiveProvider.mockReturnValue(anthropicProvider);
|
399
|
+
config.getProvider = vi.fn().mockReturnValue('anthropic');
|
400
|
+
config.getModel = vi.fn().mockReturnValue('claude-3-opus-20240229');
|
401
|
+
await saveCommand.action(context, '"Anthropic Profile"');
|
402
|
+
// Load OpenAI profile
|
403
|
+
const openaiContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
404
|
+
vi.mocked(fs.readFile).mockResolvedValue(openaiContent);
|
405
|
+
await loadCommand.action(context, '"OpenAI Profile"');
|
406
|
+
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('openai');
|
407
|
+
expect(config.setModel).toHaveBeenCalledWith('gpt-4');
|
408
|
+
// Load Anthropic profile
|
409
|
+
const anthropicContent = vi.mocked(fs.writeFile).mock
|
410
|
+
.calls[1][1];
|
411
|
+
vi.mocked(fs.readFile).mockResolvedValue(anthropicContent);
|
412
|
+
await loadCommand.action(context, '"Anthropic Profile"');
|
413
|
+
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('anthropic');
|
414
|
+
expect(config.setModel).toHaveBeenCalledWith('claude-3-opus-20240229');
|
415
|
+
});
|
416
|
+
it('should handle provider-specific parameter differences', async () => {
|
417
|
+
// OpenAI uses max_tokens, Anthropic uses max_output_tokens
|
418
|
+
const providers = [
|
419
|
+
{
|
420
|
+
name: 'openai',
|
421
|
+
params: { temperature: 0.7, max_tokens: 4096 },
|
422
|
+
model: 'gpt-4',
|
423
|
+
},
|
424
|
+
{
|
425
|
+
name: 'anthropic',
|
426
|
+
params: { temperature: 0.5, max_output_tokens: 4096 },
|
427
|
+
model: 'claude-3-opus-20240229',
|
428
|
+
},
|
429
|
+
];
|
430
|
+
for (const providerConfig of providers) {
|
431
|
+
mockProvider.name = providerConfig.name;
|
432
|
+
mockProvider.getModelParams = vi
|
433
|
+
.fn()
|
434
|
+
.mockReturnValue(providerConfig.params);
|
435
|
+
config.getProvider = vi.fn().mockReturnValue(providerConfig.name);
|
436
|
+
config.getModel = vi.fn().mockReturnValue(providerConfig.model);
|
437
|
+
await saveCommand.action(context, `"${providerConfig.name} Profile"`);
|
438
|
+
}
|
439
|
+
// Verify each profile has correct provider-specific params
|
440
|
+
const savedProfiles = vi
|
441
|
+
.mocked(fs.writeFile)
|
442
|
+
.mock.calls.map((call) => JSON.parse(call[1]));
|
443
|
+
expect(savedProfiles[0]).toMatchObject({
|
444
|
+
provider: 'openai',
|
445
|
+
modelParams: { temperature: 0.7, max_tokens: 4096 },
|
446
|
+
});
|
447
|
+
expect(savedProfiles[1]).toMatchObject({
|
448
|
+
provider: 'anthropic',
|
449
|
+
modelParams: { temperature: 0.5, max_output_tokens: 4096 },
|
450
|
+
});
|
451
|
+
});
|
452
|
+
});
|
453
|
+
describe('CLI Mode with --load Flag', () => {
|
454
|
+
it('should load profile in non-interactive mode', async () => {
|
455
|
+
// Create a profile to load
|
456
|
+
const testProfile = {
|
457
|
+
version: 1,
|
458
|
+
provider: 'openai',
|
459
|
+
model: 'gpt-4',
|
460
|
+
modelParams: {
|
461
|
+
temperature: 0.7,
|
462
|
+
max_tokens: 4096,
|
463
|
+
},
|
464
|
+
ephemeralSettings: {
|
465
|
+
'context-limit': 32000,
|
466
|
+
'base-url': 'https://api.openai.com/v1',
|
467
|
+
},
|
468
|
+
};
|
469
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(testProfile));
|
470
|
+
// Simulate loading profile via CLI flag
|
471
|
+
const profileManager = new ProfileManager();
|
472
|
+
const loadedProfile = await profileManager.loadProfile('CLI Profile');
|
473
|
+
expect(loadedProfile).toEqual(testProfile);
|
474
|
+
// In actual CLI mode, these would be applied during initialization
|
475
|
+
// The config would use these values when making API calls
|
476
|
+
});
|
477
|
+
it('should apply profile settings before processing prompt', async () => {
|
478
|
+
// This tests the order of operations in CLI mode
|
479
|
+
const callOrder = [];
|
480
|
+
// Mock profile loading
|
481
|
+
const testProfile = {
|
482
|
+
version: 1,
|
483
|
+
provider: 'openai',
|
484
|
+
model: 'gpt-4o-mini',
|
485
|
+
modelParams: {
|
486
|
+
temperature: 0.5,
|
487
|
+
max_tokens: 2048,
|
488
|
+
},
|
489
|
+
ephemeralSettings: {
|
490
|
+
'context-limit': 16000,
|
491
|
+
},
|
492
|
+
};
|
493
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(testProfile));
|
494
|
+
// Mock provider operations to track order
|
495
|
+
vi.mocked(mockProviderManager.setActiveProvider).mockImplementation(() => {
|
496
|
+
callOrder.push('setActiveProvider');
|
497
|
+
});
|
498
|
+
if (mockProvider.setModelParams) {
|
499
|
+
vi.mocked(mockProvider.setModelParams).mockImplementation(() => {
|
500
|
+
callOrder.push('setModelParams');
|
501
|
+
});
|
502
|
+
}
|
503
|
+
vi.mocked(mockProvider.generateChatCompletion).mockImplementation(async function* () {
|
504
|
+
callOrder.push('generateChatCompletion');
|
505
|
+
yield { content: 'Response' };
|
506
|
+
});
|
507
|
+
// Simulate CLI initialization sequence
|
508
|
+
await mockProviderManager.setActiveProvider('openai');
|
509
|
+
await mockProvider.setModelParams?.(testProfile.modelParams);
|
510
|
+
await mockProvider.generateChatCompletion?.({}, {});
|
511
|
+
expect(callOrder).toEqual([
|
512
|
+
'setActiveProvider',
|
513
|
+
'setModelParams',
|
514
|
+
'generateChatCompletion',
|
515
|
+
]);
|
516
|
+
});
|
517
|
+
});
|
518
|
+
describe('Override Behavior (Load then Modify)', () => {
|
519
|
+
it('should allow modifying parameters after loading profile', async () => {
|
520
|
+
// Load a profile
|
521
|
+
const baseProfile = {
|
522
|
+
version: 1,
|
523
|
+
provider: 'openai',
|
524
|
+
model: 'gpt-4',
|
525
|
+
modelParams: {
|
526
|
+
temperature: 0.7,
|
527
|
+
max_tokens: 4096,
|
528
|
+
top_p: 0.95,
|
529
|
+
},
|
530
|
+
ephemeralSettings: {
|
531
|
+
'context-limit': 32000,
|
532
|
+
},
|
533
|
+
};
|
534
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(baseProfile));
|
535
|
+
await loadCommand.action(context, '"Base Profile"');
|
536
|
+
// Verify profile was loaded
|
537
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith(baseProfile.modelParams);
|
538
|
+
// Override specific parameters
|
539
|
+
mockProvider.setModelParams = vi.fn();
|
540
|
+
await setCommand.action(context, 'modelparam temperature 0.9');
|
541
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
542
|
+
temperature: 0.9,
|
543
|
+
});
|
544
|
+
await setCommand.action(context, 'modelparam max_tokens 8192');
|
545
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
546
|
+
max_tokens: 8192,
|
547
|
+
});
|
548
|
+
// Original profile remains unchanged
|
549
|
+
const reloadedProfile = JSON.parse(await fs.readFile(path.join(profilesDir, 'Base Profile.json'), 'utf8'));
|
550
|
+
expect(reloadedProfile.modelParams.temperature).toBe(0.7);
|
551
|
+
expect(reloadedProfile.modelParams.max_tokens).toBe(4096);
|
552
|
+
});
|
553
|
+
it('should allow switching providers after loading profile', async () => {
|
554
|
+
// Load OpenAI profile
|
555
|
+
const openaiProfile = {
|
556
|
+
version: 1,
|
557
|
+
provider: 'openai',
|
558
|
+
model: 'gpt-4',
|
559
|
+
modelParams: {
|
560
|
+
temperature: 0.7,
|
561
|
+
},
|
562
|
+
ephemeralSettings: {},
|
563
|
+
};
|
564
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(openaiProfile));
|
565
|
+
await loadCommand.action(context, '"OpenAI Profile"');
|
566
|
+
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('openai');
|
567
|
+
// Switch to Anthropic manually
|
568
|
+
mockProviderManager.setActiveProvider = vi.fn();
|
569
|
+
await mockProviderManager.setActiveProvider('anthropic');
|
570
|
+
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('anthropic');
|
571
|
+
// Set Anthropic-specific parameters
|
572
|
+
await setCommand.action(context, 'modelparam max_output_tokens 4096');
|
573
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
574
|
+
max_output_tokens: 4096,
|
575
|
+
});
|
576
|
+
});
|
577
|
+
});
|
578
|
+
describe('Edge Cases', () => {
|
579
|
+
it('should handle missing provider support gracefully', async () => {
|
580
|
+
// Provider without model params support
|
581
|
+
const basicProvider = {
|
582
|
+
name: 'basic-provider',
|
583
|
+
getModels: vi.fn().mockResolvedValue([]),
|
584
|
+
generateChatCompletion: vi.fn(),
|
585
|
+
getServerTools: vi.fn().mockReturnValue([]),
|
586
|
+
invokeServerTool: vi.fn().mockResolvedValue(undefined),
|
587
|
+
// No setModelParams or getModelParams
|
588
|
+
};
|
589
|
+
mockProviderManager.getActiveProvider.mockReturnValue(basicProvider);
|
590
|
+
// Try to set model params
|
591
|
+
const result = await setCommand.action(context, 'modelparam temperature 0.7');
|
592
|
+
expect(result).toEqual({
|
593
|
+
type: 'message',
|
594
|
+
messageType: 'error',
|
595
|
+
content: "Provider 'basic-provider' does not support model parameters",
|
596
|
+
});
|
597
|
+
// Can still save profile without model params
|
598
|
+
await saveCommand.action(context, '"Basic Provider Profile"');
|
599
|
+
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
600
|
+
const savedProfile = JSON.parse(savedContent);
|
601
|
+
expect(savedProfile.modelParams).toEqual({});
|
602
|
+
});
|
603
|
+
it('should handle corrupted profile files', async () => {
|
604
|
+
const corruptedCases = [
|
605
|
+
{ content: '{ invalid json }', error: 'corrupted' },
|
606
|
+
{ content: '{}', error: 'invalid: missing required fields' },
|
607
|
+
{
|
608
|
+
content: JSON.stringify({
|
609
|
+
version: 2,
|
610
|
+
provider: 'openai',
|
611
|
+
model: 'gpt-4',
|
612
|
+
modelParams: {},
|
613
|
+
ephemeralSettings: {},
|
614
|
+
}),
|
615
|
+
error: 'Unsupported profile version',
|
616
|
+
},
|
617
|
+
{
|
618
|
+
content: JSON.stringify({ version: 1, provider: 'openai' }),
|
619
|
+
error: 'invalid: missing required fields',
|
620
|
+
},
|
621
|
+
];
|
622
|
+
for (const testCase of corruptedCases) {
|
623
|
+
vi.mocked(fs.readFile).mockResolvedValue(testCase.content);
|
624
|
+
const result = await loadCommand.action(context, '"Corrupted Profile"');
|
625
|
+
expect(result?.messageType).toBe('error');
|
626
|
+
// The error messages come with 'Failed to load profile: ' prefix
|
627
|
+
if (testCase.error === 'Unsupported profile version') {
|
628
|
+
expect(result?.content?.toLowerCase()).toContain(testCase.error.toLowerCase());
|
629
|
+
}
|
630
|
+
else {
|
631
|
+
expect(result?.content).toContain(testCase.error);
|
632
|
+
}
|
633
|
+
}
|
634
|
+
});
|
635
|
+
it('should handle file system errors during save/load', async () => {
|
636
|
+
// Permission error during save
|
637
|
+
vi.mocked(fs.writeFile).mockRejectedValue(new Error('EACCES: permission denied'));
|
638
|
+
let result = await saveCommand.action(context, '"Permission Test"');
|
639
|
+
expect(result).toEqual({
|
640
|
+
type: 'message',
|
641
|
+
messageType: 'error',
|
642
|
+
content: 'Failed to save profile: EACCES: permission denied',
|
643
|
+
});
|
644
|
+
// File not found during load
|
645
|
+
vi.mocked(fs.readFile).mockRejectedValue(new Error('ENOENT: no such file or directory'));
|
646
|
+
result = await loadCommand.action(context, '"Missing Profile"');
|
647
|
+
expect(result).toEqual({
|
648
|
+
type: 'message',
|
649
|
+
messageType: 'error',
|
650
|
+
content: "Profile 'Missing Profile' not found",
|
651
|
+
});
|
652
|
+
});
|
653
|
+
it('should handle very large parameter sets', async () => {
|
654
|
+
// Create a profile with many parameters
|
655
|
+
const largeParams = {};
|
656
|
+
for (let i = 0; i < 100; i++) {
|
657
|
+
largeParams[`param_${i}`] = i % 2 === 0 ? i * 0.1 : `value_${i}`;
|
658
|
+
}
|
659
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue(largeParams);
|
660
|
+
await saveCommand.action(context, '"Large Profile"');
|
661
|
+
// Verify all parameters were saved
|
662
|
+
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
663
|
+
const savedProfile = JSON.parse(savedContent);
|
664
|
+
expect(Object.keys(savedProfile.modelParams)).toHaveLength(100);
|
665
|
+
// Load and verify all parameters are restored
|
666
|
+
vi.mocked(fs.readFile).mockResolvedValue(savedContent);
|
667
|
+
mockProvider.setModelParams = vi.fn();
|
668
|
+
await loadCommand.action(context, '"Large Profile"');
|
669
|
+
expect(mockProvider.setModelParams).toHaveBeenCalledWith(largeParams);
|
670
|
+
});
|
671
|
+
it('should preserve numeric precision in parameters', async () => {
|
672
|
+
const preciseParams = {
|
673
|
+
temperature: 0.123456789,
|
674
|
+
top_p: 0.999999999,
|
675
|
+
frequency_penalty: -0.000000001,
|
676
|
+
seed: 9007199254740991, // Max safe integer
|
677
|
+
};
|
678
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue(preciseParams);
|
679
|
+
await saveCommand.action(context, '"Precision Profile"');
|
680
|
+
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
681
|
+
vi.mocked(fs.readFile).mockResolvedValue(savedContent);
|
682
|
+
mockProvider.setModelParams = vi.fn();
|
683
|
+
await loadCommand.action(context, '"Precision Profile"');
|
684
|
+
// Verify precision was preserved
|
685
|
+
const mockCalls = vi.mocked(mockProvider.setModelParams).mock.calls;
|
686
|
+
expect(mockCalls).toHaveLength(1);
|
687
|
+
const calledParams = mockCalls[0]?.[0];
|
688
|
+
expect(calledParams).toBeDefined();
|
689
|
+
expect(calledParams?.temperature).toBe(0.123456789);
|
690
|
+
expect(calledParams?.top_p).toBe(0.999999999);
|
691
|
+
expect(calledParams?.frequency_penalty).toBe(-0.000000001);
|
692
|
+
expect(calledParams?.seed).toBe(9007199254740991);
|
693
|
+
});
|
694
|
+
});
|
695
|
+
describe('Real Integration with File System', () => {
|
696
|
+
it('should verify complete data flow from commands to API', async () => {
|
697
|
+
// This test verifies the entire flow without mocking file operations
|
698
|
+
// In a real environment, this would create actual files
|
699
|
+
// Set up a complete workflow
|
700
|
+
const workflow = async () => {
|
701
|
+
// 1. Set parameters
|
702
|
+
await setCommand.action(context, 'modelparam temperature 0.75');
|
703
|
+
await setCommand.action(context, 'modelparam max_tokens 3000');
|
704
|
+
await setCommand.action(context, 'modelparam response_format {"type":"json_object"}');
|
705
|
+
// 2. Set ephemeral settings using settings.setValue
|
706
|
+
settings.setValue(SettingScope.User, 'context-limit', 25000);
|
707
|
+
settings.setValue(SettingScope.User, 'compression-threshold', 0.82);
|
708
|
+
// Update context settings merged to include these values
|
709
|
+
context.services.settings.merged['context-limit'] = 25000;
|
710
|
+
context.services.settings.merged['compression-threshold'] = 0.82;
|
711
|
+
// 3. Save profile
|
712
|
+
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
713
|
+
temperature: 0.75,
|
714
|
+
max_tokens: 3000,
|
715
|
+
response_format: { type: 'json_object' },
|
716
|
+
});
|
717
|
+
await saveCommand.action(context, '"Integration Test Profile"');
|
718
|
+
// 4. Clear state
|
719
|
+
mockProvider.setModelParams = vi.fn();
|
720
|
+
const freshSettings = {
|
721
|
+
merged: {},
|
722
|
+
setValue: vi
|
723
|
+
.fn()
|
724
|
+
.mockImplementation((scope, key, value) => {
|
725
|
+
freshSettings.merged[key] = value;
|
726
|
+
}),
|
727
|
+
};
|
728
|
+
context.services.settings =
|
729
|
+
freshSettings;
|
730
|
+
// 5. Load profile
|
731
|
+
const savedProfile = vi.mocked(fs.writeFile).mock.calls[0][1];
|
732
|
+
vi.mocked(fs.readFile).mockResolvedValue(savedProfile);
|
733
|
+
await loadCommand.action(context, '"Integration Test Profile"');
|
734
|
+
// 6. Verify complete restoration
|
735
|
+
return {
|
736
|
+
modelParams: vi.mocked(mockProvider.setModelParams).mock.calls[0][0],
|
737
|
+
ephemeralSettings: vi
|
738
|
+
.mocked(freshSettings.setValue)
|
739
|
+
.mock.calls.reduce((acc, call) => {
|
740
|
+
acc[call[1]] = call[2];
|
741
|
+
return acc;
|
742
|
+
}, {}),
|
743
|
+
};
|
744
|
+
};
|
745
|
+
const result = await workflow();
|
746
|
+
expect(result.modelParams).toEqual({
|
747
|
+
temperature: 0.75,
|
748
|
+
max_tokens: 3000,
|
749
|
+
response_format: { type: 'json_object' },
|
750
|
+
});
|
751
|
+
expect(result.ephemeralSettings).toMatchObject({
|
752
|
+
'context-limit': 25000,
|
753
|
+
'compression-threshold': 0.82,
|
754
|
+
});
|
755
|
+
});
|
756
|
+
});
|
757
|
+
describe('Profile Manager Integration', () => {
|
758
|
+
it('should work with ProfileManager for save and load operations', async () => {
|
759
|
+
const profileManager = new ProfileManager();
|
760
|
+
// Create a test profile
|
761
|
+
const testProfile = {
|
762
|
+
version: 1,
|
763
|
+
provider: 'openai',
|
764
|
+
model: 'gpt-4',
|
765
|
+
modelParams: {
|
766
|
+
temperature: 0.6,
|
767
|
+
max_tokens: 5000,
|
768
|
+
},
|
769
|
+
ephemeralSettings: {
|
770
|
+
'context-limit': 40000,
|
771
|
+
},
|
772
|
+
};
|
773
|
+
// Mock ProfileManager save operation
|
774
|
+
vi.mocked(fs.writeFile).mockResolvedValue(undefined);
|
775
|
+
// Save using ProfileManager (simulated)
|
776
|
+
await fs.writeFile(path.join(profilesDir, 'ProfileManager Test.json'), JSON.stringify(testProfile, null, 2), 'utf8');
|
777
|
+
// Load using ProfileManager (simulated)
|
778
|
+
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(testProfile));
|
779
|
+
const loadedProfile = await profileManager.loadProfile('ProfileManager Test');
|
780
|
+
expect(loadedProfile).toEqual(testProfile);
|
781
|
+
});
|
782
|
+
});
|
783
|
+
});
|
784
|
+
//# sourceMappingURL=modelParams.integration.test.js.map
|