@vybestack/llxprt-code 0.1.20 → 0.1.22

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