@machina.ai/cell-cli 1.8.2-rc1 → 1.11.0-rc1

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 (637) hide show
  1. package/dist/index.js +5 -5
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +8 -7
  4. package/dist/src/commands/extensions/disable.js +8 -5
  5. package/dist/src/commands/extensions/disable.js.map +1 -1
  6. package/dist/src/commands/extensions/enable.js +8 -6
  7. package/dist/src/commands/extensions/enable.js.map +1 -1
  8. package/dist/src/commands/extensions/examples/context/GEMINI.md +9 -3
  9. package/dist/src/commands/extensions/examples/mcp-server/example.d.ts +6 -0
  10. package/dist/src/commands/extensions/examples/mcp-server/example.js +46 -0
  11. package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
  12. package/dist/src/commands/extensions/install.d.ts +2 -0
  13. package/dist/src/commands/extensions/install.js +25 -5
  14. package/dist/src/commands/extensions/install.js.map +1 -1
  15. package/dist/src/commands/extensions/install.test.js +9 -9
  16. package/dist/src/commands/extensions/install.test.js.map +1 -1
  17. package/dist/src/commands/extensions/link.js +5 -4
  18. package/dist/src/commands/extensions/link.js.map +1 -1
  19. package/dist/src/commands/extensions/list.js +7 -5
  20. package/dist/src/commands/extensions/list.js.map +1 -1
  21. package/dist/src/commands/extensions/new.js +14 -20
  22. package/dist/src/commands/extensions/new.js.map +1 -1
  23. package/dist/src/commands/extensions/uninstall.js +4 -3
  24. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  25. package/dist/src/commands/extensions/update.js +18 -22
  26. package/dist/src/commands/extensions/update.js.map +1 -1
  27. package/dist/src/commands/mcp/add.js +7 -4
  28. package/dist/src/commands/mcp/add.js.map +1 -1
  29. package/dist/src/commands/mcp/add.test.d.ts +6 -0
  30. package/dist/src/commands/mcp/add.test.js +244 -0
  31. package/dist/src/commands/mcp/add.test.js.map +1 -0
  32. package/dist/src/commands/mcp/list.js +11 -9
  33. package/dist/src/commands/mcp/list.js.map +1 -1
  34. package/dist/src/commands/mcp/list.test.d.ts +6 -0
  35. package/dist/src/commands/mcp/list.test.js +118 -0
  36. package/dist/src/commands/mcp/list.test.js.map +1 -0
  37. package/dist/src/commands/mcp/remove.js +3 -2
  38. package/dist/src/commands/mcp/remove.js.map +1 -1
  39. package/dist/src/commands/mcp/remove.test.d.ts +6 -0
  40. package/dist/src/commands/mcp/remove.test.js +175 -0
  41. package/dist/src/commands/mcp/remove.test.js.map +1 -0
  42. package/dist/src/commands/mcp.test.d.ts +6 -0
  43. package/dist/src/commands/mcp.test.js +62 -0
  44. package/dist/src/commands/mcp.test.js.map +1 -0
  45. package/dist/src/config/auth.js +3 -1
  46. package/dist/src/config/auth.js.map +1 -1
  47. package/dist/src/config/config.d.ts +4 -16
  48. package/dist/src/config/config.integration.test.d.ts +6 -0
  49. package/dist/src/config/config.integration.test.js +321 -0
  50. package/dist/src/config/config.integration.test.js.map +1 -0
  51. package/dist/src/config/config.js +80 -105
  52. package/dist/src/config/config.js.map +1 -1
  53. package/dist/src/config/config.test.d.ts +6 -0
  54. package/dist/src/config/config.test.js +1949 -0
  55. package/dist/src/config/config.test.js.map +1 -0
  56. package/dist/src/config/extension.d.ts +19 -27
  57. package/dist/src/config/extension.js +159 -139
  58. package/dist/src/config/extension.js.map +1 -1
  59. package/dist/src/config/extension.test.d.ts +6 -0
  60. package/dist/src/config/extension.test.js +1088 -0
  61. package/dist/src/config/extension.test.js.map +1 -0
  62. package/dist/src/config/extensions/extensionEnablement.d.ts +3 -3
  63. package/dist/src/config/extensions/extensionEnablement.js +5 -5
  64. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  65. package/dist/src/config/extensions/extensionEnablement.test.js +26 -22
  66. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  67. package/dist/src/config/extensions/github.d.ts +23 -7
  68. package/dist/src/config/extensions/github.js +139 -88
  69. package/dist/src/config/extensions/github.js.map +1 -1
  70. package/dist/src/config/extensions/github.test.js +74 -22
  71. package/dist/src/config/extensions/github.test.js.map +1 -1
  72. package/dist/src/config/extensions/github_fetch.d.ts +7 -0
  73. package/dist/src/config/extensions/github_fetch.js +34 -0
  74. package/dist/src/config/extensions/github_fetch.js.map +1 -0
  75. package/dist/src/config/extensions/update.d.ts +5 -4
  76. package/dist/src/config/extensions/update.js +23 -16
  77. package/dist/src/config/extensions/update.js.map +1 -1
  78. package/dist/src/config/extensions/update.test.js +57 -57
  79. package/dist/src/config/extensions/update.test.js.map +1 -1
  80. package/dist/src/config/extensions/variableSchema.d.ts +2 -0
  81. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  82. package/dist/src/config/keyBindings.d.ts +2 -1
  83. package/dist/src/config/keyBindings.js +5 -3
  84. package/dist/src/config/keyBindings.js.map +1 -1
  85. package/dist/src/config/policy.d.ts +3 -2
  86. package/dist/src/config/policy.js +33 -24
  87. package/dist/src/config/policy.js.map +1 -1
  88. package/dist/src/config/policy.test.js +60 -36
  89. package/dist/src/config/policy.test.js.map +1 -1
  90. package/dist/src/config/sandboxConfig.d.ts +0 -1
  91. package/dist/src/config/sandboxConfig.js +1 -3
  92. package/dist/src/config/sandboxConfig.js.map +1 -1
  93. package/dist/src/config/settings.d.ts +10 -1
  94. package/dist/src/config/settings.js +24 -9
  95. package/dist/src/config/settings.js.map +1 -1
  96. package/dist/src/config/settings.test.d.ts +6 -0
  97. package/dist/src/config/settings.test.js +1941 -0
  98. package/dist/src/config/settings.test.js.map +1 -0
  99. package/dist/src/config/settingsSchema.d.ts +124 -3
  100. package/dist/src/config/settingsSchema.js +125 -4
  101. package/dist/src/config/settingsSchema.js.map +1 -1
  102. package/dist/src/config/trustedFolders.d.ts +0 -1
  103. package/dist/src/config/trustedFolders.js +2 -3
  104. package/dist/src/config/trustedFolders.js.map +1 -1
  105. package/dist/src/gemini.js +46 -33
  106. package/dist/src/gemini.js.map +1 -1
  107. package/dist/src/gemini.test.js +62 -19
  108. package/dist/src/gemini.test.js.map +1 -1
  109. package/dist/src/generated/git-commit.d.ts +2 -2
  110. package/dist/src/generated/git-commit.js +2 -2
  111. package/dist/src/generated/git-commit.js.map +1 -1
  112. package/dist/src/nonInteractiveCli.js +105 -4
  113. package/dist/src/nonInteractiveCli.js.map +1 -1
  114. package/dist/src/nonInteractiveCli.test.d.ts +6 -0
  115. package/dist/src/nonInteractiveCli.test.js +741 -0
  116. package/dist/src/nonInteractiveCli.test.js.map +1 -0
  117. package/dist/src/nonInteractiveCliCommands.js +2 -3
  118. package/dist/src/nonInteractiveCliCommands.js.map +1 -1
  119. package/dist/src/services/BuiltinCommandLoader.js +3 -0
  120. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  121. package/dist/src/services/BuiltinCommandLoader.test.js +37 -0
  122. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  123. package/dist/src/services/CommandService.js +2 -1
  124. package/dist/src/services/CommandService.js.map +1 -1
  125. package/dist/src/services/FileCommandLoader.d.ts +1 -1
  126. package/dist/src/services/FileCommandLoader.js +4 -4
  127. package/dist/src/services/FileCommandLoader.js.map +1 -1
  128. package/dist/src/services/FileCommandLoader.test.d.ts +6 -0
  129. package/dist/src/services/FileCommandLoader.test.js +971 -0
  130. package/dist/src/services/FileCommandLoader.test.js.map +1 -0
  131. package/dist/src/services/prompt-processors/argumentProcessor.test.d.ts +6 -0
  132. package/dist/src/services/prompt-processors/argumentProcessor.test.js +40 -0
  133. package/dist/src/services/prompt-processors/argumentProcessor.test.js.map +1 -0
  134. package/dist/src/services/prompt-processors/atFileProcessor.js +3 -2
  135. package/dist/src/services/prompt-processors/atFileProcessor.js.map +1 -1
  136. package/dist/src/services/prompt-processors/shellProcessor.js +1 -1
  137. package/dist/src/services/prompt-processors/shellProcessor.js.map +1 -1
  138. package/dist/src/services/prompt-processors/shellProcessor.test.d.ts +6 -0
  139. package/dist/src/services/prompt-processors/shellProcessor.test.js +482 -0
  140. package/dist/src/services/prompt-processors/shellProcessor.test.js.map +1 -0
  141. package/dist/src/test-utils/render.d.ts +12 -4
  142. package/dist/src/test-utils/render.js +56 -2
  143. package/dist/src/test-utils/render.js.map +1 -1
  144. package/dist/src/ui/App.js +1 -17
  145. package/dist/src/ui/App.js.map +1 -1
  146. package/dist/src/ui/App.test.d.ts +6 -0
  147. package/dist/src/ui/App.test.js +110 -0
  148. package/dist/src/ui/App.test.js.map +1 -0
  149. package/dist/src/ui/AppContainer.js +69 -39
  150. package/dist/src/ui/AppContainer.js.map +1 -1
  151. package/dist/src/ui/AppContainer.test.js +35 -9
  152. package/dist/src/ui/AppContainer.test.js.map +1 -1
  153. package/dist/src/ui/auth/AuthDialog.d.ts +1 -1
  154. package/dist/src/ui/auth/AuthDialog.js +5 -3
  155. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  156. package/dist/src/ui/auth/AuthInProgress.js +2 -2
  157. package/dist/src/ui/auth/AuthInProgress.js.map +1 -1
  158. package/dist/src/ui/auth/useAuth.d.ts +1 -1
  159. package/dist/src/ui/auth/useAuth.js +5 -3
  160. package/dist/src/ui/auth/useAuth.js.map +1 -1
  161. package/dist/src/ui/commands/aboutCommand.js +1 -1
  162. package/dist/src/ui/commands/aboutCommand.test.d.ts +6 -0
  163. package/dist/src/ui/commands/aboutCommand.test.js +130 -0
  164. package/dist/src/ui/commands/aboutCommand.test.js.map +1 -0
  165. package/dist/src/ui/commands/authCommand.js +1 -1
  166. package/dist/src/ui/commands/authCommand.test.d.ts +6 -0
  167. package/dist/src/ui/commands/authCommand.test.js +30 -0
  168. package/dist/src/ui/commands/authCommand.test.js.map +1 -0
  169. package/dist/src/ui/commands/bugCommand.js +1 -1
  170. package/dist/src/ui/commands/bugCommand.test.d.ts +6 -0
  171. package/dist/src/ui/commands/bugCommand.test.js +105 -0
  172. package/dist/src/ui/commands/bugCommand.test.js.map +1 -0
  173. package/dist/src/ui/commands/chatCommand.js +8 -25
  174. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  175. package/dist/src/ui/commands/chatCommand.test.d.ts +6 -0
  176. package/dist/src/ui/commands/chatCommand.test.js +555 -0
  177. package/dist/src/ui/commands/chatCommand.test.js.map +1 -0
  178. package/dist/src/ui/commands/clearCommand.js +1 -1
  179. package/dist/src/ui/commands/clearCommand.test.d.ts +6 -0
  180. package/dist/src/ui/commands/clearCommand.test.js +76 -0
  181. package/dist/src/ui/commands/clearCommand.test.js.map +1 -0
  182. package/dist/src/ui/commands/compressCommand.js +1 -1
  183. package/dist/src/ui/commands/compressCommand.js.map +1 -1
  184. package/dist/src/ui/commands/compressCommand.test.d.ts +6 -0
  185. package/dist/src/ui/commands/compressCommand.test.js +98 -0
  186. package/dist/src/ui/commands/compressCommand.test.js.map +1 -0
  187. package/dist/src/ui/commands/copyCommand.js +2 -1
  188. package/dist/src/ui/commands/copyCommand.js.map +1 -1
  189. package/dist/src/ui/commands/copyCommand.test.d.ts +6 -0
  190. package/dist/src/ui/commands/copyCommand.test.js +242 -0
  191. package/dist/src/ui/commands/copyCommand.test.js.map +1 -0
  192. package/dist/src/ui/commands/corgiCommand.js +1 -1
  193. package/dist/src/ui/commands/corgiCommand.js.map +1 -1
  194. package/dist/src/ui/commands/corgiCommand.test.d.ts +6 -0
  195. package/dist/src/ui/commands/corgiCommand.test.js +28 -0
  196. package/dist/src/ui/commands/corgiCommand.test.js.map +1 -0
  197. package/dist/src/ui/commands/directoryCommand.js +1 -1
  198. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  199. package/dist/src/ui/commands/directoryCommand.test.d.ts +6 -0
  200. package/dist/src/ui/commands/directoryCommand.test.js +144 -0
  201. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -0
  202. package/dist/src/ui/commands/docsCommand.js +1 -1
  203. package/dist/src/ui/commands/docsCommand.test.d.ts +6 -0
  204. package/dist/src/ui/commands/docsCommand.test.js +72 -0
  205. package/dist/src/ui/commands/docsCommand.test.js.map +1 -0
  206. package/dist/src/ui/commands/editorCommand.js +1 -1
  207. package/dist/src/ui/commands/editorCommand.test.d.ts +6 -0
  208. package/dist/src/ui/commands/editorCommand.test.js +27 -0
  209. package/dist/src/ui/commands/editorCommand.test.js.map +1 -0
  210. package/dist/src/ui/commands/extensionsCommand.js +30 -32
  211. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  212. package/dist/src/ui/commands/extensionsCommand.test.d.ts +6 -0
  213. package/dist/src/ui/commands/extensionsCommand.test.js +244 -0
  214. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -0
  215. package/dist/src/ui/commands/helpCommand.js +1 -1
  216. package/dist/src/ui/commands/helpCommand.test.d.ts +6 -0
  217. package/dist/src/ui/commands/helpCommand.test.js +42 -0
  218. package/dist/src/ui/commands/helpCommand.test.js.map +1 -0
  219. package/dist/src/ui/commands/ideCommand.js +6 -6
  220. package/dist/src/ui/commands/ideCommand.test.d.ts +6 -0
  221. package/dist/src/ui/commands/ideCommand.test.js +205 -0
  222. package/dist/src/ui/commands/ideCommand.test.js.map +1 -0
  223. package/dist/src/ui/commands/initCommand.js +1 -1
  224. package/dist/src/ui/commands/initCommand.js.map +1 -1
  225. package/dist/src/ui/commands/initCommand.test.d.ts +6 -0
  226. package/dist/src/ui/commands/initCommand.test.js +80 -0
  227. package/dist/src/ui/commands/initCommand.test.js.map +1 -0
  228. package/dist/src/ui/commands/mcpCommand.js +98 -88
  229. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  230. package/dist/src/ui/commands/mcpCommand.test.d.ts +6 -0
  231. package/dist/src/ui/commands/mcpCommand.test.js +148 -0
  232. package/dist/src/ui/commands/mcpCommand.test.js.map +1 -0
  233. package/dist/src/ui/commands/memoryCommand.js +27 -9
  234. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  235. package/dist/src/ui/commands/memoryCommand.test.d.ts +6 -0
  236. package/dist/src/ui/commands/memoryCommand.test.js +266 -0
  237. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -0
  238. package/dist/src/ui/commands/privacyCommand.js +1 -1
  239. package/dist/src/ui/commands/privacyCommand.test.d.ts +6 -0
  240. package/dist/src/ui/commands/privacyCommand.test.js +32 -0
  241. package/dist/src/ui/commands/privacyCommand.test.js.map +1 -0
  242. package/dist/src/ui/commands/profileCommand.d.ts +7 -0
  243. package/dist/src/ui/commands/profileCommand.js +23 -0
  244. package/dist/src/ui/commands/profileCommand.js.map +1 -0
  245. package/dist/src/ui/commands/quitCommand.js +1 -1
  246. package/dist/src/ui/commands/quitCommand.test.d.ts +6 -0
  247. package/dist/src/ui/commands/quitCommand.test.js +50 -0
  248. package/dist/src/ui/commands/quitCommand.test.js.map +1 -0
  249. package/dist/src/ui/commands/restoreCommand.test.d.ts +6 -0
  250. package/dist/src/ui/commands/restoreCommand.test.js +190 -0
  251. package/dist/src/ui/commands/restoreCommand.test.js.map +1 -0
  252. package/dist/src/ui/commands/settingsCommand.test.d.ts +6 -0
  253. package/dist/src/ui/commands/settingsCommand.test.js +30 -0
  254. package/dist/src/ui/commands/settingsCommand.test.js.map +1 -0
  255. package/dist/src/ui/commands/setupGithubCommand.js +4 -3
  256. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  257. package/dist/src/ui/commands/statsCommand.js +3 -3
  258. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  259. package/dist/src/ui/commands/statsCommand.test.d.ts +6 -0
  260. package/dist/src/ui/commands/statsCommand.test.js +53 -0
  261. package/dist/src/ui/commands/statsCommand.test.js.map +1 -0
  262. package/dist/src/ui/commands/terminalSetupCommand.test.d.ts +6 -0
  263. package/dist/src/ui/commands/terminalSetupCommand.test.js +66 -0
  264. package/dist/src/ui/commands/terminalSetupCommand.test.js.map +1 -0
  265. package/dist/src/ui/commands/themeCommand.js +1 -1
  266. package/dist/src/ui/commands/themeCommand.test.d.ts +6 -0
  267. package/dist/src/ui/commands/themeCommand.test.js +32 -0
  268. package/dist/src/ui/commands/themeCommand.test.js.map +1 -0
  269. package/dist/src/ui/commands/toolsCommand.js +1 -1
  270. package/dist/src/ui/commands/toolsCommand.test.d.ts +6 -0
  271. package/dist/src/ui/commands/toolsCommand.test.js +100 -0
  272. package/dist/src/ui/commands/toolsCommand.test.js.map +1 -0
  273. package/dist/src/ui/commands/types.d.ts +2 -0
  274. package/dist/src/ui/commands/types.js.map +1 -1
  275. package/dist/src/ui/commands/vimCommand.js +1 -1
  276. package/dist/src/ui/components/AnsiOutput.d.ts +1 -0
  277. package/dist/src/ui/components/AnsiOutput.js +5 -5
  278. package/dist/src/ui/components/AnsiOutput.js.map +1 -1
  279. package/dist/src/ui/components/AnsiOutput.test.js +6 -6
  280. package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
  281. package/dist/src/ui/components/AsciiArt.d.ts +3 -3
  282. package/dist/src/ui/components/AsciiArt.js +3 -3
  283. package/dist/src/ui/components/CliSpinner.d.ts +10 -0
  284. package/dist/src/ui/components/CliSpinner.js +20 -0
  285. package/dist/src/ui/components/CliSpinner.js.map +1 -0
  286. package/dist/src/ui/components/Composer.js +8 -9
  287. package/dist/src/ui/components/Composer.js.map +1 -1
  288. package/dist/src/ui/components/Composer.test.js +16 -1
  289. package/dist/src/ui/components/Composer.test.js.map +1 -1
  290. package/dist/src/ui/components/ContextSummaryDisplay.d.ts +0 -1
  291. package/dist/src/ui/components/ContextSummaryDisplay.js +4 -14
  292. package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
  293. package/dist/src/ui/components/ContextSummaryDisplay.test.d.ts +6 -0
  294. package/dist/src/ui/components/ContextSummaryDisplay.test.js +66 -0
  295. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -0
  296. package/dist/src/ui/components/DebugProfiler.d.ts +18 -0
  297. package/dist/src/ui/components/DebugProfiler.js +158 -12
  298. package/dist/src/ui/components/DebugProfiler.js.map +1 -1
  299. package/dist/src/ui/components/DebugProfiler.test.d.ts +6 -0
  300. package/dist/src/ui/components/DebugProfiler.test.js +140 -0
  301. package/dist/src/ui/components/DebugProfiler.test.js.map +1 -0
  302. package/dist/src/ui/components/DialogManager.js +1 -5
  303. package/dist/src/ui/components/DialogManager.js.map +1 -1
  304. package/dist/src/ui/components/EditorSettingsDialog.js +1 -1
  305. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  306. package/dist/src/ui/components/FolderTrustDialog.js +9 -5
  307. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
  308. package/dist/src/ui/components/FolderTrustDialog.test.js +14 -14
  309. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  310. package/dist/src/ui/components/Footer.js +7 -6
  311. package/dist/src/ui/components/Footer.js.map +1 -1
  312. package/dist/src/ui/components/Footer.test.d.ts +6 -0
  313. package/dist/src/ui/components/Footer.test.js +231 -0
  314. package/dist/src/ui/components/Footer.test.js.map +1 -0
  315. package/dist/src/ui/components/GeminiRespondingSpinner.js +2 -2
  316. package/dist/src/ui/components/GeminiRespondingSpinner.js.map +1 -1
  317. package/dist/src/ui/components/Help.js +1 -1
  318. package/dist/src/ui/components/Help.js.map +1 -1
  319. package/dist/src/ui/components/HistoryItemDisplay.js +2 -1
  320. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  321. package/dist/src/ui/components/InputPrompt.d.ts +11 -1
  322. package/dist/src/ui/components/InputPrompt.js +103 -29
  323. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  324. package/dist/src/ui/components/InputPrompt.test.d.ts +6 -0
  325. package/dist/src/ui/components/InputPrompt.test.js +1737 -0
  326. package/dist/src/ui/components/InputPrompt.test.js.map +1 -0
  327. package/dist/src/ui/components/MainContent.js +1 -1
  328. package/dist/src/ui/components/MainContent.js.map +1 -1
  329. package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +6 -0
  330. package/dist/src/ui/components/ModelStatsDisplay.test.js +285 -0
  331. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -0
  332. package/dist/src/ui/components/Notifications.js +12 -4
  333. package/dist/src/ui/components/Notifications.js.map +1 -1
  334. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +22 -18
  335. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
  336. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +10 -2
  337. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  338. package/dist/src/ui/components/QueuedMessageDisplay.js +3 -3
  339. package/dist/src/ui/components/QueuedMessageDisplay.js.map +1 -1
  340. package/dist/src/ui/components/QueuedMessageDisplay.test.js +4 -0
  341. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
  342. package/dist/src/ui/components/RawMarkdownIndicator.d.ts +7 -0
  343. package/dist/src/ui/components/RawMarkdownIndicator.js +8 -0
  344. package/dist/src/ui/components/RawMarkdownIndicator.js.map +1 -0
  345. package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +6 -0
  346. package/dist/src/ui/components/SessionSummaryDisplay.test.js +74 -0
  347. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -0
  348. package/dist/src/ui/components/SettingsDialog.js +12 -11
  349. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  350. package/dist/src/ui/components/SettingsDialog.test.js +190 -77
  351. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  352. package/dist/src/ui/components/StatsDisplay.test.d.ts +6 -0
  353. package/dist/src/ui/components/StatsDisplay.test.js +351 -0
  354. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -0
  355. package/dist/src/ui/components/ThemeDialog.d.ts +4 -2
  356. package/dist/src/ui/components/ThemeDialog.js +3 -3
  357. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  358. package/dist/src/ui/components/ThemeDialog.test.js +13 -0
  359. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  360. package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +6 -0
  361. package/dist/src/ui/components/ToolStatsDisplay.test.js +227 -0
  362. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -0
  363. package/dist/src/ui/components/messages/CompressionMessage.js +3 -3
  364. package/dist/src/ui/components/messages/CompressionMessage.js.map +1 -1
  365. package/dist/src/ui/components/messages/GeminiMessage.js +3 -1
  366. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  367. package/dist/src/ui/components/messages/GeminiMessage.test.d.ts +6 -0
  368. package/dist/src/ui/components/messages/GeminiMessage.test.js +35 -0
  369. package/dist/src/ui/components/messages/GeminiMessage.test.js.map +1 -0
  370. package/dist/src/ui/components/messages/GeminiMessageContent.js +3 -1
  371. package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
  372. package/dist/src/ui/components/messages/Todo.d.ts +7 -0
  373. package/dist/src/ui/components/messages/Todo.js +69 -0
  374. package/dist/src/ui/components/messages/Todo.js.map +1 -0
  375. package/dist/src/ui/components/messages/Todo.test.d.ts +6 -0
  376. package/dist/src/ui/components/messages/Todo.test.js +102 -0
  377. package/dist/src/ui/components/messages/Todo.test.js.map +1 -0
  378. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
  379. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  380. package/dist/src/ui/components/messages/ToolGroupMessage.js +2 -2
  381. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  382. package/dist/src/ui/components/messages/ToolMessage.js +9 -4
  383. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  384. package/dist/src/ui/components/messages/ToolMessage.test.js +2 -2
  385. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
  386. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.d.ts +6 -0
  387. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +30 -0
  388. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +1 -0
  389. package/dist/src/ui/components/messages/UserShellMessage.js +1 -1
  390. package/dist/src/ui/components/messages/UserShellMessage.js.map +1 -1
  391. package/dist/src/ui/components/shared/BaseSelectionList.test.js +33 -24
  392. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  393. package/dist/src/ui/components/shared/text-buffer.js +1 -1
  394. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  395. package/dist/src/ui/components/shared/text-buffer.test.d.ts +6 -0
  396. package/dist/src/ui/components/shared/text-buffer.test.js +1578 -0
  397. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -0
  398. package/dist/src/ui/components/shared/vim-buffer-actions.test.d.ts +6 -0
  399. package/dist/src/ui/components/shared/vim-buffer-actions.test.js +951 -0
  400. package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +1 -0
  401. package/dist/src/ui/components/views/ChatList.d.ts +12 -0
  402. package/dist/src/ui/components/views/ChatList.js +17 -0
  403. package/dist/src/ui/components/views/ChatList.js.map +1 -0
  404. package/dist/src/ui/components/views/ChatList.test.d.ts +6 -0
  405. package/dist/src/ui/components/views/ChatList.test.js +42 -0
  406. package/dist/src/ui/components/views/ChatList.test.js.map +1 -0
  407. package/dist/src/ui/components/views/ExtensionsList.js +3 -4
  408. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  409. package/dist/src/ui/components/views/ExtensionsList.test.js +2 -9
  410. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
  411. package/dist/src/ui/components/views/McpStatus.d.ts +0 -1
  412. package/dist/src/ui/components/views/McpStatus.js +4 -4
  413. package/dist/src/ui/components/views/McpStatus.js.map +1 -1
  414. package/dist/src/ui/components/views/McpStatus.test.js +0 -5
  415. package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
  416. package/dist/src/ui/components/views/ToolsList.test.js +4 -4
  417. package/dist/src/ui/components/views/ToolsList.test.js.map +1 -1
  418. package/dist/src/ui/contexts/KeypressContext.d.ts +1 -0
  419. package/dist/src/ui/contexts/KeypressContext.js +219 -53
  420. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  421. package/dist/src/ui/contexts/KeypressContext.test.js +536 -10
  422. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  423. package/dist/src/ui/contexts/SessionContext.test.d.ts +6 -0
  424. package/dist/src/ui/contexts/SessionContext.test.js +177 -0
  425. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -0
  426. package/dist/src/ui/contexts/UIActionsContext.d.ts +5 -4
  427. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  428. package/dist/src/ui/contexts/UIStateContext.d.ts +6 -4
  429. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  430. package/dist/src/ui/hooks/atCommandProcessor.js +2 -2
  431. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  432. package/dist/src/ui/hooks/shellCommandProcessor.js +5 -7
  433. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  434. package/dist/src/ui/hooks/shellCommandProcessor.test.js +19 -32
  435. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  436. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +2 -1
  437. package/dist/src/ui/hooks/slashCommandProcessor.js +11 -7
  438. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  439. package/dist/src/ui/hooks/slashCommandProcessor.test.d.ts +6 -0
  440. package/dist/src/ui/hooks/slashCommandProcessor.test.js +779 -0
  441. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -0
  442. package/dist/src/ui/hooks/useAtCompletion.js +2 -2
  443. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  444. package/dist/src/ui/hooks/useAtCompletion.test.d.ts +6 -0
  445. package/dist/src/ui/hooks/useAtCompletion.test.js +385 -0
  446. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -0
  447. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +0 -1
  448. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  449. package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -1
  450. package/dist/src/ui/hooks/useCommandCompletion.js +5 -3
  451. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  452. package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +6 -0
  453. package/dist/src/ui/hooks/useCommandCompletion.test.js +375 -0
  454. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -0
  455. package/dist/src/ui/hooks/useConsoleMessages.test.d.ts +6 -0
  456. package/dist/src/ui/hooks/useConsoleMessages.test.js +110 -0
  457. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -0
  458. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +2 -1
  459. package/dist/src/ui/hooks/useExtensionUpdates.js +71 -19
  460. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  461. package/dist/src/ui/hooks/useExtensionUpdates.test.js +28 -13
  462. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  463. package/dist/src/ui/hooks/useFlickerDetector.d.ts +14 -0
  464. package/dist/src/ui/hooks/useFlickerDetector.js +37 -0
  465. package/dist/src/ui/hooks/useFlickerDetector.js.map +1 -0
  466. package/dist/src/ui/hooks/useFlickerDetector.test.d.ts +6 -0
  467. package/dist/src/ui/hooks/useFlickerDetector.test.js +102 -0
  468. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -0
  469. package/dist/src/ui/hooks/useFocus.test.d.ts +6 -0
  470. package/dist/src/ui/hooks/useFocus.test.js +115 -0
  471. package/dist/src/ui/hooks/useFocus.test.js.map +1 -0
  472. package/dist/src/ui/hooks/useFolderTrust.d.ts +2 -1
  473. package/dist/src/ui/hooks/useFolderTrust.js +12 -3
  474. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
  475. package/dist/src/ui/hooks/useFolderTrust.test.d.ts +6 -0
  476. package/dist/src/ui/hooks/useFolderTrust.test.js +164 -0
  477. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -0
  478. package/dist/src/ui/hooks/useGeminiStream.js +95 -56
  479. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  480. package/dist/src/ui/hooks/useGeminiStream.test.d.ts +6 -0
  481. package/dist/src/ui/hooks/useGeminiStream.test.js +1971 -0
  482. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -0
  483. package/dist/src/ui/hooks/useHistoryManager.js +3 -3
  484. package/dist/src/ui/hooks/useHistoryManager.js.map +1 -1
  485. package/dist/src/ui/hooks/useInputHistoryStore.js +2 -1
  486. package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -1
  487. package/dist/src/ui/hooks/useKeypress.test.d.ts +6 -0
  488. package/dist/src/ui/hooks/useKeypress.test.js +234 -0
  489. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
  490. package/dist/src/ui/hooks/useLoadingIndicator.test.js +5 -0
  491. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  492. package/dist/src/ui/hooks/useMessageQueue.d.ts +1 -0
  493. package/dist/src/ui/hooks/useMessageQueue.js +14 -0
  494. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -1
  495. package/dist/src/ui/hooks/useMessageQueue.test.js +121 -0
  496. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  497. package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -0
  498. package/dist/src/ui/hooks/usePhraseCycler.js +157 -5
  499. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  500. package/dist/src/ui/hooks/usePhraseCycler.test.d.ts +6 -0
  501. package/dist/src/ui/hooks/usePhraseCycler.test.js +155 -0
  502. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -0
  503. package/dist/src/ui/hooks/useReactToolScheduler.js +2 -2
  504. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  505. package/dist/src/ui/hooks/useSelectionList.js +50 -23
  506. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  507. package/dist/src/ui/hooks/useSelectionList.test.js +24 -0
  508. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  509. package/dist/src/ui/hooks/useShellHistory.test.js +16 -10
  510. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  511. package/dist/src/ui/hooks/useShowMemoryCommand.d.ts +1 -1
  512. package/dist/src/ui/hooks/useShowMemoryCommand.js +4 -3
  513. package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
  514. package/dist/src/ui/hooks/useSlashCompletion.js +2 -1
  515. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  516. package/dist/src/ui/hooks/useTerminalSize.js +2 -3
  517. package/dist/src/ui/hooks/useTerminalSize.js.map +1 -1
  518. package/dist/src/ui/hooks/useThemeCommand.d.ts +2 -1
  519. package/dist/src/ui/hooks/useThemeCommand.js +6 -0
  520. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  521. package/dist/src/ui/hooks/useToolScheduler.test.js +3 -0
  522. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  523. package/dist/src/ui/hooks/vim.js +2 -1
  524. package/dist/src/ui/hooks/vim.js.map +1 -1
  525. package/dist/src/ui/hooks/vim.test.d.ts +6 -0
  526. package/dist/src/ui/hooks/vim.test.js +1389 -0
  527. package/dist/src/ui/hooks/vim.test.js.map +1 -0
  528. package/dist/src/ui/keyMatchers.test.js +9 -3
  529. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  530. package/dist/src/ui/layouts/DefaultAppLayout.d.ts +1 -3
  531. package/dist/src/ui/layouts/DefaultAppLayout.js +5 -2
  532. package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
  533. package/dist/src/ui/layouts/ScreenReaderAppLayout.js +4 -1
  534. package/dist/src/ui/layouts/ScreenReaderAppLayout.js.map +1 -1
  535. package/dist/src/ui/noninteractive/nonInteractiveUi.js +1 -0
  536. package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
  537. package/dist/src/ui/state/extensions.d.ts +22 -3
  538. package/dist/src/ui/state/extensions.js +26 -4
  539. package/dist/src/ui/state/extensions.js.map +1 -1
  540. package/dist/src/ui/themes/color-utils.js +2 -1
  541. package/dist/src/ui/themes/color-utils.js.map +1 -1
  542. package/dist/src/ui/themes/theme-manager.js +8 -7
  543. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  544. package/dist/src/ui/themes/theme.test.d.ts +6 -0
  545. package/dist/src/ui/themes/theme.test.js +85 -0
  546. package/dist/src/ui/themes/theme.test.js.map +1 -0
  547. package/dist/src/ui/types.d.ts +11 -3
  548. package/dist/src/ui/types.js +1 -0
  549. package/dist/src/ui/types.js.map +1 -1
  550. package/dist/src/ui/utils/CodeColorizer.d.ts +1 -1
  551. package/dist/src/ui/utils/CodeColorizer.js +4 -2
  552. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  553. package/dist/src/ui/utils/MarkdownDisplay.d.ts +1 -0
  554. package/dist/src/ui/utils/MarkdownDisplay.js +8 -1
  555. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  556. package/dist/src/ui/utils/commandUtils.js +20 -3
  557. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  558. package/dist/src/ui/utils/commandUtils.test.js +61 -6
  559. package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
  560. package/dist/src/ui/utils/computeStats.js +5 -2
  561. package/dist/src/ui/utils/computeStats.js.map +1 -1
  562. package/dist/src/ui/utils/computeStats.test.d.ts +6 -0
  563. package/dist/src/ui/utils/computeStats.test.js +262 -0
  564. package/dist/src/ui/utils/computeStats.test.js.map +1 -0
  565. package/dist/src/ui/utils/terminalSetup.js +3 -2
  566. package/dist/src/ui/utils/terminalSetup.js.map +1 -1
  567. package/dist/src/ui/utils/ui-sizing.d.ts +7 -0
  568. package/dist/src/ui/utils/ui-sizing.js +23 -0
  569. package/dist/src/ui/utils/ui-sizing.js.map +1 -0
  570. package/dist/src/ui/utils/updateCheck.d.ts +2 -1
  571. package/dist/src/ui/utils/updateCheck.js +6 -2
  572. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  573. package/dist/src/ui/utils/updateCheck.test.js +25 -10
  574. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  575. package/dist/src/utils/cleanup.test.d.ts +6 -0
  576. package/dist/src/utils/cleanup.test.js +49 -0
  577. package/dist/src/utils/cleanup.test.js.map +1 -0
  578. package/dist/src/utils/commentJson.js +95 -13
  579. package/dist/src/utils/commentJson.js.map +1 -1
  580. package/dist/src/utils/commentJson.test.js +161 -0
  581. package/dist/src/utils/commentJson.test.js.map +1 -1
  582. package/dist/src/utils/errors.d.ts +9 -3
  583. package/dist/src/utils/errors.js +87 -16
  584. package/dist/src/utils/errors.js.map +1 -1
  585. package/dist/src/utils/errors.test.js +40 -46
  586. package/dist/src/utils/errors.test.js.map +1 -1
  587. package/dist/src/utils/events.d.ts +2 -1
  588. package/dist/src/utils/events.js +1 -0
  589. package/dist/src/utils/events.js.map +1 -1
  590. package/dist/src/utils/gitUtils.js +3 -2
  591. package/dist/src/utils/gitUtils.js.map +1 -1
  592. package/dist/src/utils/handleAutoUpdate.js +4 -1
  593. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  594. package/dist/src/utils/handleAutoUpdate.test.d.ts +6 -0
  595. package/dist/src/utils/handleAutoUpdate.test.js +225 -0
  596. package/dist/src/utils/handleAutoUpdate.test.js.map +1 -0
  597. package/dist/src/utils/installationInfo.d.ts +1 -0
  598. package/dist/src/utils/installationInfo.js +4 -2
  599. package/dist/src/utils/installationInfo.js.map +1 -1
  600. package/dist/src/utils/installationInfo.test.js +8 -4
  601. package/dist/src/utils/installationInfo.test.js.map +1 -1
  602. package/dist/src/utils/readStdin.js +2 -1
  603. package/dist/src/utils/readStdin.js.map +1 -1
  604. package/dist/src/utils/sandbox-macos-permissive-open.sb +2 -0
  605. package/dist/src/utils/sandbox.js +20 -20
  606. package/dist/src/utils/sandbox.js.map +1 -1
  607. package/dist/src/utils/sessionCleanup.d.ts +22 -0
  608. package/dist/src/utils/sessionCleanup.integration.test.d.ts +6 -0
  609. package/dist/src/utils/sessionCleanup.integration.test.js +182 -0
  610. package/dist/src/utils/sessionCleanup.integration.test.js.map +1 -0
  611. package/dist/src/utils/sessionCleanup.js +214 -0
  612. package/dist/src/utils/sessionCleanup.js.map +1 -0
  613. package/dist/src/utils/sessionCleanup.test.d.ts +6 -0
  614. package/dist/src/utils/sessionCleanup.test.js +1232 -0
  615. package/dist/src/utils/sessionCleanup.test.js.map +1 -0
  616. package/dist/src/utils/sessionUtils.d.ts +37 -0
  617. package/dist/src/utils/sessionUtils.js +71 -0
  618. package/dist/src/utils/sessionUtils.js.map +1 -0
  619. package/dist/src/utils/startupWarnings.test.d.ts +6 -0
  620. package/dist/src/utils/startupWarnings.test.js +61 -0
  621. package/dist/src/utils/startupWarnings.test.js.map +1 -0
  622. package/dist/src/validateNonInterActiveAuth.js +8 -9
  623. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  624. package/dist/src/zed-integration/acp.js +1 -2
  625. package/dist/src/zed-integration/acp.js.map +1 -1
  626. package/dist/src/zed-integration/schema.d.ts +176 -176
  627. package/dist/src/zed-integration/zedIntegration.d.ts +2 -3
  628. package/dist/src/zed-integration/zedIntegration.js +12 -33
  629. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  630. package/dist/tsconfig.tsbuildinfo +1 -1
  631. package/package.json +7 -6
  632. package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +0 -11
  633. package/dist/src/ui/components/WorkspaceMigrationDialog.js +0 -44
  634. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +0 -1
  635. package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +0 -13
  636. package/dist/src/ui/hooks/useWorkspaceMigration.js +0 -54
  637. package/dist/src/ui/hooks/useWorkspaceMigration.js.map +0 -1
@@ -0,0 +1,741 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { executeToolCall, ToolErrorType, shutdownTelemetry, GeminiEventType, OutputFormat, uiTelemetryService, FatalInputError, } from '@google/gemini-cli-core';
7
+ import { runNonInteractive } from './nonInteractiveCli.js';
8
+ import { vi } from 'vitest';
9
+ // Mock core modules
10
+ vi.mock('./ui/hooks/atCommandProcessor.js');
11
+ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
12
+ const original = await importOriginal();
13
+ class MockChatRecordingService {
14
+ initialize = vi.fn();
15
+ recordMessage = vi.fn();
16
+ recordMessageTokens = vi.fn();
17
+ recordToolCalls = vi.fn();
18
+ }
19
+ return {
20
+ ...original,
21
+ executeToolCall: vi.fn(),
22
+ shutdownTelemetry: vi.fn(),
23
+ isTelemetrySdkInitialized: vi.fn().mockReturnValue(true),
24
+ ChatRecordingService: MockChatRecordingService,
25
+ uiTelemetryService: {
26
+ getMetrics: vi.fn(),
27
+ },
28
+ };
29
+ });
30
+ const mockGetCommands = vi.hoisted(() => vi.fn());
31
+ const mockCommandServiceCreate = vi.hoisted(() => vi.fn());
32
+ vi.mock('./services/CommandService.js', () => ({
33
+ CommandService: {
34
+ create: mockCommandServiceCreate,
35
+ },
36
+ }));
37
+ vi.mock('./services/FileCommandLoader.js');
38
+ vi.mock('./services/McpPromptLoader.js');
39
+ describe('runNonInteractive', () => {
40
+ let mockConfig;
41
+ let mockSettings;
42
+ let mockToolRegistry;
43
+ let mockCoreExecuteToolCall;
44
+ let mockShutdownTelemetry;
45
+ let consoleErrorSpy;
46
+ let processStdoutSpy;
47
+ let mockGeminiClient;
48
+ beforeEach(async () => {
49
+ mockCoreExecuteToolCall = vi.mocked(executeToolCall);
50
+ mockShutdownTelemetry = vi.mocked(shutdownTelemetry);
51
+ mockCommandServiceCreate.mockResolvedValue({
52
+ getCommands: mockGetCommands,
53
+ });
54
+ consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
55
+ processStdoutSpy = vi
56
+ .spyOn(process.stdout, 'write')
57
+ .mockImplementation(() => true);
58
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
59
+ throw new Error(`process.exit(${code}) called`);
60
+ });
61
+ mockToolRegistry = {
62
+ getTool: vi.fn(),
63
+ getFunctionDeclarations: vi.fn().mockReturnValue([]),
64
+ };
65
+ mockGeminiClient = {
66
+ sendMessageStream: vi.fn(),
67
+ getChatRecordingService: vi.fn(() => ({
68
+ initialize: vi.fn(),
69
+ recordMessage: vi.fn(),
70
+ recordMessageTokens: vi.fn(),
71
+ recordToolCalls: vi.fn(),
72
+ })),
73
+ };
74
+ mockConfig = {
75
+ initialize: vi.fn().mockResolvedValue(undefined),
76
+ getGeminiClient: vi.fn().mockReturnValue(mockGeminiClient),
77
+ getToolRegistry: vi.fn().mockReturnValue(mockToolRegistry),
78
+ getMaxSessionTurns: vi.fn().mockReturnValue(10),
79
+ getSessionId: vi.fn().mockReturnValue('test-session-id'),
80
+ getProjectRoot: vi.fn().mockReturnValue('/test/project'),
81
+ storage: {
82
+ getProjectTempDir: vi
83
+ .fn()
84
+ .mockReturnValue('/test/project/.cell-cli/tmp'),
85
+ },
86
+ getIdeMode: vi.fn().mockReturnValue(false),
87
+ getContentGeneratorConfig: vi.fn().mockReturnValue({}),
88
+ getDebugMode: vi.fn().mockReturnValue(false),
89
+ getOutputFormat: vi.fn().mockReturnValue('text'),
90
+ getFolderTrust: vi.fn().mockReturnValue(false),
91
+ isTrustedFolder: vi.fn().mockReturnValue(false),
92
+ };
93
+ mockSettings = {
94
+ system: { path: '', settings: {} },
95
+ systemDefaults: { path: '', settings: {} },
96
+ user: { path: '', settings: {} },
97
+ workspace: { path: '', settings: {} },
98
+ errors: [],
99
+ setValue: vi.fn(),
100
+ merged: {
101
+ security: {
102
+ auth: {
103
+ enforcedType: undefined,
104
+ },
105
+ },
106
+ },
107
+ isTrusted: true,
108
+ migratedInMemorScopes: new Set(),
109
+ forScope: vi.fn(),
110
+ computeMergedSettings: vi.fn(),
111
+ };
112
+ const { handleAtCommand } = await import('./ui/hooks/atCommandProcessor.js');
113
+ vi.mocked(handleAtCommand).mockImplementation(async ({ query }) => ({
114
+ processedQuery: [{ text: query }],
115
+ shouldProceed: true,
116
+ }));
117
+ });
118
+ afterEach(() => {
119
+ vi.restoreAllMocks();
120
+ });
121
+ async function* createStreamFromEvents(events) {
122
+ for (const event of events) {
123
+ yield event;
124
+ }
125
+ }
126
+ it('should process input and write text output', async () => {
127
+ const events = [
128
+ { type: GeminiEventType.Content, value: 'Hello' },
129
+ { type: GeminiEventType.Content, value: ' World' },
130
+ {
131
+ type: GeminiEventType.Finished,
132
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
133
+ },
134
+ ];
135
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
136
+ await runNonInteractive(mockConfig, mockSettings, 'Test input', 'prompt-id-1');
137
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Test input' }], expect.any(AbortSignal), 'prompt-id-1');
138
+ expect(processStdoutSpy).toHaveBeenCalledWith('Hello');
139
+ expect(processStdoutSpy).toHaveBeenCalledWith(' World');
140
+ expect(processStdoutSpy).toHaveBeenCalledWith('\n');
141
+ expect(mockShutdownTelemetry).toHaveBeenCalled();
142
+ });
143
+ it('should handle a single tool call and respond', async () => {
144
+ const toolCallEvent = {
145
+ type: GeminiEventType.ToolCallRequest,
146
+ value: {
147
+ callId: 'tool-1',
148
+ name: 'testTool',
149
+ args: { arg1: 'value1' },
150
+ isClientInitiated: false,
151
+ prompt_id: 'prompt-id-2',
152
+ },
153
+ };
154
+ const toolResponse = [{ text: 'Tool response' }];
155
+ mockCoreExecuteToolCall.mockResolvedValue({
156
+ status: 'success',
157
+ request: {
158
+ callId: 'tool-1',
159
+ name: 'testTool',
160
+ args: { arg1: 'value1' },
161
+ isClientInitiated: false,
162
+ prompt_id: 'prompt-id-2',
163
+ },
164
+ tool: {},
165
+ invocation: {},
166
+ response: {
167
+ responseParts: toolResponse,
168
+ callId: 'tool-1',
169
+ error: undefined,
170
+ errorType: undefined,
171
+ contentLength: undefined,
172
+ },
173
+ });
174
+ const firstCallEvents = [toolCallEvent];
175
+ const secondCallEvents = [
176
+ { type: GeminiEventType.Content, value: 'Final answer' },
177
+ {
178
+ type: GeminiEventType.Finished,
179
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
180
+ },
181
+ ];
182
+ mockGeminiClient.sendMessageStream
183
+ .mockReturnValueOnce(createStreamFromEvents(firstCallEvents))
184
+ .mockReturnValueOnce(createStreamFromEvents(secondCallEvents));
185
+ await runNonInteractive(mockConfig, mockSettings, 'Use a tool', 'prompt-id-2');
186
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
187
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledWith(mockConfig, expect.objectContaining({ name: 'testTool' }), expect.any(AbortSignal));
188
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenNthCalledWith(2, [{ text: 'Tool response' }], expect.any(AbortSignal), 'prompt-id-2');
189
+ expect(processStdoutSpy).toHaveBeenCalledWith('Final answer');
190
+ expect(processStdoutSpy).toHaveBeenCalledWith('\n');
191
+ });
192
+ it('should handle error during tool execution and should send error back to the model', async () => {
193
+ const toolCallEvent = {
194
+ type: GeminiEventType.ToolCallRequest,
195
+ value: {
196
+ callId: 'tool-1',
197
+ name: 'errorTool',
198
+ args: {},
199
+ isClientInitiated: false,
200
+ prompt_id: 'prompt-id-3',
201
+ },
202
+ };
203
+ mockCoreExecuteToolCall.mockResolvedValue({
204
+ status: 'error',
205
+ request: {
206
+ callId: 'tool-1',
207
+ name: 'errorTool',
208
+ args: {},
209
+ isClientInitiated: false,
210
+ prompt_id: 'prompt-id-3',
211
+ },
212
+ tool: {},
213
+ response: {
214
+ callId: 'tool-1',
215
+ error: new Error('Execution failed'),
216
+ errorType: ToolErrorType.EXECUTION_FAILED,
217
+ responseParts: [
218
+ {
219
+ functionResponse: {
220
+ name: 'errorTool',
221
+ response: {
222
+ output: 'Error: Execution failed',
223
+ },
224
+ },
225
+ },
226
+ ],
227
+ resultDisplay: 'Execution failed',
228
+ contentLength: undefined,
229
+ },
230
+ });
231
+ const finalResponse = [
232
+ {
233
+ type: GeminiEventType.Content,
234
+ value: 'Sorry, let me try again.',
235
+ },
236
+ {
237
+ type: GeminiEventType.Finished,
238
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
239
+ },
240
+ ];
241
+ mockGeminiClient.sendMessageStream
242
+ .mockReturnValueOnce(createStreamFromEvents([toolCallEvent]))
243
+ .mockReturnValueOnce(createStreamFromEvents(finalResponse));
244
+ await runNonInteractive(mockConfig, mockSettings, 'Trigger tool error', 'prompt-id-3');
245
+ expect(mockCoreExecuteToolCall).toHaveBeenCalled();
246
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error executing tool errorTool: Execution failed');
247
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
248
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenNthCalledWith(2, [
249
+ {
250
+ functionResponse: {
251
+ name: 'errorTool',
252
+ response: {
253
+ output: 'Error: Execution failed',
254
+ },
255
+ },
256
+ },
257
+ ], expect.any(AbortSignal), 'prompt-id-3');
258
+ expect(processStdoutSpy).toHaveBeenCalledWith('Sorry, let me try again.');
259
+ });
260
+ it('should exit with error if sendMessageStream throws initially', async () => {
261
+ const apiError = new Error('API connection failed');
262
+ mockGeminiClient.sendMessageStream.mockImplementation(() => {
263
+ throw apiError;
264
+ });
265
+ await expect(runNonInteractive(mockConfig, mockSettings, 'Initial fail', 'prompt-id-4')).rejects.toThrow(apiError);
266
+ });
267
+ it('should not exit if a tool is not found, and should send error back to model', async () => {
268
+ const toolCallEvent = {
269
+ type: GeminiEventType.ToolCallRequest,
270
+ value: {
271
+ callId: 'tool-1',
272
+ name: 'nonexistentTool',
273
+ args: {},
274
+ isClientInitiated: false,
275
+ prompt_id: 'prompt-id-5',
276
+ },
277
+ };
278
+ mockCoreExecuteToolCall.mockResolvedValue({
279
+ status: 'error',
280
+ request: {
281
+ callId: 'tool-1',
282
+ name: 'nonexistentTool',
283
+ args: {},
284
+ isClientInitiated: false,
285
+ prompt_id: 'prompt-id-5',
286
+ },
287
+ response: {
288
+ callId: 'tool-1',
289
+ error: new Error('Tool "nonexistentTool" not found in registry.'),
290
+ resultDisplay: 'Tool "nonexistentTool" not found in registry.',
291
+ responseParts: [],
292
+ errorType: undefined,
293
+ contentLength: undefined,
294
+ },
295
+ });
296
+ const finalResponse = [
297
+ {
298
+ type: GeminiEventType.Content,
299
+ value: "Sorry, I can't find that tool.",
300
+ },
301
+ {
302
+ type: GeminiEventType.Finished,
303
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
304
+ },
305
+ ];
306
+ mockGeminiClient.sendMessageStream
307
+ .mockReturnValueOnce(createStreamFromEvents([toolCallEvent]))
308
+ .mockReturnValueOnce(createStreamFromEvents(finalResponse));
309
+ await runNonInteractive(mockConfig, mockSettings, 'Trigger tool not found', 'prompt-id-5');
310
+ expect(mockCoreExecuteToolCall).toHaveBeenCalled();
311
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error executing tool nonexistentTool: Tool "nonexistentTool" not found in registry.');
312
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
313
+ expect(processStdoutSpy).toHaveBeenCalledWith("Sorry, I can't find that tool.");
314
+ });
315
+ it('should exit when max session turns are exceeded', async () => {
316
+ vi.mocked(mockConfig.getMaxSessionTurns).mockReturnValue(0);
317
+ await expect(runNonInteractive(mockConfig, mockSettings, 'Trigger loop', 'prompt-id-6')).rejects.toThrow('process.exit(53) called');
318
+ });
319
+ it('should preprocess @include commands before sending to the model', async () => {
320
+ // 1. Mock the imported atCommandProcessor
321
+ const { handleAtCommand } = await import('./ui/hooks/atCommandProcessor.js');
322
+ const mockHandleAtCommand = vi.mocked(handleAtCommand);
323
+ // 2. Define the raw input and the expected processed output
324
+ const rawInput = 'Summarize @file.txt';
325
+ const processedParts = [
326
+ { text: 'Summarize @file.txt' },
327
+ { text: '\n--- Content from referenced files ---\n' },
328
+ { text: 'This is the content of the file.' },
329
+ { text: '\n--- End of content ---' },
330
+ ];
331
+ // 3. Setup the mock to return the processed parts
332
+ mockHandleAtCommand.mockResolvedValue({
333
+ processedQuery: processedParts,
334
+ shouldProceed: true,
335
+ });
336
+ // Mock a simple stream response from the Gemini client
337
+ const events = [
338
+ { type: GeminiEventType.Content, value: 'Summary complete.' },
339
+ {
340
+ type: GeminiEventType.Finished,
341
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
342
+ },
343
+ ];
344
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
345
+ // 4. Run the non-interactive mode with the raw input
346
+ await runNonInteractive(mockConfig, mockSettings, rawInput, 'prompt-id-7');
347
+ // 5. Assert that sendMessageStream was called with the PROCESSED parts, not the raw input
348
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(processedParts, expect.any(AbortSignal), 'prompt-id-7');
349
+ // 6. Assert the final output is correct
350
+ expect(processStdoutSpy).toHaveBeenCalledWith('Summary complete.');
351
+ });
352
+ it('should process input and write JSON output with stats', async () => {
353
+ const events = [
354
+ { type: GeminiEventType.Content, value: 'Hello World' },
355
+ {
356
+ type: GeminiEventType.Finished,
357
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
358
+ },
359
+ ];
360
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
361
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
362
+ const mockMetrics = {
363
+ models: {},
364
+ tools: {
365
+ totalCalls: 0,
366
+ totalSuccess: 0,
367
+ totalFail: 0,
368
+ totalDurationMs: 0,
369
+ totalDecisions: {
370
+ accept: 0,
371
+ reject: 0,
372
+ modify: 0,
373
+ auto_accept: 0,
374
+ },
375
+ byName: {},
376
+ },
377
+ files: {
378
+ totalLinesAdded: 0,
379
+ totalLinesRemoved: 0,
380
+ },
381
+ };
382
+ vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(mockMetrics);
383
+ await runNonInteractive(mockConfig, mockSettings, 'Test input', 'prompt-id-1');
384
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Test input' }], expect.any(AbortSignal), 'prompt-id-1');
385
+ expect(processStdoutSpy).toHaveBeenCalledWith(JSON.stringify({ response: 'Hello World', stats: mockMetrics }, null, 2));
386
+ });
387
+ it('should write JSON output with stats for tool-only commands (no text response)', async () => {
388
+ // Test the scenario where a command completes successfully with only tool calls
389
+ // but no text response - this would have caught the original bug
390
+ const toolCallEvent = {
391
+ type: GeminiEventType.ToolCallRequest,
392
+ value: {
393
+ callId: 'tool-1',
394
+ name: 'testTool',
395
+ args: { arg1: 'value1' },
396
+ isClientInitiated: false,
397
+ prompt_id: 'prompt-id-tool-only',
398
+ },
399
+ };
400
+ const toolResponse = [{ text: 'Tool executed successfully' }];
401
+ mockCoreExecuteToolCall.mockResolvedValue({
402
+ status: 'success',
403
+ request: {
404
+ callId: 'tool-1',
405
+ name: 'testTool',
406
+ args: { arg1: 'value1' },
407
+ isClientInitiated: false,
408
+ prompt_id: 'prompt-id-tool-only',
409
+ },
410
+ tool: {},
411
+ invocation: {},
412
+ response: {
413
+ responseParts: toolResponse,
414
+ callId: 'tool-1',
415
+ error: undefined,
416
+ errorType: undefined,
417
+ contentLength: undefined,
418
+ },
419
+ });
420
+ // First call returns only tool call, no content
421
+ const firstCallEvents = [
422
+ toolCallEvent,
423
+ {
424
+ type: GeminiEventType.Finished,
425
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 5 } },
426
+ },
427
+ ];
428
+ // Second call returns no content (tool-only completion)
429
+ const secondCallEvents = [
430
+ {
431
+ type: GeminiEventType.Finished,
432
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 3 } },
433
+ },
434
+ ];
435
+ mockGeminiClient.sendMessageStream
436
+ .mockReturnValueOnce(createStreamFromEvents(firstCallEvents))
437
+ .mockReturnValueOnce(createStreamFromEvents(secondCallEvents));
438
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
439
+ const mockMetrics = {
440
+ models: {},
441
+ tools: {
442
+ totalCalls: 1,
443
+ totalSuccess: 1,
444
+ totalFail: 0,
445
+ totalDurationMs: 100,
446
+ totalDecisions: {
447
+ accept: 1,
448
+ reject: 0,
449
+ modify: 0,
450
+ auto_accept: 0,
451
+ },
452
+ byName: {
453
+ testTool: {
454
+ count: 1,
455
+ success: 1,
456
+ fail: 0,
457
+ durationMs: 100,
458
+ decisions: {
459
+ accept: 1,
460
+ reject: 0,
461
+ modify: 0,
462
+ auto_accept: 0,
463
+ },
464
+ },
465
+ },
466
+ },
467
+ files: {
468
+ totalLinesAdded: 0,
469
+ totalLinesRemoved: 0,
470
+ },
471
+ };
472
+ vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(mockMetrics);
473
+ await runNonInteractive(mockConfig, mockSettings, 'Execute tool only', 'prompt-id-tool-only');
474
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
475
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledWith(mockConfig, expect.objectContaining({ name: 'testTool' }), expect.any(AbortSignal));
476
+ // This should output JSON with empty response but include stats
477
+ expect(processStdoutSpy).toHaveBeenCalledWith(JSON.stringify({ response: '', stats: mockMetrics }, null, 2));
478
+ });
479
+ it('should write JSON output with stats for empty response commands', async () => {
480
+ // Test the scenario where a command completes but produces no content at all
481
+ const events = [
482
+ {
483
+ type: GeminiEventType.Finished,
484
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 1 } },
485
+ },
486
+ ];
487
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
488
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
489
+ const mockMetrics = {
490
+ models: {},
491
+ tools: {
492
+ totalCalls: 0,
493
+ totalSuccess: 0,
494
+ totalFail: 0,
495
+ totalDurationMs: 0,
496
+ totalDecisions: {
497
+ accept: 0,
498
+ reject: 0,
499
+ modify: 0,
500
+ auto_accept: 0,
501
+ },
502
+ byName: {},
503
+ },
504
+ files: {
505
+ totalLinesAdded: 0,
506
+ totalLinesRemoved: 0,
507
+ },
508
+ };
509
+ vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(mockMetrics);
510
+ await runNonInteractive(mockConfig, mockSettings, 'Empty response test', 'prompt-id-empty');
511
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Empty response test' }], expect.any(AbortSignal), 'prompt-id-empty');
512
+ // This should output JSON with empty response but include stats
513
+ expect(processStdoutSpy).toHaveBeenCalledWith(JSON.stringify({ response: '', stats: mockMetrics }, null, 2));
514
+ });
515
+ it('should handle errors in JSON format', async () => {
516
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
517
+ const testError = new Error('Invalid input provided');
518
+ mockGeminiClient.sendMessageStream.mockImplementation(() => {
519
+ throw testError;
520
+ });
521
+ // Mock console.error to capture JSON error output
522
+ const consoleErrorJsonSpy = vi
523
+ .spyOn(console, 'error')
524
+ .mockImplementation(() => { });
525
+ let thrownError = null;
526
+ try {
527
+ await runNonInteractive(mockConfig, mockSettings, 'Test input', 'prompt-id-error');
528
+ // Should not reach here
529
+ expect.fail('Expected process.exit to be called');
530
+ }
531
+ catch (error) {
532
+ thrownError = error;
533
+ }
534
+ // Should throw because of mocked process.exit
535
+ expect(thrownError?.message).toBe('process.exit(1) called');
536
+ expect(consoleErrorJsonSpy).toHaveBeenCalledWith(JSON.stringify({
537
+ error: {
538
+ type: 'Error',
539
+ message: 'Invalid input provided',
540
+ code: 1,
541
+ },
542
+ }, null, 2));
543
+ });
544
+ it('should handle FatalInputError with custom exit code in JSON format', async () => {
545
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
546
+ const fatalError = new FatalInputError('Invalid command syntax provided');
547
+ mockGeminiClient.sendMessageStream.mockImplementation(() => {
548
+ throw fatalError;
549
+ });
550
+ // Mock console.error to capture JSON error output
551
+ const consoleErrorJsonSpy = vi
552
+ .spyOn(console, 'error')
553
+ .mockImplementation(() => { });
554
+ let thrownError = null;
555
+ try {
556
+ await runNonInteractive(mockConfig, mockSettings, 'Invalid syntax', 'prompt-id-fatal');
557
+ // Should not reach here
558
+ expect.fail('Expected process.exit to be called');
559
+ }
560
+ catch (error) {
561
+ thrownError = error;
562
+ }
563
+ // Should throw because of mocked process.exit with custom exit code
564
+ expect(thrownError?.message).toBe('process.exit(42) called');
565
+ expect(consoleErrorJsonSpy).toHaveBeenCalledWith(JSON.stringify({
566
+ error: {
567
+ type: 'FatalInputError',
568
+ message: 'Invalid command syntax provided',
569
+ code: 42,
570
+ },
571
+ }, null, 2));
572
+ });
573
+ it('should execute a slash command that returns a prompt', async () => {
574
+ const mockCommand = {
575
+ name: 'testcommand',
576
+ description: 'a test command',
577
+ action: vi.fn().mockResolvedValue({
578
+ type: 'submit_prompt',
579
+ content: [{ text: 'Prompt from command' }],
580
+ }),
581
+ };
582
+ mockGetCommands.mockReturnValue([mockCommand]);
583
+ const events = [
584
+ { type: GeminiEventType.Content, value: 'Response from command' },
585
+ {
586
+ type: GeminiEventType.Finished,
587
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 5 } },
588
+ },
589
+ ];
590
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
591
+ await runNonInteractive(mockConfig, mockSettings, '/testcommand', 'prompt-id-slash');
592
+ // Ensure the prompt sent to the model is from the command, not the raw input
593
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Prompt from command' }], expect.any(AbortSignal), 'prompt-id-slash');
594
+ expect(processStdoutSpy).toHaveBeenCalledWith('Response from command');
595
+ });
596
+ it('should throw FatalInputError if a command requires confirmation', async () => {
597
+ const mockCommand = {
598
+ name: 'confirm',
599
+ description: 'a command that needs confirmation',
600
+ action: vi.fn().mockResolvedValue({
601
+ type: 'confirm_shell_commands',
602
+ commands: ['rm -rf /'],
603
+ }),
604
+ };
605
+ mockGetCommands.mockReturnValue([mockCommand]);
606
+ await expect(runNonInteractive(mockConfig, mockSettings, '/confirm', 'prompt-id-confirm')).rejects.toThrow('Exiting due to a confirmation prompt requested by the command.');
607
+ });
608
+ it('should treat an unknown slash command as a regular prompt', async () => {
609
+ // No commands are mocked, so any slash command is "unknown"
610
+ mockGetCommands.mockReturnValue([]);
611
+ const events = [
612
+ { type: GeminiEventType.Content, value: 'Response to unknown' },
613
+ {
614
+ type: GeminiEventType.Finished,
615
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 5 } },
616
+ },
617
+ ];
618
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
619
+ await runNonInteractive(mockConfig, mockSettings, '/unknowncommand', 'prompt-id-unknown');
620
+ // Ensure the raw input is sent to the model
621
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: '/unknowncommand' }], expect.any(AbortSignal), 'prompt-id-unknown');
622
+ expect(processStdoutSpy).toHaveBeenCalledWith('Response to unknown');
623
+ });
624
+ it('should throw for unhandled command result types', async () => {
625
+ const mockCommand = {
626
+ name: 'noaction',
627
+ description: 'unhandled type',
628
+ action: vi.fn().mockResolvedValue({
629
+ type: 'unhandled',
630
+ }),
631
+ };
632
+ mockGetCommands.mockReturnValue([mockCommand]);
633
+ await expect(runNonInteractive(mockConfig, mockSettings, '/noaction', 'prompt-id-unhandled')).rejects.toThrow('Exiting due to command result that is not supported in non-interactive mode.');
634
+ });
635
+ it('should pass arguments to the slash command action', async () => {
636
+ const mockAction = vi.fn().mockResolvedValue({
637
+ type: 'submit_prompt',
638
+ content: [{ text: 'Prompt from command' }],
639
+ });
640
+ const mockCommand = {
641
+ name: 'testargs',
642
+ description: 'a test command',
643
+ action: mockAction,
644
+ };
645
+ mockGetCommands.mockReturnValue([mockCommand]);
646
+ const events = [
647
+ { type: GeminiEventType.Content, value: 'Acknowledged' },
648
+ {
649
+ type: GeminiEventType.Finished,
650
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 1 } },
651
+ },
652
+ ];
653
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
654
+ await runNonInteractive(mockConfig, mockSettings, '/testargs arg1 arg2', 'prompt-id-args');
655
+ expect(mockAction).toHaveBeenCalledWith(expect.any(Object), 'arg1 arg2');
656
+ expect(processStdoutSpy).toHaveBeenCalledWith('Acknowledged');
657
+ });
658
+ it('should instantiate CommandService with correct loaders for slash commands', async () => {
659
+ // This test indirectly checks that handleSlashCommand is using the right loaders.
660
+ const { FileCommandLoader } = await import('./services/FileCommandLoader.js');
661
+ const { McpPromptLoader } = await import('./services/McpPromptLoader.js');
662
+ mockGetCommands.mockReturnValue([]); // No commands found, so it will fall through
663
+ const events = [
664
+ { type: GeminiEventType.Content, value: 'Acknowledged' },
665
+ {
666
+ type: GeminiEventType.Finished,
667
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 1 } },
668
+ },
669
+ ];
670
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
671
+ await runNonInteractive(mockConfig, mockSettings, '/mycommand', 'prompt-id-loaders');
672
+ // Check that loaders were instantiated with the config
673
+ expect(FileCommandLoader).toHaveBeenCalledTimes(1);
674
+ expect(FileCommandLoader).toHaveBeenCalledWith(mockConfig);
675
+ expect(McpPromptLoader).toHaveBeenCalledTimes(1);
676
+ expect(McpPromptLoader).toHaveBeenCalledWith(mockConfig);
677
+ // Check that instances were passed to CommandService.create
678
+ expect(mockCommandServiceCreate).toHaveBeenCalledTimes(1);
679
+ const loadersArg = mockCommandServiceCreate.mock.calls[0][0];
680
+ expect(loadersArg).toHaveLength(2);
681
+ expect(loadersArg[0]).toBe(vi.mocked(McpPromptLoader).mock.instances[0]);
682
+ expect(loadersArg[1]).toBe(vi.mocked(FileCommandLoader).mock.instances[0]);
683
+ });
684
+ it('should allow a normally-excluded tool when --allowed-tools is set', async () => {
685
+ // By default, ShellTool is excluded in non-interactive mode.
686
+ // This test ensures that --allowed-tools overrides this exclusion.
687
+ vi.mocked(mockConfig.getToolRegistry).mockReturnValue({
688
+ getTool: vi.fn().mockReturnValue({
689
+ name: 'ShellTool',
690
+ description: 'A shell tool',
691
+ run: vi.fn(),
692
+ }),
693
+ getFunctionDeclarations: vi.fn().mockReturnValue([{ name: 'ShellTool' }]),
694
+ });
695
+ const toolCallEvent = {
696
+ type: GeminiEventType.ToolCallRequest,
697
+ value: {
698
+ callId: 'tool-shell-1',
699
+ name: 'ShellTool',
700
+ args: { command: 'ls' },
701
+ isClientInitiated: false,
702
+ prompt_id: 'prompt-id-allowed',
703
+ },
704
+ };
705
+ const toolResponse = [{ text: 'file.txt' }];
706
+ mockCoreExecuteToolCall.mockResolvedValue({
707
+ status: 'success',
708
+ request: {
709
+ callId: 'tool-shell-1',
710
+ name: 'ShellTool',
711
+ args: { command: 'ls' },
712
+ isClientInitiated: false,
713
+ prompt_id: 'prompt-id-allowed',
714
+ },
715
+ tool: {},
716
+ invocation: {},
717
+ response: {
718
+ responseParts: toolResponse,
719
+ callId: 'tool-shell-1',
720
+ error: undefined,
721
+ errorType: undefined,
722
+ contentLength: undefined,
723
+ },
724
+ });
725
+ const firstCallEvents = [toolCallEvent];
726
+ const secondCallEvents = [
727
+ { type: GeminiEventType.Content, value: 'file.txt' },
728
+ {
729
+ type: GeminiEventType.Finished,
730
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
731
+ },
732
+ ];
733
+ mockGeminiClient.sendMessageStream
734
+ .mockReturnValueOnce(createStreamFromEvents(firstCallEvents))
735
+ .mockReturnValueOnce(createStreamFromEvents(secondCallEvents));
736
+ await runNonInteractive(mockConfig, mockSettings, 'List the files', 'prompt-id-allowed');
737
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledWith(mockConfig, expect.objectContaining({ name: 'ShellTool' }), expect.any(AbortSignal));
738
+ expect(processStdoutSpy).toHaveBeenCalledWith('file.txt');
739
+ });
740
+ });
741
+ //# sourceMappingURL=nonInteractiveCli.test.js.map