@machina.ai/cell-cli 1.10.0-rc1 → 1.13.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 (813) hide show
  1. package/dist/index.js +5 -5
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +14 -12
  4. package/dist/src/commands/extensions/disable.d.ts +1 -1
  5. package/dist/src/commands/extensions/disable.js +19 -8
  6. package/dist/src/commands/extensions/disable.js.map +1 -1
  7. package/dist/src/commands/extensions/enable.d.ts +1 -1
  8. package/dist/src/commands/extensions/enable.js +19 -9
  9. package/dist/src/commands/extensions/enable.js.map +1 -1
  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 +1 -0
  13. package/dist/src/commands/extensions/install.js +29 -4
  14. package/dist/src/commands/extensions/install.js.map +1 -1
  15. package/dist/src/commands/extensions/install.test.js +39 -19
  16. package/dist/src/commands/extensions/install.test.js.map +1 -1
  17. package/dist/src/commands/extensions/link.js +16 -4
  18. package/dist/src/commands/extensions/link.js.map +1 -1
  19. package/dist/src/commands/extensions/list.js +17 -6
  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 +16 -4
  24. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  25. package/dist/src/commands/extensions/update.js +28 -23
  26. package/dist/src/commands/extensions/update.js.map +1 -1
  27. package/dist/src/commands/extensions/validate.d.ts +12 -0
  28. package/dist/src/commands/extensions/validate.js +83 -0
  29. package/dist/src/commands/extensions/validate.js.map +1 -0
  30. package/dist/src/commands/extensions/validate.test.d.ts +6 -0
  31. package/dist/src/commands/extensions/validate.test.js +93 -0
  32. package/dist/src/commands/extensions/validate.test.js.map +1 -0
  33. package/dist/src/commands/extensions.js +3 -0
  34. package/dist/src/commands/extensions.js.map +1 -1
  35. package/dist/src/commands/mcp/add.js +7 -4
  36. package/dist/src/commands/mcp/add.js.map +1 -1
  37. package/dist/src/commands/mcp/add.test.d.ts +6 -0
  38. package/dist/src/commands/mcp/add.test.js +247 -0
  39. package/dist/src/commands/mcp/add.test.js.map +1 -0
  40. package/dist/src/commands/mcp/list.js +18 -9
  41. package/dist/src/commands/mcp/list.js.map +1 -1
  42. package/dist/src/commands/mcp/list.test.d.ts +6 -0
  43. package/dist/src/commands/mcp/list.test.js +128 -0
  44. package/dist/src/commands/mcp/list.test.js.map +1 -0
  45. package/dist/src/commands/mcp/remove.js +3 -2
  46. package/dist/src/commands/mcp/remove.js.map +1 -1
  47. package/dist/src/commands/mcp/remove.test.d.ts +6 -0
  48. package/dist/src/commands/mcp/remove.test.js +175 -0
  49. package/dist/src/commands/mcp/remove.test.js.map +1 -0
  50. package/dist/src/commands/mcp.test.d.ts +6 -0
  51. package/dist/src/commands/mcp.test.js +62 -0
  52. package/dist/src/commands/mcp.test.js.map +1 -0
  53. package/dist/src/config/auth.js +0 -3
  54. package/dist/src/config/auth.js.map +1 -1
  55. package/dist/src/config/config.d.ts +6 -15
  56. package/dist/src/config/config.integration.test.d.ts +6 -0
  57. package/dist/src/config/config.integration.test.js +321 -0
  58. package/dist/src/config/config.integration.test.js.map +1 -0
  59. package/dist/src/config/config.js +85 -164
  60. package/dist/src/config/config.js.map +1 -1
  61. package/dist/src/config/config.test.d.ts +6 -0
  62. package/dist/src/config/config.test.js +1972 -0
  63. package/dist/src/config/config.test.js.map +1 -0
  64. package/dist/src/config/extension-manager.d.ts +63 -0
  65. package/dist/src/config/extension-manager.js +450 -0
  66. package/dist/src/config/extension-manager.js.map +1 -0
  67. package/dist/src/config/extension.d.ts +4 -61
  68. package/dist/src/config/extension.js +1 -538
  69. package/dist/src/config/extension.js.map +1 -1
  70. package/dist/src/config/extension.test.d.ts +6 -0
  71. package/dist/src/config/extension.test.js +1412 -0
  72. package/dist/src/config/extension.test.js.map +1 -0
  73. package/dist/src/config/extensions/consent.d.ts +38 -0
  74. package/dist/src/config/extensions/consent.js +123 -0
  75. package/dist/src/config/extensions/consent.js.map +1 -0
  76. package/dist/src/config/extensions/extensionEnablement.d.ts +2 -2
  77. package/dist/src/config/extensions/extensionEnablement.js +7 -5
  78. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  79. package/dist/src/config/extensions/extensionEnablement.test.js +31 -28
  80. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  81. package/dist/src/config/extensions/extensionSettings.d.ts +15 -0
  82. package/dist/src/config/extensions/extensionSettings.js +113 -0
  83. package/dist/src/config/extensions/extensionSettings.js.map +1 -0
  84. package/dist/src/config/extensions/extensionSettings.test.d.ts +6 -0
  85. package/dist/src/config/extensions/extensionSettings.test.js +254 -0
  86. package/dist/src/config/extensions/extensionSettings.test.js.map +1 -0
  87. package/dist/src/config/extensions/github.d.ts +18 -9
  88. package/dist/src/config/extensions/github.js +108 -36
  89. package/dist/src/config/extensions/github.js.map +1 -1
  90. package/dist/src/config/extensions/github.test.js +158 -164
  91. package/dist/src/config/extensions/github.test.js.map +1 -1
  92. package/dist/src/config/extensions/github_fetch.d.ts +1 -1
  93. package/dist/src/config/extensions/github_fetch.js +13 -1
  94. package/dist/src/config/extensions/github_fetch.js.map +1 -1
  95. package/dist/src/config/extensions/github_fetch.test.d.ts +6 -0
  96. package/dist/src/config/extensions/github_fetch.test.js +169 -0
  97. package/dist/src/config/extensions/github_fetch.test.js.map +1 -0
  98. package/dist/src/config/extensions/storage.d.ts +14 -0
  99. package/dist/src/config/extensions/storage.js +32 -0
  100. package/dist/src/config/extensions/storage.js.map +1 -0
  101. package/dist/src/config/extensions/update.d.ts +5 -4
  102. package/dist/src/config/extensions/update.js +41 -37
  103. package/dist/src/config/extensions/update.js.map +1 -1
  104. package/dist/src/config/extensions/update.test.js +72 -74
  105. package/dist/src/config/extensions/update.test.js.map +1 -1
  106. package/dist/src/config/extensions/variableSchema.d.ts +0 -4
  107. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  108. package/dist/src/config/extensions/variables.d.ts +4 -0
  109. package/dist/src/config/extensions/variables.js +6 -0
  110. package/dist/src/config/extensions/variables.js.map +1 -1
  111. package/dist/src/config/keyBindings.d.ts +5 -1
  112. package/dist/src/config/keyBindings.js +34 -10
  113. package/dist/src/config/keyBindings.js.map +1 -1
  114. package/dist/src/config/keyBindings.test.js +17 -0
  115. package/dist/src/config/keyBindings.test.js.map +1 -1
  116. package/dist/src/config/policies/read-only.toml +56 -0
  117. package/dist/src/config/policies/write.toml +63 -0
  118. package/dist/src/config/policies/yolo.toml +31 -0
  119. package/dist/src/config/policy-engine.integration.test.js +41 -38
  120. package/dist/src/config/policy-engine.integration.test.js.map +1 -1
  121. package/dist/src/config/policy.d.ts +4 -3
  122. package/dist/src/config/policy.js +13 -142
  123. package/dist/src/config/policy.js.map +1 -1
  124. package/dist/src/config/sandboxConfig.d.ts +1 -2
  125. package/dist/src/config/sandboxConfig.js +7 -6
  126. package/dist/src/config/sandboxConfig.js.map +1 -1
  127. package/dist/src/config/settings.d.ts +2 -1
  128. package/dist/src/config/settings.js +59 -15
  129. package/dist/src/config/settings.js.map +1 -1
  130. package/dist/src/config/settings.test.d.ts +6 -0
  131. package/dist/src/config/settings.test.js +2000 -0
  132. package/dist/src/config/settings.test.js.map +1 -0
  133. package/dist/src/config/settingsSchema.d.ts +170 -28
  134. package/dist/src/config/settingsSchema.js +418 -27
  135. package/dist/src/config/settingsSchema.js.map +1 -1
  136. package/dist/src/config/settingsSchema.test.js +42 -1
  137. package/dist/src/config/settingsSchema.test.js.map +1 -1
  138. package/dist/src/config/trustedFolders.d.ts +1 -1
  139. package/dist/src/config/trustedFolders.js +4 -2
  140. package/dist/src/config/trustedFolders.js.map +1 -1
  141. package/dist/src/core/initializer.js +2 -1
  142. package/dist/src/core/initializer.js.map +1 -1
  143. package/dist/src/gemini.d.ts +1 -1
  144. package/dist/src/gemini.js +63 -27
  145. package/dist/src/gemini.js.map +1 -1
  146. package/dist/src/gemini.test.js +123 -34
  147. package/dist/src/gemini.test.js.map +1 -1
  148. package/dist/src/generated/git-commit.d.ts +2 -2
  149. package/dist/src/generated/git-commit.js +2 -2
  150. package/dist/src/nonInteractiveCli.d.ts +9 -1
  151. package/dist/src/nonInteractiveCli.js +205 -10
  152. package/dist/src/nonInteractiveCli.js.map +1 -1
  153. package/dist/src/nonInteractiveCli.test.d.ts +6 -0
  154. package/dist/src/nonInteractiveCli.test.js +984 -0
  155. package/dist/src/nonInteractiveCli.test.js.map +1 -0
  156. package/dist/src/nonInteractiveCliCommands.js +2 -2
  157. package/dist/src/nonInteractiveCliCommands.js.map +1 -1
  158. package/dist/src/services/BuiltinCommandLoader.js +4 -0
  159. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  160. package/dist/src/services/BuiltinCommandLoader.test.js +22 -0
  161. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  162. package/dist/src/services/CommandService.js +2 -1
  163. package/dist/src/services/CommandService.js.map +1 -1
  164. package/dist/src/services/FeedbackService.js +2 -2
  165. package/dist/src/services/FeedbackService.js.map +1 -1
  166. package/dist/src/services/FileCommandLoader.test.d.ts +6 -0
  167. package/dist/src/services/FileCommandLoader.test.js +971 -0
  168. package/dist/src/services/FileCommandLoader.test.js.map +1 -0
  169. package/dist/src/services/McpPromptLoader.js +2 -2
  170. package/dist/src/services/McpPromptLoader.js.map +1 -1
  171. package/dist/src/services/McpPromptLoader.test.js +4 -2
  172. package/dist/src/services/McpPromptLoader.test.js.map +1 -1
  173. package/dist/src/services/prompt-processors/argumentProcessor.test.d.ts +6 -0
  174. package/dist/src/services/prompt-processors/argumentProcessor.test.js +40 -0
  175. package/dist/src/services/prompt-processors/argumentProcessor.test.js.map +1 -0
  176. package/dist/src/services/prompt-processors/atFileProcessor.js +3 -2
  177. package/dist/src/services/prompt-processors/atFileProcessor.js.map +1 -1
  178. package/dist/src/services/prompt-processors/shellProcessor.test.d.ts +6 -0
  179. package/dist/src/services/prompt-processors/shellProcessor.test.js +482 -0
  180. package/dist/src/services/prompt-processors/shellProcessor.test.js.map +1 -0
  181. package/dist/src/test-utils/async.d.ts +9 -0
  182. package/dist/src/test-utils/async.js +29 -0
  183. package/dist/src/test-utils/async.js.map +1 -0
  184. package/dist/src/test-utils/createExtension.d.ts +3 -1
  185. package/dist/src/test-utils/createExtension.js +3 -3
  186. package/dist/src/test-utils/createExtension.js.map +1 -1
  187. package/dist/src/test-utils/render.d.ts +17 -2
  188. package/dist/src/test-utils/render.js +69 -4
  189. package/dist/src/test-utils/render.js.map +1 -1
  190. package/dist/src/test-utils/render.test.d.ts +6 -0
  191. package/dist/src/test-utils/render.test.js +79 -0
  192. package/dist/src/test-utils/render.test.js.map +1 -0
  193. package/dist/src/ui/App.test.d.ts +6 -0
  194. package/dist/src/ui/App.test.js +110 -0
  195. package/dist/src/ui/App.test.js.map +1 -0
  196. package/dist/src/ui/AppContainer.js +223 -92
  197. package/dist/src/ui/AppContainer.js.map +1 -1
  198. package/dist/src/ui/AppContainer.test.js +531 -147
  199. package/dist/src/ui/AppContainer.test.js.map +1 -1
  200. package/dist/src/ui/IdeIntegrationNudge.js +1 -1
  201. package/dist/src/ui/IdeIntegrationNudge.js.map +1 -1
  202. package/dist/src/ui/auth/ApiAuthDialog.d.ts +14 -0
  203. package/dist/src/ui/auth/ApiAuthDialog.js +26 -0
  204. package/dist/src/ui/auth/ApiAuthDialog.js.map +1 -0
  205. package/dist/src/ui/auth/ApiAuthDialog.test.d.ts +6 -0
  206. package/dist/src/ui/auth/ApiAuthDialog.test.js +91 -0
  207. package/dist/src/ui/auth/ApiAuthDialog.test.js.map +1 -0
  208. package/dist/src/ui/auth/AuthDialog.d.ts +1 -1
  209. package/dist/src/ui/auth/AuthDialog.js +9 -3
  210. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  211. package/dist/src/ui/auth/useAuth.d.ts +3 -1
  212. package/dist/src/ui/auth/useAuth.js +35 -4
  213. package/dist/src/ui/auth/useAuth.js.map +1 -1
  214. package/dist/src/ui/colors.js +3 -0
  215. package/dist/src/ui/colors.js.map +1 -1
  216. package/dist/src/ui/commands/aboutCommand.js +1 -1
  217. package/dist/src/ui/commands/aboutCommand.test.d.ts +6 -0
  218. package/dist/src/ui/commands/aboutCommand.test.js +130 -0
  219. package/dist/src/ui/commands/aboutCommand.test.js.map +1 -0
  220. package/dist/src/ui/commands/authCommand.js +1 -1
  221. package/dist/src/ui/commands/authCommand.test.d.ts +6 -0
  222. package/dist/src/ui/commands/authCommand.test.js +30 -0
  223. package/dist/src/ui/commands/authCommand.test.js.map +1 -0
  224. package/dist/src/ui/commands/bugCommand.js +1 -1
  225. package/dist/src/ui/commands/bugCommand.test.d.ts +6 -0
  226. package/dist/src/ui/commands/bugCommand.test.js +105 -0
  227. package/dist/src/ui/commands/bugCommand.test.js.map +1 -0
  228. package/dist/src/ui/commands/chatCommand.js +1 -1
  229. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  230. package/dist/src/ui/commands/chatCommand.test.d.ts +6 -0
  231. package/dist/src/ui/commands/chatCommand.test.js +555 -0
  232. package/dist/src/ui/commands/chatCommand.test.js.map +1 -0
  233. package/dist/src/ui/commands/clearCommand.js +1 -1
  234. package/dist/src/ui/commands/clearCommand.test.d.ts +6 -0
  235. package/dist/src/ui/commands/clearCommand.test.js +76 -0
  236. package/dist/src/ui/commands/clearCommand.test.js.map +1 -0
  237. package/dist/src/ui/commands/compressCommand.js +1 -1
  238. package/dist/src/ui/commands/compressCommand.js.map +1 -1
  239. package/dist/src/ui/commands/compressCommand.test.d.ts +6 -0
  240. package/dist/src/ui/commands/compressCommand.test.js +98 -0
  241. package/dist/src/ui/commands/compressCommand.test.js.map +1 -0
  242. package/dist/src/ui/commands/copyCommand.js +2 -1
  243. package/dist/src/ui/commands/copyCommand.js.map +1 -1
  244. package/dist/src/ui/commands/copyCommand.test.d.ts +6 -0
  245. package/dist/src/ui/commands/copyCommand.test.js +242 -0
  246. package/dist/src/ui/commands/copyCommand.test.js.map +1 -0
  247. package/dist/src/ui/commands/corgiCommand.js +1 -1
  248. package/dist/src/ui/commands/corgiCommand.js.map +1 -1
  249. package/dist/src/ui/commands/corgiCommand.test.d.ts +6 -0
  250. package/dist/src/ui/commands/corgiCommand.test.js +28 -0
  251. package/dist/src/ui/commands/corgiCommand.test.js.map +1 -0
  252. package/dist/src/ui/commands/directoryCommand.js +1 -1
  253. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  254. package/dist/src/ui/commands/directoryCommand.test.d.ts +6 -0
  255. package/dist/src/ui/commands/directoryCommand.test.js +144 -0
  256. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -0
  257. package/dist/src/ui/commands/docsCommand.js +1 -1
  258. package/dist/src/ui/commands/docsCommand.test.d.ts +6 -0
  259. package/dist/src/ui/commands/docsCommand.test.js +72 -0
  260. package/dist/src/ui/commands/docsCommand.test.js.map +1 -0
  261. package/dist/src/ui/commands/editorCommand.js +1 -1
  262. package/dist/src/ui/commands/editorCommand.test.d.ts +6 -0
  263. package/dist/src/ui/commands/editorCommand.test.js +27 -0
  264. package/dist/src/ui/commands/editorCommand.test.js.map +1 -0
  265. package/dist/src/ui/commands/extensionsCommand.js +64 -11
  266. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  267. package/dist/src/ui/commands/extensionsCommand.test.d.ts +6 -0
  268. package/dist/src/ui/commands/extensionsCommand.test.js +315 -0
  269. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -0
  270. package/dist/src/ui/commands/helpCommand.js +1 -1
  271. package/dist/src/ui/commands/helpCommand.test.d.ts +6 -0
  272. package/dist/src/ui/commands/helpCommand.test.js +42 -0
  273. package/dist/src/ui/commands/helpCommand.test.js.map +1 -0
  274. package/dist/src/ui/commands/ideCommand.js +6 -6
  275. package/dist/src/ui/commands/ideCommand.test.d.ts +6 -0
  276. package/dist/src/ui/commands/ideCommand.test.js +205 -0
  277. package/dist/src/ui/commands/ideCommand.test.js.map +1 -0
  278. package/dist/src/ui/commands/initCommand.js +1 -1
  279. package/dist/src/ui/commands/initCommand.js.map +1 -1
  280. package/dist/src/ui/commands/initCommand.test.d.ts +6 -0
  281. package/dist/src/ui/commands/initCommand.test.js +80 -0
  282. package/dist/src/ui/commands/initCommand.test.js.map +1 -0
  283. package/dist/src/ui/commands/mcpCommand.js +110 -100
  284. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  285. package/dist/src/ui/commands/mcpCommand.test.d.ts +6 -0
  286. package/dist/src/ui/commands/mcpCommand.test.js +152 -0
  287. package/dist/src/ui/commands/mcpCommand.test.js.map +1 -0
  288. package/dist/src/ui/commands/memoryCommand.js +6 -6
  289. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  290. package/dist/src/ui/commands/memoryCommand.test.d.ts +6 -0
  291. package/dist/src/ui/commands/memoryCommand.test.js +268 -0
  292. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -0
  293. package/dist/src/ui/commands/policiesCommand.d.ts +7 -0
  294. package/dist/src/ui/commands/policiesCommand.js +59 -0
  295. package/dist/src/ui/commands/policiesCommand.js.map +1 -0
  296. package/dist/src/ui/commands/policiesCommand.test.d.ts +6 -0
  297. package/dist/src/ui/commands/policiesCommand.test.js +83 -0
  298. package/dist/src/ui/commands/policiesCommand.test.js.map +1 -0
  299. package/dist/src/ui/commands/privacyCommand.js +1 -1
  300. package/dist/src/ui/commands/privacyCommand.test.d.ts +6 -0
  301. package/dist/src/ui/commands/privacyCommand.test.js +32 -0
  302. package/dist/src/ui/commands/privacyCommand.test.js.map +1 -0
  303. package/dist/src/ui/commands/quitCommand.js +1 -1
  304. package/dist/src/ui/commands/quitCommand.test.d.ts +6 -0
  305. package/dist/src/ui/commands/quitCommand.test.js +50 -0
  306. package/dist/src/ui/commands/quitCommand.test.js.map +1 -0
  307. package/dist/src/ui/commands/restoreCommand.test.d.ts +6 -0
  308. package/dist/src/ui/commands/restoreCommand.test.js +190 -0
  309. package/dist/src/ui/commands/restoreCommand.test.js.map +1 -0
  310. package/dist/src/ui/commands/settingsCommand.test.d.ts +6 -0
  311. package/dist/src/ui/commands/settingsCommand.test.js +30 -0
  312. package/dist/src/ui/commands/settingsCommand.test.js.map +1 -0
  313. package/dist/src/ui/commands/setupGithubCommand.js +4 -3
  314. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  315. package/dist/src/ui/commands/setupGithubCommand.test.js +1 -2
  316. package/dist/src/ui/commands/setupGithubCommand.test.js.map +1 -1
  317. package/dist/src/ui/commands/statsCommand.js +3 -3
  318. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  319. package/dist/src/ui/commands/statsCommand.test.d.ts +6 -0
  320. package/dist/src/ui/commands/statsCommand.test.js +53 -0
  321. package/dist/src/ui/commands/statsCommand.test.js.map +1 -0
  322. package/dist/src/ui/commands/terminalSetupCommand.test.d.ts +6 -0
  323. package/dist/src/ui/commands/terminalSetupCommand.test.js +66 -0
  324. package/dist/src/ui/commands/terminalSetupCommand.test.js.map +1 -0
  325. package/dist/src/ui/commands/themeCommand.js +1 -1
  326. package/dist/src/ui/commands/themeCommand.test.d.ts +6 -0
  327. package/dist/src/ui/commands/themeCommand.test.js +32 -0
  328. package/dist/src/ui/commands/themeCommand.test.js.map +1 -0
  329. package/dist/src/ui/commands/toolsCommand.js +1 -1
  330. package/dist/src/ui/commands/toolsCommand.test.d.ts +6 -0
  331. package/dist/src/ui/commands/toolsCommand.test.js +100 -0
  332. package/dist/src/ui/commands/toolsCommand.test.js.map +1 -0
  333. package/dist/src/ui/commands/types.d.ts +1 -0
  334. package/dist/src/ui/commands/vimCommand.js +1 -1
  335. package/dist/src/ui/components/AnsiOutput.test.js +1 -1
  336. package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
  337. package/dist/src/ui/components/AsciiArt.d.ts +3 -3
  338. package/dist/src/ui/components/AsciiArt.js +3 -3
  339. package/dist/src/ui/components/Composer.js +6 -4
  340. package/dist/src/ui/components/Composer.js.map +1 -1
  341. package/dist/src/ui/components/Composer.test.js +21 -3
  342. package/dist/src/ui/components/Composer.test.js.map +1 -1
  343. package/dist/src/ui/components/ConfigInitDisplay.js +4 -6
  344. package/dist/src/ui/components/ConfigInitDisplay.js.map +1 -1
  345. package/dist/src/ui/components/ConsentPrompt.test.js +18 -8
  346. package/dist/src/ui/components/ConsentPrompt.test.js.map +1 -1
  347. package/dist/src/ui/components/ConsoleSummaryDisplay.js +1 -1
  348. package/dist/src/ui/components/ConsoleSummaryDisplay.js.map +1 -1
  349. package/dist/src/ui/components/ContextSummaryDisplay.d.ts +0 -1
  350. package/dist/src/ui/components/ContextSummaryDisplay.js +2 -12
  351. package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
  352. package/dist/src/ui/components/ContextSummaryDisplay.test.d.ts +6 -0
  353. package/dist/src/ui/components/ContextSummaryDisplay.test.js +71 -0
  354. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -0
  355. package/dist/src/ui/components/DetailedMessagesDisplay.js +1 -1
  356. package/dist/src/ui/components/DetailedMessagesDisplay.js.map +1 -1
  357. package/dist/src/ui/components/DialogManager.js +5 -5
  358. package/dist/src/ui/components/DialogManager.js.map +1 -1
  359. package/dist/src/ui/components/EditorSettingsDialog.js +1 -1
  360. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  361. package/dist/src/ui/components/FolderTrustDialog.test.js +8 -3
  362. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  363. package/dist/src/ui/components/Footer.js +4 -3
  364. package/dist/src/ui/components/Footer.js.map +1 -1
  365. package/dist/src/ui/components/Footer.test.d.ts +6 -0
  366. package/dist/src/ui/components/Footer.test.js +314 -0
  367. package/dist/src/ui/components/Footer.test.js.map +1 -0
  368. package/dist/src/ui/components/Header.test.js +13 -5
  369. package/dist/src/ui/components/Header.test.js.map +1 -1
  370. package/dist/src/ui/components/Help.test.js +5 -4
  371. package/dist/src/ui/components/Help.test.js.map +1 -1
  372. package/dist/src/ui/components/HistoryItemDisplay.js +1 -1
  373. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  374. package/dist/src/ui/components/InputPrompt.d.ts +4 -0
  375. package/dist/src/ui/components/InputPrompt.js +80 -12
  376. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  377. package/dist/src/ui/components/InputPrompt.test.d.ts +6 -0
  378. package/dist/src/ui/components/InputPrompt.test.js +1786 -0
  379. package/dist/src/ui/components/InputPrompt.test.js.map +1 -0
  380. package/dist/src/ui/components/LoadingIndicator.js +2 -2
  381. package/dist/src/ui/components/LoadingIndicator.js.map +1 -1
  382. package/dist/src/ui/components/LoadingIndicator.test.js +28 -15
  383. package/dist/src/ui/components/LoadingIndicator.test.js.map +1 -1
  384. package/dist/src/ui/components/LoopDetectionConfirmation.js +1 -1
  385. package/dist/src/ui/components/LoopDetectionConfirmation.js.map +1 -1
  386. package/dist/src/ui/components/LoopDetectionConfirmation.test.js +2 -2
  387. package/dist/src/ui/components/LoopDetectionConfirmation.test.js.map +1 -1
  388. package/dist/src/ui/components/MainContent.js +15 -4
  389. package/dist/src/ui/components/MainContent.js.map +1 -1
  390. package/dist/src/ui/components/ModelDialog.js +1 -1
  391. package/dist/src/ui/components/ModelDialog.js.map +1 -1
  392. package/dist/src/ui/components/ModelDialog.test.js +23 -13
  393. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  394. package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +6 -0
  395. package/dist/src/ui/components/ModelStatsDisplay.test.js +285 -0
  396. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -0
  397. package/dist/src/ui/components/Notifications.js +38 -5
  398. package/dist/src/ui/components/Notifications.js.map +1 -1
  399. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +22 -18
  400. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
  401. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +12 -4
  402. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  403. package/dist/src/ui/components/PrepareLabel.test.js +14 -8
  404. package/dist/src/ui/components/PrepareLabel.test.js.map +1 -1
  405. package/dist/src/ui/components/ProQuotaDialog.test.js +14 -6
  406. package/dist/src/ui/components/ProQuotaDialog.test.js.map +1 -1
  407. package/dist/src/ui/components/QueuedMessageDisplay.js +3 -3
  408. package/dist/src/ui/components/QueuedMessageDisplay.js.map +1 -1
  409. package/dist/src/ui/components/QueuedMessageDisplay.test.js +15 -6
  410. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
  411. package/dist/src/ui/components/RawMarkdownIndicator.d.ts +7 -0
  412. package/dist/src/ui/components/RawMarkdownIndicator.js +8 -0
  413. package/dist/src/ui/components/RawMarkdownIndicator.js.map +1 -0
  414. package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +6 -0
  415. package/dist/src/ui/components/SessionSummaryDisplay.test.js +74 -0
  416. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -0
  417. package/dist/src/ui/components/SettingsDialog.js +43 -35
  418. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  419. package/dist/src/ui/components/SettingsDialog.test.js +554 -545
  420. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  421. package/dist/src/ui/components/ShellConfirmationDialog.js +1 -1
  422. package/dist/src/ui/components/ShellConfirmationDialog.js.map +1 -1
  423. package/dist/src/ui/components/ShellConfirmationDialog.test.js +2 -2
  424. package/dist/src/ui/components/ShellConfirmationDialog.test.js.map +1 -1
  425. package/dist/src/ui/components/StatsDisplay.test.d.ts +6 -0
  426. package/dist/src/ui/components/StatsDisplay.test.js +351 -0
  427. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -0
  428. package/dist/src/ui/components/SuggestionsDisplay.js +1 -1
  429. package/dist/src/ui/components/SuggestionsDisplay.js.map +1 -1
  430. package/dist/src/ui/components/ThemeDialog.d.ts +4 -2
  431. package/dist/src/ui/components/ThemeDialog.js +3 -3
  432. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  433. package/dist/src/ui/components/ThemeDialog.test.js +14 -1
  434. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  435. package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +6 -0
  436. package/dist/src/ui/components/ToolStatsDisplay.test.js +227 -0
  437. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -0
  438. package/dist/src/ui/components/messages/CompressionMessage.test.js +25 -17
  439. package/dist/src/ui/components/messages/CompressionMessage.test.js.map +1 -1
  440. package/dist/src/ui/components/messages/DiffRenderer.test.js +1 -1
  441. package/dist/src/ui/components/messages/DiffRenderer.test.js.map +1 -1
  442. package/dist/src/ui/components/messages/GeminiMessage.js +3 -1
  443. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  444. package/dist/src/ui/components/messages/GeminiMessage.test.d.ts +6 -0
  445. package/dist/src/ui/components/messages/GeminiMessage.test.js +35 -0
  446. package/dist/src/ui/components/messages/GeminiMessage.test.js.map +1 -0
  447. package/dist/src/ui/components/messages/GeminiMessageContent.js +3 -1
  448. package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
  449. package/dist/src/ui/components/messages/InfoMessage.js +1 -1
  450. package/dist/src/ui/components/messages/InfoMessage.js.map +1 -1
  451. package/dist/src/ui/components/messages/Todo.d.ts +7 -0
  452. package/dist/src/ui/components/messages/Todo.js +91 -0
  453. package/dist/src/ui/components/messages/Todo.js.map +1 -0
  454. package/dist/src/ui/components/messages/Todo.test.d.ts +6 -0
  455. package/dist/src/ui/components/messages/Todo.test.js +114 -0
  456. package/dist/src/ui/components/messages/Todo.test.js.map +1 -0
  457. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
  458. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  459. package/dist/src/ui/components/messages/ToolGroupMessage.js +1 -1
  460. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  461. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +29 -15
  462. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  463. package/dist/src/ui/components/messages/ToolMessage.js +8 -3
  464. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  465. package/dist/src/ui/components/messages/ToolMessage.test.js +2 -2
  466. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
  467. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.d.ts +6 -0
  468. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +30 -0
  469. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +1 -0
  470. package/dist/src/ui/components/messages/UserShellMessage.js +1 -1
  471. package/dist/src/ui/components/messages/UserShellMessage.js.map +1 -1
  472. package/dist/src/ui/components/messages/WarningMessage.js +2 -2
  473. package/dist/src/ui/components/messages/WarningMessage.js.map +1 -1
  474. package/dist/src/ui/components/shared/BaseSelectionList.test.js +34 -25
  475. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  476. package/dist/src/ui/components/shared/MaxSizedBox.test.js +43 -22
  477. package/dist/src/ui/components/shared/MaxSizedBox.test.js.map +1 -1
  478. package/dist/src/ui/components/shared/TextInput.d.ts +15 -0
  479. package/dist/src/ui/components/shared/TextInput.js +38 -0
  480. package/dist/src/ui/components/shared/TextInput.js.map +1 -0
  481. package/dist/src/ui/components/shared/TextInput.test.d.ts +6 -0
  482. package/dist/src/ui/components/shared/TextInput.test.js +242 -0
  483. package/dist/src/ui/components/shared/TextInput.test.js.map +1 -0
  484. package/dist/src/ui/components/shared/text-buffer.d.ts +9 -2
  485. package/dist/src/ui/components/shared/text-buffer.js +52 -14
  486. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  487. package/dist/src/ui/components/shared/text-buffer.test.d.ts +6 -0
  488. package/dist/src/ui/components/shared/text-buffer.test.js +1761 -0
  489. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -0
  490. package/dist/src/ui/components/shared/vim-buffer-actions.test.d.ts +6 -0
  491. package/dist/src/ui/components/shared/vim-buffer-actions.test.js +951 -0
  492. package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +1 -0
  493. package/dist/src/ui/components/views/ChatList.test.js +7 -4
  494. package/dist/src/ui/components/views/ChatList.test.js.map +1 -1
  495. package/dist/src/ui/components/views/ExtensionsList.d.ts +7 -1
  496. package/dist/src/ui/components/views/ExtensionsList.js +12 -15
  497. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  498. package/dist/src/ui/components/views/ExtensionsList.test.js +43 -29
  499. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
  500. package/dist/src/ui/components/views/McpStatus.d.ts +0 -1
  501. package/dist/src/ui/components/views/McpStatus.js +4 -4
  502. package/dist/src/ui/components/views/McpStatus.js.map +1 -1
  503. package/dist/src/ui/components/views/McpStatus.test.js +23 -17
  504. package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
  505. package/dist/src/ui/components/views/ToolsList.test.js +4 -4
  506. package/dist/src/ui/components/views/ToolsList.test.js.map +1 -1
  507. package/dist/src/ui/contexts/KeypressContext.d.ts +4 -2
  508. package/dist/src/ui/contexts/KeypressContext.js +635 -439
  509. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  510. package/dist/src/ui/contexts/KeypressContext.test.js +634 -515
  511. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  512. package/dist/src/ui/contexts/MouseContext.d.ts +21 -0
  513. package/dist/src/ui/contexts/MouseContext.js +89 -0
  514. package/dist/src/ui/contexts/MouseContext.js.map +1 -0
  515. package/dist/src/ui/contexts/MouseContext.test.d.ts +6 -0
  516. package/dist/src/ui/contexts/MouseContext.test.js +164 -0
  517. package/dist/src/ui/contexts/MouseContext.test.js.map +1 -0
  518. package/dist/src/ui/contexts/SessionContext.test.d.ts +6 -0
  519. package/dist/src/ui/contexts/SessionContext.test.js +195 -0
  520. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -0
  521. package/dist/src/ui/contexts/UIActionsContext.d.ts +7 -4
  522. package/dist/src/ui/contexts/UIStateContext.d.ts +5 -3
  523. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  524. package/dist/src/ui/hooks/atCommandProcessor.js +33 -11
  525. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  526. package/dist/src/ui/hooks/atCommandProcessor.test.js +163 -64
  527. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  528. package/dist/src/ui/hooks/shellCommandProcessor.js +0 -1
  529. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  530. package/dist/src/ui/hooks/shellCommandProcessor.test.js +64 -35
  531. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  532. package/dist/src/ui/hooks/slashCommandProcessor.js +2 -0
  533. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  534. package/dist/src/ui/hooks/slashCommandProcessor.test.d.ts +6 -0
  535. package/dist/src/ui/hooks/slashCommandProcessor.test.js +807 -0
  536. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -0
  537. package/dist/src/ui/hooks/useAtCompletion.js +2 -2
  538. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  539. package/dist/src/ui/hooks/useAtCompletion.test.d.ts +6 -0
  540. package/dist/src/ui/hooks/useAtCompletion.test.js +396 -0
  541. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -0
  542. package/dist/src/ui/hooks/useAutoAcceptIndicator.js +10 -0
  543. package/dist/src/ui/hooks/useAutoAcceptIndicator.js.map +1 -1
  544. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +32 -2
  545. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  546. package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -1
  547. package/dist/src/ui/hooks/useCommandCompletion.js +5 -3
  548. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  549. package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +6 -0
  550. package/dist/src/ui/hooks/useCommandCompletion.test.js +377 -0
  551. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -0
  552. package/dist/src/ui/hooks/useConsoleMessages.test.d.ts +6 -0
  553. package/dist/src/ui/hooks/useConsoleMessages.test.js +127 -0
  554. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -0
  555. package/dist/src/ui/hooks/useEditorSettings.test.js +40 -34
  556. package/dist/src/ui/hooks/useEditorSettings.test.js.map +1 -1
  557. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +14 -4
  558. package/dist/src/ui/hooks/useExtensionUpdates.js +18 -11
  559. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  560. package/dist/src/ui/hooks/useExtensionUpdates.test.js +52 -35
  561. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  562. package/dist/src/ui/hooks/useFlickerDetector.test.js +9 -5
  563. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -1
  564. package/dist/src/ui/hooks/useFocus.test.d.ts +6 -0
  565. package/dist/src/ui/hooks/useFocus.test.js +131 -0
  566. package/dist/src/ui/hooks/useFocus.test.js.map +1 -0
  567. package/dist/src/ui/hooks/useFolderTrust.test.d.ts +6 -0
  568. package/dist/src/ui/hooks/useFolderTrust.test.js +188 -0
  569. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -0
  570. package/dist/src/ui/hooks/useGeminiStream.js +119 -74
  571. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  572. package/dist/src/ui/hooks/useGeminiStream.test.d.ts +6 -0
  573. package/dist/src/ui/hooks/useGeminiStream.test.js +1820 -0
  574. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -0
  575. package/dist/src/ui/hooks/useGitBranchName.js +4 -0
  576. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  577. package/dist/src/ui/hooks/useGitBranchName.test.js +46 -34
  578. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  579. package/dist/src/ui/hooks/useHistoryManager.test.js +2 -1
  580. package/dist/src/ui/hooks/useHistoryManager.test.js.map +1 -1
  581. package/dist/src/ui/hooks/useIdeTrustListener.test.js +40 -9
  582. package/dist/src/ui/hooks/useIdeTrustListener.test.js.map +1 -1
  583. package/dist/src/ui/hooks/useInputHistory.test.js +2 -1
  584. package/dist/src/ui/hooks/useInputHistory.test.js.map +1 -1
  585. package/dist/src/ui/hooks/useInputHistoryStore.js +2 -1
  586. package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -1
  587. package/dist/src/ui/hooks/useInputHistoryStore.test.js +2 -1
  588. package/dist/src/ui/hooks/useInputHistoryStore.test.js.map +1 -1
  589. package/dist/src/ui/hooks/useKeypress.test.d.ts +6 -0
  590. package/dist/src/ui/hooks/useKeypress.test.js +223 -0
  591. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
  592. package/dist/src/ui/hooks/useLoadingIndicator.test.js +29 -6
  593. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  594. package/dist/src/ui/hooks/useMemoryMonitor.test.js +10 -5
  595. package/dist/src/ui/hooks/useMemoryMonitor.test.js.map +1 -1
  596. package/dist/src/ui/hooks/useMessageQueue.d.ts +1 -0
  597. package/dist/src/ui/hooks/useMessageQueue.js +14 -0
  598. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -1
  599. package/dist/src/ui/hooks/useMessageQueue.test.js +173 -35
  600. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  601. package/dist/src/ui/hooks/useModelCommand.test.js +21 -11
  602. package/dist/src/ui/hooks/useModelCommand.test.js.map +1 -1
  603. package/dist/src/ui/hooks/useMouse.d.ts +17 -0
  604. package/dist/src/ui/hooks/useMouse.js +27 -0
  605. package/dist/src/ui/hooks/useMouse.js.map +1 -0
  606. package/dist/src/ui/hooks/useMouse.test.d.ts +6 -0
  607. package/dist/src/ui/hooks/useMouse.test.js +57 -0
  608. package/dist/src/ui/hooks/useMouse.test.js.map +1 -0
  609. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js +2 -2
  610. package/dist/src/ui/hooks/usePermissionsModifyTrust.test.js.map +1 -1
  611. package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -0
  612. package/dist/src/ui/hooks/usePhraseCycler.js +156 -5
  613. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  614. package/dist/src/ui/hooks/usePhraseCycler.test.d.ts +6 -0
  615. package/dist/src/ui/hooks/usePhraseCycler.test.js +158 -0
  616. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -0
  617. package/dist/src/ui/hooks/usePrivacySettings.test.js +26 -6
  618. package/dist/src/ui/hooks/usePrivacySettings.test.js.map +1 -1
  619. package/dist/src/ui/hooks/usePromptCompletion.js +2 -2
  620. package/dist/src/ui/hooks/usePromptCompletion.js.map +1 -1
  621. package/dist/src/ui/hooks/useQuotaAndFallback.js +13 -14
  622. package/dist/src/ui/hooks/useQuotaAndFallback.js.map +1 -1
  623. package/dist/src/ui/hooks/useQuotaAndFallback.test.js +55 -48
  624. package/dist/src/ui/hooks/useQuotaAndFallback.test.js.map +1 -1
  625. package/dist/src/ui/hooks/useReactToolScheduler.d.ts +8 -1
  626. package/dist/src/ui/hooks/useReactToolScheduler.js +61 -36
  627. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  628. package/dist/src/ui/hooks/useReactToolScheduler.test.d.ts +6 -0
  629. package/dist/src/ui/hooks/useReactToolScheduler.test.js +65 -0
  630. package/dist/src/ui/hooks/useReactToolScheduler.test.js.map +1 -0
  631. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js +2 -2
  632. package/dist/src/ui/hooks/useReverseSearchCompletion.test.js.map +1 -1
  633. package/dist/src/ui/hooks/useSelectionList.js +5 -4
  634. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  635. package/dist/src/ui/hooks/useSelectionList.test.js +272 -183
  636. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  637. package/dist/src/ui/hooks/useShellHistory.test.js +52 -20
  638. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  639. package/dist/src/ui/hooks/useShowMemoryCommand.d.ts +1 -1
  640. package/dist/src/ui/hooks/useShowMemoryCommand.js +4 -3
  641. package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
  642. package/dist/src/ui/hooks/useSlashCompletion.js +20 -8
  643. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  644. package/dist/src/ui/hooks/useSlashCompletion.test.js +275 -137
  645. package/dist/src/ui/hooks/useSlashCompletion.test.js.map +1 -1
  646. package/dist/src/ui/hooks/useThemeCommand.d.ts +2 -1
  647. package/dist/src/ui/hooks/useThemeCommand.js +6 -0
  648. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  649. package/dist/src/ui/hooks/useTimer.test.js +43 -14
  650. package/dist/src/ui/hooks/useTimer.test.js.map +1 -1
  651. package/dist/src/ui/hooks/useToolScheduler.test.js +229 -242
  652. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  653. package/dist/src/ui/hooks/vim.js +2 -1
  654. package/dist/src/ui/hooks/vim.js.map +1 -1
  655. package/dist/src/ui/hooks/vim.test.d.ts +6 -0
  656. package/dist/src/ui/hooks/vim.test.js +1269 -0
  657. package/dist/src/ui/hooks/vim.test.js.map +1 -0
  658. package/dist/src/ui/keyMatchers.test.js +39 -6
  659. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  660. package/dist/src/ui/state/extensions.d.ts +1 -0
  661. package/dist/src/ui/state/extensions.js +1 -0
  662. package/dist/src/ui/state/extensions.js.map +1 -1
  663. package/dist/src/ui/themes/ansi-light.js +1 -0
  664. package/dist/src/ui/themes/ansi-light.js.map +1 -1
  665. package/dist/src/ui/themes/ansi.js +1 -0
  666. package/dist/src/ui/themes/ansi.js.map +1 -1
  667. package/dist/src/ui/themes/atom-one-dark.js +2 -0
  668. package/dist/src/ui/themes/atom-one-dark.js.map +1 -1
  669. package/dist/src/ui/themes/ayu-light.js +2 -0
  670. package/dist/src/ui/themes/ayu-light.js.map +1 -1
  671. package/dist/src/ui/themes/ayu.js +2 -0
  672. package/dist/src/ui/themes/ayu.js.map +1 -1
  673. package/dist/src/ui/themes/color-utils.d.ts +1 -0
  674. package/dist/src/ui/themes/color-utils.js +8 -1
  675. package/dist/src/ui/themes/color-utils.js.map +1 -1
  676. package/dist/src/ui/themes/color-utils.test.js +13 -1
  677. package/dist/src/ui/themes/color-utils.test.js.map +1 -1
  678. package/dist/src/ui/themes/dracula.js +2 -0
  679. package/dist/src/ui/themes/dracula.js.map +1 -1
  680. package/dist/src/ui/themes/github-dark.js +2 -0
  681. package/dist/src/ui/themes/github-dark.js.map +1 -1
  682. package/dist/src/ui/themes/github-light.js +2 -0
  683. package/dist/src/ui/themes/github-light.js.map +1 -1
  684. package/dist/src/ui/themes/googlecode.js +2 -0
  685. package/dist/src/ui/themes/googlecode.js.map +1 -1
  686. package/dist/src/ui/themes/no-color.js +3 -0
  687. package/dist/src/ui/themes/no-color.js.map +1 -1
  688. package/dist/src/ui/themes/semantic-tokens.d.ts +2 -0
  689. package/dist/src/ui/themes/semantic-tokens.js +6 -0
  690. package/dist/src/ui/themes/semantic-tokens.js.map +1 -1
  691. package/dist/src/ui/themes/shades-of-purple.js +2 -0
  692. package/dist/src/ui/themes/shades-of-purple.js.map +1 -1
  693. package/dist/src/ui/themes/theme-manager.js +8 -7
  694. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  695. package/dist/src/ui/themes/theme.d.ts +3 -0
  696. package/dist/src/ui/themes/theme.js +14 -3
  697. package/dist/src/ui/themes/theme.js.map +1 -1
  698. package/dist/src/ui/themes/theme.test.d.ts +6 -0
  699. package/dist/src/ui/themes/theme.test.js +151 -0
  700. package/dist/src/ui/themes/theme.test.js.map +1 -0
  701. package/dist/src/ui/themes/xcode.js +2 -0
  702. package/dist/src/ui/themes/xcode.js.map +1 -1
  703. package/dist/src/ui/types.d.ts +3 -2
  704. package/dist/src/ui/types.js +2 -0
  705. package/dist/src/ui/types.js.map +1 -1
  706. package/dist/src/ui/utils/CodeColorizer.d.ts +1 -1
  707. package/dist/src/ui/utils/CodeColorizer.js +6 -3
  708. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  709. package/dist/src/ui/utils/InlineMarkdownRenderer.d.ts +1 -0
  710. package/dist/src/ui/utils/InlineMarkdownRenderer.js +11 -10
  711. package/dist/src/ui/utils/InlineMarkdownRenderer.js.map +1 -1
  712. package/dist/src/ui/utils/MarkdownDisplay.d.ts +1 -0
  713. package/dist/src/ui/utils/MarkdownDisplay.js +19 -10
  714. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  715. package/dist/src/ui/utils/clipboardUtils.js +2 -2
  716. package/dist/src/ui/utils/clipboardUtils.js.map +1 -1
  717. package/dist/src/ui/utils/commandUtils.js +20 -3
  718. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  719. package/dist/src/ui/utils/commandUtils.test.js +61 -6
  720. package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
  721. package/dist/src/ui/utils/computeStats.js +5 -2
  722. package/dist/src/ui/utils/computeStats.js.map +1 -1
  723. package/dist/src/ui/utils/computeStats.test.d.ts +6 -0
  724. package/dist/src/ui/utils/computeStats.test.js +262 -0
  725. package/dist/src/ui/utils/computeStats.test.js.map +1 -0
  726. package/dist/src/ui/utils/input.d.ts +17 -0
  727. package/dist/src/ui/utils/input.js +51 -0
  728. package/dist/src/ui/utils/input.js.map +1 -0
  729. package/dist/src/ui/utils/input.test.d.ts +6 -0
  730. package/dist/src/ui/utils/input.test.js +44 -0
  731. package/dist/src/ui/utils/input.test.js.map +1 -0
  732. package/dist/src/ui/utils/kittyProtocolDetector.js +13 -4
  733. package/dist/src/ui/utils/kittyProtocolDetector.js.map +1 -1
  734. package/dist/src/ui/utils/mouse.d.ts +31 -0
  735. package/dist/src/ui/utils/mouse.js +164 -0
  736. package/dist/src/ui/utils/mouse.js.map +1 -0
  737. package/dist/src/ui/utils/mouse.test.d.ts +6 -0
  738. package/dist/src/ui/utils/mouse.test.js +131 -0
  739. package/dist/src/ui/utils/mouse.test.js.map +1 -0
  740. package/dist/src/ui/utils/terminalSetup.js +3 -2
  741. package/dist/src/ui/utils/terminalSetup.js.map +1 -1
  742. package/dist/src/ui/utils/textOutput.d.ts +25 -0
  743. package/dist/src/ui/utils/textOutput.js +49 -0
  744. package/dist/src/ui/utils/textOutput.js.map +1 -0
  745. package/dist/src/ui/utils/textOutput.test.d.ts +6 -0
  746. package/dist/src/ui/utils/textOutput.test.js +79 -0
  747. package/dist/src/ui/utils/textOutput.test.js.map +1 -0
  748. package/dist/src/ui/utils/updateCheck.d.ts +9 -2
  749. package/dist/src/ui/utils/updateCheck.js +38 -30
  750. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  751. package/dist/src/ui/utils/updateCheck.test.js +48 -59
  752. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  753. package/dist/src/utils/cleanup.test.d.ts +6 -0
  754. package/dist/src/utils/cleanup.test.js +49 -0
  755. package/dist/src/utils/cleanup.test.js.map +1 -0
  756. package/dist/src/utils/commentJson.js +2 -2
  757. package/dist/src/utils/commentJson.js.map +1 -1
  758. package/dist/src/utils/commentJson.test.js +7 -6
  759. package/dist/src/utils/commentJson.test.js.map +1 -1
  760. package/dist/src/utils/envVarResolver.d.ts +2 -2
  761. package/dist/src/utils/envVarResolver.js +10 -7
  762. package/dist/src/utils/envVarResolver.js.map +1 -1
  763. package/dist/src/utils/errors.d.ts +1 -0
  764. package/dist/src/utils/errors.js +66 -5
  765. package/dist/src/utils/errors.js.map +1 -1
  766. package/dist/src/utils/events.d.ts +11 -2
  767. package/dist/src/utils/events.js +1 -0
  768. package/dist/src/utils/events.js.map +1 -1
  769. package/dist/src/utils/gitUtils.js +3 -2
  770. package/dist/src/utils/gitUtils.js.map +1 -1
  771. package/dist/src/utils/handleAutoUpdate.js +9 -3
  772. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  773. package/dist/src/utils/handleAutoUpdate.test.d.ts +6 -0
  774. package/dist/src/utils/handleAutoUpdate.test.js +225 -0
  775. package/dist/src/utils/handleAutoUpdate.test.js.map +1 -0
  776. package/dist/src/utils/installationInfo.js +2 -2
  777. package/dist/src/utils/installationInfo.js.map +1 -1
  778. package/dist/src/utils/installationInfo.test.js +8 -4
  779. package/dist/src/utils/installationInfo.test.js.map +1 -1
  780. package/dist/src/utils/readStdin.js +2 -1
  781. package/dist/src/utils/readStdin.js.map +1 -1
  782. package/dist/src/utils/sandbox-macos-permissive-open.sb +2 -0
  783. package/dist/src/utils/sandbox.js +28 -30
  784. package/dist/src/utils/sandbox.js.map +1 -1
  785. package/dist/src/utils/sessionCleanup.js +4 -4
  786. package/dist/src/utils/sessionCleanup.js.map +1 -1
  787. package/dist/src/utils/startupWarnings.test.d.ts +6 -0
  788. package/dist/src/utils/startupWarnings.test.js +61 -0
  789. package/dist/src/utils/startupWarnings.test.js.map +1 -0
  790. package/dist/src/utils/version.js +6 -2
  791. package/dist/src/utils/version.js.map +1 -1
  792. package/dist/src/validateNonInterActiveAuth.js +2 -2
  793. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  794. package/dist/src/zed-integration/acp.js +2 -1
  795. package/dist/src/zed-integration/acp.js.map +1 -1
  796. package/dist/src/zed-integration/schema.d.ts +4 -4
  797. package/dist/src/zed-integration/zedIntegration.d.ts +2 -2
  798. package/dist/src/zed-integration/zedIntegration.js +16 -25
  799. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  800. package/dist/tsconfig.tsbuildinfo +1 -1
  801. package/package.json +17 -17
  802. package/dist/src/config/policy.test.js +0 -336
  803. package/dist/src/config/policy.test.js.map +0 -1
  804. package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +0 -11
  805. package/dist/src/ui/components/WorkspaceMigrationDialog.js +0 -44
  806. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +0 -1
  807. package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +0 -13
  808. package/dist/src/ui/hooks/useWorkspaceMigration.js +0 -59
  809. package/dist/src/ui/hooks/useWorkspaceMigration.js.map +0 -1
  810. package/dist/src/utils/package.d.ts +0 -12
  811. package/dist/src/utils/package.js +0 -24
  812. package/dist/src/utils/package.js.map +0 -1
  813. /package/dist/src/{config/policy.test.d.ts → commands/extensions/examples/mcp-server/example.d.ts} +0 -0
@@ -0,0 +1,984 @@
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, CoreEvent, } from '@google/gemini-cli-core';
7
+ import { runNonInteractive } from './nonInteractiveCli.js';
8
+ import { describe, it, expect, beforeEach, afterEach, vi, } from 'vitest';
9
+ // Mock core modules
10
+ vi.mock('./ui/hooks/atCommandProcessor.js');
11
+ const mockCoreEvents = vi.hoisted(() => ({
12
+ on: vi.fn(),
13
+ off: vi.fn(),
14
+ drainFeedbackBacklog: vi.fn(),
15
+ emit: vi.fn(),
16
+ }));
17
+ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
18
+ const original = await importOriginal();
19
+ class MockChatRecordingService {
20
+ initialize = vi.fn();
21
+ recordMessage = vi.fn();
22
+ recordMessageTokens = vi.fn();
23
+ recordToolCalls = vi.fn();
24
+ }
25
+ return {
26
+ ...original,
27
+ executeToolCall: vi.fn(),
28
+ shutdownTelemetry: vi.fn(),
29
+ isTelemetrySdkInitialized: vi.fn().mockReturnValue(true),
30
+ ChatRecordingService: MockChatRecordingService,
31
+ uiTelemetryService: {
32
+ getMetrics: vi.fn(),
33
+ },
34
+ coreEvents: mockCoreEvents,
35
+ };
36
+ });
37
+ const mockGetCommands = vi.hoisted(() => vi.fn());
38
+ const mockCommandServiceCreate = vi.hoisted(() => vi.fn());
39
+ vi.mock('./services/CommandService.js', () => ({
40
+ CommandService: {
41
+ create: mockCommandServiceCreate,
42
+ },
43
+ }));
44
+ vi.mock('./services/FileCommandLoader.js');
45
+ vi.mock('./services/McpPromptLoader.js');
46
+ describe('runNonInteractive', () => {
47
+ let mockConfig;
48
+ let mockSettings;
49
+ let mockToolRegistry;
50
+ let mockCoreExecuteToolCall;
51
+ let mockShutdownTelemetry;
52
+ let consoleErrorSpy;
53
+ let processStdoutSpy;
54
+ let processStderrSpy;
55
+ let mockGeminiClient;
56
+ const MOCK_SESSION_METRICS = {
57
+ models: {},
58
+ tools: {
59
+ totalCalls: 0,
60
+ totalSuccess: 0,
61
+ totalFail: 0,
62
+ totalDurationMs: 0,
63
+ totalDecisions: {
64
+ accept: 0,
65
+ reject: 0,
66
+ modify: 0,
67
+ auto_accept: 0,
68
+ },
69
+ byName: {},
70
+ },
71
+ files: {
72
+ totalLinesAdded: 0,
73
+ totalLinesRemoved: 0,
74
+ },
75
+ };
76
+ beforeEach(async () => {
77
+ mockCoreExecuteToolCall = vi.mocked(executeToolCall);
78
+ mockShutdownTelemetry = vi.mocked(shutdownTelemetry);
79
+ mockCommandServiceCreate.mockResolvedValue({
80
+ getCommands: mockGetCommands,
81
+ });
82
+ consoleErrorSpy = vi.spyOn(console, 'error').mockImplementation(() => { });
83
+ processStdoutSpy = vi
84
+ .spyOn(process.stdout, 'write')
85
+ .mockImplementation(() => true);
86
+ processStderrSpy = vi
87
+ .spyOn(process.stderr, 'write')
88
+ .mockImplementation(() => true);
89
+ vi.spyOn(process, 'exit').mockImplementation((code) => {
90
+ throw new Error(`process.exit(${code}) called`);
91
+ });
92
+ mockToolRegistry = {
93
+ getTool: vi.fn(),
94
+ getFunctionDeclarations: vi.fn().mockReturnValue([]),
95
+ };
96
+ mockGeminiClient = {
97
+ sendMessageStream: vi.fn(),
98
+ getChatRecordingService: vi.fn(() => ({
99
+ initialize: vi.fn(),
100
+ recordMessage: vi.fn(),
101
+ recordMessageTokens: vi.fn(),
102
+ recordToolCalls: vi.fn(),
103
+ })),
104
+ };
105
+ mockConfig = {
106
+ initialize: vi.fn().mockResolvedValue(undefined),
107
+ getGeminiClient: vi.fn().mockReturnValue(mockGeminiClient),
108
+ getToolRegistry: vi.fn().mockReturnValue(mockToolRegistry),
109
+ getMaxSessionTurns: vi.fn().mockReturnValue(10),
110
+ getSessionId: vi.fn().mockReturnValue('test-session-id'),
111
+ getProjectRoot: vi.fn().mockReturnValue('/test/project'),
112
+ storage: {
113
+ getProjectTempDir: vi
114
+ .fn()
115
+ .mockReturnValue('/test/project/.cell-cli/tmp'),
116
+ },
117
+ getIdeMode: vi.fn().mockReturnValue(false),
118
+ getContentGeneratorConfig: vi.fn().mockReturnValue({}),
119
+ getDebugMode: vi.fn().mockReturnValue(false),
120
+ getOutputFormat: vi.fn().mockReturnValue('text'),
121
+ getFolderTrust: vi.fn().mockReturnValue(false),
122
+ isTrustedFolder: vi.fn().mockReturnValue(false),
123
+ };
124
+ mockSettings = {
125
+ system: { path: '', settings: {} },
126
+ systemDefaults: { path: '', settings: {} },
127
+ user: { path: '', settings: {} },
128
+ workspace: { path: '', settings: {} },
129
+ errors: [],
130
+ setValue: vi.fn(),
131
+ merged: {
132
+ security: {
133
+ auth: {
134
+ enforcedType: undefined,
135
+ },
136
+ },
137
+ },
138
+ isTrusted: true,
139
+ migratedInMemorScopes: new Set(),
140
+ forScope: vi.fn(),
141
+ computeMergedSettings: vi.fn(),
142
+ };
143
+ const { handleAtCommand } = await import('./ui/hooks/atCommandProcessor.js');
144
+ vi.mocked(handleAtCommand).mockImplementation(async ({ query }) => ({
145
+ processedQuery: [{ text: query }],
146
+ shouldProceed: true,
147
+ }));
148
+ });
149
+ afterEach(() => {
150
+ vi.restoreAllMocks();
151
+ });
152
+ async function* createStreamFromEvents(events) {
153
+ for (const event of events) {
154
+ yield event;
155
+ }
156
+ }
157
+ const getWrittenOutput = () => processStdoutSpy.mock.calls.map((c) => c[0]).join('');
158
+ it('should process input and write text output', async () => {
159
+ const events = [
160
+ { type: GeminiEventType.Content, value: 'Hello' },
161
+ { type: GeminiEventType.Content, value: ' World' },
162
+ {
163
+ type: GeminiEventType.Finished,
164
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
165
+ },
166
+ ];
167
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
168
+ await runNonInteractive({
169
+ config: mockConfig,
170
+ settings: mockSettings,
171
+ input: 'Test input',
172
+ prompt_id: 'prompt-id-1',
173
+ });
174
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Test input' }], expect.any(AbortSignal), 'prompt-id-1');
175
+ expect(getWrittenOutput()).toBe('Hello World\n');
176
+ expect(mockShutdownTelemetry).toHaveBeenCalled();
177
+ });
178
+ it('should handle a single tool call and respond', async () => {
179
+ const toolCallEvent = {
180
+ type: GeminiEventType.ToolCallRequest,
181
+ value: {
182
+ callId: 'tool-1',
183
+ name: 'testTool',
184
+ args: { arg1: 'value1' },
185
+ isClientInitiated: false,
186
+ prompt_id: 'prompt-id-2',
187
+ },
188
+ };
189
+ const toolResponse = [{ text: 'Tool response' }];
190
+ mockCoreExecuteToolCall.mockResolvedValue({
191
+ status: 'success',
192
+ request: {
193
+ callId: 'tool-1',
194
+ name: 'testTool',
195
+ args: { arg1: 'value1' },
196
+ isClientInitiated: false,
197
+ prompt_id: 'prompt-id-2',
198
+ },
199
+ tool: {},
200
+ invocation: {},
201
+ response: {
202
+ responseParts: toolResponse,
203
+ callId: 'tool-1',
204
+ error: undefined,
205
+ errorType: undefined,
206
+ contentLength: undefined,
207
+ },
208
+ });
209
+ const firstCallEvents = [toolCallEvent];
210
+ const secondCallEvents = [
211
+ { type: GeminiEventType.Content, value: 'Final answer' },
212
+ {
213
+ type: GeminiEventType.Finished,
214
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
215
+ },
216
+ ];
217
+ mockGeminiClient.sendMessageStream
218
+ .mockReturnValueOnce(createStreamFromEvents(firstCallEvents))
219
+ .mockReturnValueOnce(createStreamFromEvents(secondCallEvents));
220
+ await runNonInteractive({
221
+ config: mockConfig,
222
+ settings: mockSettings,
223
+ input: 'Use a tool',
224
+ prompt_id: 'prompt-id-2',
225
+ });
226
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
227
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledWith(mockConfig, expect.objectContaining({ name: 'testTool' }), expect.any(AbortSignal));
228
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenNthCalledWith(2, [{ text: 'Tool response' }], expect.any(AbortSignal), 'prompt-id-2');
229
+ expect(getWrittenOutput()).toBe('Final answer\n');
230
+ });
231
+ it('should write a single newline between sequential text outputs from the model', async () => {
232
+ // This test simulates a multi-turn conversation to ensure that a single newline
233
+ // is printed between each block of text output from the model.
234
+ // 1. Define the tool requests that the model will ask the CLI to run.
235
+ const toolCallEvent = {
236
+ type: GeminiEventType.ToolCallRequest,
237
+ value: {
238
+ callId: 'mock-tool',
239
+ name: 'mockTool',
240
+ args: {},
241
+ isClientInitiated: false,
242
+ prompt_id: 'prompt-id-multi',
243
+ },
244
+ };
245
+ // 2. Mock the execution of the tools. We just need them to succeed.
246
+ mockCoreExecuteToolCall.mockResolvedValue({
247
+ status: 'success',
248
+ request: toolCallEvent.value, // This is generic enough for both calls
249
+ tool: {},
250
+ invocation: {},
251
+ response: {
252
+ responseParts: [],
253
+ callId: 'mock-tool',
254
+ },
255
+ });
256
+ // 3. Define the sequence of events streamed from the mock model.
257
+ // Turn 1: Model outputs text, then requests a tool call.
258
+ const modelTurn1 = [
259
+ { type: GeminiEventType.Content, value: 'Use mock tool' },
260
+ toolCallEvent,
261
+ ];
262
+ // Turn 2: Model outputs more text, then requests another tool call.
263
+ const modelTurn2 = [
264
+ { type: GeminiEventType.Content, value: 'Use mock tool again' },
265
+ toolCallEvent,
266
+ ];
267
+ // Turn 3: Model outputs a final answer.
268
+ const modelTurn3 = [
269
+ { type: GeminiEventType.Content, value: 'Finished.' },
270
+ {
271
+ type: GeminiEventType.Finished,
272
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
273
+ },
274
+ ];
275
+ mockGeminiClient.sendMessageStream
276
+ .mockReturnValueOnce(createStreamFromEvents(modelTurn1))
277
+ .mockReturnValueOnce(createStreamFromEvents(modelTurn2))
278
+ .mockReturnValueOnce(createStreamFromEvents(modelTurn3));
279
+ // 4. Run the command.
280
+ await runNonInteractive({
281
+ config: mockConfig,
282
+ settings: mockSettings,
283
+ input: 'Use mock tool multiple times',
284
+ prompt_id: 'prompt-id-multi',
285
+ });
286
+ // 5. Verify the output.
287
+ // The rendered output should contain the text from each turn, separated by a
288
+ // single newline, with a final newline at the end.
289
+ expect(getWrittenOutput()).toMatchSnapshot();
290
+ // Also verify the tools were called as expected.
291
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledTimes(2);
292
+ });
293
+ it('should handle error during tool execution and should send error back to the model', async () => {
294
+ const toolCallEvent = {
295
+ type: GeminiEventType.ToolCallRequest,
296
+ value: {
297
+ callId: 'tool-1',
298
+ name: 'errorTool',
299
+ args: {},
300
+ isClientInitiated: false,
301
+ prompt_id: 'prompt-id-3',
302
+ },
303
+ };
304
+ mockCoreExecuteToolCall.mockResolvedValue({
305
+ status: 'error',
306
+ request: {
307
+ callId: 'tool-1',
308
+ name: 'errorTool',
309
+ args: {},
310
+ isClientInitiated: false,
311
+ prompt_id: 'prompt-id-3',
312
+ },
313
+ tool: {},
314
+ response: {
315
+ callId: 'tool-1',
316
+ error: new Error('Execution failed'),
317
+ errorType: ToolErrorType.EXECUTION_FAILED,
318
+ responseParts: [
319
+ {
320
+ functionResponse: {
321
+ name: 'errorTool',
322
+ response: {
323
+ output: 'Error: Execution failed',
324
+ },
325
+ },
326
+ },
327
+ ],
328
+ resultDisplay: 'Execution failed',
329
+ contentLength: undefined,
330
+ },
331
+ });
332
+ const finalResponse = [
333
+ {
334
+ type: GeminiEventType.Content,
335
+ value: 'Sorry, let me try again.',
336
+ },
337
+ {
338
+ type: GeminiEventType.Finished,
339
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
340
+ },
341
+ ];
342
+ mockGeminiClient.sendMessageStream
343
+ .mockReturnValueOnce(createStreamFromEvents([toolCallEvent]))
344
+ .mockReturnValueOnce(createStreamFromEvents(finalResponse));
345
+ await runNonInteractive({
346
+ config: mockConfig,
347
+ settings: mockSettings,
348
+ input: 'Trigger tool error',
349
+ prompt_id: 'prompt-id-3',
350
+ });
351
+ expect(mockCoreExecuteToolCall).toHaveBeenCalled();
352
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error executing tool errorTool: Execution failed');
353
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
354
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenNthCalledWith(2, [
355
+ {
356
+ functionResponse: {
357
+ name: 'errorTool',
358
+ response: {
359
+ output: 'Error: Execution failed',
360
+ },
361
+ },
362
+ },
363
+ ], expect.any(AbortSignal), 'prompt-id-3');
364
+ expect(getWrittenOutput()).toBe('Sorry, let me try again.\n');
365
+ });
366
+ it('should exit with error if sendMessageStream throws initially', async () => {
367
+ const apiError = new Error('API connection failed');
368
+ mockGeminiClient.sendMessageStream.mockImplementation(() => {
369
+ throw apiError;
370
+ });
371
+ await expect(runNonInteractive({
372
+ config: mockConfig,
373
+ settings: mockSettings,
374
+ input: 'Initial fail',
375
+ prompt_id: 'prompt-id-4',
376
+ })).rejects.toThrow(apiError);
377
+ });
378
+ it('should not exit if a tool is not found, and should send error back to model', async () => {
379
+ const toolCallEvent = {
380
+ type: GeminiEventType.ToolCallRequest,
381
+ value: {
382
+ callId: 'tool-1',
383
+ name: 'nonexistentTool',
384
+ args: {},
385
+ isClientInitiated: false,
386
+ prompt_id: 'prompt-id-5',
387
+ },
388
+ };
389
+ mockCoreExecuteToolCall.mockResolvedValue({
390
+ status: 'error',
391
+ request: {
392
+ callId: 'tool-1',
393
+ name: 'nonexistentTool',
394
+ args: {},
395
+ isClientInitiated: false,
396
+ prompt_id: 'prompt-id-5',
397
+ },
398
+ response: {
399
+ callId: 'tool-1',
400
+ error: new Error('Tool "nonexistentTool" not found in registry.'),
401
+ resultDisplay: 'Tool "nonexistentTool" not found in registry.',
402
+ responseParts: [],
403
+ errorType: undefined,
404
+ contentLength: undefined,
405
+ },
406
+ });
407
+ const finalResponse = [
408
+ {
409
+ type: GeminiEventType.Content,
410
+ value: "Sorry, I can't find that tool.",
411
+ },
412
+ {
413
+ type: GeminiEventType.Finished,
414
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
415
+ },
416
+ ];
417
+ mockGeminiClient.sendMessageStream
418
+ .mockReturnValueOnce(createStreamFromEvents([toolCallEvent]))
419
+ .mockReturnValueOnce(createStreamFromEvents(finalResponse));
420
+ await runNonInteractive({
421
+ config: mockConfig,
422
+ settings: mockSettings,
423
+ input: 'Trigger tool not found',
424
+ prompt_id: 'prompt-id-5',
425
+ });
426
+ expect(mockCoreExecuteToolCall).toHaveBeenCalled();
427
+ expect(consoleErrorSpy).toHaveBeenCalledWith('Error executing tool nonexistentTool: Tool "nonexistentTool" not found in registry.');
428
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
429
+ expect(getWrittenOutput()).toBe("Sorry, I can't find that tool.\n");
430
+ });
431
+ it('should exit when max session turns are exceeded', async () => {
432
+ vi.mocked(mockConfig.getMaxSessionTurns).mockReturnValue(0);
433
+ await expect(runNonInteractive({
434
+ config: mockConfig,
435
+ settings: mockSettings,
436
+ input: 'Trigger loop',
437
+ prompt_id: 'prompt-id-6',
438
+ })).rejects.toThrow('process.exit(53) called');
439
+ });
440
+ it('should preprocess @include commands before sending to the model', async () => {
441
+ // 1. Mock the imported atCommandProcessor
442
+ const { handleAtCommand } = await import('./ui/hooks/atCommandProcessor.js');
443
+ const mockHandleAtCommand = vi.mocked(handleAtCommand);
444
+ // 2. Define the raw input and the expected processed output
445
+ const rawInput = 'Summarize @file.txt';
446
+ const processedParts = [
447
+ { text: 'Summarize @file.txt' },
448
+ { text: '\n--- Content from referenced files ---\n' },
449
+ { text: 'This is the content of the file.' },
450
+ { text: '\n--- End of content ---' },
451
+ ];
452
+ // 3. Setup the mock to return the processed parts
453
+ mockHandleAtCommand.mockResolvedValue({
454
+ processedQuery: processedParts,
455
+ shouldProceed: true,
456
+ });
457
+ // Mock a simple stream response from the Gemini client
458
+ const events = [
459
+ { type: GeminiEventType.Content, value: 'Summary complete.' },
460
+ {
461
+ type: GeminiEventType.Finished,
462
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
463
+ },
464
+ ];
465
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
466
+ // 4. Run the non-interactive mode with the raw input
467
+ await runNonInteractive({
468
+ config: mockConfig,
469
+ settings: mockSettings,
470
+ input: rawInput,
471
+ prompt_id: 'prompt-id-7',
472
+ });
473
+ // 5. Assert that sendMessageStream was called with the PROCESSED parts, not the raw input
474
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith(processedParts, expect.any(AbortSignal), 'prompt-id-7');
475
+ // 6. Assert the final output is correct
476
+ expect(getWrittenOutput()).toBe('Summary complete.\n');
477
+ });
478
+ it('should process input and write JSON output with stats', async () => {
479
+ const events = [
480
+ { type: GeminiEventType.Content, value: 'Hello World' },
481
+ {
482
+ type: GeminiEventType.Finished,
483
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
484
+ },
485
+ ];
486
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
487
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
488
+ vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(MOCK_SESSION_METRICS);
489
+ await runNonInteractive({
490
+ config: mockConfig,
491
+ settings: mockSettings,
492
+ input: 'Test input',
493
+ prompt_id: 'prompt-id-1',
494
+ });
495
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Test input' }], expect.any(AbortSignal), 'prompt-id-1');
496
+ expect(processStdoutSpy).toHaveBeenCalledWith(JSON.stringify({ response: 'Hello World', stats: MOCK_SESSION_METRICS }, null, 2));
497
+ });
498
+ it('should write JSON output with stats for tool-only commands (no text response)', async () => {
499
+ // Test the scenario where a command completes successfully with only tool calls
500
+ // but no text response - this would have caught the original bug
501
+ const toolCallEvent = {
502
+ type: GeminiEventType.ToolCallRequest,
503
+ value: {
504
+ callId: 'tool-1',
505
+ name: 'testTool',
506
+ args: { arg1: 'value1' },
507
+ isClientInitiated: false,
508
+ prompt_id: 'prompt-id-tool-only',
509
+ },
510
+ };
511
+ const toolResponse = [{ text: 'Tool executed successfully' }];
512
+ mockCoreExecuteToolCall.mockResolvedValue({
513
+ status: 'success',
514
+ request: {
515
+ callId: 'tool-1',
516
+ name: 'testTool',
517
+ args: { arg1: 'value1' },
518
+ isClientInitiated: false,
519
+ prompt_id: 'prompt-id-tool-only',
520
+ },
521
+ tool: {},
522
+ invocation: {},
523
+ response: {
524
+ responseParts: toolResponse,
525
+ callId: 'tool-1',
526
+ error: undefined,
527
+ errorType: undefined,
528
+ contentLength: undefined,
529
+ },
530
+ });
531
+ // First call returns only tool call, no content
532
+ const firstCallEvents = [
533
+ toolCallEvent,
534
+ {
535
+ type: GeminiEventType.Finished,
536
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 5 } },
537
+ },
538
+ ];
539
+ // Second call returns no content (tool-only completion)
540
+ const secondCallEvents = [
541
+ {
542
+ type: GeminiEventType.Finished,
543
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 3 } },
544
+ },
545
+ ];
546
+ mockGeminiClient.sendMessageStream
547
+ .mockReturnValueOnce(createStreamFromEvents(firstCallEvents))
548
+ .mockReturnValueOnce(createStreamFromEvents(secondCallEvents));
549
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
550
+ vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(MOCK_SESSION_METRICS);
551
+ await runNonInteractive({
552
+ config: mockConfig,
553
+ settings: mockSettings,
554
+ input: 'Execute tool only',
555
+ prompt_id: 'prompt-id-tool-only',
556
+ });
557
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledTimes(2);
558
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledWith(mockConfig, expect.objectContaining({ name: 'testTool' }), expect.any(AbortSignal));
559
+ // This should output JSON with empty response but include stats
560
+ expect(processStdoutSpy).toHaveBeenCalledWith(JSON.stringify({ response: '', stats: MOCK_SESSION_METRICS }, null, 2));
561
+ });
562
+ it('should write JSON output with stats for empty response commands', async () => {
563
+ // Test the scenario where a command completes but produces no content at all
564
+ const events = [
565
+ {
566
+ type: GeminiEventType.Finished,
567
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 1 } },
568
+ },
569
+ ];
570
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
571
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
572
+ vi.mocked(uiTelemetryService.getMetrics).mockReturnValue(MOCK_SESSION_METRICS);
573
+ await runNonInteractive({
574
+ config: mockConfig,
575
+ settings: mockSettings,
576
+ input: 'Empty response test',
577
+ prompt_id: 'prompt-id-empty',
578
+ });
579
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Empty response test' }], expect.any(AbortSignal), 'prompt-id-empty');
580
+ // This should output JSON with empty response but include stats
581
+ expect(processStdoutSpy).toHaveBeenCalledWith(JSON.stringify({ response: '', stats: MOCK_SESSION_METRICS }, null, 2));
582
+ });
583
+ it('should handle errors in JSON format', async () => {
584
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
585
+ const testError = new Error('Invalid input provided');
586
+ mockGeminiClient.sendMessageStream.mockImplementation(() => {
587
+ throw testError;
588
+ });
589
+ // Mock console.error to capture JSON error output
590
+ const consoleErrorJsonSpy = vi
591
+ .spyOn(console, 'error')
592
+ .mockImplementation(() => { });
593
+ let thrownError = null;
594
+ try {
595
+ await runNonInteractive({
596
+ config: mockConfig,
597
+ settings: mockSettings,
598
+ input: 'Test input',
599
+ prompt_id: 'prompt-id-error',
600
+ });
601
+ // Should not reach here
602
+ expect.fail('Expected process.exit to be called');
603
+ }
604
+ catch (error) {
605
+ thrownError = error;
606
+ }
607
+ // Should throw because of mocked process.exit
608
+ expect(thrownError?.message).toBe('process.exit(1) called');
609
+ expect(consoleErrorJsonSpy).toHaveBeenCalledWith(JSON.stringify({
610
+ error: {
611
+ type: 'Error',
612
+ message: 'Invalid input provided',
613
+ code: 1,
614
+ },
615
+ }, null, 2));
616
+ });
617
+ it('should handle FatalInputError with custom exit code in JSON format', async () => {
618
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
619
+ const fatalError = new FatalInputError('Invalid command syntax provided');
620
+ mockGeminiClient.sendMessageStream.mockImplementation(() => {
621
+ throw fatalError;
622
+ });
623
+ // Mock console.error to capture JSON error output
624
+ const consoleErrorJsonSpy = vi
625
+ .spyOn(console, 'error')
626
+ .mockImplementation(() => { });
627
+ let thrownError = null;
628
+ try {
629
+ await runNonInteractive({
630
+ config: mockConfig,
631
+ settings: mockSettings,
632
+ input: 'Invalid syntax',
633
+ prompt_id: 'prompt-id-fatal',
634
+ });
635
+ // Should not reach here
636
+ expect.fail('Expected process.exit to be called');
637
+ }
638
+ catch (error) {
639
+ thrownError = error;
640
+ }
641
+ // Should throw because of mocked process.exit with custom exit code
642
+ expect(thrownError?.message).toBe('process.exit(42) called');
643
+ expect(consoleErrorJsonSpy).toHaveBeenCalledWith(JSON.stringify({
644
+ error: {
645
+ type: 'FatalInputError',
646
+ message: 'Invalid command syntax provided',
647
+ code: 42,
648
+ },
649
+ }, null, 2));
650
+ });
651
+ it('should execute a slash command that returns a prompt', async () => {
652
+ const mockCommand = {
653
+ name: 'testcommand',
654
+ description: 'a test command',
655
+ action: vi.fn().mockResolvedValue({
656
+ type: 'submit_prompt',
657
+ content: [{ text: 'Prompt from command' }],
658
+ }),
659
+ };
660
+ mockGetCommands.mockReturnValue([mockCommand]);
661
+ const events = [
662
+ { type: GeminiEventType.Content, value: 'Response from command' },
663
+ {
664
+ type: GeminiEventType.Finished,
665
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 5 } },
666
+ },
667
+ ];
668
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
669
+ await runNonInteractive({
670
+ config: mockConfig,
671
+ settings: mockSettings,
672
+ input: '/testcommand',
673
+ prompt_id: 'prompt-id-slash',
674
+ });
675
+ // Ensure the prompt sent to the model is from the command, not the raw input
676
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: 'Prompt from command' }], expect.any(AbortSignal), 'prompt-id-slash');
677
+ expect(getWrittenOutput()).toBe('Response from command\n');
678
+ });
679
+ it('should throw FatalInputError if a command requires confirmation', async () => {
680
+ const mockCommand = {
681
+ name: 'confirm',
682
+ description: 'a command that needs confirmation',
683
+ action: vi.fn().mockResolvedValue({
684
+ type: 'confirm_shell_commands',
685
+ commands: ['rm -rf /'],
686
+ }),
687
+ };
688
+ mockGetCommands.mockReturnValue([mockCommand]);
689
+ await expect(runNonInteractive({
690
+ config: mockConfig,
691
+ settings: mockSettings,
692
+ input: '/confirm',
693
+ prompt_id: 'prompt-id-confirm',
694
+ })).rejects.toThrow('Exiting due to a confirmation prompt requested by the command.');
695
+ });
696
+ it('should treat an unknown slash command as a regular prompt', async () => {
697
+ // No commands are mocked, so any slash command is "unknown"
698
+ mockGetCommands.mockReturnValue([]);
699
+ const events = [
700
+ { type: GeminiEventType.Content, value: 'Response to unknown' },
701
+ {
702
+ type: GeminiEventType.Finished,
703
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 5 } },
704
+ },
705
+ ];
706
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
707
+ await runNonInteractive({
708
+ config: mockConfig,
709
+ settings: mockSettings,
710
+ input: '/unknowncommand',
711
+ prompt_id: 'prompt-id-unknown',
712
+ });
713
+ // Ensure the raw input is sent to the model
714
+ expect(mockGeminiClient.sendMessageStream).toHaveBeenCalledWith([{ text: '/unknowncommand' }], expect.any(AbortSignal), 'prompt-id-unknown');
715
+ expect(getWrittenOutput()).toBe('Response to unknown\n');
716
+ });
717
+ it('should throw for unhandled command result types', async () => {
718
+ const mockCommand = {
719
+ name: 'noaction',
720
+ description: 'unhandled type',
721
+ action: vi.fn().mockResolvedValue({
722
+ type: 'unhandled',
723
+ }),
724
+ };
725
+ mockGetCommands.mockReturnValue([mockCommand]);
726
+ await expect(runNonInteractive({
727
+ config: mockConfig,
728
+ settings: mockSettings,
729
+ input: '/noaction',
730
+ prompt_id: 'prompt-id-unhandled',
731
+ })).rejects.toThrow('Exiting due to command result that is not supported in non-interactive mode.');
732
+ });
733
+ it('should pass arguments to the slash command action', async () => {
734
+ const mockAction = vi.fn().mockResolvedValue({
735
+ type: 'submit_prompt',
736
+ content: [{ text: 'Prompt from command' }],
737
+ });
738
+ const mockCommand = {
739
+ name: 'testargs',
740
+ description: 'a test command',
741
+ action: mockAction,
742
+ };
743
+ mockGetCommands.mockReturnValue([mockCommand]);
744
+ const events = [
745
+ { type: GeminiEventType.Content, value: 'Acknowledged' },
746
+ {
747
+ type: GeminiEventType.Finished,
748
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 1 } },
749
+ },
750
+ ];
751
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
752
+ await runNonInteractive({
753
+ config: mockConfig,
754
+ settings: mockSettings,
755
+ input: '/testargs arg1 arg2',
756
+ prompt_id: 'prompt-id-args',
757
+ });
758
+ expect(mockAction).toHaveBeenCalledWith(expect.any(Object), 'arg1 arg2');
759
+ expect(getWrittenOutput()).toBe('Acknowledged\n');
760
+ });
761
+ it('should instantiate CommandService with correct loaders for slash commands', async () => {
762
+ // This test indirectly checks that handleSlashCommand is using the right loaders.
763
+ const { FileCommandLoader } = await import('./services/FileCommandLoader.js');
764
+ const { McpPromptLoader } = await import('./services/McpPromptLoader.js');
765
+ mockGetCommands.mockReturnValue([]); // No commands found, so it will fall through
766
+ const events = [
767
+ { type: GeminiEventType.Content, value: 'Acknowledged' },
768
+ {
769
+ type: GeminiEventType.Finished,
770
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 1 } },
771
+ },
772
+ ];
773
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
774
+ await runNonInteractive({
775
+ config: mockConfig,
776
+ settings: mockSettings,
777
+ input: '/mycommand',
778
+ prompt_id: 'prompt-id-loaders',
779
+ });
780
+ // Check that loaders were instantiated with the config
781
+ expect(FileCommandLoader).toHaveBeenCalledTimes(1);
782
+ expect(FileCommandLoader).toHaveBeenCalledWith(mockConfig);
783
+ expect(McpPromptLoader).toHaveBeenCalledTimes(1);
784
+ expect(McpPromptLoader).toHaveBeenCalledWith(mockConfig);
785
+ // Check that instances were passed to CommandService.create
786
+ expect(mockCommandServiceCreate).toHaveBeenCalledTimes(1);
787
+ const loadersArg = mockCommandServiceCreate.mock.calls[0][0];
788
+ expect(loadersArg).toHaveLength(2);
789
+ expect(loadersArg[0]).toBe(vi.mocked(McpPromptLoader).mock.instances[0]);
790
+ expect(loadersArg[1]).toBe(vi.mocked(FileCommandLoader).mock.instances[0]);
791
+ });
792
+ it('should allow a normally-excluded tool when --allowed-tools is set', async () => {
793
+ // By default, ShellTool is excluded in non-interactive mode.
794
+ // This test ensures that --allowed-tools overrides this exclusion.
795
+ vi.mocked(mockConfig.getToolRegistry).mockReturnValue({
796
+ getTool: vi.fn().mockReturnValue({
797
+ name: 'ShellTool',
798
+ description: 'A shell tool',
799
+ run: vi.fn(),
800
+ }),
801
+ getFunctionDeclarations: vi.fn().mockReturnValue([{ name: 'ShellTool' }]),
802
+ });
803
+ const toolCallEvent = {
804
+ type: GeminiEventType.ToolCallRequest,
805
+ value: {
806
+ callId: 'tool-shell-1',
807
+ name: 'ShellTool',
808
+ args: { command: 'ls' },
809
+ isClientInitiated: false,
810
+ prompt_id: 'prompt-id-allowed',
811
+ },
812
+ };
813
+ const toolResponse = [{ text: 'file.txt' }];
814
+ mockCoreExecuteToolCall.mockResolvedValue({
815
+ status: 'success',
816
+ request: {
817
+ callId: 'tool-shell-1',
818
+ name: 'ShellTool',
819
+ args: { command: 'ls' },
820
+ isClientInitiated: false,
821
+ prompt_id: 'prompt-id-allowed',
822
+ },
823
+ tool: {},
824
+ invocation: {},
825
+ response: {
826
+ responseParts: toolResponse,
827
+ callId: 'tool-shell-1',
828
+ error: undefined,
829
+ errorType: undefined,
830
+ contentLength: undefined,
831
+ },
832
+ });
833
+ const firstCallEvents = [toolCallEvent];
834
+ const secondCallEvents = [
835
+ { type: GeminiEventType.Content, value: 'file.txt' },
836
+ {
837
+ type: GeminiEventType.Finished,
838
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
839
+ },
840
+ ];
841
+ mockGeminiClient.sendMessageStream
842
+ .mockReturnValueOnce(createStreamFromEvents(firstCallEvents))
843
+ .mockReturnValueOnce(createStreamFromEvents(secondCallEvents));
844
+ await runNonInteractive({
845
+ config: mockConfig,
846
+ settings: mockSettings,
847
+ input: 'List the files',
848
+ prompt_id: 'prompt-id-allowed',
849
+ });
850
+ expect(mockCoreExecuteToolCall).toHaveBeenCalledWith(mockConfig, expect.objectContaining({ name: 'ShellTool' }), expect.any(AbortSignal));
851
+ expect(getWrittenOutput()).toBe('file.txt\n');
852
+ });
853
+ describe('CoreEvents Integration', () => {
854
+ it('subscribes to UserFeedback and drains backlog on start', async () => {
855
+ const events = [
856
+ {
857
+ type: GeminiEventType.Finished,
858
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 0 } },
859
+ },
860
+ ];
861
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
862
+ await runNonInteractive({
863
+ config: mockConfig,
864
+ settings: mockSettings,
865
+ input: 'test',
866
+ prompt_id: 'prompt-id-events',
867
+ });
868
+ expect(mockCoreEvents.on).toHaveBeenCalledWith(CoreEvent.UserFeedback, expect.any(Function));
869
+ expect(mockCoreEvents.drainFeedbackBacklog).toHaveBeenCalledTimes(1);
870
+ });
871
+ it('unsubscribes from UserFeedback on finish', async () => {
872
+ const events = [
873
+ {
874
+ type: GeminiEventType.Finished,
875
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 0 } },
876
+ },
877
+ ];
878
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
879
+ await runNonInteractive({
880
+ config: mockConfig,
881
+ settings: mockSettings,
882
+ input: 'test',
883
+ prompt_id: 'prompt-id-events',
884
+ });
885
+ expect(mockCoreEvents.off).toHaveBeenCalledWith(CoreEvent.UserFeedback, expect.any(Function));
886
+ });
887
+ it('logs to process.stderr when UserFeedback event is received', async () => {
888
+ const events = [
889
+ {
890
+ type: GeminiEventType.Finished,
891
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 0 } },
892
+ },
893
+ ];
894
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
895
+ await runNonInteractive({
896
+ config: mockConfig,
897
+ settings: mockSettings,
898
+ input: 'test',
899
+ prompt_id: 'prompt-id-events',
900
+ });
901
+ // Get the registered handler
902
+ const handler = mockCoreEvents.on.mock.calls.find((call) => call[0] === CoreEvent.UserFeedback)?.[1];
903
+ expect(handler).toBeDefined();
904
+ // Simulate an event
905
+ const payload = {
906
+ severity: 'error',
907
+ message: 'Test error message',
908
+ };
909
+ handler(payload);
910
+ expect(processStderrSpy).toHaveBeenCalledWith('[ERROR] Test error message\n');
911
+ });
912
+ it('logs optional error object to process.stderr in debug mode', async () => {
913
+ vi.mocked(mockConfig.getDebugMode).mockReturnValue(true);
914
+ const events = [
915
+ {
916
+ type: GeminiEventType.Finished,
917
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 0 } },
918
+ },
919
+ ];
920
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
921
+ await runNonInteractive({
922
+ config: mockConfig,
923
+ settings: mockSettings,
924
+ input: 'test',
925
+ prompt_id: 'prompt-id-events',
926
+ });
927
+ // Get the registered handler
928
+ const handler = mockCoreEvents.on.mock.calls.find((call) => call[0] === CoreEvent.UserFeedback)?.[1];
929
+ expect(handler).toBeDefined();
930
+ // Simulate an event with error object
931
+ const errorObj = new Error('Original error');
932
+ // Mock stack for deterministic testing
933
+ errorObj.stack = 'Error: Original error\n at test';
934
+ const payload = {
935
+ severity: 'warning',
936
+ message: 'Test warning message',
937
+ error: errorObj,
938
+ };
939
+ handler(payload);
940
+ expect(processStderrSpy).toHaveBeenCalledWith('[WARNING] Test warning message\n');
941
+ expect(processStderrSpy).toHaveBeenCalledWith('Error: Original error\n at test\n');
942
+ });
943
+ });
944
+ it('should display a deprecation warning if hasDeprecatedPromptArg is true', async () => {
945
+ const events = [
946
+ { type: GeminiEventType.Content, value: 'Final Answer' },
947
+ {
948
+ type: GeminiEventType.Finished,
949
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
950
+ },
951
+ ];
952
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
953
+ await runNonInteractive({
954
+ config: mockConfig,
955
+ settings: mockSettings,
956
+ input: 'Test input',
957
+ prompt_id: 'prompt-id-deprecated',
958
+ hasDeprecatedPromptArg: true,
959
+ });
960
+ expect(processStderrSpy).toHaveBeenCalledWith('The --prompt (-p) flag has been deprecated and will be removed in a future version. Please use a positional argument for your prompt. See gemini --help for more information.\n');
961
+ expect(processStdoutSpy).toHaveBeenCalledWith('Final Answer');
962
+ });
963
+ it('should display a deprecation warning for JSON format', async () => {
964
+ const events = [
965
+ { type: GeminiEventType.Content, value: 'Final Answer' },
966
+ {
967
+ type: GeminiEventType.Finished,
968
+ value: { reason: undefined, usageMetadata: { totalTokenCount: 10 } },
969
+ },
970
+ ];
971
+ mockGeminiClient.sendMessageStream.mockReturnValue(createStreamFromEvents(events));
972
+ vi.mocked(mockConfig.getOutputFormat).mockReturnValue(OutputFormat.JSON);
973
+ await runNonInteractive({
974
+ config: mockConfig,
975
+ settings: mockSettings,
976
+ input: 'Test input',
977
+ prompt_id: 'prompt-id-deprecated-json',
978
+ hasDeprecatedPromptArg: true,
979
+ });
980
+ const deprecateText = 'The --prompt (-p) flag has been deprecated and will be removed in a future version. Please use a positional argument for your prompt. See gemini --help for more information.\n';
981
+ expect(processStderrSpy).toHaveBeenCalledWith(deprecateText);
982
+ });
983
+ });
984
+ //# sourceMappingURL=nonInteractiveCli.test.js.map