@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.
Files changed (269) hide show
  1. package/dist/package.json +5 -3
  2. package/dist/src/auth/__tests__/oauthManager.safety.test.d.ts +6 -0
  3. package/dist/src/auth/__tests__/oauthManager.safety.test.js +49 -0
  4. package/dist/src/auth/__tests__/oauthManager.safety.test.js.map +1 -0
  5. package/dist/src/auth/oauth-manager.d.ts +11 -0
  6. package/dist/src/auth/oauth-manager.js +62 -29
  7. package/dist/src/auth/oauth-manager.js.map +1 -1
  8. package/dist/src/auth/oauth-manager.spec.js +7 -2
  9. package/dist/src/auth/oauth-manager.spec.js.map +1 -1
  10. package/dist/src/config/__tests__/nonInteractiveTools.test.d.ts +6 -0
  11. package/dist/src/config/__tests__/nonInteractiveTools.test.js +13 -0
  12. package/dist/src/config/__tests__/nonInteractiveTools.test.js.map +1 -0
  13. package/dist/src/config/__tests__/profileBootstrap.test.d.ts +6 -0
  14. package/dist/src/config/__tests__/profileBootstrap.test.js +91 -0
  15. package/dist/src/config/__tests__/profileBootstrap.test.js.map +1 -0
  16. package/dist/src/config/config.d.ts +6 -2
  17. package/dist/src/config/config.js +219 -18
  18. package/dist/src/config/config.js.map +1 -1
  19. package/dist/src/config/profileBootstrap.d.ts +64 -0
  20. package/dist/src/config/profileBootstrap.js +140 -0
  21. package/dist/src/config/profileBootstrap.js.map +1 -0
  22. package/dist/src/gemini.js +68 -23
  23. package/dist/src/gemini.js.map +1 -1
  24. package/dist/src/gemini.test.js +1 -2
  25. package/dist/src/gemini.test.js.map +1 -1
  26. package/dist/src/generated/git-commit.d.ts +1 -1
  27. package/dist/src/generated/git-commit.js +1 -1
  28. package/dist/src/integration-tests/base-url-behavior.integration.test.js +110 -450
  29. package/dist/src/integration-tests/base-url-behavior.integration.test.js.map +1 -1
  30. package/dist/src/integration-tests/model-params-isolation.integration.test.js +101 -539
  31. package/dist/src/integration-tests/model-params-isolation.integration.test.js.map +1 -1
  32. package/dist/src/integration-tests/modelParams.integration.test.js +86 -761
  33. package/dist/src/integration-tests/modelParams.integration.test.js.map +1 -1
  34. package/dist/src/integration-tests/provider-multi-runtime.integration.test.d.ts +6 -0
  35. package/dist/src/integration-tests/provider-multi-runtime.integration.test.js +198 -0
  36. package/dist/src/integration-tests/provider-multi-runtime.integration.test.js.map +1 -0
  37. package/dist/src/integration-tests/provider-switching.integration.test.js +97 -151
  38. package/dist/src/integration-tests/provider-switching.integration.test.js.map +1 -1
  39. package/dist/src/integration-tests/runtime-isolation.test.d.ts +13 -0
  40. package/dist/src/integration-tests/runtime-isolation.test.js +170 -0
  41. package/dist/src/integration-tests/runtime-isolation.test.js.map +1 -0
  42. package/dist/src/integration-tests/test-utils.js +19 -2
  43. package/dist/src/integration-tests/test-utils.js.map +1 -1
  44. package/dist/src/integration-tests/test-utils.test.js +9 -8
  45. package/dist/src/integration-tests/test-utils.test.js.map +1 -1
  46. package/dist/src/integration-tests/todo-continuation.integration.test.js +5 -2
  47. package/dist/src/integration-tests/todo-continuation.integration.test.js.map +1 -1
  48. package/dist/src/integration-tests/tools-governance.integration.test.d.ts +6 -0
  49. package/dist/src/integration-tests/tools-governance.integration.test.js +98 -0
  50. package/dist/src/integration-tests/tools-governance.integration.test.js.map +1 -0
  51. package/dist/src/nonInteractiveCli.js +36 -11
  52. package/dist/src/nonInteractiveCli.js.map +1 -1
  53. package/dist/src/providers/logging/git-stats.test.js +11 -1
  54. package/dist/src/providers/logging/git-stats.test.js.map +1 -1
  55. package/dist/src/providers/logging/multi-provider-logging.integration.test.js +1 -2
  56. package/dist/src/providers/logging/multi-provider-logging.integration.test.js.map +1 -1
  57. package/dist/src/providers/logging/performance.test.js +1 -1
  58. package/dist/src/providers/logging/performance.test.js.map +1 -1
  59. package/dist/src/providers/oauth-provider-registration.d.ts +2 -2
  60. package/dist/src/providers/oauth-provider-registration.js +25 -9
  61. package/dist/src/providers/oauth-provider-registration.js.map +1 -1
  62. package/dist/src/providers/provider-gemini-switching.test.js +67 -89
  63. package/dist/src/providers/provider-gemini-switching.test.js.map +1 -1
  64. package/dist/src/providers/provider-switching.integration.test.js +42 -98
  65. package/dist/src/providers/provider-switching.integration.test.js.map +1 -1
  66. package/dist/src/providers/providerConfigUtils.d.ts +12 -7
  67. package/dist/src/providers/providerConfigUtils.js +31 -99
  68. package/dist/src/providers/providerConfigUtils.js.map +1 -1
  69. package/dist/src/providers/providerManagerInstance.d.ts +17 -1
  70. package/dist/src/providers/providerManagerInstance.js +157 -175
  71. package/dist/src/providers/providerManagerInstance.js.map +1 -1
  72. package/dist/src/providers/providerManagerInstance.oauthRegistration.test.js +19 -15
  73. package/dist/src/providers/providerManagerInstance.oauthRegistration.test.js.map +1 -1
  74. package/dist/src/providers/providerManagerInstance.test.js +2 -5
  75. package/dist/src/providers/providerManagerInstance.test.js.map +1 -1
  76. package/dist/src/runtime/__tests__/profileApplication.test.d.ts +5 -0
  77. package/dist/src/runtime/__tests__/profileApplication.test.js +232 -0
  78. package/dist/src/runtime/__tests__/profileApplication.test.js.map +1 -0
  79. package/dist/src/runtime/__tests__/runtimeIsolation.test.d.ts +5 -0
  80. package/dist/src/runtime/__tests__/runtimeIsolation.test.js +376 -0
  81. package/dist/src/runtime/__tests__/runtimeIsolation.test.js.map +1 -0
  82. package/dist/src/runtime/agentRuntimeAdapter.d.ts +249 -0
  83. package/dist/src/runtime/agentRuntimeAdapter.js +506 -0
  84. package/dist/src/runtime/agentRuntimeAdapter.js.map +1 -0
  85. package/dist/src/runtime/agentRuntimeAdapter.spec.d.ts +6 -0
  86. package/dist/src/runtime/agentRuntimeAdapter.spec.js +866 -0
  87. package/dist/src/runtime/agentRuntimeAdapter.spec.js.map +1 -0
  88. package/dist/src/runtime/messages.d.ts +28 -0
  89. package/dist/src/runtime/messages.js +64 -0
  90. package/dist/src/runtime/messages.js.map +1 -0
  91. package/dist/src/runtime/profileApplication.d.ts +33 -0
  92. package/dist/src/runtime/profileApplication.js +191 -0
  93. package/dist/src/runtime/profileApplication.js.map +1 -0
  94. package/dist/src/runtime/providerConfigUtils.test.d.ts +1 -0
  95. package/dist/src/runtime/providerConfigUtils.test.js +68 -0
  96. package/dist/src/runtime/providerConfigUtils.test.js.map +1 -0
  97. package/dist/src/runtime/runtimeContextFactory.d.ts +102 -0
  98. package/dist/src/runtime/runtimeContextFactory.js +190 -0
  99. package/dist/src/runtime/runtimeContextFactory.js.map +1 -0
  100. package/dist/src/runtime/runtimeSettings.d.ts +217 -0
  101. package/dist/src/runtime/runtimeSettings.js +1094 -0
  102. package/dist/src/runtime/runtimeSettings.js.map +1 -0
  103. package/dist/src/runtime/runtimeSettings.test.d.ts +1 -0
  104. package/dist/src/runtime/runtimeSettings.test.js +320 -0
  105. package/dist/src/runtime/runtimeSettings.test.js.map +1 -0
  106. package/dist/src/services/BuiltinCommandLoader.d.ts +13 -4
  107. package/dist/src/services/BuiltinCommandLoader.js +17 -4
  108. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  109. package/dist/src/services/McpPromptLoader.js +34 -13
  110. package/dist/src/services/McpPromptLoader.js.map +1 -1
  111. package/dist/src/test-utils/mockCommandContext.js +5 -2
  112. package/dist/src/test-utils/mockCommandContext.js.map +1 -1
  113. package/dist/src/ui/App.js +29 -49
  114. package/dist/src/ui/App.js.map +1 -1
  115. package/dist/src/ui/commands/aboutCommand.js +59 -38
  116. package/dist/src/ui/commands/aboutCommand.js.map +1 -1
  117. package/dist/src/ui/commands/authCommand.js +7 -9
  118. package/dist/src/ui/commands/authCommand.js.map +1 -1
  119. package/dist/src/ui/commands/baseurlCommand.js +8 -44
  120. package/dist/src/ui/commands/baseurlCommand.js.map +1 -1
  121. package/dist/src/ui/commands/chatCommand.js +28 -12
  122. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  123. package/dist/src/ui/commands/diagnosticsCommand.d.ts +0 -3
  124. package/dist/src/ui/commands/diagnosticsCommand.js +45 -191
  125. package/dist/src/ui/commands/diagnosticsCommand.js.map +1 -1
  126. package/dist/src/ui/commands/keyCommand.js +9 -58
  127. package/dist/src/ui/commands/keyCommand.js.map +1 -1
  128. package/dist/src/ui/commands/keyCommand.test.js +48 -102
  129. package/dist/src/ui/commands/keyCommand.test.js.map +1 -1
  130. package/dist/src/ui/commands/keyfileCommand.js +42 -93
  131. package/dist/src/ui/commands/keyfileCommand.js.map +1 -1
  132. package/dist/src/ui/commands/logoutCommand.js +2 -2
  133. package/dist/src/ui/commands/logoutCommand.js.map +1 -1
  134. package/dist/src/ui/commands/mcpCommand.js +29 -7
  135. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  136. package/dist/src/ui/commands/modelCommand.js +8 -59
  137. package/dist/src/ui/commands/modelCommand.js.map +1 -1
  138. package/dist/src/ui/commands/profileCommand.js +151 -267
  139. package/dist/src/ui/commands/profileCommand.js.map +1 -1
  140. package/dist/src/ui/commands/profileCommand.test.js +88 -344
  141. package/dist/src/ui/commands/profileCommand.test.js.map +1 -1
  142. package/dist/src/ui/commands/providerCommand.js +9 -3
  143. package/dist/src/ui/commands/providerCommand.js.map +1 -1
  144. package/dist/src/ui/commands/restoreCommand.js +38 -18
  145. package/dist/src/ui/commands/restoreCommand.js.map +1 -1
  146. package/dist/src/ui/commands/schema/argumentResolver.test.d.ts +6 -0
  147. package/dist/src/ui/commands/schema/argumentResolver.test.js +619 -0
  148. package/dist/src/ui/commands/schema/argumentResolver.test.js.map +1 -0
  149. package/dist/src/ui/commands/schema/index.d.ts +15 -0
  150. package/dist/src/ui/commands/schema/index.js +320 -0
  151. package/dist/src/ui/commands/schema/index.js.map +1 -0
  152. package/dist/src/ui/commands/schema/types.d.ts +61 -0
  153. package/dist/src/ui/commands/schema/types.js +12 -0
  154. package/dist/src/ui/commands/schema/types.js.map +1 -0
  155. package/dist/src/ui/commands/setCommand.js +641 -325
  156. package/dist/src/ui/commands/setCommand.js.map +1 -1
  157. package/dist/src/ui/commands/setCommand.test.js +92 -388
  158. package/dist/src/ui/commands/setCommand.test.js.map +1 -1
  159. package/dist/src/ui/commands/statusCommand.js +2 -2
  160. package/dist/src/ui/commands/statusCommand.js.map +1 -1
  161. package/dist/src/ui/commands/subagentCommand.d.ts +16 -0
  162. package/dist/src/ui/commands/subagentCommand.js +674 -0
  163. package/dist/src/ui/commands/subagentCommand.js.map +1 -0
  164. package/dist/src/ui/commands/test/setCommand.mutation.test.d.ts +6 -0
  165. package/dist/src/ui/commands/test/setCommand.mutation.test.js +132 -0
  166. package/dist/src/ui/commands/test/setCommand.mutation.test.js.map +1 -0
  167. package/dist/src/ui/commands/test/setCommand.phase09.test.d.ts +6 -0
  168. package/dist/src/ui/commands/test/setCommand.phase09.test.js +222 -0
  169. package/dist/src/ui/commands/test/setCommand.phase09.test.js.map +1 -0
  170. package/dist/src/ui/commands/test/subagentCommand.schema.test.d.ts +6 -0
  171. package/dist/src/ui/commands/test/subagentCommand.schema.test.js +125 -0
  172. package/dist/src/ui/commands/test/subagentCommand.schema.test.js.map +1 -0
  173. package/dist/src/ui/commands/test/subagentCommand.test.d.ts +1 -0
  174. package/dist/src/ui/commands/test/subagentCommand.test.js +598 -0
  175. package/dist/src/ui/commands/test/subagentCommand.test.js.map +1 -0
  176. package/dist/src/ui/commands/toolformatCommand.js +25 -98
  177. package/dist/src/ui/commands/toolformatCommand.js.map +1 -1
  178. package/dist/src/ui/commands/toolformatCommand.test.js +56 -102
  179. package/dist/src/ui/commands/toolformatCommand.test.js.map +1 -1
  180. package/dist/src/ui/commands/toolsCommand.js +187 -31
  181. package/dist/src/ui/commands/toolsCommand.js.map +1 -1
  182. package/dist/src/ui/commands/types.d.ts +11 -2
  183. package/dist/src/ui/commands/types.js.map +1 -1
  184. package/dist/src/ui/components/AuthDialog.js +16 -55
  185. package/dist/src/ui/components/AuthDialog.js.map +1 -1
  186. package/dist/src/ui/components/Footer.js +4 -5
  187. package/dist/src/ui/components/Footer.js.map +1 -1
  188. package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
  189. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  190. package/dist/src/ui/components/InputPrompt.js +1 -1
  191. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  192. package/dist/src/ui/components/StatsDisplay.js +6 -11
  193. package/dist/src/ui/components/StatsDisplay.js.map +1 -1
  194. package/dist/src/ui/components/SuggestionsDisplay.d.ts +13 -1
  195. package/dist/src/ui/components/SuggestionsDisplay.js +22 -3
  196. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  197. package/dist/src/ui/components/messages/ToolGroupMessage.d.ts +1 -0
  198. package/dist/src/ui/components/messages/ToolGroupMessage.js +14 -14
  199. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  200. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +1 -0
  201. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  202. package/dist/src/ui/containers/SessionController.js +61 -117
  203. package/dist/src/ui/containers/SessionController.js.map +1 -1
  204. package/dist/src/ui/contexts/RuntimeContext.d.ts +61 -0
  205. package/dist/src/ui/contexts/RuntimeContext.js +118 -0
  206. package/dist/src/ui/contexts/RuntimeContext.js.map +1 -0
  207. package/dist/src/ui/contexts/TodoProvider.d.ts +1 -0
  208. package/dist/src/ui/contexts/TodoProvider.js +10 -8
  209. package/dist/src/ui/contexts/TodoProvider.js.map +1 -1
  210. package/dist/src/ui/contexts/ToolCallProvider.d.ts +1 -0
  211. package/dist/src/ui/contexts/ToolCallProvider.js +10 -9
  212. package/dist/src/ui/contexts/ToolCallProvider.js.map +1 -1
  213. package/dist/src/ui/hooks/__tests__/useSlashCompletion.set.phase09.test.d.ts +6 -0
  214. package/dist/src/ui/hooks/__tests__/useSlashCompletion.set.phase09.test.js +39 -0
  215. package/dist/src/ui/hooks/__tests__/useSlashCompletion.set.phase09.test.js.map +1 -0
  216. package/dist/src/ui/hooks/atCommandProcessor.js +11 -3
  217. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  218. package/dist/src/ui/hooks/atCommandProcessor.test.js +3 -1
  219. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  220. package/dist/src/ui/hooks/shellCommandProcessor.js +4 -1
  221. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  222. package/dist/src/ui/hooks/shellCommandProcessor.test.js +1 -0
  223. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  224. package/dist/src/ui/hooks/slashCommandProcessor.js +27 -1
  225. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  226. package/dist/src/ui/hooks/useAuthCommand.js +11 -3
  227. package/dist/src/ui/hooks/useAuthCommand.js.map +1 -1
  228. package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -0
  229. package/dist/src/ui/hooks/useCommandCompletion.js +2 -0
  230. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  231. package/dist/src/ui/hooks/useGeminiStream.js +37 -11
  232. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  233. package/dist/src/ui/hooks/useGeminiStream.subagent.spec.d.ts +6 -0
  234. package/dist/src/ui/hooks/useGeminiStream.subagent.spec.js +232 -0
  235. package/dist/src/ui/hooks/useGeminiStream.subagent.spec.js.map +1 -0
  236. package/dist/src/ui/hooks/useLoadProfileDialog.d.ts +1 -1
  237. package/dist/src/ui/hooks/useLoadProfileDialog.js +18 -57
  238. package/dist/src/ui/hooks/useLoadProfileDialog.js.map +1 -1
  239. package/dist/src/ui/hooks/useOpenAIProviderInfo.d.ts +1 -1
  240. package/dist/src/ui/hooks/useOpenAIProviderInfo.js +12 -7
  241. package/dist/src/ui/hooks/useOpenAIProviderInfo.js.map +1 -1
  242. package/dist/src/ui/hooks/useProviderDialog.d.ts +1 -1
  243. package/dist/src/ui/hooks/useProviderDialog.js +17 -90
  244. package/dist/src/ui/hooks/useProviderDialog.js.map +1 -1
  245. package/dist/src/ui/hooks/useProviderModelDialog.d.ts +2 -2
  246. package/dist/src/ui/hooks/useProviderModelDialog.js +11 -12
  247. package/dist/src/ui/hooks/useProviderModelDialog.js.map +1 -1
  248. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +3 -1
  249. package/dist/src/ui/hooks/useReactToolScheduler.js +144 -34
  250. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  251. package/dist/src/ui/hooks/useSlashCompletion.d.ts +32 -0
  252. package/dist/src/ui/hooks/useSlashCompletion.js +154 -77
  253. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  254. package/dist/src/ui/hooks/useSlashCompletion.test.js +39 -14
  255. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  256. package/dist/src/ui/hooks/useToolScheduler.test.js +108 -79
  257. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  258. package/dist/src/ui/types.d.ts +1 -0
  259. package/dist/src/ui/types.js.map +1 -1
  260. package/dist/src/utils/sandbox.js +7 -5
  261. package/dist/src/utils/sandbox.js.map +1 -1
  262. package/dist/src/validateNonInterActiveAuth.js +4 -2
  263. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  264. package/dist/src/zed-integration/schema.d.ts +30 -30
  265. package/dist/src/zed-integration/zedIntegration.js +112 -39
  266. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  267. package/dist/tsconfig.build.tsbuildinfo +1 -0
  268. package/package.json +5 -3
  269. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -3,568 +3,130 @@
3
3
  * Copyright 2025 Vybestack LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
7
- import { Config, ProviderManager, ProfileManager, } from '@vybestack/llxprt-code-core';
6
+ import { beforeEach, afterEach, describe, expect, it } from 'vitest';
7
+ import { Config, ProviderManager, } from '@vybestack/llxprt-code-core';
8
+ import { setCliRuntimeContext, registerCliProviderInfrastructure, resetCliProviderInfrastructure, setActiveModelParam, clearActiveModelParam, getActiveModelParams, switchActiveProvider, buildRuntimeProfileSnapshot, applyProfileSnapshot, setActiveModel, } from '../runtime/runtimeSettings.js';
8
9
  import { createTempDirectory, cleanupTempDirectory } from './test-utils.js';
9
- import * as os from 'os';
10
- // Mock os.homedir to use temp directory
11
- vi.mock('os', async (importOriginal) => {
12
- const actual = await importOriginal();
10
+ function createStubProvider(name) {
13
11
  return {
14
- ...actual,
15
- homedir: vi.fn(),
12
+ name,
13
+ async getModels() {
14
+ return [
15
+ {
16
+ id: `${name}-model`,
17
+ name: `${name}-model`,
18
+ provider: name,
19
+ supportedToolFormats: [],
20
+ },
21
+ ];
22
+ },
23
+ getDefaultModel() {
24
+ return `${name}-model`;
25
+ },
26
+ async *generateChatCompletion() {
27
+ yield {
28
+ speaker: 'ai',
29
+ blocks: [{ type: 'text', text: `response-from-${name}` }],
30
+ };
31
+ },
32
+ getServerTools() {
33
+ return [];
34
+ },
35
+ async invokeServerTool() {
36
+ return {};
37
+ },
38
+ clearState() {
39
+ // Intentionally blank; runtime helpers now manage state in SettingsService.
40
+ },
16
41
  };
17
- });
18
- describe('Model Parameters Isolation Between Providers', () => {
42
+ }
43
+ describe('Runtime model parameter isolation', () => {
19
44
  let tempDir;
20
45
  let config;
21
46
  let providerManager;
22
- let profileManager;
23
- let originalSetActiveProvider;
47
+ let settingsService;
24
48
  beforeEach(async () => {
25
49
  tempDir = await createTempDirectory();
26
- // Mock os.homedir to return temp directory
27
- vi.mocked(os.homedir).mockReturnValue(tempDir);
28
- // Create real Config instance
29
50
  config = new Config({
30
- sessionId: 'test-session',
51
+ sessionId: 'model-params-isolation',
31
52
  targetDir: tempDir,
32
53
  debugMode: false,
33
54
  cwd: tempDir,
34
- model: 'test-model',
55
+ model: 'alpha-model',
35
56
  });
36
- // Create real ProviderManager and ProfileManager instances
37
- providerManager = new ProviderManager();
38
- profileManager = new ProfileManager();
39
- config.setProviderManager(providerManager);
40
- // Wrap setActiveProvider to automatically clear state on previous provider
41
- originalSetActiveProvider =
42
- providerManager.setActiveProvider.bind(providerManager);
43
- providerManager.setActiveProvider = (providerName) => {
44
- // Clear state on current provider before switching
45
- try {
46
- const currentProvider = providerManager.getActiveProvider();
47
- if (currentProvider && 'clearState' in currentProvider) {
48
- currentProvider.clearState();
49
- }
50
- }
51
- catch {
52
- // No active provider yet, that's OK
53
- }
54
- return originalSetActiveProvider(providerName);
55
- };
56
57
  await config.initialize();
58
+ settingsService = config.getSettingsService();
59
+ providerManager = new ProviderManager({ settingsService, config });
60
+ // Register stub providers used by the tests.
61
+ providerManager.registerProvider(createStubProvider('alpha'));
62
+ providerManager.registerProvider(createStubProvider('beta'));
63
+ providerManager.registerProvider(createStubProvider('gamma'));
64
+ registerCliProviderInfrastructure(providerManager, {});
65
+ setCliRuntimeContext(settingsService, config, {
66
+ metadata: { source: 'model-params-isolation.integration.test.ts' },
67
+ });
68
+ providerManager.setActiveProvider('alpha');
69
+ await setActiveModel('alpha-model');
57
70
  });
58
71
  afterEach(async () => {
72
+ resetCliProviderInfrastructure();
59
73
  await cleanupTempDirectory(tempDir);
60
- vi.clearAllMocks();
61
74
  });
62
- describe('Provider Switching Model Parameter Isolation', () => {
63
- it('should isolate model parameters between different providers', async () => {
64
- // Create mock providers with model parameter tracking
65
- const openaiProvider = createMockProvider('openai');
66
- const anthropicProvider = createMockProvider('anthropic');
67
- // Register providers
68
- providerManager.registerProvider(openaiProvider);
69
- providerManager.registerProvider(anthropicProvider);
70
- // Set OpenAI as active and configure model params
71
- providerManager.setActiveProvider('openai');
72
- openaiProvider.setModelParams?.({
73
- temperature: 0.8,
74
- max_tokens: 4096,
75
- frequency_penalty: 0.5,
76
- });
77
- // Verify OpenAI has its params
78
- expect(openaiProvider.getModelParams?.()).toEqual({
79
- temperature: 0.8,
80
- max_tokens: 4096,
81
- frequency_penalty: 0.5,
82
- });
83
- // Switch to Anthropic
84
- providerManager.setActiveProvider('anthropic');
85
- // Verify OpenAI's model params are cleared
86
- expect(openaiProvider.getModelParams?.()).toBeUndefined();
87
- // Set different params for Anthropic
88
- anthropicProvider.setModelParams?.({
89
- temperature: 0.5,
90
- max_output_tokens: 8192,
91
- top_k: 40,
92
- });
93
- // Verify Anthropic has its own params
94
- expect(anthropicProvider.getModelParams?.()).toEqual({
95
- temperature: 0.5,
96
- max_output_tokens: 8192,
97
- top_k: 40,
98
- });
99
- // Switch back to OpenAI
100
- providerManager.setActiveProvider('openai');
101
- // Verify Anthropic's params are cleared
102
- expect(anthropicProvider.getModelParams?.()).toBeUndefined();
103
- // Verify OpenAI doesn't retain previous params
104
- expect(openaiProvider.getModelParams?.()).toBeUndefined();
105
- });
106
- it('should clear model parameters when switching providers', async () => {
107
- const providerA = createMockProvider('providerA');
108
- const providerB = createMockProvider('providerB');
109
- providerManager.registerProvider(providerA);
110
- providerManager.registerProvider(providerB);
111
- // Set complex params for provider A
112
- providerManager.setActiveProvider('providerA');
113
- const complexParams = {
114
- temperature: 0.7,
115
- max_tokens: 2000,
116
- top_p: 0.95,
117
- presence_penalty: 0.1,
118
- response_format: { type: 'json_object' },
119
- seed: 12345,
120
- };
121
- providerA.setModelParams?.(complexParams);
122
- expect(providerA.getModelParams?.()).toEqual(complexParams);
123
- // Switch to provider B
124
- providerManager.setActiveProvider('providerB');
125
- // Verify provider A's params are completely cleared
126
- expect(providerA.getModelParams?.()).toBeUndefined();
127
- // Verify provider B starts with no params
128
- expect(providerB.getModelParams?.()).toBeUndefined();
129
- });
130
- it('should handle provider-specific parameter names correctly', async () => {
131
- const openai = createMockProvider('openai');
132
- const anthropic = createMockProvider('anthropic');
133
- const gemini = createMockProvider('gemini');
134
- providerManager.registerProvider(openai);
135
- providerManager.registerProvider(anthropic);
136
- providerManager.registerProvider(gemini);
137
- // OpenAI uses max_tokens
138
- providerManager.setActiveProvider('openai');
139
- openai.setModelParams?.({ max_tokens: 4096 });
140
- expect(openai.getModelParams?.()).toEqual({ max_tokens: 4096 });
141
- // Anthropic uses max_output_tokens
142
- providerManager.setActiveProvider('anthropic');
143
- expect(openai.getModelParams?.()).toBeUndefined(); // OpenAI cleared
144
- anthropic.setModelParams?.({ max_output_tokens: 4096 });
145
- expect(anthropic.getModelParams?.()).toEqual({ max_output_tokens: 4096 });
146
- // Gemini uses maxOutputTokens
147
- providerManager.setActiveProvider('gemini');
148
- expect(anthropic.getModelParams?.()).toBeUndefined(); // Anthropic cleared
149
- gemini.setModelParams?.({ maxOutputTokens: 4096 });
150
- expect(gemini.getModelParams?.()).toEqual({ maxOutputTokens: 4096 });
151
- // All providers should have cleared state when not active
152
- providerManager.setActiveProvider('openai');
153
- expect(gemini.getModelParams?.()).toBeUndefined();
75
+ it('keeps model parameters scoped to the active provider', async () => {
76
+ expect(getActiveModelParams()).toEqual({});
77
+ setActiveModelParam('temperature', 0.8);
78
+ setActiveModelParam('max_tokens', 2048);
79
+ expect(getActiveModelParams()).toEqual({
80
+ temperature: 0.8,
81
+ max_tokens: 2048,
154
82
  });
83
+ expect(settingsService.getProviderSettings('alpha').temperature).toBe(0.8);
84
+ await switchActiveProvider('beta');
85
+ expect(getActiveModelParams()).toEqual({});
86
+ expect(settingsService.getProviderSettings('alpha').temperature).toBe(0.8);
87
+ setActiveModelParam('temperature', 0.35);
88
+ expect(getActiveModelParams()).toEqual({ temperature: 0.35 });
89
+ await switchActiveProvider('alpha');
90
+ expect(getActiveModelParams()).toEqual({});
91
+ expect(settingsService.getProviderSettings('alpha').temperature).toBeUndefined();
92
+ expect(settingsService.getProviderSettings('beta').temperature).toBe(0.35);
155
93
  });
156
- describe('Profile Save and Load with Model Parameters', () => {
157
- it('should save and load profiles with provider-specific model parameters', async () => {
158
- const openaiProvider = createMockProvider('openai');
159
- providerManager.registerProvider(openaiProvider);
160
- providerManager.setActiveProvider('openai');
161
- // Set model and params
162
- config.setModel('gpt-4');
163
- const modelParams = {
164
- temperature: 0.8,
165
- max_tokens: 4096,
166
- seed: 42,
167
- };
168
- openaiProvider.setModelParams?.(modelParams);
169
- // Clear any existing ephemeral settings first
170
- const existingSettings = config.getEphemeralSettings();
171
- Object.keys(existingSettings).forEach((key) => {
172
- config.setEphemeralSetting(key, undefined);
173
- });
174
- // Set only our test ephemeral settings
175
- config.setEphemeralSetting('context-limit', 32000);
176
- config.setEphemeralSetting('base-url', 'https://api.openai.com/v1');
177
- // Create profile with only our settings
178
- const profile = {
179
- version: 1,
180
- provider: 'openai',
181
- model: config.getModel(),
182
- modelParams: openaiProvider.getModelParams?.() || {},
183
- ephemeralSettings: {
184
- 'context-limit': 32000,
185
- 'base-url': 'https://api.openai.com/v1',
186
- },
187
- };
188
- // Save profile
189
- await profileManager.saveProfile('test-profile', profile);
190
- // Clear state
191
- openaiProvider.clearState?.();
192
- config.setEphemeralSetting('context-limit', undefined);
193
- config.setEphemeralSetting('base-url', undefined);
194
- // Load profile
195
- const loadedProfile = await profileManager.loadProfile('test-profile');
196
- expect(loadedProfile).toEqual(profile);
197
- expect(loadedProfile.modelParams).toEqual(modelParams);
198
- expect(loadedProfile.ephemeralSettings).toEqual({
199
- 'context-limit': 32000,
200
- 'base-url': 'https://api.openai.com/v1',
201
- });
202
- });
203
- it('should isolate model parameters in different profiles', async () => {
204
- const openaiProvider = createMockProvider('openai');
205
- const anthropicProvider = createMockProvider('anthropic');
206
- providerManager.registerProvider(openaiProvider);
207
- providerManager.registerProvider(anthropicProvider);
208
- // Create OpenAI profile
209
- providerManager.setActiveProvider('openai');
210
- config.setModel('gpt-4');
211
- openaiProvider.setModelParams?.({
212
- temperature: 0.7,
213
- max_tokens: 4096,
214
- });
215
- const openaiProfile = {
216
- version: 1,
217
- provider: 'openai',
218
- model: 'gpt-4',
219
- modelParams: openaiProvider.getModelParams?.() || {},
220
- ephemeralSettings: { 'tool-format': 'openai' },
221
- };
222
- await profileManager.saveProfile('openai-prod', openaiProfile);
223
- // Create Anthropic profile
224
- providerManager.setActiveProvider('anthropic');
225
- config.setModel('claude-3-opus-20240229');
226
- anthropicProvider.setModelParams?.({
227
- temperature: 0.5,
228
- max_output_tokens: 8192,
229
- top_k: 40,
230
- });
231
- const anthropicProfile = {
232
- version: 1,
233
- provider: 'anthropic',
234
- model: 'claude-3-opus-20240229',
235
- modelParams: anthropicProvider.getModelParams?.() || {},
236
- ephemeralSettings: { 'tool-format': 'anthropic' },
237
- };
238
- await profileManager.saveProfile('anthropic-prod', anthropicProfile);
239
- // Load OpenAI profile
240
- const loadedOpenai = await profileManager.loadProfile('openai-prod');
241
- expect(loadedOpenai.modelParams).toEqual({
242
- temperature: 0.7,
243
- max_tokens: 4096,
244
- });
245
- // Load Anthropic profile
246
- const loadedAnthropic = await profileManager.loadProfile('anthropic-prod');
247
- expect(loadedAnthropic.modelParams).toEqual({
248
- temperature: 0.5,
249
- max_output_tokens: 8192,
250
- top_k: 40,
251
- });
252
- // Verify profiles are independent
253
- expect(loadedOpenai.provider).not.toBe(loadedAnthropic.provider);
254
- expect(loadedOpenai.modelParams).not.toEqual(loadedAnthropic.modelParams);
255
- });
256
- });
257
- describe('Model Parameter Command Integration', () => {
258
- it('should handle /set modelparam commands correctly', async () => {
259
- const provider = createMockProvider('test-provider');
260
- providerManager.registerProvider(provider);
261
- providerManager.setActiveProvider('test-provider');
262
- // Simulate /set modelparam temperature 0.8
263
- provider.setModelParams?.({ temperature: 0.8 });
264
- expect(provider.getModelParams?.()).toEqual({ temperature: 0.8 });
265
- // Simulate /set modelparam max_tokens 4096
266
- provider.setModelParams?.({ max_tokens: 4096 });
267
- expect(provider.getModelParams?.()).toEqual({ max_tokens: 4096 });
268
- // Simulate /set modelparam response_format {"type":"json_object"}
269
- provider.setModelParams?.({ response_format: { type: 'json_object' } });
270
- expect(provider.getModelParams?.()).toEqual({
271
- response_format: { type: 'json_object' },
272
- });
273
- });
274
- it('should clear model params when unsetting', async () => {
275
- const provider = createMockProvider('test-provider');
276
- providerManager.registerProvider(provider);
277
- providerManager.setActiveProvider('test-provider');
278
- // Set multiple params
279
- provider.setModelParams?.({
280
- temperature: 0.8,
281
- max_tokens: 4096,
282
- top_p: 0.95,
283
- });
284
- // Unset specific param (simulated by setting to undefined)
285
- const currentParams = provider.getModelParams?.() || {};
286
- delete currentParams.temperature;
287
- provider.setModelParams?.(currentParams);
288
- expect(provider.getModelParams?.()).toEqual({
289
- max_tokens: 4096,
290
- top_p: 0.95,
291
- });
292
- // Clear all params
293
- provider.setModelParams?.(undefined);
294
- expect(provider.getModelParams?.()).toBeUndefined();
295
- });
296
- });
297
- describe('Default Model Setting on Provider Switch', () => {
298
- it('should set default model when switching providers', async () => {
299
- const openai = createMockProvider('openai');
300
- openai.getModels = async () => [
301
- {
302
- id: 'gpt-4',
303
- name: 'GPT-4',
304
- provider: 'openai',
305
- supportedToolFormats: [],
306
- },
307
- {
308
- id: 'gpt-4o-mini',
309
- name: 'GPT-4.0 Mini',
310
- provider: 'openai',
311
- supportedToolFormats: [],
312
- },
313
- ];
314
- openai.getDefaultModel = () => 'gpt-4';
315
- const anthropic = createMockProvider('anthropic');
316
- anthropic.getModels = async () => [
317
- {
318
- id: 'claude-3-opus-20240229',
319
- name: 'Claude 3 Opus',
320
- provider: 'anthropic',
321
- supportedToolFormats: [],
322
- },
323
- {
324
- id: 'claude-3-sonnet',
325
- name: 'Claude 3 Sonnet',
326
- provider: 'anthropic',
327
- supportedToolFormats: [],
328
- },
329
- ];
330
- anthropic.getDefaultModel = () => 'claude-3-opus-20240229';
331
- providerManager.registerProvider(openai);
332
- providerManager.registerProvider(anthropic);
333
- // Start with OpenAI
334
- providerManager.setActiveProvider('openai');
335
- config.setModel('gpt-4');
336
- expect(config.getModel()).toBe('gpt-4');
337
- // Switch to Anthropic
338
- providerManager.setActiveProvider('anthropic');
339
- config.setModel('claude-3-opus-20240229');
340
- expect(config.getModel()).toBe('claude-3-opus-20240229');
341
- // Switch back to OpenAI - should not retain previous model
342
- providerManager.setActiveProvider('openai');
343
- // In real implementation, this would be handled by the CLI
344
- // setting the default model for the provider
94
+ it('builds runtime profile snapshots with provider-scoped params', () => {
95
+ setActiveModelParam('top_p', 0.91);
96
+ setActiveModelParam('response_format', { type: 'json_object' });
97
+ const snapshot = buildRuntimeProfileSnapshot();
98
+ expect(snapshot.provider).toBe('alpha');
99
+ expect(snapshot.model).toBe('alpha-model');
100
+ expect(snapshot.modelParams).toEqual({
101
+ top_p: 0.91,
102
+ response_format: { type: 'json_object' },
345
103
  });
346
104
  });
347
- describe('Complex Workflow Integration', () => {
348
- it('should handle complete workflow: set params, save profile, switch provider, load profile', async () => {
349
- const openai = createMockProvider('openai');
350
- const anthropic = createMockProvider('anthropic');
351
- providerManager.registerProvider(openai);
352
- providerManager.registerProvider(anthropic);
353
- // Step 1: Configure OpenAI
354
- providerManager.setActiveProvider('openai');
355
- config.setModel('gpt-4');
356
- openai.setModelParams?.({
357
- temperature: 0.8,
358
- max_tokens: 4096,
359
- response_format: { type: 'json_object' },
360
- });
361
- config.setEphemeralSetting('context-limit', 32000);
362
- config.setEphemeralSetting('api-version', '2024-01-01');
363
- // Step 2: Save OpenAI profile
364
- const openaiProfile = {
365
- version: 1,
366
- provider: 'openai',
367
- model: 'gpt-4',
368
- modelParams: openai.getModelParams?.() || {},
369
- ephemeralSettings: config.getEphemeralSettings(),
370
- };
371
- await profileManager.saveProfile('openai-config', openaiProfile);
372
- // Step 3: Switch to Anthropic
373
- providerManager.setActiveProvider('anthropic');
374
- // Verify OpenAI params are cleared
375
- expect(openai.getModelParams?.()).toBeUndefined();
376
- // Configure Anthropic
377
- config.setModel('claude-3-opus-20240229');
378
- anthropic.setModelParams?.({
379
- temperature: 0.5,
380
- max_output_tokens: 8192,
381
- top_k: 40,
382
- });
383
- // Step 4: Switch back to OpenAI
384
- providerManager.setActiveProvider('openai');
385
- // Verify Anthropic params are cleared
386
- expect(anthropic.getModelParams?.()).toBeUndefined();
387
- // Step 5: Load OpenAI profile
388
- const loadedProfile = await profileManager.loadProfile('openai-config');
389
- // Apply loaded settings (simulating what the CLI would do)
390
- providerManager.setActiveProvider(loadedProfile.provider);
391
- config.setModel(loadedProfile.model);
392
- openai.setModelParams?.(loadedProfile.modelParams);
393
- Object.entries(loadedProfile.ephemeralSettings).forEach(([key, value]) => {
394
- config.setEphemeralSetting(key, value);
395
- });
396
- // Verify everything is restored
397
- expect(openai.getModelParams?.()).toEqual({
398
- temperature: 0.8,
399
- max_tokens: 4096,
400
- response_format: { type: 'json_object' },
401
- });
402
- expect(config.getEphemeralSetting('context-limit')).toBe(32000);
403
- expect(config.getEphemeralSetting('api-version')).toBe('2024-01-01');
404
- });
405
- it('should maintain isolation when rapidly switching between providers', async () => {
406
- const providers = ['openai', 'anthropic', 'gemini', 'cohere'].map((name) => createMockProvider(name));
407
- providers.forEach((p) => providerManager.registerProvider(p));
408
- // Rapidly switch and set params
409
- for (let i = 0; i < 10; i++) {
410
- const provider = providers[i % providers.length];
411
- providerManager.setActiveProvider(provider.name);
412
- // Set unique params for each iteration
413
- provider.setModelParams?.({
414
- temperature: 0.1 * (i + 1),
415
- iteration: i,
416
- provider: provider.name,
417
- });
418
- // Verify only active provider has params
419
- providers.forEach((p) => {
420
- if (p.name === provider.name) {
421
- expect(p.getModelParams?.()).toBeDefined();
422
- expect(p.getModelParams?.()?.iteration).toBe(i);
423
- }
424
- else {
425
- expect(p.getModelParams?.()).toBeUndefined();
426
- }
427
- });
428
- }
429
- });
105
+ it('applies profile snapshots and refreshes runtime state', async () => {
106
+ const profile = {
107
+ version: 1,
108
+ provider: 'beta',
109
+ model: 'beta-model',
110
+ modelParams: {
111
+ temperature: 0.55,
112
+ top_p: 0.88,
113
+ },
114
+ ephemeralSettings: {
115
+ 'context-limit': 64000,
116
+ },
117
+ };
118
+ await applyProfileSnapshot(profile, { profileName: 'beta-profile' });
119
+ expect(settingsService.get('activeProvider')).toBe('beta');
120
+ expect(config.getModel()).toBe('beta-model');
121
+ expect(settingsService.getProviderSettings('beta').temperature).toBe(0.55);
122
+ expect(settingsService.getProviderSettings('beta').top_p).toBe(0.88);
123
+ expect(config.getEphemeralSetting('context-limit')).toBe(64000);
430
124
  });
431
- describe('Edge Cases and Error Handling', () => {
432
- it('should handle providers without model parameter support', async () => {
433
- const basicProvider = {
434
- name: 'basic-provider',
435
- getModels: async () => [
436
- {
437
- id: 'basic-model',
438
- name: 'Basic Model',
439
- provider: 'basic-provider',
440
- supportedToolFormats: [],
441
- },
442
- ],
443
- getDefaultModel: () => 'basic-model',
444
- async *generateChatCompletion() {
445
- yield {
446
- speaker: 'ai',
447
- blocks: [{ type: 'text', text: 'test' }],
448
- };
449
- },
450
- getServerTools: () => [],
451
- invokeServerTool: async () => ({ result: 'test' }),
452
- // No model param methods
453
- };
454
- providerManager.registerProvider(basicProvider);
455
- providerManager.setActiveProvider('basic-provider');
456
- // Should not throw when provider doesn't support model params
457
- expect(() => {
458
- const params = basicProvider.getModelParams?.();
459
- expect(params).toBeUndefined();
460
- }).not.toThrow();
461
- });
462
- it('should handle setting model params before provider is registered', async () => {
463
- // This tests defensive programming - params should not be set if provider not found
464
- const provider = createMockProvider('late-provider');
465
- // Try to set active before registering (should fail)
466
- expect(() => {
467
- providerManager.setActiveProvider('late-provider');
468
- }).toThrow();
469
- // Register and then it should work
470
- providerManager.registerProvider(provider);
471
- providerManager.setActiveProvider('late-provider');
472
- provider.setModelParams?.({ temperature: 0.7 });
473
- expect(provider.getModelParams?.()).toEqual({ temperature: 0.7 });
474
- });
475
- it('should preserve model param types correctly', async () => {
476
- const provider = createMockProvider('type-test');
477
- providerManager.registerProvider(provider);
478
- providerManager.setActiveProvider('type-test');
479
- const complexParams = {
480
- // Numbers
481
- temperature: 0.7,
482
- max_tokens: 4096,
483
- seed: 12345,
484
- frequency_penalty: -0.5,
485
- // Booleans
486
- stream: true,
487
- logprobs: false,
488
- // Strings
489
- stop: '\n\n',
490
- suffix: '_end',
491
- // Arrays
492
- stop_sequences: ['\n', '###', 'END'],
493
- // Objects
494
- response_format: { type: 'json_object' },
495
- logit_bias: { '50256': -100, '1234': 50 },
496
- // Null
497
- user: null,
498
- };
499
- provider.setModelParams?.(complexParams);
500
- const retrieved = provider.getModelParams?.();
501
- // Verify all types are preserved
502
- expect(retrieved).toEqual(complexParams);
503
- expect(typeof retrieved?.temperature).toBe('number');
504
- expect(typeof retrieved?.stream).toBe('boolean');
505
- expect(typeof retrieved?.stop).toBe('string');
506
- expect(Array.isArray(retrieved?.stop_sequences)).toBe(true);
507
- expect(typeof retrieved?.response_format).toBe('object');
508
- expect(retrieved?.user).toBeNull();
509
- });
125
+ it('clears individual model params via helper', () => {
126
+ setActiveModelParam('temperature', 0.42);
127
+ expect(getActiveModelParams()).toEqual({ temperature: 0.42 });
128
+ clearActiveModelParam('temperature');
129
+ expect(getActiveModelParams()).toEqual({});
510
130
  });
511
131
  });
512
- // Helper function to create a mock provider with full state management
513
- function createMockProvider(name) {
514
- const provider = {
515
- name,
516
- apiKey: undefined,
517
- modelParams: undefined,
518
- model: undefined,
519
- state: {},
520
- setApiKey(key) {
521
- provider.apiKey = key;
522
- },
523
- getApiKey() {
524
- return provider.apiKey;
525
- },
526
- setModelParams(params) {
527
- provider.modelParams = params;
528
- },
529
- getModelParams() {
530
- return provider.modelParams;
531
- },
532
- setModel(model) {
533
- provider.model = model;
534
- },
535
- getModel() {
536
- return provider.model;
537
- },
538
- clearState() {
539
- provider.apiKey = undefined;
540
- provider.modelParams = undefined;
541
- provider.model = undefined;
542
- provider.state = {};
543
- },
544
- getModels: async () => [
545
- {
546
- id: `${name}-model-1`,
547
- name: `${name} Model 1`,
548
- provider: name,
549
- supportedToolFormats: [],
550
- },
551
- {
552
- id: `${name}-model-2`,
553
- name: `${name} Model 2`,
554
- provider: name,
555
- supportedToolFormats: [],
556
- },
557
- ],
558
- getDefaultModel: () => `${name}-model-1`,
559
- async *generateChatCompletion() {
560
- yield {
561
- speaker: 'ai',
562
- blocks: [{ type: 'text', text: `Response from ${name}` }],
563
- };
564
- },
565
- getServerTools: () => [],
566
- invokeServerTool: async () => ({ result: 'test' }),
567
- };
568
- return provider;
569
- }
570
132
  //# sourceMappingURL=model-params-isolation.integration.test.js.map