@vybestack/llxprt-code 0.4.8 → 0.5.0-nightly.251102.6bb3db7a
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/package.json +5 -3
- package/dist/src/auth/__tests__/oauthManager.safety.test.d.ts +6 -0
- package/dist/src/auth/__tests__/oauthManager.safety.test.js +49 -0
- package/dist/src/auth/__tests__/oauthManager.safety.test.js.map +1 -0
- package/dist/src/auth/oauth-manager.d.ts +11 -0
- package/dist/src/auth/oauth-manager.js +62 -29
- package/dist/src/auth/oauth-manager.js.map +1 -1
- package/dist/src/auth/oauth-manager.spec.js +7 -2
- package/dist/src/auth/oauth-manager.spec.js.map +1 -1
- package/dist/src/config/__tests__/nonInteractiveTools.test.d.ts +6 -0
- package/dist/src/config/__tests__/nonInteractiveTools.test.js +13 -0
- package/dist/src/config/__tests__/nonInteractiveTools.test.js.map +1 -0
- package/dist/src/config/__tests__/profileBootstrap.test.d.ts +6 -0
- package/dist/src/config/__tests__/profileBootstrap.test.js +91 -0
- package/dist/src/config/__tests__/profileBootstrap.test.js.map +1 -0
- package/dist/src/config/config.d.ts +6 -2
- package/dist/src/config/config.js +219 -18
- package/dist/src/config/config.js.map +1 -1
- package/dist/src/config/profileBootstrap.d.ts +64 -0
- package/dist/src/config/profileBootstrap.js +140 -0
- package/dist/src/config/profileBootstrap.js.map +1 -0
- package/dist/src/gemini.js +68 -23
- package/dist/src/gemini.js.map +1 -1
- package/dist/src/gemini.test.js +1 -2
- package/dist/src/gemini.test.js.map +1 -1
- 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.js +110 -450
- package/dist/src/integration-tests/base-url-behavior.integration.test.js.map +1 -1
- package/dist/src/integration-tests/model-params-isolation.integration.test.js +101 -539
- package/dist/src/integration-tests/model-params-isolation.integration.test.js.map +1 -1
- package/dist/src/integration-tests/modelParams.integration.test.js +86 -761
- package/dist/src/integration-tests/modelParams.integration.test.js.map +1 -1
- package/dist/src/integration-tests/provider-multi-runtime.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/provider-multi-runtime.integration.test.js +198 -0
- package/dist/src/integration-tests/provider-multi-runtime.integration.test.js.map +1 -0
- package/dist/src/integration-tests/provider-switching.integration.test.js +97 -151
- package/dist/src/integration-tests/provider-switching.integration.test.js.map +1 -1
- package/dist/src/integration-tests/runtime-isolation.test.d.ts +13 -0
- package/dist/src/integration-tests/runtime-isolation.test.js +170 -0
- package/dist/src/integration-tests/runtime-isolation.test.js.map +1 -0
- package/dist/src/integration-tests/test-utils.js +19 -2
- package/dist/src/integration-tests/test-utils.js.map +1 -1
- package/dist/src/integration-tests/test-utils.test.js +9 -8
- package/dist/src/integration-tests/test-utils.test.js.map +1 -1
- package/dist/src/integration-tests/todo-continuation.integration.test.js +5 -2
- package/dist/src/integration-tests/todo-continuation.integration.test.js.map +1 -1
- package/dist/src/integration-tests/tools-governance.integration.test.d.ts +6 -0
- package/dist/src/integration-tests/tools-governance.integration.test.js +98 -0
- package/dist/src/integration-tests/tools-governance.integration.test.js.map +1 -0
- package/dist/src/nonInteractiveCli.js +36 -11
- package/dist/src/nonInteractiveCli.js.map +1 -1
- package/dist/src/providers/logging/git-stats.test.js +11 -1
- package/dist/src/providers/logging/git-stats.test.js.map +1 -1
- package/dist/src/providers/logging/multi-provider-logging.integration.test.js +1 -2
- package/dist/src/providers/logging/multi-provider-logging.integration.test.js.map +1 -1
- package/dist/src/providers/logging/performance.test.js +1 -1
- package/dist/src/providers/logging/performance.test.js.map +1 -1
- package/dist/src/providers/oauth-provider-registration.d.ts +2 -2
- package/dist/src/providers/oauth-provider-registration.js +25 -9
- package/dist/src/providers/oauth-provider-registration.js.map +1 -1
- package/dist/src/providers/provider-gemini-switching.test.js +67 -89
- package/dist/src/providers/provider-gemini-switching.test.js.map +1 -1
- package/dist/src/providers/provider-switching.integration.test.js +42 -98
- package/dist/src/providers/provider-switching.integration.test.js.map +1 -1
- package/dist/src/providers/providerConfigUtils.d.ts +12 -7
- package/dist/src/providers/providerConfigUtils.js +31 -99
- package/dist/src/providers/providerConfigUtils.js.map +1 -1
- package/dist/src/providers/providerManagerInstance.d.ts +17 -1
- package/dist/src/providers/providerManagerInstance.js +157 -175
- package/dist/src/providers/providerManagerInstance.js.map +1 -1
- package/dist/src/providers/providerManagerInstance.oauthRegistration.test.js +19 -15
- package/dist/src/providers/providerManagerInstance.oauthRegistration.test.js.map +1 -1
- package/dist/src/providers/providerManagerInstance.test.js +2 -5
- package/dist/src/providers/providerManagerInstance.test.js.map +1 -1
- package/dist/src/runtime/__tests__/profileApplication.test.d.ts +5 -0
- package/dist/src/runtime/__tests__/profileApplication.test.js +232 -0
- package/dist/src/runtime/__tests__/profileApplication.test.js.map +1 -0
- package/dist/src/runtime/__tests__/runtimeIsolation.test.d.ts +5 -0
- package/dist/src/runtime/__tests__/runtimeIsolation.test.js +376 -0
- package/dist/src/runtime/__tests__/runtimeIsolation.test.js.map +1 -0
- package/dist/src/runtime/agentRuntimeAdapter.d.ts +249 -0
- package/dist/src/runtime/agentRuntimeAdapter.js +506 -0
- package/dist/src/runtime/agentRuntimeAdapter.js.map +1 -0
- package/dist/src/runtime/agentRuntimeAdapter.spec.d.ts +6 -0
- package/dist/src/runtime/agentRuntimeAdapter.spec.js +866 -0
- package/dist/src/runtime/agentRuntimeAdapter.spec.js.map +1 -0
- package/dist/src/runtime/messages.d.ts +28 -0
- package/dist/src/runtime/messages.js +64 -0
- package/dist/src/runtime/messages.js.map +1 -0
- package/dist/src/runtime/profileApplication.d.ts +33 -0
- package/dist/src/runtime/profileApplication.js +191 -0
- package/dist/src/runtime/profileApplication.js.map +1 -0
- package/dist/src/runtime/providerConfigUtils.test.d.ts +1 -0
- package/dist/src/runtime/providerConfigUtils.test.js +68 -0
- package/dist/src/runtime/providerConfigUtils.test.js.map +1 -0
- package/dist/src/runtime/runtimeContextFactory.d.ts +102 -0
- package/dist/src/runtime/runtimeContextFactory.js +190 -0
- package/dist/src/runtime/runtimeContextFactory.js.map +1 -0
- package/dist/src/runtime/runtimeSettings.d.ts +217 -0
- package/dist/src/runtime/runtimeSettings.js +1094 -0
- package/dist/src/runtime/runtimeSettings.js.map +1 -0
- package/dist/src/runtime/runtimeSettings.test.d.ts +1 -0
- package/dist/src/runtime/runtimeSettings.test.js +320 -0
- package/dist/src/runtime/runtimeSettings.test.js.map +1 -0
- package/dist/src/services/BuiltinCommandLoader.d.ts +13 -4
- package/dist/src/services/BuiltinCommandLoader.js +17 -4
- package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
- package/dist/src/services/McpPromptLoader.js +34 -13
- package/dist/src/services/McpPromptLoader.js.map +1 -1
- package/dist/src/test-utils/mockCommandContext.js +5 -2
- package/dist/src/test-utils/mockCommandContext.js.map +1 -1
- package/dist/src/ui/App.js +29 -49
- package/dist/src/ui/App.js.map +1 -1
- package/dist/src/ui/commands/aboutCommand.js +59 -38
- package/dist/src/ui/commands/aboutCommand.js.map +1 -1
- package/dist/src/ui/commands/authCommand.js +7 -9
- package/dist/src/ui/commands/authCommand.js.map +1 -1
- package/dist/src/ui/commands/baseurlCommand.js +8 -44
- package/dist/src/ui/commands/baseurlCommand.js.map +1 -1
- package/dist/src/ui/commands/chatCommand.js +28 -12
- package/dist/src/ui/commands/chatCommand.js.map +1 -1
- package/dist/src/ui/commands/diagnosticsCommand.d.ts +0 -3
- package/dist/src/ui/commands/diagnosticsCommand.js +45 -191
- package/dist/src/ui/commands/diagnosticsCommand.js.map +1 -1
- package/dist/src/ui/commands/keyCommand.js +9 -58
- package/dist/src/ui/commands/keyCommand.js.map +1 -1
- package/dist/src/ui/commands/keyCommand.test.js +48 -102
- package/dist/src/ui/commands/keyCommand.test.js.map +1 -1
- package/dist/src/ui/commands/keyfileCommand.js +42 -93
- package/dist/src/ui/commands/keyfileCommand.js.map +1 -1
- package/dist/src/ui/commands/logoutCommand.js +2 -2
- package/dist/src/ui/commands/logoutCommand.js.map +1 -1
- package/dist/src/ui/commands/mcpCommand.js +29 -7
- package/dist/src/ui/commands/mcpCommand.js.map +1 -1
- package/dist/src/ui/commands/modelCommand.js +8 -59
- package/dist/src/ui/commands/modelCommand.js.map +1 -1
- package/dist/src/ui/commands/profileCommand.js +151 -267
- package/dist/src/ui/commands/profileCommand.js.map +1 -1
- package/dist/src/ui/commands/profileCommand.test.js +88 -344
- package/dist/src/ui/commands/profileCommand.test.js.map +1 -1
- package/dist/src/ui/commands/providerCommand.js +9 -3
- package/dist/src/ui/commands/providerCommand.js.map +1 -1
- package/dist/src/ui/commands/restoreCommand.js +38 -18
- package/dist/src/ui/commands/restoreCommand.js.map +1 -1
- package/dist/src/ui/commands/schema/argumentResolver.test.d.ts +6 -0
- package/dist/src/ui/commands/schema/argumentResolver.test.js +619 -0
- package/dist/src/ui/commands/schema/argumentResolver.test.js.map +1 -0
- package/dist/src/ui/commands/schema/index.d.ts +15 -0
- package/dist/src/ui/commands/schema/index.js +320 -0
- package/dist/src/ui/commands/schema/index.js.map +1 -0
- package/dist/src/ui/commands/schema/types.d.ts +61 -0
- package/dist/src/ui/commands/schema/types.js +12 -0
- package/dist/src/ui/commands/schema/types.js.map +1 -0
- package/dist/src/ui/commands/setCommand.js +641 -325
- package/dist/src/ui/commands/setCommand.js.map +1 -1
- package/dist/src/ui/commands/setCommand.test.js +92 -388
- package/dist/src/ui/commands/setCommand.test.js.map +1 -1
- package/dist/src/ui/commands/statusCommand.js +2 -2
- package/dist/src/ui/commands/statusCommand.js.map +1 -1
- package/dist/src/ui/commands/subagentCommand.d.ts +16 -0
- package/dist/src/ui/commands/subagentCommand.js +674 -0
- package/dist/src/ui/commands/subagentCommand.js.map +1 -0
- package/dist/src/ui/commands/test/setCommand.mutation.test.d.ts +6 -0
- package/dist/src/ui/commands/test/setCommand.mutation.test.js +132 -0
- package/dist/src/ui/commands/test/setCommand.mutation.test.js.map +1 -0
- package/dist/src/ui/commands/test/setCommand.phase09.test.d.ts +6 -0
- package/dist/src/ui/commands/test/setCommand.phase09.test.js +222 -0
- package/dist/src/ui/commands/test/setCommand.phase09.test.js.map +1 -0
- package/dist/src/ui/commands/test/subagentCommand.schema.test.d.ts +6 -0
- package/dist/src/ui/commands/test/subagentCommand.schema.test.js +125 -0
- package/dist/src/ui/commands/test/subagentCommand.schema.test.js.map +1 -0
- package/dist/src/ui/commands/test/subagentCommand.test.d.ts +1 -0
- package/dist/src/ui/commands/test/subagentCommand.test.js +598 -0
- package/dist/src/ui/commands/test/subagentCommand.test.js.map +1 -0
- package/dist/src/ui/commands/toolformatCommand.js +25 -98
- package/dist/src/ui/commands/toolformatCommand.js.map +1 -1
- package/dist/src/ui/commands/toolformatCommand.test.js +56 -102
- package/dist/src/ui/commands/toolformatCommand.test.js.map +1 -1
- package/dist/src/ui/commands/toolsCommand.js +187 -31
- package/dist/src/ui/commands/toolsCommand.js.map +1 -1
- package/dist/src/ui/commands/types.d.ts +11 -2
- package/dist/src/ui/commands/types.js.map +1 -1
- package/dist/src/ui/components/AuthDialog.js +16 -55
- package/dist/src/ui/components/AuthDialog.js.map +1 -1
- package/dist/src/ui/components/Footer.js +4 -5
- package/dist/src/ui/components/Footer.js.map +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
- package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
- package/dist/src/ui/components/InputPrompt.js +1 -1
- package/dist/src/ui/components/InputPrompt.js.map +1 -1
- package/dist/src/ui/components/StatsDisplay.js +6 -11
- package/dist/src/ui/components/StatsDisplay.js.map +1 -1
- package/dist/src/ui/components/SuggestionsDisplay.d.ts +13 -1
- package/dist/src/ui/components/SuggestionsDisplay.js +22 -3
- package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.d.ts +1 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.js +14 -14
- package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js +1 -0
- package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
- package/dist/src/ui/containers/SessionController.js +61 -117
- package/dist/src/ui/containers/SessionController.js.map +1 -1
- package/dist/src/ui/contexts/RuntimeContext.d.ts +61 -0
- package/dist/src/ui/contexts/RuntimeContext.js +118 -0
- package/dist/src/ui/contexts/RuntimeContext.js.map +1 -0
- package/dist/src/ui/contexts/TodoProvider.d.ts +1 -0
- package/dist/src/ui/contexts/TodoProvider.js +10 -8
- package/dist/src/ui/contexts/TodoProvider.js.map +1 -1
- package/dist/src/ui/contexts/ToolCallProvider.d.ts +1 -0
- package/dist/src/ui/contexts/ToolCallProvider.js +10 -9
- package/dist/src/ui/contexts/ToolCallProvider.js.map +1 -1
- package/dist/src/ui/hooks/__tests__/useSlashCompletion.set.phase09.test.d.ts +6 -0
- package/dist/src/ui/hooks/__tests__/useSlashCompletion.set.phase09.test.js +39 -0
- package/dist/src/ui/hooks/__tests__/useSlashCompletion.set.phase09.test.js.map +1 -0
- package/dist/src/ui/hooks/atCommandProcessor.js +11 -3
- package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js +3 -1
- package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.js +4 -1
- package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/shellCommandProcessor.test.js +1 -0
- package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js +27 -1
- package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
- package/dist/src/ui/hooks/useAuthCommand.js +11 -3
- package/dist/src/ui/hooks/useAuthCommand.js.map +1 -1
- package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -0
- package/dist/src/ui/hooks/useCommandCompletion.js +2 -0
- package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.js +37 -11
- package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
- package/dist/src/ui/hooks/useGeminiStream.subagent.spec.d.ts +6 -0
- package/dist/src/ui/hooks/useGeminiStream.subagent.spec.js +232 -0
- package/dist/src/ui/hooks/useGeminiStream.subagent.spec.js.map +1 -0
- package/dist/src/ui/hooks/useLoadProfileDialog.d.ts +1 -1
- package/dist/src/ui/hooks/useLoadProfileDialog.js +18 -57
- package/dist/src/ui/hooks/useLoadProfileDialog.js.map +1 -1
- package/dist/src/ui/hooks/useOpenAIProviderInfo.d.ts +1 -1
- package/dist/src/ui/hooks/useOpenAIProviderInfo.js +12 -7
- package/dist/src/ui/hooks/useOpenAIProviderInfo.js.map +1 -1
- package/dist/src/ui/hooks/useProviderDialog.d.ts +1 -1
- package/dist/src/ui/hooks/useProviderDialog.js +17 -90
- package/dist/src/ui/hooks/useProviderDialog.js.map +1 -1
- package/dist/src/ui/hooks/useProviderModelDialog.d.ts +2 -2
- package/dist/src/ui/hooks/useProviderModelDialog.js +11 -12
- package/dist/src/ui/hooks/useProviderModelDialog.js.map +1 -1
- package/dist/src/ui/hooks/useReactToolScheduler.d.ts +3 -1
- package/dist/src/ui/hooks/useReactToolScheduler.js +144 -34
- package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.d.ts +32 -0
- package/dist/src/ui/hooks/useSlashCompletion.js +154 -77
- package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
- package/dist/src/ui/hooks/useSlashCompletion.test.js +39 -14
- package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
- package/dist/src/ui/hooks/useToolScheduler.test.js +108 -79
- package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
- package/dist/src/ui/types.d.ts +1 -0
- package/dist/src/ui/types.js.map +1 -1
- package/dist/src/utils/sandbox.js +7 -5
- package/dist/src/utils/sandbox.js.map +1 -1
- package/dist/src/validateNonInterActiveAuth.js +4 -2
- package/dist/src/validateNonInterActiveAuth.js.map +1 -1
- package/dist/src/zed-integration/schema.d.ts +30 -30
- package/dist/src/zed-integration/zedIntegration.js +112 -39
- package/dist/src/zed-integration/zedIntegration.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -0
- package/package.json +5 -3
- package/dist/tsconfig.tsbuildinfo +0 -1
|
@@ -3,785 +3,110 @@
|
|
|
3
3
|
* Copyright 2025 Vybestack LLC
|
|
4
4
|
* SPDX-License-Identifier: Apache-2.0
|
|
5
5
|
*/
|
|
6
|
-
import {
|
|
7
|
-
import
|
|
8
|
-
import os from 'os';
|
|
9
|
-
import path from 'path';
|
|
6
|
+
import { beforeEach, afterEach, describe, expect, it } from 'vitest';
|
|
7
|
+
import { Config, ProviderManager, } from '@vybestack/llxprt-code-core';
|
|
10
8
|
import { createMockCommandContext } from '../test-utils/mockCommandContext.js';
|
|
11
9
|
import { setCommand } from '../ui/commands/setCommand.js';
|
|
12
|
-
import {
|
|
13
|
-
|
|
14
|
-
|
|
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();
|
|
10
|
+
import { setCliRuntimeContext, registerCliProviderInfrastructure, resetCliProviderInfrastructure, getActiveModelParams, buildRuntimeProfileSnapshot, clearActiveModelParam, } from '../runtime/runtimeSettings.js';
|
|
11
|
+
import { createTempDirectory, cleanupTempDirectory } from './test-utils.js';
|
|
12
|
+
function createStubProvider(name) {
|
|
34
13
|
return {
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
}),
|
|
14
|
+
name,
|
|
15
|
+
async getModels() {
|
|
16
|
+
return [
|
|
17
|
+
{
|
|
18
|
+
id: `${name}-model`,
|
|
19
|
+
name: `${name}-model`,
|
|
20
|
+
provider: name,
|
|
21
|
+
supportedToolFormats: [],
|
|
60
22
|
},
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
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',
|
|
23
|
+
];
|
|
24
|
+
},
|
|
25
|
+
getDefaultModel() {
|
|
26
|
+
return `${name}-model`;
|
|
27
|
+
},
|
|
28
|
+
async *generateChatCompletion() {
|
|
29
|
+
yield {
|
|
30
|
+
speaker: 'ai',
|
|
31
|
+
blocks: [{ type: 'text', text: `response-from-${name}` }],
|
|
32
|
+
};
|
|
33
|
+
},
|
|
34
|
+
getServerTools() {
|
|
35
|
+
return [];
|
|
36
|
+
},
|
|
37
|
+
async invokeServerTool() {
|
|
38
|
+
return {};
|
|
85
39
|
},
|
|
86
40
|
};
|
|
41
|
+
}
|
|
42
|
+
describe('CLI model parameter command integration', () => {
|
|
43
|
+
let tempDir;
|
|
44
|
+
let config;
|
|
45
|
+
let settingsService;
|
|
46
|
+
let providerManager;
|
|
47
|
+
let context;
|
|
48
|
+
const runSetCommand = async (args) => {
|
|
49
|
+
if (!setCommand.action) {
|
|
50
|
+
throw new Error('setCommand.action is not defined');
|
|
51
|
+
}
|
|
52
|
+
return setCommand.action(context, args);
|
|
53
|
+
};
|
|
87
54
|
beforeEach(async () => {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
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
|
|
55
|
+
tempDir = await createTempDirectory();
|
|
56
|
+
config = new Config({
|
|
57
|
+
sessionId: 'model-params-integration',
|
|
58
|
+
targetDir: tempDir,
|
|
59
|
+
debugMode: false,
|
|
60
|
+
cwd: tempDir,
|
|
61
|
+
model: 'alpha-model',
|
|
62
|
+
});
|
|
63
|
+
await config.initialize();
|
|
64
|
+
settingsService = config.getSettingsService();
|
|
65
|
+
providerManager = new ProviderManager({ settingsService, config });
|
|
66
|
+
providerManager.registerProvider(createStubProvider('alpha'));
|
|
67
|
+
providerManager.setActiveProvider('alpha');
|
|
68
|
+
registerCliProviderInfrastructure(providerManager, {});
|
|
69
|
+
setCliRuntimeContext(settingsService, config, {
|
|
70
|
+
metadata: { source: 'modelParams.integration.test.ts' },
|
|
71
|
+
});
|
|
152
72
|
context = createMockCommandContext({
|
|
153
73
|
services: {
|
|
154
74
|
config: config,
|
|
155
|
-
settings:
|
|
75
|
+
settings: settingsService,
|
|
156
76
|
},
|
|
157
77
|
});
|
|
158
78
|
});
|
|
159
|
-
afterEach(() => {
|
|
160
|
-
|
|
79
|
+
afterEach(async () => {
|
|
80
|
+
resetCliProviderInfrastructure();
|
|
81
|
+
await cleanupTempDirectory(tempDir);
|
|
161
82
|
});
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|
-
});
|
|
83
|
+
it('sets provider-scoped model params via /set modelparam', async () => {
|
|
84
|
+
await runSetCommand('modelparam temperature 0.9');
|
|
85
|
+
expect(getActiveModelParams()).toEqual({ temperature: 0.9 });
|
|
86
|
+
expect(settingsService.getProviderSettings('alpha').temperature).toBe(0.9);
|
|
280
87
|
});
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
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
|
-
});
|
|
88
|
+
it('clears model params using /set unset modelparam', async () => {
|
|
89
|
+
await runSetCommand('modelparam max_tokens 4096');
|
|
90
|
+
expect(getActiveModelParams()).toEqual({ max_tokens: 4096 });
|
|
91
|
+
await runSetCommand('unset modelparam max_tokens');
|
|
92
|
+
expect(getActiveModelParams()).toEqual({});
|
|
93
|
+
expect(settingsService.getProviderSettings('alpha').max_tokens).toBeUndefined();
|
|
379
94
|
});
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
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
|
-
});
|
|
95
|
+
it('produces runtime profile snapshots that include current model params', async () => {
|
|
96
|
+
await runSetCommand('modelparam response_format {"type":"json_object"}');
|
|
97
|
+
await runSetCommand('modelparam top_p 0.92');
|
|
98
|
+
const snapshot = buildRuntimeProfileSnapshot();
|
|
99
|
+
expect(snapshot.provider).toBe('alpha');
|
|
100
|
+
expect(snapshot.modelParams).toEqual({
|
|
101
|
+
response_format: { type: 'json_object' },
|
|
102
|
+
top_p: 0.92,
|
|
451
103
|
});
|
|
452
104
|
});
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
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 {
|
|
506
|
-
speaker: 'ai',
|
|
507
|
-
blocks: [{ type: 'text', text: 'Response' }],
|
|
508
|
-
};
|
|
509
|
-
});
|
|
510
|
-
// Simulate CLI initialization sequence
|
|
511
|
-
await mockProviderManager.setActiveProvider('openai');
|
|
512
|
-
await mockProvider.setModelParams?.(testProfile.modelParams);
|
|
513
|
-
await mockProvider.generateChatCompletion?.({}, {});
|
|
514
|
-
expect(callOrder).toEqual([
|
|
515
|
-
'setActiveProvider',
|
|
516
|
-
'setModelParams',
|
|
517
|
-
'generateChatCompletion',
|
|
518
|
-
]);
|
|
519
|
-
});
|
|
520
|
-
});
|
|
521
|
-
describe('Override Behavior (Load then Modify)', () => {
|
|
522
|
-
it('should allow modifying parameters after loading profile', async () => {
|
|
523
|
-
// Load a profile
|
|
524
|
-
const baseProfile = {
|
|
525
|
-
version: 1,
|
|
526
|
-
provider: 'openai',
|
|
527
|
-
model: 'gpt-4',
|
|
528
|
-
modelParams: {
|
|
529
|
-
temperature: 0.7,
|
|
530
|
-
max_tokens: 4096,
|
|
531
|
-
top_p: 0.95,
|
|
532
|
-
},
|
|
533
|
-
ephemeralSettings: {
|
|
534
|
-
'context-limit': 32000,
|
|
535
|
-
},
|
|
536
|
-
};
|
|
537
|
-
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(baseProfile));
|
|
538
|
-
await loadCommand.action(context, '"Base Profile"');
|
|
539
|
-
// Verify profile was loaded
|
|
540
|
-
expect(mockProvider.setModelParams).toHaveBeenCalledWith(baseProfile.modelParams);
|
|
541
|
-
// Override specific parameters
|
|
542
|
-
mockProvider.setModelParams = vi.fn();
|
|
543
|
-
await setCommand.action(context, 'modelparam temperature 0.9');
|
|
544
|
-
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
|
545
|
-
temperature: 0.9,
|
|
546
|
-
});
|
|
547
|
-
await setCommand.action(context, 'modelparam max_tokens 8192');
|
|
548
|
-
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
|
549
|
-
max_tokens: 8192,
|
|
550
|
-
});
|
|
551
|
-
// Original profile remains unchanged
|
|
552
|
-
const reloadedProfile = JSON.parse(await fs.readFile(path.join(profilesDir, 'Base Profile.json'), 'utf8'));
|
|
553
|
-
expect(reloadedProfile.modelParams.temperature).toBe(0.7);
|
|
554
|
-
expect(reloadedProfile.modelParams.max_tokens).toBe(4096);
|
|
555
|
-
});
|
|
556
|
-
it('should allow switching providers after loading profile', async () => {
|
|
557
|
-
// Load OpenAI profile
|
|
558
|
-
const openaiProfile = {
|
|
559
|
-
version: 1,
|
|
560
|
-
provider: 'openai',
|
|
561
|
-
model: 'gpt-4',
|
|
562
|
-
modelParams: {
|
|
563
|
-
temperature: 0.7,
|
|
564
|
-
},
|
|
565
|
-
ephemeralSettings: {},
|
|
566
|
-
};
|
|
567
|
-
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(openaiProfile));
|
|
568
|
-
await loadCommand.action(context, '"OpenAI Profile"');
|
|
569
|
-
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('openai');
|
|
570
|
-
// Switch to Anthropic manually
|
|
571
|
-
mockProviderManager.setActiveProvider = vi.fn();
|
|
572
|
-
await mockProviderManager.setActiveProvider('anthropic');
|
|
573
|
-
expect(mockProviderManager.setActiveProvider).toHaveBeenCalledWith('anthropic');
|
|
574
|
-
// Set Anthropic-specific parameters
|
|
575
|
-
await setCommand.action(context, 'modelparam max_output_tokens 4096');
|
|
576
|
-
expect(mockProvider.setModelParams).toHaveBeenCalledWith({
|
|
577
|
-
max_output_tokens: 4096,
|
|
578
|
-
});
|
|
579
|
-
});
|
|
580
|
-
});
|
|
581
|
-
describe('Edge Cases', () => {
|
|
582
|
-
it('should handle missing provider support gracefully', async () => {
|
|
583
|
-
// Provider without model params support
|
|
584
|
-
const basicProvider = {
|
|
585
|
-
name: 'basic-provider',
|
|
586
|
-
getModels: vi.fn().mockResolvedValue([]),
|
|
587
|
-
generateChatCompletion: vi.fn(),
|
|
588
|
-
getServerTools: vi.fn().mockReturnValue([]),
|
|
589
|
-
invokeServerTool: vi.fn().mockResolvedValue(undefined),
|
|
590
|
-
// No setModelParams or getModelParams
|
|
591
|
-
};
|
|
592
|
-
mockProviderManager.getActiveProvider.mockReturnValue(basicProvider);
|
|
593
|
-
// Try to set model params
|
|
594
|
-
const result = await setCommand.action(context, 'modelparam temperature 0.7');
|
|
595
|
-
expect(result).toEqual({
|
|
596
|
-
type: 'message',
|
|
597
|
-
messageType: 'error',
|
|
598
|
-
content: "Provider 'basic-provider' does not support model parameters",
|
|
599
|
-
});
|
|
600
|
-
// Can still save profile without model params
|
|
601
|
-
await saveCommand.action(context, '"Basic Provider Profile"');
|
|
602
|
-
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
|
603
|
-
const savedProfile = JSON.parse(savedContent);
|
|
604
|
-
expect(savedProfile.modelParams).toEqual({});
|
|
605
|
-
});
|
|
606
|
-
it('should handle corrupted profile files', async () => {
|
|
607
|
-
const corruptedCases = [
|
|
608
|
-
{ content: '{ invalid json }', error: 'corrupted' },
|
|
609
|
-
{ content: '{}', error: 'invalid: missing required fields' },
|
|
610
|
-
{
|
|
611
|
-
content: JSON.stringify({
|
|
612
|
-
version: 2,
|
|
613
|
-
provider: 'openai',
|
|
614
|
-
model: 'gpt-4',
|
|
615
|
-
modelParams: {},
|
|
616
|
-
ephemeralSettings: {},
|
|
617
|
-
}),
|
|
618
|
-
error: 'Unsupported profile version',
|
|
619
|
-
},
|
|
620
|
-
{
|
|
621
|
-
content: JSON.stringify({ version: 1, provider: 'openai' }),
|
|
622
|
-
error: 'invalid: missing required fields',
|
|
623
|
-
},
|
|
624
|
-
];
|
|
625
|
-
for (const testCase of corruptedCases) {
|
|
626
|
-
vi.mocked(fs.readFile).mockResolvedValue(testCase.content);
|
|
627
|
-
const result = await loadCommand.action(context, '"Corrupted Profile"');
|
|
628
|
-
expect(result?.messageType).toBe('error');
|
|
629
|
-
// The error messages come with 'Failed to load profile: ' prefix
|
|
630
|
-
if (testCase.error === 'Unsupported profile version') {
|
|
631
|
-
expect(result?.content?.toLowerCase()).toContain(testCase.error.toLowerCase());
|
|
632
|
-
}
|
|
633
|
-
else {
|
|
634
|
-
expect(result?.content).toContain(testCase.error);
|
|
635
|
-
}
|
|
636
|
-
}
|
|
637
|
-
});
|
|
638
|
-
it('should handle file system errors during save/load', async () => {
|
|
639
|
-
// Permission error during save
|
|
640
|
-
vi.mocked(fs.writeFile).mockRejectedValue(new Error('EACCES: permission denied'));
|
|
641
|
-
let result = await saveCommand.action(context, '"Permission Test"');
|
|
642
|
-
expect(result).toEqual({
|
|
643
|
-
type: 'message',
|
|
644
|
-
messageType: 'error',
|
|
645
|
-
content: 'Failed to save profile: EACCES: permission denied',
|
|
646
|
-
});
|
|
647
|
-
// File not found during load
|
|
648
|
-
vi.mocked(fs.readFile).mockRejectedValue(new Error('ENOENT: no such file or directory'));
|
|
649
|
-
result = await loadCommand.action(context, '"Missing Profile"');
|
|
650
|
-
expect(result).toEqual({
|
|
651
|
-
type: 'message',
|
|
652
|
-
messageType: 'error',
|
|
653
|
-
content: "Profile 'Missing Profile' not found",
|
|
654
|
-
});
|
|
655
|
-
});
|
|
656
|
-
it('should handle very large parameter sets', async () => {
|
|
657
|
-
// Create a profile with many parameters
|
|
658
|
-
const largeParams = {};
|
|
659
|
-
for (let i = 0; i < 100; i++) {
|
|
660
|
-
largeParams[`param_${i}`] = i % 2 === 0 ? i * 0.1 : `value_${i}`;
|
|
661
|
-
}
|
|
662
|
-
mockProvider.getModelParams = vi.fn().mockReturnValue(largeParams);
|
|
663
|
-
await saveCommand.action(context, '"Large Profile"');
|
|
664
|
-
// Verify all parameters were saved
|
|
665
|
-
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
|
666
|
-
const savedProfile = JSON.parse(savedContent);
|
|
667
|
-
expect(Object.keys(savedProfile.modelParams)).toHaveLength(100);
|
|
668
|
-
// Load and verify all parameters are restored
|
|
669
|
-
vi.mocked(fs.readFile).mockResolvedValue(savedContent);
|
|
670
|
-
mockProvider.setModelParams = vi.fn();
|
|
671
|
-
await loadCommand.action(context, '"Large Profile"');
|
|
672
|
-
expect(mockProvider.setModelParams).toHaveBeenCalledWith(largeParams);
|
|
673
|
-
});
|
|
674
|
-
it('should preserve numeric precision in parameters', async () => {
|
|
675
|
-
const preciseParams = {
|
|
676
|
-
temperature: 0.123456789,
|
|
677
|
-
top_p: 0.999999999,
|
|
678
|
-
frequency_penalty: -0.000000001,
|
|
679
|
-
seed: 9007199254740991, // Max safe integer
|
|
680
|
-
};
|
|
681
|
-
mockProvider.getModelParams = vi.fn().mockReturnValue(preciseParams);
|
|
682
|
-
await saveCommand.action(context, '"Precision Profile"');
|
|
683
|
-
const savedContent = vi.mocked(fs.writeFile).mock.calls[0][1];
|
|
684
|
-
vi.mocked(fs.readFile).mockResolvedValue(savedContent);
|
|
685
|
-
mockProvider.setModelParams = vi.fn();
|
|
686
|
-
await loadCommand.action(context, '"Precision Profile"');
|
|
687
|
-
// Verify precision was preserved
|
|
688
|
-
const mockCalls = vi.mocked(mockProvider.setModelParams).mock.calls;
|
|
689
|
-
expect(mockCalls).toHaveLength(1);
|
|
690
|
-
const calledParams = mockCalls[0]?.[0];
|
|
691
|
-
expect(calledParams).toBeDefined();
|
|
692
|
-
expect(calledParams?.temperature).toBe(0.123456789);
|
|
693
|
-
expect(calledParams?.top_p).toBe(0.999999999);
|
|
694
|
-
expect(calledParams?.frequency_penalty).toBe(-0.000000001);
|
|
695
|
-
expect(calledParams?.seed).toBe(9007199254740991);
|
|
696
|
-
});
|
|
697
|
-
});
|
|
698
|
-
describe('Real Integration with File System', () => {
|
|
699
|
-
it('should verify complete data flow from commands to API', async () => {
|
|
700
|
-
// This test verifies the entire flow without mocking file operations
|
|
701
|
-
// In a real environment, this would create actual files
|
|
702
|
-
// Set up a complete workflow
|
|
703
|
-
const workflow = async () => {
|
|
704
|
-
// 1. Set parameters
|
|
705
|
-
await setCommand.action(context, 'modelparam temperature 0.75');
|
|
706
|
-
await setCommand.action(context, 'modelparam max_tokens 3000');
|
|
707
|
-
await setCommand.action(context, 'modelparam response_format {"type":"json_object"}');
|
|
708
|
-
// 2. Set ephemeral settings using settings.setValue
|
|
709
|
-
settings.setValue(SettingScope.User, 'context-limit', 25000);
|
|
710
|
-
settings.setValue(SettingScope.User, 'compression-threshold', 0.82);
|
|
711
|
-
// Update context settings merged to include these values
|
|
712
|
-
context.services.settings.merged['context-limit'] = 25000;
|
|
713
|
-
context.services.settings.merged['compression-threshold'] = 0.82;
|
|
714
|
-
// 3. Save profile
|
|
715
|
-
mockProvider.getModelParams = vi.fn().mockReturnValue({
|
|
716
|
-
temperature: 0.75,
|
|
717
|
-
max_tokens: 3000,
|
|
718
|
-
response_format: { type: 'json_object' },
|
|
719
|
-
});
|
|
720
|
-
await saveCommand.action(context, '"Integration Test Profile"');
|
|
721
|
-
// 4. Clear state
|
|
722
|
-
mockProvider.setModelParams = vi.fn();
|
|
723
|
-
const freshSettings = {
|
|
724
|
-
merged: {},
|
|
725
|
-
setValue: vi
|
|
726
|
-
.fn()
|
|
727
|
-
.mockImplementation((scope, key, value) => {
|
|
728
|
-
freshSettings.merged[key] = value;
|
|
729
|
-
}),
|
|
730
|
-
};
|
|
731
|
-
context.services.settings =
|
|
732
|
-
freshSettings;
|
|
733
|
-
// 5. Load profile
|
|
734
|
-
const savedProfile = vi.mocked(fs.writeFile).mock.calls[0][1];
|
|
735
|
-
vi.mocked(fs.readFile).mockResolvedValue(savedProfile);
|
|
736
|
-
await loadCommand.action(context, '"Integration Test Profile"');
|
|
737
|
-
// 6. Verify complete restoration
|
|
738
|
-
return {
|
|
739
|
-
modelParams: vi.mocked(mockProvider.setModelParams).mock.calls[0][0],
|
|
740
|
-
ephemeralSettings: vi
|
|
741
|
-
.mocked(freshSettings.setValue)
|
|
742
|
-
.mock.calls.reduce((acc, call) => {
|
|
743
|
-
acc[call[1]] = call[2];
|
|
744
|
-
return acc;
|
|
745
|
-
}, {}),
|
|
746
|
-
};
|
|
747
|
-
};
|
|
748
|
-
const result = await workflow();
|
|
749
|
-
expect(result.modelParams).toEqual({
|
|
750
|
-
temperature: 0.75,
|
|
751
|
-
max_tokens: 3000,
|
|
752
|
-
response_format: { type: 'json_object' },
|
|
753
|
-
});
|
|
754
|
-
expect(result.ephemeralSettings).toMatchObject({
|
|
755
|
-
'context-limit': 25000,
|
|
756
|
-
'compression-threshold': 0.82,
|
|
757
|
-
});
|
|
758
|
-
});
|
|
759
|
-
});
|
|
760
|
-
describe('Profile Manager Integration', () => {
|
|
761
|
-
it('should work with ProfileManager for save and load operations', async () => {
|
|
762
|
-
const profileManager = new ProfileManager();
|
|
763
|
-
// Create a test profile
|
|
764
|
-
const testProfile = {
|
|
765
|
-
version: 1,
|
|
766
|
-
provider: 'openai',
|
|
767
|
-
model: 'gpt-4',
|
|
768
|
-
modelParams: {
|
|
769
|
-
temperature: 0.6,
|
|
770
|
-
max_tokens: 5000,
|
|
771
|
-
},
|
|
772
|
-
ephemeralSettings: {
|
|
773
|
-
'context-limit': 40000,
|
|
774
|
-
},
|
|
775
|
-
};
|
|
776
|
-
// Mock ProfileManager save operation
|
|
777
|
-
vi.mocked(fs.writeFile).mockResolvedValue(undefined);
|
|
778
|
-
// Save using ProfileManager (simulated)
|
|
779
|
-
await fs.writeFile(path.join(profilesDir, 'ProfileManager Test.json'), JSON.stringify(testProfile, null, 2), 'utf8');
|
|
780
|
-
// Load using ProfileManager (simulated)
|
|
781
|
-
vi.mocked(fs.readFile).mockResolvedValue(JSON.stringify(testProfile));
|
|
782
|
-
const loadedProfile = await profileManager.loadProfile('ProfileManager Test');
|
|
783
|
-
expect(loadedProfile).toEqual(testProfile);
|
|
784
|
-
});
|
|
105
|
+
it('supports clearing params directly through helper', async () => {
|
|
106
|
+
await runSetCommand('modelparam temperature 0.7');
|
|
107
|
+
expect(getActiveModelParams()).toEqual({ temperature: 0.7 });
|
|
108
|
+
clearActiveModelParam('temperature');
|
|
109
|
+
expect(getActiveModelParams()).toEqual({});
|
|
785
110
|
});
|
|
786
111
|
});
|
|
787
112
|
//# sourceMappingURL=modelParams.integration.test.js.map
|