@vybestack/llxprt-code 0.1.20-nightly.250818.90f427f5 → 0.1.21

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