@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,841 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ /* eslint-disable @typescript-eslint/no-explicit-any */
7
+ import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
8
+ import { renderHook, act } from '@testing-library/react';
9
+ import { useReactToolScheduler, mapToDisplay, } from './useReactToolScheduler.js';
10
+ import { ToolConfirmationOutcome, ApprovalMode, Kind, BaseDeclarativeTool, BaseToolInvocation, } from '@vybestack/llxprt-code-core';
11
+ import { ToolCallStatus, } from '../types.js';
12
+ // Mocks
13
+ vi.mock('@google/gemini-cli-core', async () => {
14
+ const actual = await vi.importActual('@google/gemini-cli-core');
15
+ return {
16
+ ...actual,
17
+ ToolRegistry: vi.fn(),
18
+ Config: vi.fn(),
19
+ };
20
+ });
21
+ const mockToolRegistry = {
22
+ getTool: vi.fn(),
23
+ };
24
+ const mockConfig = {
25
+ getToolRegistry: vi.fn(() => mockToolRegistry),
26
+ getApprovalMode: vi.fn(() => ApprovalMode.DEFAULT),
27
+ getUsageStatisticsEnabled: () => true,
28
+ getDebugMode: () => false,
29
+ };
30
+ class MockToolInvocation extends BaseToolInvocation {
31
+ tool;
32
+ constructor(tool, params) {
33
+ super(params);
34
+ this.tool = tool;
35
+ }
36
+ getDescription() {
37
+ return JSON.stringify(this.params);
38
+ }
39
+ shouldConfirmExecute(abortSignal) {
40
+ return this.tool.shouldConfirmExecute(this.params, abortSignal);
41
+ }
42
+ execute(signal, updateOutput, terminalColumns, terminalRows) {
43
+ return this.tool.execute(this.params, signal, updateOutput, terminalColumns, terminalRows);
44
+ }
45
+ }
46
+ class MockTool extends BaseDeclarativeTool {
47
+ constructor(name, displayName, canUpdateOutput = false, shouldConfirm = false, isOutputMarkdown = false) {
48
+ super(name, displayName, 'A mock tool for testing', Kind.Other, {}, isOutputMarkdown, canUpdateOutput);
49
+ if (shouldConfirm) {
50
+ this.shouldConfirmExecute.mockImplementation(async () => ({
51
+ type: 'edit',
52
+ title: 'Mock Tool Requires Confirmation',
53
+ onConfirm: mockOnUserConfirmForToolConfirmation,
54
+ filePath: 'mock',
55
+ fileName: 'mockToolRequiresConfirmation.ts',
56
+ fileDiff: 'Mock tool requires confirmation',
57
+ originalContent: 'Original content',
58
+ newContent: 'New content',
59
+ }));
60
+ }
61
+ }
62
+ execute = vi.fn();
63
+ shouldConfirmExecute = vi.fn();
64
+ createInvocation(params) {
65
+ return new MockToolInvocation(this, params);
66
+ }
67
+ }
68
+ const mockTool = new MockTool('mockTool', 'Mock Tool');
69
+ const mockToolWithLiveOutput = new MockTool('mockToolWithLiveOutput', 'Mock Tool With Live Output', true);
70
+ let mockOnUserConfirmForToolConfirmation;
71
+ const mockToolRequiresConfirmation = new MockTool('mockToolRequiresConfirmation', 'Mock Tool Requires Confirmation', false, true);
72
+ describe('useReactToolScheduler in YOLO Mode', () => {
73
+ let onComplete;
74
+ let setPendingHistoryItem;
75
+ beforeEach(() => {
76
+ onComplete = vi.fn();
77
+ setPendingHistoryItem = vi.fn();
78
+ mockToolRegistry.getTool.mockClear();
79
+ mockToolRequiresConfirmation.execute.mockClear();
80
+ mockToolRequiresConfirmation.shouldConfirmExecute.mockClear();
81
+ // IMPORTANT: Enable YOLO mode for this test suite
82
+ mockConfig.getApprovalMode.mockReturnValue(ApprovalMode.YOLO);
83
+ vi.useFakeTimers();
84
+ });
85
+ afterEach(() => {
86
+ vi.clearAllTimers();
87
+ vi.useRealTimers();
88
+ // IMPORTANT: Disable YOLO mode after this test suite
89
+ mockConfig.getApprovalMode.mockReturnValue(ApprovalMode.DEFAULT);
90
+ });
91
+ const renderSchedulerInYoloMode = () => renderHook(() => useReactToolScheduler(onComplete, mockConfig, setPendingHistoryItem, () => undefined, () => { }));
92
+ it('should skip confirmation and execute tool directly when yoloMode is true', async () => {
93
+ mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
94
+ const expectedOutput = 'YOLO Confirmed output';
95
+ mockToolRequiresConfirmation.execute.mockResolvedValue({
96
+ llmContent: expectedOutput,
97
+ returnDisplay: 'YOLO Formatted tool output',
98
+ summary: 'YOLO summary',
99
+ });
100
+ const { result } = renderSchedulerInYoloMode();
101
+ const schedule = result.current[1];
102
+ const request = {
103
+ callId: 'yoloCall',
104
+ name: 'mockToolRequiresConfirmation',
105
+ args: { data: 'any data' },
106
+ };
107
+ act(() => {
108
+ schedule(request, new AbortController().signal);
109
+ });
110
+ await act(async () => {
111
+ await vi.runAllTimersAsync(); // Process validation
112
+ });
113
+ await act(async () => {
114
+ await vi.runAllTimersAsync(); // Process scheduling
115
+ });
116
+ await act(async () => {
117
+ await vi.runAllTimersAsync(); // Process execution
118
+ });
119
+ // Check that shouldConfirmExecute was NOT called
120
+ expect(mockToolRequiresConfirmation.shouldConfirmExecute).not.toHaveBeenCalled();
121
+ // Check that execute WAS called
122
+ expect(mockToolRequiresConfirmation.execute).toHaveBeenCalledWith(request.args, expect.any(AbortSignal), undefined, undefined, undefined);
123
+ // Check that onComplete was called with success
124
+ expect(onComplete).toHaveBeenCalledWith([
125
+ expect.objectContaining({
126
+ status: 'success',
127
+ request,
128
+ response: expect.objectContaining({
129
+ resultDisplay: 'YOLO Formatted tool output',
130
+ responseParts: {
131
+ functionResponse: {
132
+ id: 'yoloCall',
133
+ name: 'mockToolRequiresConfirmation',
134
+ response: { output: expectedOutput },
135
+ },
136
+ },
137
+ }),
138
+ }),
139
+ ]);
140
+ // Ensure no confirmation UI was triggered (setPendingHistoryItem should not have been called with confirmation details)
141
+ const setPendingHistoryItemCalls = setPendingHistoryItem.mock.calls;
142
+ const confirmationCall = setPendingHistoryItemCalls.find((call) => {
143
+ const item = typeof call[0] === 'function' ? call[0]({}) : call[0];
144
+ return item?.tools?.[0]?.confirmationDetails;
145
+ });
146
+ expect(confirmationCall).toBeUndefined();
147
+ });
148
+ });
149
+ describe('useReactToolScheduler', () => {
150
+ // TODO(ntaylormullen): The following tests are skipped due to difficulties in
151
+ // reliably testing the asynchronous state updates and interactions with timers.
152
+ // These tests involve complex sequences of events, including confirmations,
153
+ // live output updates, and cancellations, which are challenging to assert
154
+ // correctly with the current testing setup. Further investigation is needed
155
+ // to find a robust way to test these scenarios.
156
+ let onComplete;
157
+ let setPendingHistoryItem;
158
+ let capturedOnConfirmForTest;
159
+ beforeEach(() => {
160
+ onComplete = vi.fn();
161
+ capturedOnConfirmForTest = undefined;
162
+ setPendingHistoryItem = vi.fn((updaterOrValue) => {
163
+ let pendingItem = null;
164
+ if (typeof updaterOrValue === 'function') {
165
+ // Loosen the type for prevState to allow for more flexible updates in tests
166
+ const prevState = {
167
+ type: 'tool_group', // Still default to tool_group for most cases
168
+ tools: [],
169
+ };
170
+ pendingItem = updaterOrValue(prevState); // Allow any for more flexibility
171
+ }
172
+ else {
173
+ pendingItem = updaterOrValue;
174
+ }
175
+ // Capture onConfirm if it exists, regardless of the exact type of pendingItem
176
+ // This is a common pattern in these tests.
177
+ if (pendingItem?.tools?.[0]?.confirmationDetails
178
+ ?.onConfirm) {
179
+ capturedOnConfirmForTest = pendingItem
180
+ .tools[0].confirmationDetails?.onConfirm;
181
+ }
182
+ });
183
+ mockToolRegistry.getTool.mockClear();
184
+ mockTool.execute.mockClear();
185
+ mockTool.shouldConfirmExecute.mockClear();
186
+ mockToolWithLiveOutput.execute.mockClear();
187
+ mockToolWithLiveOutput.shouldConfirmExecute.mockClear();
188
+ mockToolRequiresConfirmation.execute.mockClear();
189
+ mockToolRequiresConfirmation.shouldConfirmExecute.mockClear();
190
+ mockOnUserConfirmForToolConfirmation = vi.fn();
191
+ mockToolRequiresConfirmation.shouldConfirmExecute.mockImplementation(async () => ({
192
+ onConfirm: mockOnUserConfirmForToolConfirmation,
193
+ fileName: 'mockToolRequiresConfirmation.ts',
194
+ fileDiff: 'Mock tool requires confirmation',
195
+ type: 'edit',
196
+ title: 'Mock Tool Requires Confirmation',
197
+ }));
198
+ vi.useFakeTimers();
199
+ });
200
+ afterEach(() => {
201
+ vi.clearAllTimers();
202
+ vi.useRealTimers();
203
+ });
204
+ const renderScheduler = () => renderHook(() => useReactToolScheduler(onComplete, mockConfig, setPendingHistoryItem, () => undefined, () => { }));
205
+ it('initial state should be empty', () => {
206
+ const { result } = renderScheduler();
207
+ expect(result.current[0]).toEqual([]);
208
+ });
209
+ it('should schedule and execute a tool call successfully', async () => {
210
+ mockToolRegistry.getTool.mockReturnValue(mockTool);
211
+ mockTool.execute.mockResolvedValue({
212
+ llmContent: 'Tool output',
213
+ returnDisplay: 'Formatted tool output',
214
+ summary: 'Formatted summary',
215
+ });
216
+ mockTool.shouldConfirmExecute.mockResolvedValue(null);
217
+ const { result } = renderScheduler();
218
+ const schedule = result.current[1];
219
+ const request = {
220
+ callId: 'call1',
221
+ name: 'mockTool',
222
+ args: { param: 'value' },
223
+ };
224
+ act(() => {
225
+ schedule(request, new AbortController().signal);
226
+ });
227
+ await act(async () => {
228
+ await vi.runAllTimersAsync();
229
+ });
230
+ await act(async () => {
231
+ await vi.runAllTimersAsync();
232
+ });
233
+ await act(async () => {
234
+ await vi.runAllTimersAsync();
235
+ });
236
+ expect(mockTool.execute).toHaveBeenCalledWith(request.args, expect.any(AbortSignal), undefined, undefined, undefined);
237
+ expect(onComplete).toHaveBeenCalledWith([
238
+ expect.objectContaining({
239
+ status: 'success',
240
+ request,
241
+ response: expect.objectContaining({
242
+ resultDisplay: 'Formatted tool output',
243
+ responseParts: {
244
+ functionResponse: {
245
+ id: 'call1',
246
+ name: 'mockTool',
247
+ response: { output: 'Tool output' },
248
+ },
249
+ },
250
+ }),
251
+ }),
252
+ ]);
253
+ expect(result.current[0]).toEqual([]);
254
+ });
255
+ it('should handle tool not found', async () => {
256
+ mockToolRegistry.getTool.mockReturnValue(undefined);
257
+ const { result } = renderScheduler();
258
+ const schedule = result.current[1];
259
+ const request = {
260
+ callId: 'call1',
261
+ name: 'nonexistentTool',
262
+ args: {},
263
+ };
264
+ act(() => {
265
+ schedule(request, new AbortController().signal);
266
+ });
267
+ await act(async () => {
268
+ await vi.runAllTimersAsync();
269
+ });
270
+ await act(async () => {
271
+ await vi.runAllTimersAsync();
272
+ });
273
+ expect(onComplete).toHaveBeenCalledWith([
274
+ expect.objectContaining({
275
+ status: 'error',
276
+ request,
277
+ response: expect.objectContaining({
278
+ error: expect.objectContaining({
279
+ message: 'Tool "nonexistentTool" not found in registry.',
280
+ }),
281
+ }),
282
+ }),
283
+ ]);
284
+ expect(result.current[0]).toEqual([]);
285
+ });
286
+ it('should handle error during shouldConfirmExecute', async () => {
287
+ mockToolRegistry.getTool.mockReturnValue(mockTool);
288
+ const confirmError = new Error('Confirmation check failed');
289
+ mockTool.shouldConfirmExecute.mockRejectedValue(confirmError);
290
+ const { result } = renderScheduler();
291
+ const schedule = result.current[1];
292
+ const request = {
293
+ callId: 'call1',
294
+ name: 'mockTool',
295
+ args: {},
296
+ };
297
+ act(() => {
298
+ schedule(request, new AbortController().signal);
299
+ });
300
+ await act(async () => {
301
+ await vi.runAllTimersAsync();
302
+ });
303
+ await act(async () => {
304
+ await vi.runAllTimersAsync();
305
+ });
306
+ expect(onComplete).toHaveBeenCalledWith([
307
+ expect.objectContaining({
308
+ status: 'error',
309
+ request,
310
+ response: expect.objectContaining({
311
+ error: confirmError,
312
+ }),
313
+ }),
314
+ ]);
315
+ expect(result.current[0]).toEqual([]);
316
+ });
317
+ it('should handle error during execute', async () => {
318
+ mockToolRegistry.getTool.mockReturnValue(mockTool);
319
+ mockTool.shouldConfirmExecute.mockResolvedValue(null);
320
+ const execError = new Error('Execution failed');
321
+ mockTool.execute.mockRejectedValue(execError);
322
+ const { result } = renderScheduler();
323
+ const schedule = result.current[1];
324
+ const request = {
325
+ callId: 'call1',
326
+ name: 'mockTool',
327
+ args: {},
328
+ };
329
+ act(() => {
330
+ schedule(request, new AbortController().signal);
331
+ });
332
+ await act(async () => {
333
+ await vi.runAllTimersAsync();
334
+ });
335
+ await act(async () => {
336
+ await vi.runAllTimersAsync();
337
+ });
338
+ await act(async () => {
339
+ await vi.runAllTimersAsync();
340
+ });
341
+ expect(onComplete).toHaveBeenCalledWith([
342
+ expect.objectContaining({
343
+ status: 'error',
344
+ request,
345
+ response: expect.objectContaining({
346
+ error: execError,
347
+ }),
348
+ }),
349
+ ]);
350
+ expect(result.current[0]).toEqual([]);
351
+ });
352
+ it.skip('should handle tool requiring confirmation - approved', async () => {
353
+ mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
354
+ const expectedOutput = 'Confirmed output';
355
+ mockToolRequiresConfirmation.execute.mockResolvedValue({
356
+ llmContent: expectedOutput,
357
+ returnDisplay: 'Confirmed display',
358
+ summary: 'Confirmed summary',
359
+ });
360
+ const { result } = renderScheduler();
361
+ const schedule = result.current[1];
362
+ const request = {
363
+ callId: 'callConfirm',
364
+ name: 'mockToolRequiresConfirmation',
365
+ args: { data: 'sensitive' },
366
+ };
367
+ act(() => {
368
+ schedule(request, new AbortController().signal);
369
+ });
370
+ await act(async () => {
371
+ await vi.runAllTimersAsync();
372
+ });
373
+ expect(setPendingHistoryItem).toHaveBeenCalled();
374
+ expect(capturedOnConfirmForTest).toBeDefined();
375
+ await act(async () => {
376
+ await capturedOnConfirmForTest?.(ToolConfirmationOutcome.ProceedOnce);
377
+ });
378
+ await act(async () => {
379
+ await vi.runAllTimersAsync();
380
+ });
381
+ await act(async () => {
382
+ await vi.runAllTimersAsync();
383
+ });
384
+ await act(async () => {
385
+ await vi.runAllTimersAsync();
386
+ });
387
+ expect(mockOnUserConfirmForToolConfirmation).toHaveBeenCalledWith(ToolConfirmationOutcome.ProceedOnce);
388
+ expect(mockToolRequiresConfirmation.execute).toHaveBeenCalled();
389
+ expect(onComplete).toHaveBeenCalledWith([
390
+ expect.objectContaining({
391
+ status: 'success',
392
+ request,
393
+ response: expect.objectContaining({
394
+ resultDisplay: 'Confirmed display',
395
+ responseParts: expect.arrayContaining([
396
+ expect.objectContaining({
397
+ functionResponse: expect.objectContaining({
398
+ response: { output: expectedOutput },
399
+ }),
400
+ }),
401
+ ]),
402
+ }),
403
+ }),
404
+ ]);
405
+ });
406
+ it.skip('should handle tool requiring confirmation - cancelled by user', async () => {
407
+ mockToolRegistry.getTool.mockReturnValue(mockToolRequiresConfirmation);
408
+ const { result } = renderScheduler();
409
+ const schedule = result.current[1];
410
+ const request = {
411
+ callId: 'callConfirmCancel',
412
+ name: 'mockToolRequiresConfirmation',
413
+ args: {},
414
+ };
415
+ act(() => {
416
+ schedule(request, new AbortController().signal);
417
+ });
418
+ await act(async () => {
419
+ await vi.runAllTimersAsync();
420
+ });
421
+ expect(setPendingHistoryItem).toHaveBeenCalled();
422
+ expect(capturedOnConfirmForTest).toBeDefined();
423
+ await act(async () => {
424
+ await capturedOnConfirmForTest?.(ToolConfirmationOutcome.Cancel);
425
+ });
426
+ await act(async () => {
427
+ await vi.runAllTimersAsync();
428
+ });
429
+ await act(async () => {
430
+ await vi.runAllTimersAsync();
431
+ });
432
+ expect(mockOnUserConfirmForToolConfirmation).toHaveBeenCalledWith(ToolConfirmationOutcome.Cancel);
433
+ expect(onComplete).toHaveBeenCalledWith([
434
+ expect.objectContaining({
435
+ status: 'cancelled',
436
+ request,
437
+ response: expect.objectContaining({
438
+ responseParts: expect.arrayContaining([
439
+ expect.objectContaining({
440
+ functionResponse: expect.objectContaining({
441
+ response: expect.objectContaining({
442
+ error: `User did not allow tool call ${request.name}. Reason: User cancelled.`,
443
+ }),
444
+ }),
445
+ }),
446
+ ]),
447
+ }),
448
+ }),
449
+ ]);
450
+ });
451
+ it.skip('should handle live output updates', async () => {
452
+ mockToolRegistry.getTool.mockReturnValue(mockToolWithLiveOutput);
453
+ let liveUpdateFn;
454
+ let resolveExecutePromise;
455
+ const executePromise = new Promise((resolve) => {
456
+ resolveExecutePromise = resolve;
457
+ });
458
+ mockToolWithLiveOutput.execute.mockImplementation(async (_args, _signal, updateFn) => {
459
+ liveUpdateFn = updateFn;
460
+ return executePromise;
461
+ });
462
+ mockToolWithLiveOutput.shouldConfirmExecute.mockResolvedValue(null);
463
+ const { result } = renderScheduler();
464
+ const schedule = result.current[1];
465
+ const request = {
466
+ callId: 'liveCall',
467
+ name: 'mockToolWithLiveOutput',
468
+ args: {},
469
+ };
470
+ act(() => {
471
+ schedule(request, new AbortController().signal);
472
+ });
473
+ await act(async () => {
474
+ await vi.runAllTimersAsync();
475
+ });
476
+ expect(liveUpdateFn).toBeDefined();
477
+ expect(setPendingHistoryItem).toHaveBeenCalled();
478
+ await act(async () => {
479
+ liveUpdateFn?.('Live output 1');
480
+ });
481
+ await act(async () => {
482
+ await vi.runAllTimersAsync();
483
+ });
484
+ await act(async () => {
485
+ liveUpdateFn?.('Live output 2');
486
+ });
487
+ await act(async () => {
488
+ await vi.runAllTimersAsync();
489
+ });
490
+ act(() => {
491
+ resolveExecutePromise({
492
+ llmContent: 'Final output',
493
+ returnDisplay: 'Final display',
494
+ summary: 'Final summary',
495
+ });
496
+ });
497
+ await act(async () => {
498
+ await vi.runAllTimersAsync();
499
+ });
500
+ await act(async () => {
501
+ await vi.runAllTimersAsync();
502
+ });
503
+ expect(onComplete).toHaveBeenCalledWith([
504
+ expect.objectContaining({
505
+ status: 'success',
506
+ request,
507
+ response: expect.objectContaining({
508
+ resultDisplay: 'Final display',
509
+ responseParts: expect.arrayContaining([
510
+ expect.objectContaining({
511
+ functionResponse: expect.objectContaining({
512
+ response: { output: 'Final output' },
513
+ }),
514
+ }),
515
+ ]),
516
+ }),
517
+ }),
518
+ ]);
519
+ expect(result.current[0]).toEqual([]);
520
+ });
521
+ it('should schedule and execute multiple tool calls', async () => {
522
+ const tool1 = new MockTool('tool1', 'Tool 1');
523
+ tool1.execute.mockResolvedValue({
524
+ llmContent: 'Output 1',
525
+ returnDisplay: 'Display 1',
526
+ summary: 'Summary 1',
527
+ });
528
+ tool1.shouldConfirmExecute.mockResolvedValue(null);
529
+ const tool2 = new MockTool('tool2', 'Tool 2');
530
+ tool2.execute.mockResolvedValue({
531
+ llmContent: 'Output 2',
532
+ returnDisplay: 'Display 2',
533
+ summary: 'Summary 2',
534
+ });
535
+ tool2.shouldConfirmExecute.mockResolvedValue(null);
536
+ mockToolRegistry.getTool.mockImplementation((name) => {
537
+ if (name === 'tool1')
538
+ return tool1;
539
+ if (name === 'tool2')
540
+ return tool2;
541
+ return undefined;
542
+ });
543
+ const { result } = renderScheduler();
544
+ const schedule = result.current[1];
545
+ const requests = [
546
+ { callId: 'multi1', name: 'tool1', args: { p: 1 } },
547
+ { callId: 'multi2', name: 'tool2', args: { p: 2 } },
548
+ ];
549
+ act(() => {
550
+ schedule(requests, new AbortController().signal);
551
+ });
552
+ await act(async () => {
553
+ await vi.runAllTimersAsync();
554
+ });
555
+ await act(async () => {
556
+ await vi.runAllTimersAsync();
557
+ });
558
+ await act(async () => {
559
+ await vi.runAllTimersAsync();
560
+ });
561
+ await act(async () => {
562
+ await vi.runAllTimersAsync();
563
+ });
564
+ expect(onComplete).toHaveBeenCalledTimes(1);
565
+ const completedCalls = onComplete.mock.calls[0][0];
566
+ expect(completedCalls.length).toBe(2);
567
+ const call1Result = completedCalls.find((c) => c.request.callId === 'multi1');
568
+ const call2Result = completedCalls.find((c) => c.request.callId === 'multi2');
569
+ expect(call1Result).toMatchObject({
570
+ status: 'success',
571
+ request: requests[0],
572
+ response: expect.objectContaining({
573
+ resultDisplay: 'Display 1',
574
+ responseParts: {
575
+ functionResponse: {
576
+ id: 'multi1',
577
+ name: 'tool1',
578
+ response: { output: 'Output 1' },
579
+ },
580
+ },
581
+ }),
582
+ });
583
+ expect(call2Result).toMatchObject({
584
+ status: 'success',
585
+ request: requests[1],
586
+ response: expect.objectContaining({
587
+ resultDisplay: 'Display 2',
588
+ responseParts: {
589
+ functionResponse: {
590
+ id: 'multi2',
591
+ name: 'tool2',
592
+ response: { output: 'Output 2' },
593
+ },
594
+ },
595
+ }),
596
+ });
597
+ expect(result.current[0]).toEqual([]);
598
+ });
599
+ it.skip('should throw error if scheduling while already running', async () => {
600
+ mockToolRegistry.getTool.mockReturnValue(mockTool);
601
+ const longExecutePromise = new Promise((resolve) => setTimeout(() => resolve({
602
+ llmContent: 'done',
603
+ returnDisplay: 'done display',
604
+ summary: 'done summary',
605
+ }), 50));
606
+ mockTool.execute.mockReturnValue(longExecutePromise);
607
+ mockTool.shouldConfirmExecute.mockResolvedValue(null);
608
+ const { result } = renderScheduler();
609
+ const schedule = result.current[1];
610
+ const request1 = {
611
+ callId: 'run1',
612
+ name: 'mockTool',
613
+ args: {},
614
+ };
615
+ const request2 = {
616
+ callId: 'run2',
617
+ name: 'mockTool',
618
+ args: {},
619
+ };
620
+ act(() => {
621
+ schedule(request1, new AbortController().signal);
622
+ });
623
+ await act(async () => {
624
+ await vi.runAllTimersAsync();
625
+ });
626
+ expect(() => schedule(request2, new AbortController().signal)).toThrow('Cannot schedule tool calls while other tool calls are running');
627
+ await act(async () => {
628
+ await vi.advanceTimersByTimeAsync(50);
629
+ await vi.runAllTimersAsync();
630
+ await act(async () => {
631
+ await vi.runAllTimersAsync();
632
+ });
633
+ });
634
+ expect(onComplete).toHaveBeenCalledWith([
635
+ expect.objectContaining({
636
+ status: 'success',
637
+ request: request1,
638
+ response: expect.objectContaining({ resultDisplay: 'done display' }),
639
+ }),
640
+ ]);
641
+ expect(result.current[0]).toEqual([]);
642
+ });
643
+ });
644
+ describe('mapToDisplay', () => {
645
+ const baseRequest = {
646
+ callId: 'testCallId',
647
+ name: 'testTool',
648
+ args: { foo: 'bar' },
649
+ };
650
+ const baseTool = new MockTool('testTool', 'Test Tool Display');
651
+ const baseResponse = {
652
+ callId: 'testCallId',
653
+ responseParts: [
654
+ {
655
+ functionResponse: {
656
+ name: 'testTool',
657
+ id: 'testCallId',
658
+ response: { output: 'Test output' },
659
+ },
660
+ },
661
+ ],
662
+ resultDisplay: 'Test display output',
663
+ error: undefined,
664
+ };
665
+ const baseInvocation = baseTool.build(baseRequest.args);
666
+ const testCases = [
667
+ {
668
+ name: 'validating',
669
+ status: 'validating',
670
+ extraProps: { tool: baseTool, invocation: baseInvocation },
671
+ expectedStatus: ToolCallStatus.Executing,
672
+ expectedName: baseTool.displayName,
673
+ expectedDescription: baseInvocation.getDescription(),
674
+ },
675
+ {
676
+ name: 'awaiting_approval',
677
+ status: 'awaiting_approval',
678
+ extraProps: {
679
+ tool: baseTool,
680
+ invocation: baseInvocation,
681
+ confirmationDetails: {
682
+ onConfirm: vi.fn(),
683
+ type: 'edit',
684
+ title: 'Test Tool Display',
685
+ serverName: 'testTool',
686
+ toolName: 'testTool',
687
+ toolDisplayName: 'Test Tool Display',
688
+ filePath: 'mock',
689
+ fileName: 'test.ts',
690
+ fileDiff: 'Test diff',
691
+ originalContent: 'Original content',
692
+ newContent: 'New content',
693
+ },
694
+ },
695
+ expectedStatus: ToolCallStatus.Confirming,
696
+ expectedName: baseTool.displayName,
697
+ expectedDescription: baseInvocation.getDescription(),
698
+ },
699
+ {
700
+ name: 'scheduled',
701
+ status: 'scheduled',
702
+ extraProps: { tool: baseTool, invocation: baseInvocation },
703
+ expectedStatus: ToolCallStatus.Pending,
704
+ expectedName: baseTool.displayName,
705
+ expectedDescription: baseInvocation.getDescription(),
706
+ },
707
+ {
708
+ name: 'executing no live output',
709
+ status: 'executing',
710
+ extraProps: { tool: baseTool, invocation: baseInvocation },
711
+ expectedStatus: ToolCallStatus.Executing,
712
+ expectedName: baseTool.displayName,
713
+ expectedDescription: baseInvocation.getDescription(),
714
+ },
715
+ {
716
+ name: 'executing with live output',
717
+ status: 'executing',
718
+ extraProps: {
719
+ tool: baseTool,
720
+ invocation: baseInvocation,
721
+ liveOutput: 'Live test output',
722
+ },
723
+ expectedStatus: ToolCallStatus.Executing,
724
+ expectedResultDisplay: 'Live test output',
725
+ expectedName: baseTool.displayName,
726
+ expectedDescription: baseInvocation.getDescription(),
727
+ },
728
+ {
729
+ name: 'success',
730
+ status: 'success',
731
+ extraProps: {
732
+ tool: baseTool,
733
+ invocation: baseInvocation,
734
+ response: baseResponse,
735
+ },
736
+ expectedStatus: ToolCallStatus.Success,
737
+ expectedResultDisplay: baseResponse.resultDisplay,
738
+ expectedName: baseTool.displayName,
739
+ expectedDescription: baseInvocation.getDescription(),
740
+ },
741
+ {
742
+ name: 'error tool not found',
743
+ status: 'error',
744
+ extraProps: {
745
+ response: {
746
+ ...baseResponse,
747
+ error: new Error('Test error tool not found'),
748
+ resultDisplay: 'Error display tool not found',
749
+ },
750
+ },
751
+ expectedStatus: ToolCallStatus.Error,
752
+ expectedResultDisplay: 'Error display tool not found',
753
+ expectedName: baseRequest.name,
754
+ expectedDescription: JSON.stringify(baseRequest.args),
755
+ },
756
+ {
757
+ name: 'error tool execution failed',
758
+ status: 'error',
759
+ extraProps: {
760
+ tool: baseTool,
761
+ response: {
762
+ ...baseResponse,
763
+ error: new Error('Tool execution failed'),
764
+ resultDisplay: 'Execution failed display',
765
+ },
766
+ },
767
+ expectedStatus: ToolCallStatus.Error,
768
+ expectedResultDisplay: 'Execution failed display',
769
+ expectedName: baseTool.displayName, // Changed from baseTool.name
770
+ expectedDescription: baseInvocation.getDescription(),
771
+ },
772
+ {
773
+ name: 'cancelled',
774
+ status: 'cancelled',
775
+ extraProps: {
776
+ tool: baseTool,
777
+ invocation: baseInvocation,
778
+ response: {
779
+ ...baseResponse,
780
+ resultDisplay: 'Cancelled display',
781
+ },
782
+ },
783
+ expectedStatus: ToolCallStatus.Canceled,
784
+ expectedResultDisplay: 'Cancelled display',
785
+ expectedName: baseTool.displayName,
786
+ expectedDescription: baseInvocation.getDescription(),
787
+ },
788
+ ];
789
+ testCases.forEach(({ name: testName, status, extraProps, expectedStatus, expectedResultDisplay, expectedName, expectedDescription, }) => {
790
+ it(`should map ToolCall with status '${status}' (${testName}) correctly`, () => {
791
+ const toolCall = {
792
+ request: baseRequest,
793
+ status,
794
+ ...(extraProps || {}),
795
+ };
796
+ const display = mapToDisplay(toolCall);
797
+ expect(display.type).toBe('tool_group');
798
+ expect(display.tools.length).toBe(1);
799
+ const toolDisplay = display.tools[0];
800
+ expect(toolDisplay.callId).toBe(baseRequest.callId);
801
+ expect(toolDisplay.status).toBe(expectedStatus);
802
+ expect(toolDisplay.resultDisplay).toBe(expectedResultDisplay);
803
+ expect(toolDisplay.name).toBe(expectedName);
804
+ expect(toolDisplay.description).toBe(expectedDescription);
805
+ expect(toolDisplay.renderOutputAsMarkdown).toBe(extraProps?.tool?.isOutputMarkdown ?? false);
806
+ if (status === 'awaiting_approval') {
807
+ expect(toolDisplay.confirmationDetails).toBe(extraProps.confirmationDetails);
808
+ }
809
+ else {
810
+ expect(toolDisplay.confirmationDetails).toBeUndefined();
811
+ }
812
+ });
813
+ });
814
+ it('should map an array of ToolCalls correctly', () => {
815
+ const toolCall1 = {
816
+ request: { ...baseRequest, callId: 'call1' },
817
+ status: 'success',
818
+ tool: baseTool,
819
+ invocation: baseTool.build(baseRequest.args),
820
+ response: { ...baseResponse, callId: 'call1' },
821
+ };
822
+ const toolForCall2 = new MockTool(baseTool.name, baseTool.displayName, false, false, true);
823
+ const toolCall2 = {
824
+ request: { ...baseRequest, callId: 'call2' },
825
+ status: 'executing',
826
+ tool: toolForCall2,
827
+ invocation: toolForCall2.build(baseRequest.args),
828
+ liveOutput: 'markdown output',
829
+ };
830
+ const display = mapToDisplay([toolCall1, toolCall2]);
831
+ expect(display.tools.length).toBe(2);
832
+ expect(display.tools[0].callId).toBe('call1');
833
+ expect(display.tools[0].status).toBe(ToolCallStatus.Success);
834
+ expect(display.tools[0].renderOutputAsMarkdown).toBe(false);
835
+ expect(display.tools[1].callId).toBe('call2');
836
+ expect(display.tools[1].status).toBe(ToolCallStatus.Executing);
837
+ expect(display.tools[1].resultDisplay).toBe('markdown output');
838
+ expect(display.tools[1].renderOutputAsMarkdown).toBe(true);
839
+ });
840
+ });
841
+ //# sourceMappingURL=useToolScheduler.test.js.map