@machina.ai/cell-cli 1.41.1-rc1 → 1.45.1-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 (562) hide show
  1. package/dist/index.js +17 -17
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +5 -5
  4. package/dist/src/acp/README.md +81 -0
  5. package/dist/src/acp/{commandHandler.d.ts → acpCommandHandler.d.ts} +1 -1
  6. package/dist/src/acp/{commandHandler.js → acpCommandHandler.js} +2 -2
  7. package/dist/src/acp/acpCommandHandler.js.map +1 -0
  8. package/dist/src/acp/{commandHandler.test.js → acpCommandHandler.test.js} +4 -5
  9. package/dist/src/acp/acpCommandHandler.test.js.map +1 -0
  10. package/dist/src/acp/acpErrors.d.ts +1 -1
  11. package/dist/src/acp/acpErrors.js +1 -1
  12. package/dist/src/acp/acpErrors.test.d.ts +1 -1
  13. package/dist/src/acp/acpErrors.test.js +1 -1
  14. package/dist/src/acp/{fileSystemService.d.ts → acpFileSystemService.d.ts} +1 -1
  15. package/dist/src/acp/{fileSystemService.js → acpFileSystemService.js} +7 -4
  16. package/dist/src/acp/acpFileSystemService.js.map +1 -0
  17. package/dist/src/acp/{fileSystemService.test.js → acpFileSystemService.test.js} +3 -3
  18. package/dist/src/acp/acpFileSystemService.test.js.map +1 -0
  19. package/dist/src/acp/acpResume.test.d.ts +1 -1
  20. package/dist/src/acp/acpResume.test.js +12 -7
  21. package/dist/src/acp/acpResume.test.js.map +1 -1
  22. package/dist/src/acp/acpRpcDispatcher.d.ts +28 -0
  23. package/dist/src/acp/acpRpcDispatcher.js +177 -0
  24. package/dist/src/acp/acpRpcDispatcher.js.map +1 -0
  25. package/dist/src/acp/acpRpcDispatcher.test.d.ts +6 -0
  26. package/dist/src/acp/acpRpcDispatcher.test.js +238 -0
  27. package/dist/src/acp/acpRpcDispatcher.test.js.map +1 -0
  28. package/dist/src/acp/acpSession.d.ts +36 -0
  29. package/dist/src/acp/{acpClient.js → acpSession.js} +333 -774
  30. package/dist/src/acp/acpSession.js.map +1 -0
  31. package/dist/src/acp/acpSession.test.d.ts +6 -0
  32. package/dist/src/acp/acpSession.test.js +739 -0
  33. package/dist/src/acp/acpSession.test.js.map +1 -0
  34. package/dist/src/acp/acpSessionManager.d.ts +30 -0
  35. package/dist/src/acp/acpSessionManager.js +206 -0
  36. package/dist/src/acp/acpSessionManager.js.map +1 -0
  37. package/dist/src/acp/acpSessionManager.test.d.ts +6 -0
  38. package/dist/src/acp/acpSessionManager.test.js +283 -0
  39. package/dist/src/acp/acpSessionManager.test.js.map +1 -0
  40. package/dist/src/acp/acpStdioTransport.d.ts +9 -0
  41. package/dist/src/acp/acpStdioTransport.js +23 -0
  42. package/dist/src/acp/acpStdioTransport.js.map +1 -0
  43. package/dist/src/acp/acpUtils.d.ts +56 -0
  44. package/dist/src/acp/acpUtils.js +288 -0
  45. package/dist/src/acp/acpUtils.js.map +1 -0
  46. package/dist/src/acp/commands/commandRegistry.d.ts +1 -1
  47. package/dist/src/acp/commands/commandRegistry.js +1 -1
  48. package/dist/src/acp/commands/extensions.d.ts +1 -1
  49. package/dist/src/acp/commands/extensions.js +1 -1
  50. package/dist/src/acp/commands/extensions.test.d.ts +6 -0
  51. package/dist/src/acp/commands/extensions.test.js +70 -0
  52. package/dist/src/acp/commands/extensions.test.js.map +1 -0
  53. package/dist/src/acp/commands/init.d.ts +1 -1
  54. package/dist/src/acp/commands/init.js +1 -1
  55. package/dist/src/acp/commands/memory.d.ts +3 -8
  56. package/dist/src/acp/commands/memory.js +18 -47
  57. package/dist/src/acp/commands/memory.js.map +1 -1
  58. package/dist/src/acp/commands/restore.d.ts +1 -1
  59. package/dist/src/acp/commands/restore.js +1 -1
  60. package/dist/src/acp/commands/restore.test.js +7 -13
  61. package/dist/src/acp/commands/restore.test.js.map +1 -1
  62. package/dist/src/acp/commands/types.d.ts +1 -1
  63. package/dist/src/acp/commands/types.js +1 -1
  64. package/dist/src/commands/extensions/configure.test.js +6 -2
  65. package/dist/src/commands/extensions/configure.test.js.map +1 -1
  66. package/dist/src/commands/extensions/utils.d.ts +1 -1
  67. package/dist/src/commands/extensions/utils.js +1 -2
  68. package/dist/src/commands/extensions/utils.js.map +1 -1
  69. package/dist/src/commands/mcp/list.js +19 -5
  70. package/dist/src/commands/mcp/list.js.map +1 -1
  71. package/dist/src/commands/mcp/list.test.js +285 -100
  72. package/dist/src/commands/mcp/list.test.js.map +1 -1
  73. package/dist/src/config/auth.d.ts +1 -1
  74. package/dist/src/config/auth.js +4 -3
  75. package/dist/src/config/auth.js.map +1 -1
  76. package/dist/src/config/auth.test.js +11 -4
  77. package/dist/src/config/auth.test.js.map +1 -1
  78. package/dist/src/config/config.d.ts +4 -0
  79. package/dist/src/config/config.js +65 -47
  80. package/dist/src/config/config.js.map +1 -1
  81. package/dist/src/config/config.test.js +25 -106
  82. package/dist/src/config/config.test.js.map +1 -1
  83. package/dist/src/config/extension-manager-agents.test.js +2 -0
  84. package/dist/src/config/extension-manager-agents.test.js.map +1 -1
  85. package/dist/src/config/extension-manager-hydration.test.js +2 -0
  86. package/dist/src/config/extension-manager-hydration.test.js.map +1 -1
  87. package/dist/src/config/extension-manager-scope.test.js +4 -2
  88. package/dist/src/config/extension-manager-scope.test.js.map +1 -1
  89. package/dist/src/config/extension-manager-themes.spec.js +2 -0
  90. package/dist/src/config/extension-manager-themes.spec.js.map +1 -1
  91. package/dist/src/config/extension-manager.d.ts +2 -2
  92. package/dist/src/config/extension-manager.js +2 -1
  93. package/dist/src/config/extension-manager.js.map +1 -1
  94. package/dist/src/config/extensionRegistryClient.js +0 -1
  95. package/dist/src/config/extensionRegistryClient.js.map +1 -1
  96. package/dist/src/config/extensions/consent.d.ts +1 -1
  97. package/dist/src/config/extensions/consent.js +5 -4
  98. package/dist/src/config/extensions/consent.js.map +1 -1
  99. package/dist/src/config/extensions/consent.test.js +22 -0
  100. package/dist/src/config/extensions/consent.test.js.map +1 -1
  101. package/dist/src/config/extensions/extensionEnablement.js +4 -2
  102. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  103. package/dist/src/config/extensions/extensionSettings.d.ts +3 -3
  104. package/dist/src/config/extensions/extensionSettings.js +7 -3
  105. package/dist/src/config/extensions/extensionSettings.js.map +1 -1
  106. package/dist/src/config/extensions/variables.js +1 -3
  107. package/dist/src/config/extensions/variables.js.map +1 -1
  108. package/dist/src/config/footerItems.d.ts +4 -0
  109. package/dist/src/config/footerItems.js +6 -0
  110. package/dist/src/config/footerItems.js.map +1 -1
  111. package/dist/src/config/footerItems.test.js +1 -0
  112. package/dist/src/config/footerItems.test.js.map +1 -1
  113. package/dist/src/config/mcp/mcpServerEnablement.js +1 -1
  114. package/dist/src/config/mcp/mcpServerEnablement.js.map +1 -1
  115. package/dist/src/config/mutual-exclusivity.test.js +33 -0
  116. package/dist/src/config/mutual-exclusivity.test.js.map +1 -0
  117. package/dist/src/config/settings-env-isolation.test.d.ts +6 -0
  118. package/dist/src/config/settings-env-isolation.test.js +188 -0
  119. package/dist/src/config/settings-env-isolation.test.js.map +1 -0
  120. package/dist/src/config/settings.d.ts +15 -1
  121. package/dist/src/config/settings.js +89 -17
  122. package/dist/src/config/settings.js.map +1 -1
  123. package/dist/src/config/settings.test.js +167 -0
  124. package/dist/src/config/settings.test.js.map +1 -1
  125. package/dist/src/config/settingsSchema.d.ts +56 -25
  126. package/dist/src/config/settingsSchema.js +66 -27
  127. package/dist/src/config/settingsSchema.js.map +1 -1
  128. package/dist/src/config/settingsSchema.test.js +8 -0
  129. package/dist/src/config/settingsSchema.test.js.map +1 -1
  130. package/dist/src/config/skipExtensions.test.d.ts +6 -0
  131. package/dist/src/config/skipExtensions.test.js +49 -0
  132. package/dist/src/config/skipExtensions.test.js.map +1 -0
  133. package/dist/src/config/workspace-policy-cli.test.js +0 -5
  134. package/dist/src/config/workspace-policy-cli.test.js.map +1 -1
  135. package/dist/src/gemini.d.ts +2 -2
  136. package/dist/src/gemini.js +120 -31
  137. package/dist/src/gemini.js.map +1 -1
  138. package/dist/src/gemini.test.js +147 -16
  139. package/dist/src/gemini.test.js.map +1 -1
  140. package/dist/src/gemini_cleanup.test.js +1 -1
  141. package/dist/src/gemini_cleanup.test.js.map +1 -1
  142. package/dist/src/generated/git-commit.d.ts +2 -2
  143. package/dist/src/generated/git-commit.js +2 -2
  144. package/dist/src/interactiveCli.js +1 -1
  145. package/dist/src/interactiveCli.js.map +1 -1
  146. package/dist/src/nonInteractiveCli.d.ts +7 -0
  147. package/dist/src/nonInteractiveCli.js +56 -6
  148. package/dist/src/nonInteractiveCli.js.map +1 -1
  149. package/dist/src/nonInteractiveCli.test.js +253 -18
  150. package/dist/src/nonInteractiveCli.test.js.map +1 -1
  151. package/dist/src/nonInteractiveCliAgentSession.d.ts +7 -0
  152. package/dist/src/nonInteractiveCliAgentSession.js +22 -3
  153. package/dist/src/nonInteractiveCliAgentSession.js.map +1 -1
  154. package/dist/src/nonInteractiveCliAgentSession.test.js +200 -20
  155. package/dist/src/nonInteractiveCliAgentSession.test.js.map +1 -1
  156. package/dist/src/output-redirection.test.d.ts +6 -0
  157. package/dist/src/output-redirection.test.js +77 -0
  158. package/dist/src/output-redirection.test.js.map +1 -0
  159. package/dist/src/patches/http-proxy-agent.d.ts +6 -0
  160. package/dist/src/patches/http-proxy-agent.js +8 -0
  161. package/dist/src/patches/http-proxy-agent.js.map +1 -0
  162. package/dist/src/patches/https-proxy-agent.d.ts +6 -0
  163. package/dist/src/patches/https-proxy-agent.js +8 -0
  164. package/dist/src/patches/https-proxy-agent.js.map +1 -0
  165. package/dist/src/services/BuiltinCommandLoader.js +5 -1
  166. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  167. package/dist/src/services/BuiltinCommandLoader.test.js +6 -1
  168. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  169. package/dist/src/services/FileCommandLoader.d.ts +21 -0
  170. package/dist/src/services/FileCommandLoader.js +58 -6
  171. package/dist/src/services/FileCommandLoader.js.map +1 -1
  172. package/dist/src/services/FileCommandLoader.test.js +27 -1
  173. package/dist/src/services/FileCommandLoader.test.js.map +1 -1
  174. package/dist/src/test-utils/mockCommandContext.js +6 -1
  175. package/dist/src/test-utils/mockCommandContext.js.map +1 -1
  176. package/dist/src/test-utils/mockConfig.js +0 -3
  177. package/dist/src/test-utils/mockConfig.js.map +1 -1
  178. package/dist/src/test-utils/render.js +1 -0
  179. package/dist/src/test-utils/render.js.map +1 -1
  180. package/dist/src/test-utils/settings.d.ts +1 -0
  181. package/dist/src/test-utils/settings.js.map +1 -1
  182. package/dist/src/ui/AppContainer.js +60 -73
  183. package/dist/src/ui/AppContainer.js.map +1 -1
  184. package/dist/src/ui/AppContainer.test.js +101 -1
  185. package/dist/src/ui/AppContainer.test.js.map +1 -1
  186. package/dist/src/ui/auth/AuthDialog.js +6 -3
  187. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  188. package/dist/src/ui/auth/AuthDialog.test.js +33 -10
  189. package/dist/src/ui/auth/AuthDialog.test.js.map +1 -1
  190. package/dist/src/ui/auth/LoginRestartDialog.d.ts +13 -0
  191. package/dist/src/ui/auth/{LoginWithGoogleRestartDialog.js → LoginRestartDialog.js} +7 -6
  192. package/dist/src/ui/auth/LoginRestartDialog.js.map +1 -0
  193. package/dist/src/ui/auth/LoginRestartDialog.test.d.ts +6 -0
  194. package/dist/src/ui/auth/{LoginWithGoogleRestartDialog.test.js → LoginRestartDialog.test.js} +13 -8
  195. package/dist/src/ui/auth/LoginRestartDialog.test.js.map +1 -0
  196. package/dist/src/ui/auth/useAuth.d.ts +1 -1
  197. package/dist/src/ui/auth/useAuth.js +2 -2
  198. package/dist/src/ui/auth/useAuth.js.map +1 -1
  199. package/dist/src/ui/auth/useAuth.test.js +10 -10
  200. package/dist/src/ui/auth/useAuth.test.js.map +1 -1
  201. package/dist/src/ui/commands/agentsCommand.js +19 -2
  202. package/dist/src/ui/commands/agentsCommand.js.map +1 -1
  203. package/dist/src/ui/commands/agentsCommand.test.js +34 -3
  204. package/dist/src/ui/commands/agentsCommand.test.js.map +1 -1
  205. package/dist/src/ui/commands/bugCommand.js +36 -0
  206. package/dist/src/ui/commands/bugCommand.js.map +1 -1
  207. package/dist/src/ui/commands/bugCommand.test.js +106 -1
  208. package/dist/src/ui/commands/bugCommand.test.js.map +1 -1
  209. package/dist/src/ui/commands/bugMemoryCommand.d.ts +7 -0
  210. package/dist/src/ui/commands/bugMemoryCommand.js +62 -0
  211. package/dist/src/ui/commands/bugMemoryCommand.js.map +1 -0
  212. package/dist/src/ui/commands/bugMemoryCommand.test.js +100 -0
  213. package/dist/src/ui/commands/bugMemoryCommand.test.js.map +1 -0
  214. package/dist/src/ui/commands/commandsCommand.js +52 -4
  215. package/dist/src/ui/commands/commandsCommand.js.map +1 -1
  216. package/dist/src/ui/commands/commandsCommand.test.js +75 -2
  217. package/dist/src/ui/commands/commandsCommand.test.js.map +1 -1
  218. package/dist/src/ui/commands/compressCommand.js +28 -26
  219. package/dist/src/ui/commands/compressCommand.js.map +1 -1
  220. package/dist/src/ui/commands/compressCommand.test.js +5 -0
  221. package/dist/src/ui/commands/compressCommand.test.js.map +1 -1
  222. package/dist/src/ui/commands/directoryCommand.js +2 -2
  223. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  224. package/dist/src/ui/commands/directoryCommand.test.js +1 -0
  225. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -1
  226. package/dist/src/ui/commands/exportSessionCommand.d.ts +7 -0
  227. package/dist/src/ui/commands/exportSessionCommand.js +74 -0
  228. package/dist/src/ui/commands/exportSessionCommand.js.map +1 -0
  229. package/dist/src/ui/commands/exportSessionCommand.test.js +100 -0
  230. package/dist/src/ui/commands/exportSessionCommand.test.js.map +1 -0
  231. package/dist/src/ui/commands/extensionsCommand.js +1 -0
  232. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  233. package/dist/src/ui/commands/extensionsCommand.test.js +4 -0
  234. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -1
  235. package/dist/src/ui/commands/marketplaceCommand.js +13 -1
  236. package/dist/src/ui/commands/marketplaceCommand.js.map +1 -1
  237. package/dist/src/ui/commands/memoryCommand.d.ts +2 -1
  238. package/dist/src/ui/commands/memoryCommand.js +110 -117
  239. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  240. package/dist/src/ui/commands/memoryCommand.test.js +18 -71
  241. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -1
  242. package/dist/src/ui/commands/quitCommand.js +3 -1
  243. package/dist/src/ui/commands/quitCommand.js.map +1 -1
  244. package/dist/src/ui/commands/quitCommand.test.js +46 -1
  245. package/dist/src/ui/commands/quitCommand.test.js.map +1 -1
  246. package/dist/src/ui/commands/rewindCommand.js.map +1 -1
  247. package/dist/src/ui/commands/skillsCommand.js +1 -1
  248. package/dist/src/ui/commands/skillsCommand.js.map +1 -1
  249. package/dist/src/ui/commands/skillsCommand.test.js +19 -0
  250. package/dist/src/ui/commands/skillsCommand.test.js.map +1 -1
  251. package/dist/src/ui/commands/types.d.ts +3 -1
  252. package/dist/src/ui/commands/types.js.map +1 -1
  253. package/dist/src/ui/components/AsciiArt.d.ts +6 -6
  254. package/dist/src/ui/components/AsciiArt.js +6 -6
  255. package/dist/src/ui/components/AskUserDialog.js +3 -1
  256. package/dist/src/ui/components/AskUserDialog.js.map +1 -1
  257. package/dist/src/ui/components/AskUserDialog.test.js +43 -0
  258. package/dist/src/ui/components/AskUserDialog.test.js.map +1 -1
  259. package/dist/src/ui/components/Composer.js +1 -1
  260. package/dist/src/ui/components/Composer.js.map +1 -1
  261. package/dist/src/ui/components/DialogManager.js +4 -0
  262. package/dist/src/ui/components/DialogManager.js.map +1 -1
  263. package/dist/src/ui/components/EditorSettingsDialog.js +3 -6
  264. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  265. package/dist/src/ui/components/Footer.js +6 -0
  266. package/dist/src/ui/components/Footer.js.map +1 -1
  267. package/dist/src/ui/components/FooterConfigDialog.js +1 -0
  268. package/dist/src/ui/components/FooterConfigDialog.js.map +1 -1
  269. package/dist/src/ui/components/FooterConfigDialog.test.js +1 -1
  270. package/dist/src/ui/components/FooterConfigDialog.test.js.map +1 -1
  271. package/dist/src/ui/components/HistoryItemDisplay.js +3 -1
  272. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  273. package/dist/src/ui/components/HistoryItemDisplay.test.js +15 -0
  274. package/dist/src/ui/components/HistoryItemDisplay.test.js.map +1 -1
  275. package/dist/src/ui/components/{SkillInboxDialog.d.ts → InboxDialog.d.ts} +3 -2
  276. package/dist/src/ui/components/InboxDialog.js +756 -0
  277. package/dist/src/ui/components/InboxDialog.js.map +1 -0
  278. package/dist/src/ui/components/InboxDialog.test.d.ts +6 -0
  279. package/dist/src/ui/components/InboxDialog.test.js +824 -0
  280. package/dist/src/ui/components/InboxDialog.test.js.map +1 -0
  281. package/dist/src/ui/components/InputPrompt.d.ts +3 -0
  282. package/dist/src/ui/components/InputPrompt.js +35 -17
  283. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  284. package/dist/src/ui/components/InputPrompt.test.js +95 -46
  285. package/dist/src/ui/components/InputPrompt.test.js.map +1 -1
  286. package/dist/src/ui/components/ListeningIndicator.d.ts +10 -0
  287. package/dist/src/ui/components/ListeningIndicator.js +30 -0
  288. package/dist/src/ui/components/ListeningIndicator.js.map +1 -0
  289. package/dist/src/ui/components/MainContent.test.js +23 -3
  290. package/dist/src/ui/components/MainContent.test.js.map +1 -1
  291. package/dist/src/ui/components/ModelDialog.js +40 -34
  292. package/dist/src/ui/components/ModelDialog.js.map +1 -1
  293. package/dist/src/ui/components/ModelDialog.test.js +30 -27
  294. package/dist/src/ui/components/ModelDialog.test.js.map +1 -1
  295. package/dist/src/ui/components/ModelStatsDisplay.js +1 -1
  296. package/dist/src/ui/components/ModelStatsDisplay.js.map +1 -1
  297. package/dist/src/ui/components/ModelStatsDisplay.test.js +41 -0
  298. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -1
  299. package/dist/src/ui/components/SessionBrowser.js +7 -0
  300. package/dist/src/ui/components/SessionBrowser.js.map +1 -1
  301. package/dist/src/ui/components/SessionSummaryDisplay.js +9 -4
  302. package/dist/src/ui/components/SessionSummaryDisplay.js.map +1 -1
  303. package/dist/src/ui/components/SessionSummaryDisplay.test.js +12 -23
  304. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -1
  305. package/dist/src/ui/components/SettingsDialog.js +37 -17
  306. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  307. package/dist/src/ui/components/SettingsDialog.test.js +83 -1
  308. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  309. package/dist/src/ui/components/StatsDisplay.js +2 -2
  310. package/dist/src/ui/components/StatsDisplay.js.map +1 -1
  311. package/dist/src/ui/components/StatsDisplay.test.js +24 -0
  312. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -1
  313. package/dist/src/ui/components/ThemeDialog.constants.d.ts +26 -0
  314. package/dist/src/ui/components/ThemeDialog.constants.js +27 -0
  315. package/dist/src/ui/components/ThemeDialog.constants.js.map +1 -0
  316. package/dist/src/ui/components/ThemeDialog.js +5 -15
  317. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  318. package/dist/src/ui/components/ToolConfirmationQueue.test.js +1 -1
  319. package/dist/src/ui/components/ToolConfirmationQueue.test.js.map +1 -1
  320. package/dist/src/ui/components/VoiceModelDialog.js +7 -2
  321. package/dist/src/ui/components/VoiceModelDialog.js.map +1 -1
  322. package/dist/src/ui/components/VoiceModelDialog.test.d.ts +6 -0
  323. package/dist/src/ui/components/VoiceModelDialog.test.js +68 -0
  324. package/dist/src/ui/components/VoiceModelDialog.test.js.map +1 -0
  325. package/dist/src/ui/components/messages/ExportSessionMessage.d.ts +11 -0
  326. package/dist/src/ui/components/messages/ExportSessionMessage.js +15 -0
  327. package/dist/src/ui/components/messages/ExportSessionMessage.js.map +1 -0
  328. package/dist/src/ui/components/messages/ExportSessionMessage.test.d.ts +6 -0
  329. package/dist/src/ui/components/messages/ExportSessionMessage.test.js +31 -0
  330. package/dist/src/ui/components/messages/ExportSessionMessage.test.js.map +1 -0
  331. package/dist/src/ui/components/messages/ShellToolMessage.js +6 -2
  332. package/dist/src/ui/components/messages/ShellToolMessage.js.map +1 -1
  333. package/dist/src/ui/components/messages/ShellToolMessage.test.js +33 -0
  334. package/dist/src/ui/components/messages/ShellToolMessage.test.js.map +1 -1
  335. package/dist/src/ui/components/messages/SubagentGroupDisplay.js +13 -13
  336. package/dist/src/ui/components/messages/SubagentGroupDisplay.js.map +1 -1
  337. package/dist/src/ui/components/messages/SubagentGroupDisplay.test.js +5 -5
  338. package/dist/src/ui/components/messages/SubagentGroupDisplay.test.js.map +1 -1
  339. package/dist/src/ui/components/messages/SubagentHistoryMessage.test.js +4 -3
  340. package/dist/src/ui/components/messages/SubagentHistoryMessage.test.js.map +1 -1
  341. package/dist/src/ui/components/messages/SubagentProgressDisplay.d.ts +1 -1
  342. package/dist/src/ui/components/messages/SubagentProgressDisplay.js +7 -6
  343. package/dist/src/ui/components/messages/SubagentProgressDisplay.js.map +1 -1
  344. package/dist/src/ui/components/messages/SubagentProgressDisplay.test.js +10 -9
  345. package/dist/src/ui/components/messages/SubagentProgressDisplay.test.js.map +1 -1
  346. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +3 -9
  347. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  348. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js +60 -0
  349. package/dist/src/ui/components/messages/ToolConfirmationMessage.test.js.map +1 -1
  350. package/dist/src/ui/components/messages/ToolGroupDisplay.d.ts +13 -0
  351. package/dist/src/ui/components/messages/ToolGroupDisplay.js +78 -0
  352. package/dist/src/ui/components/messages/ToolGroupDisplay.js.map +1 -0
  353. package/dist/src/ui/components/messages/ToolGroupDisplay.test.d.ts +6 -0
  354. package/dist/src/ui/components/messages/ToolGroupDisplay.test.js +210 -0
  355. package/dist/src/ui/components/messages/ToolGroupDisplay.test.js.map +1 -0
  356. package/dist/src/ui/components/messages/ToolGroupMessage.js +4 -2
  357. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  358. package/dist/src/ui/components/messages/ToolGroupMessage.test.js +28 -0
  359. package/dist/src/ui/components/messages/ToolGroupMessage.test.js.map +1 -1
  360. package/dist/src/ui/components/messages/ToolGroupMessageRegression.test.js +3 -3
  361. package/dist/src/ui/components/messages/ToolGroupMessageRegression.test.js.map +1 -1
  362. package/dist/src/ui/components/messages/ToolMessage.js +6 -2
  363. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  364. package/dist/src/ui/components/messages/ToolShared.d.ts +1 -0
  365. package/dist/src/ui/components/messages/ToolShared.js +5 -3
  366. package/dist/src/ui/components/messages/ToolShared.js.map +1 -1
  367. package/dist/src/ui/components/messages/ToolShared.test.js +18 -1
  368. package/dist/src/ui/components/messages/ToolShared.test.js.map +1 -1
  369. package/dist/src/ui/components/shared/BaseSettingsDialog.d.ts +6 -1
  370. package/dist/src/ui/components/shared/BaseSettingsDialog.js +8 -8
  371. package/dist/src/ui/components/shared/BaseSettingsDialog.js.map +1 -1
  372. package/dist/src/ui/components/shared/performance.test.js +9 -0
  373. package/dist/src/ui/components/shared/performance.test.js.map +1 -1
  374. package/dist/src/ui/components/shared/text-buffer.js +22 -5
  375. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  376. package/dist/src/ui/components/shared/text-buffer.test.js +211 -0
  377. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -1
  378. package/dist/src/ui/constants/tips.js +0 -1
  379. package/dist/src/ui/constants/tips.js.map +1 -1
  380. package/dist/src/ui/contexts/UIActionsContext.d.ts +1 -0
  381. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  382. package/dist/src/ui/contexts/UIStateContext.d.ts +2 -0
  383. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  384. package/dist/src/ui/hooks/atCommandProcessor.js +83 -73
  385. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  386. package/dist/src/ui/hooks/atCommandProcessor.test.js +134 -42
  387. package/dist/src/ui/hooks/atCommandProcessor.test.js.map +1 -1
  388. package/dist/src/ui/hooks/slashCommandProcessor.js +13 -0
  389. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  390. package/dist/src/ui/hooks/slashCommandProcessor.test.js +85 -0
  391. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -1
  392. package/dist/src/ui/hooks/useAgentStream.d.ts +2 -2
  393. package/dist/src/ui/hooks/useAgentStream.js +63 -30
  394. package/dist/src/ui/hooks/useAgentStream.js.map +1 -1
  395. package/dist/src/ui/hooks/useAgentStream.test.js +1 -1
  396. package/dist/src/ui/hooks/useAgentStream.test.js.map +1 -1
  397. package/dist/src/ui/hooks/useAtCompletion.js +0 -2
  398. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  399. package/dist/src/ui/hooks/useGeminiStream.d.ts +2 -2
  400. package/dist/src/ui/hooks/useGeminiStream.js +48 -29
  401. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  402. package/dist/src/ui/hooks/useGeminiStream.test.js +44 -82
  403. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -1
  404. package/dist/src/ui/hooks/useGitBranchName.js +29 -16
  405. package/dist/src/ui/hooks/useGitBranchName.js.map +1 -1
  406. package/dist/src/ui/hooks/useGitBranchName.test.js +102 -51
  407. package/dist/src/ui/hooks/useGitBranchName.test.js.map +1 -1
  408. package/dist/src/ui/hooks/useIncludeDirsTrust.js +2 -2
  409. package/dist/src/ui/hooks/useIncludeDirsTrust.js.map +1 -1
  410. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js +2 -0
  411. package/dist/src/ui/hooks/useIncludeDirsTrust.test.js.map +1 -1
  412. package/dist/src/ui/hooks/useMessageQueue.d.ts +2 -1
  413. package/dist/src/ui/hooks/useMessageQueue.js +3 -1
  414. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -1
  415. package/dist/src/ui/hooks/useMessageQueue.test.js +38 -0
  416. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  417. package/dist/src/ui/hooks/useSessionBrowser.d.ts +3 -3
  418. package/dist/src/ui/hooks/useSessionBrowser.js.map +1 -1
  419. package/dist/src/ui/hooks/useSessionBrowser.test.js +44 -38
  420. package/dist/src/ui/hooks/useSessionBrowser.test.js.map +1 -1
  421. package/dist/src/ui/hooks/useSessionResume.d.ts +3 -3
  422. package/dist/src/ui/hooks/useSessionResume.js.map +1 -1
  423. package/dist/src/ui/hooks/useSessionResume.test.js +6 -4
  424. package/dist/src/ui/hooks/useSessionResume.test.js.map +1 -1
  425. package/dist/src/ui/hooks/useSuspend.d.ts +1 -3
  426. package/dist/src/ui/hooks/useSuspend.js +3 -17
  427. package/dist/src/ui/hooks/useSuspend.js.map +1 -1
  428. package/dist/src/ui/hooks/useSuspend.test.js +0 -14
  429. package/dist/src/ui/hooks/useSuspend.test.js.map +1 -1
  430. package/dist/src/ui/hooks/useToolScheduler.test.js +6 -6
  431. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  432. package/dist/src/ui/hooks/useVoiceMode.js +25 -19
  433. package/dist/src/ui/hooks/useVoiceMode.js.map +1 -1
  434. package/dist/src/ui/hooks/vim-passthrough.test.js +10 -0
  435. package/dist/src/ui/hooks/vim-passthrough.test.js.map +1 -1
  436. package/dist/src/ui/hooks/vim.js +8 -0
  437. package/dist/src/ui/hooks/vim.js.map +1 -1
  438. package/dist/src/ui/hooks/vim.test.js +61 -0
  439. package/dist/src/ui/hooks/vim.test.js.map +1 -1
  440. package/dist/src/ui/key/keyBindings.d.ts +2 -0
  441. package/dist/src/ui/key/keyBindings.js +26 -9
  442. package/dist/src/ui/key/keyBindings.js.map +1 -1
  443. package/dist/src/ui/key/keyBindings.test.js +24 -0
  444. package/dist/src/ui/key/keyBindings.test.js.map +1 -1
  445. package/dist/src/ui/key/keyMatchers.test.js +26 -5
  446. package/dist/src/ui/key/keyMatchers.test.js.map +1 -1
  447. package/dist/src/ui/themes/theme-manager.js +0 -2
  448. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  449. package/dist/src/ui/types.d.ts +23 -2
  450. package/dist/src/ui/types.js +3 -2
  451. package/dist/src/ui/types.js.map +1 -1
  452. package/dist/src/ui/utils/TableRenderer.js +6 -6
  453. package/dist/src/ui/utils/TableRenderer.js.map +1 -1
  454. package/dist/src/ui/utils/TableRenderer.test.js +10 -0
  455. package/dist/src/ui/utils/TableRenderer.test.js.map +1 -1
  456. package/dist/src/ui/utils/directoryUtils.test.js +0 -5
  457. package/dist/src/ui/utils/directoryUtils.test.js.map +1 -1
  458. package/dist/src/ui/utils/editorUtils.d.ts +2 -1
  459. package/dist/src/ui/utils/editorUtils.js +75 -28
  460. package/dist/src/ui/utils/editorUtils.js.map +1 -1
  461. package/dist/src/ui/utils/latexToUnicode.d.ts +21 -0
  462. package/dist/src/ui/utils/latexToUnicode.js +538 -0
  463. package/dist/src/ui/utils/latexToUnicode.js.map +1 -0
  464. package/dist/src/ui/utils/latexToUnicode.test.d.ts +6 -0
  465. package/dist/src/ui/utils/latexToUnicode.test.js +222 -0
  466. package/dist/src/ui/utils/latexToUnicode.test.js.map +1 -0
  467. package/dist/src/ui/utils/markdownParsingUtils.d.ts +1 -5
  468. package/dist/src/ui/utils/markdownParsingUtils.js +36 -1
  469. package/dist/src/ui/utils/markdownParsingUtils.js.map +1 -1
  470. package/dist/src/ui/utils/markdownParsingUtils.test.js +35 -0
  471. package/dist/src/ui/utils/markdownParsingUtils.test.js.map +1 -1
  472. package/dist/src/ui/utils/memorySnapshot.d.ts +19 -0
  473. package/dist/src/ui/utils/memorySnapshot.js +28 -0
  474. package/dist/src/ui/utils/memorySnapshot.js.map +1 -0
  475. package/dist/src/ui/utils/memorySnapshot.test.d.ts +6 -0
  476. package/dist/src/ui/utils/memorySnapshot.test.js +62 -0
  477. package/dist/src/ui/utils/memorySnapshot.test.js.map +1 -0
  478. package/dist/src/ui/utils/updateCheck.js +11 -2
  479. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  480. package/dist/src/ui/utils/updateCheck.test.js +73 -0
  481. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  482. package/dist/src/utils/commands.d.ts +1 -1
  483. package/dist/src/utils/commands.js +1 -1
  484. package/dist/src/utils/commands.test.js +14 -14
  485. package/dist/src/utils/commands.test.js.map +1 -1
  486. package/dist/src/utils/envVarResolver.js +10 -7
  487. package/dist/src/utils/envVarResolver.js.map +1 -1
  488. package/dist/src/utils/gitUtils.js +1 -2
  489. package/dist/src/utils/gitUtils.js.map +1 -1
  490. package/dist/src/utils/handleAutoUpdate.d.ts +1 -1
  491. package/dist/src/utils/handleAutoUpdate.js +15 -3
  492. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  493. package/dist/src/utils/handleAutoUpdate.test.js +45 -16
  494. package/dist/src/utils/handleAutoUpdate.test.js.map +1 -1
  495. package/dist/src/utils/installationInfo.d.ts +1 -0
  496. package/dist/src/utils/installationInfo.js +16 -1
  497. package/dist/src/utils/installationInfo.js.map +1 -1
  498. package/dist/src/utils/installationInfo.test.js +16 -0
  499. package/dist/src/utils/installationInfo.test.js.map +1 -1
  500. package/dist/src/utils/jsonoutput.js +0 -2
  501. package/dist/src/utils/jsonoutput.js.map +1 -1
  502. package/dist/src/utils/processUtils.d.ts +28 -0
  503. package/dist/src/utils/processUtils.js +71 -0
  504. package/dist/src/utils/processUtils.js.map +1 -1
  505. package/dist/src/utils/processUtils.test.js +122 -1
  506. package/dist/src/utils/processUtils.test.js.map +1 -1
  507. package/dist/src/utils/readStdin.js +22 -4
  508. package/dist/src/utils/readStdin.js.map +1 -1
  509. package/dist/src/utils/readStdin.test.js +32 -0
  510. package/dist/src/utils/readStdin.test.js.map +1 -1
  511. package/dist/src/utils/relaunch.js +6 -13
  512. package/dist/src/utils/relaunch.js.map +1 -1
  513. package/dist/src/utils/relaunch.test.js +82 -86
  514. package/dist/src/utils/relaunch.test.js.map +1 -1
  515. package/dist/src/utils/sandbox.js +34 -24
  516. package/dist/src/utils/sandbox.js.map +1 -1
  517. package/dist/src/utils/sandbox.test.js +108 -9
  518. package/dist/src/utils/sandbox.test.js.map +1 -1
  519. package/dist/src/utils/sandboxUtils.js +12 -7
  520. package/dist/src/utils/sandboxUtils.js.map +1 -1
  521. package/dist/src/utils/sandboxUtils.test.js +68 -0
  522. package/dist/src/utils/sandboxUtils.test.js.map +1 -1
  523. package/dist/src/utils/sessionCleanup.js +49 -14
  524. package/dist/src/utils/sessionCleanup.js.map +1 -1
  525. package/dist/src/utils/sessionCleanup.test.js +63 -0
  526. package/dist/src/utils/sessionCleanup.test.js.map +1 -1
  527. package/dist/src/utils/sessionUtils.js +22 -7
  528. package/dist/src/utils/sessionUtils.js.map +1 -1
  529. package/dist/src/utils/sessionUtils.test.js +99 -0
  530. package/dist/src/utils/sessionUtils.test.js.map +1 -1
  531. package/dist/src/utils/sessions.js +2 -4
  532. package/dist/src/utils/sessions.js.map +1 -1
  533. package/dist/src/utils/sessions.test.js +9 -12
  534. package/dist/src/utils/sessions.test.js.map +1 -1
  535. package/dist/src/utils/userStartupWarnings.js +4 -3
  536. package/dist/src/utils/userStartupWarnings.js.map +1 -1
  537. package/dist/src/utils/userStartupWarnings.test.js +40 -3
  538. package/dist/src/utils/userStartupWarnings.test.js.map +1 -1
  539. package/dist/src/validateNonInterActiveAuth.js +1 -1
  540. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  541. package/dist/tsconfig.tsbuildinfo +1 -1
  542. package/package.json +5 -5
  543. package/dist/src/acp/acpClient.d.ts +0 -56
  544. package/dist/src/acp/acpClient.js.map +0 -1
  545. package/dist/src/acp/acpClient.test.js +0 -1814
  546. package/dist/src/acp/acpClient.test.js.map +0 -1
  547. package/dist/src/acp/commandHandler.js.map +0 -1
  548. package/dist/src/acp/commandHandler.test.js.map +0 -1
  549. package/dist/src/acp/fileSystemService.js.map +0 -1
  550. package/dist/src/acp/fileSystemService.test.js.map +0 -1
  551. package/dist/src/ui/auth/LoginWithGoogleRestartDialog.d.ts +0 -12
  552. package/dist/src/ui/auth/LoginWithGoogleRestartDialog.js.map +0 -1
  553. package/dist/src/ui/auth/LoginWithGoogleRestartDialog.test.js.map +0 -1
  554. package/dist/src/ui/components/SkillInboxDialog.js +0 -420
  555. package/dist/src/ui/components/SkillInboxDialog.js.map +0 -1
  556. package/dist/src/ui/components/SkillInboxDialog.test.js +0 -467
  557. package/dist/src/ui/components/SkillInboxDialog.test.js.map +0 -1
  558. /package/dist/src/acp/{commandHandler.test.d.ts → acpCommandHandler.test.d.ts} +0 -0
  559. /package/dist/src/{ui/components/SkillInboxDialog.test.d.ts → acp/acpFileSystemService.test.d.ts} +0 -0
  560. /package/dist/src/{acp/acpClient.test.d.ts → config/mutual-exclusivity.test.d.ts} +0 -0
  561. /package/dist/src/{acp/fileSystemService.test.d.ts → ui/commands/bugMemoryCommand.test.d.ts} +0 -0
  562. /package/dist/src/ui/{auth/LoginWithGoogleRestartDialog.test.d.ts → commands/exportSessionCommand.test.d.ts} +0 -0
@@ -1,352 +1,21 @@
1
1
  /**
2
2
  * @license
3
- * Copyright 2025 Google LLC
3
+ * Copyright 2026 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { CoreToolCallStatus, AuthType, logToolCall, convertToFunctionResponse, ToolConfirmationOutcome, clearCachedCredentialFile, isNodeError, getErrorMessage, isWithinRoot, getErrorStatus, MCPServerConfig, DiscoveredMCPTool, StreamEventType, ToolCallEvent, debugLogger, ReadManyFilesTool, REFERENCE_CONTENT_START, createWorkingStdio, startupProfiler, Kind, partListUnionToString, LlmRole, ApprovalMode, getVersion, convertSessionToClientHistory, DEFAULT_GEMINI_MODEL, DEFAULT_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_FLASH_LITE_MODEL, PREVIEW_GEMINI_MODEL, PREVIEW_GEMINI_3_1_MODEL, PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL, PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL, PREVIEW_GEMINI_FLASH_MODEL, DEFAULT_GEMINI_MODEL_AUTO, PREVIEW_GEMINI_MODEL_AUTO, getDisplayString, processSingleFileContent, InvalidStreamError, updatePolicy, } from '@google/gemini-cli-core';
6
+ import { CoreToolCallStatus, coreEvents, CoreEvent, logToolCall, convertToFunctionResponse, ToolConfirmationOutcome, getErrorStatus, DiscoveredMCPTool, ToolCallEvent, debugLogger, ReadManyFilesTool, partListUnionToString, updatePolicy, getErrorMessage, isTextPart, GeminiEventType, isWithinRoot, processSingleFileContent, isNodeError, REFERENCE_CONTENT_START, InvalidStreamError, MessageBusType, PolicyDecision, resolveAtCommandPath, } from '@google/gemini-cli-core';
7
7
  import * as acp from '@agentclientprotocol/sdk';
8
- import { AcpFileSystemService } from './fileSystemService.js';
9
- import { getAcpErrorMessage } from './acpErrors.js';
10
- import { Readable, Writable } from 'node:stream';
11
- function hasMeta(obj) {
12
- return typeof obj === 'object' && obj !== null && '_meta' in obj;
13
- }
14
- import { SettingScope, loadSettings, } from '../config/settings.js';
15
- import { createPolicyUpdater } from '../config/policy.js';
16
8
  import * as fs from 'node:fs/promises';
17
9
  import * as path from 'node:path';
18
- import { z } from 'zod';
19
10
  import { randomUUID } from 'node:crypto';
20
- import { loadCliConfig } from '../config/config.js';
21
- import { runExitCleanup } from '../utils/cleanup.js';
22
- import { SessionSelector } from '../utils/sessionUtils.js';
23
- import { startAutoMemoryIfEnabled } from '../utils/autoMemory.js';
24
- import { CommandHandler } from './commandHandler.js';
25
- const RequestPermissionResponseSchema = z.object({
26
- outcome: z.discriminatedUnion('outcome', [
27
- z.object({ outcome: z.literal('cancelled') }),
28
- z.object({
29
- outcome: z.literal('selected'),
30
- optionId: z.string(),
31
- }),
32
- ]),
11
+ import { CommandHandler } from './acpCommandHandler.js';
12
+ import { toToolCallContent, toPermissionOptions, toAcpToolKind, buildAvailableModes, RequestPermissionResponseSchema, } from './acpUtils.js';
13
+ import { z } from 'zod';
14
+ import { getAcpErrorMessage } from './acpErrors.js';
15
+ const StructuredErrorSchema = z.object({
16
+ status: z.number().optional(),
17
+ message: z.string().optional(),
33
18
  });
34
- export async function runAcpClient(config, settings, argv) {
35
- // ... (skip unchanged lines) ...
36
- const { stdout: workingStdout } = createWorkingStdio();
37
- const stdout = Writable.toWeb(workingStdout);
38
- // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
39
- const stdin = Readable.toWeb(process.stdin);
40
- const stream = acp.ndJsonStream(stdout, stdin);
41
- const connection = new acp.AgentSideConnection((connection) => new GeminiAgent(config, settings, argv, connection), stream);
42
- // SIGTERM/SIGINT handlers (in sdk.ts) don't fire when stdin closes.
43
- // We must explicitly await the connection close to flush telemetry.
44
- // Use finally() to ensure cleanup runs even on stream errors.
45
- await connection.closed.finally(runExitCleanup);
46
- }
47
- export class GeminiAgent {
48
- context;
49
- settings;
50
- argv;
51
- connection;
52
- static callIdCounter = 0;
53
- static generateCallId(name) {
54
- return `${name}-${Date.now()}-${++GeminiAgent.callIdCounter}`;
55
- }
56
- sessions = new Map();
57
- clientCapabilities;
58
- apiKey;
59
- baseUrl;
60
- customHeaders;
61
- constructor(context, settings, argv, connection) {
62
- this.context = context;
63
- this.settings = settings;
64
- this.argv = argv;
65
- this.connection = connection;
66
- }
67
- async initialize(args) {
68
- this.clientCapabilities = args.clientCapabilities;
69
- const authMethods = [
70
- {
71
- id: AuthType.LOGIN_WITH_GOOGLE,
72
- name: 'Log in with Google',
73
- description: 'Log in with your Google account',
74
- },
75
- {
76
- id: AuthType.USE_GEMINI,
77
- name: 'Gemini API key',
78
- description: 'Use an API key with Gemini Developer API',
79
- _meta: {
80
- 'api-key': {
81
- provider: 'google',
82
- },
83
- },
84
- },
85
- {
86
- id: AuthType.USE_VERTEX_AI,
87
- name: 'Vertex AI',
88
- description: 'Use an API key with Vertex AI GenAI API',
89
- },
90
- {
91
- id: AuthType.GATEWAY,
92
- name: 'AI API Gateway',
93
- description: 'Use a custom AI API Gateway',
94
- _meta: {
95
- gateway: {
96
- protocol: 'google',
97
- restartRequired: 'false',
98
- },
99
- },
100
- },
101
- ];
102
- await this.context.config.initialize();
103
- const version = await getVersion();
104
- return {
105
- protocolVersion: acp.PROTOCOL_VERSION,
106
- authMethods,
107
- agentInfo: {
108
- name: 'gemini-cli',
109
- title: 'Cell CLI',
110
- version,
111
- },
112
- agentCapabilities: {
113
- loadSession: true,
114
- promptCapabilities: {
115
- image: true,
116
- audio: true,
117
- embeddedContext: true,
118
- },
119
- mcpCapabilities: {
120
- http: true,
121
- sse: true,
122
- },
123
- },
124
- };
125
- }
126
- async authenticate(req) {
127
- const { methodId } = req;
128
- const method = z.nativeEnum(AuthType).parse(methodId);
129
- const selectedAuthType = this.settings.merged.security.auth.selectedType;
130
- // Only clear credentials when switching to a different auth method
131
- if (selectedAuthType && selectedAuthType !== method) {
132
- await clearCachedCredentialFile();
133
- }
134
- // Check for api-key in _meta
135
- const meta = hasMeta(req) ? req._meta : undefined;
136
- const apiKey = typeof meta?.['api-key'] === 'string' ? meta['api-key'] : undefined;
137
- // Refresh auth with the requested method
138
- // This will reuse existing credentials if they're valid,
139
- // or perform new authentication if needed
140
- try {
141
- if (apiKey) {
142
- this.apiKey = apiKey;
143
- }
144
- // Extract gateway details if present
145
- const gatewaySchema = z.object({
146
- baseUrl: z.string().optional(),
147
- headers: z.record(z.string()).optional(),
148
- });
149
- let baseUrl;
150
- let headers;
151
- if (meta?.['gateway']) {
152
- const result = gatewaySchema.safeParse(meta['gateway']);
153
- if (result.success) {
154
- baseUrl = result.data.baseUrl;
155
- headers = result.data.headers;
156
- }
157
- else {
158
- throw new acp.RequestError(-32602, `Malformed gateway payload: ${result.error.message}`);
159
- }
160
- }
161
- this.baseUrl = baseUrl;
162
- this.customHeaders = headers;
163
- await this.context.config.refreshAuth(method, undefined, apiKey ?? this.apiKey, baseUrl, headers);
164
- }
165
- catch (e) {
166
- throw new acp.RequestError(-32000, getAcpErrorMessage(e));
167
- }
168
- this.settings.setValue(SettingScope.User, 'security.auth.selectedType', method);
169
- }
170
- async newSession({ cwd, mcpServers, }) {
171
- const sessionId = randomUUID();
172
- const loadedSettings = loadSettings(cwd);
173
- const config = await this.newSessionConfig(sessionId, cwd, mcpServers, loadedSettings);
174
- const authType = loadedSettings.merged.security.auth.selectedType || AuthType.USE_GEMINI;
175
- let isAuthenticated = false;
176
- let authErrorMessage = '';
177
- try {
178
- await config.refreshAuth(authType, undefined, this.apiKey, this.baseUrl, this.customHeaders);
179
- isAuthenticated = true;
180
- // Extra validation for Gemini API key
181
- const contentGeneratorConfig = config.getContentGeneratorConfig();
182
- if (authType === AuthType.USE_GEMINI &&
183
- (!contentGeneratorConfig || !contentGeneratorConfig.apiKey)) {
184
- isAuthenticated = false;
185
- authErrorMessage = 'Gemini API key is missing or not configured.';
186
- }
187
- }
188
- catch (e) {
189
- isAuthenticated = false;
190
- authErrorMessage = getAcpErrorMessage(e);
191
- debugLogger.error(`Authentication failed: ${e instanceof Error ? e.stack : e}`);
192
- }
193
- if (!isAuthenticated) {
194
- throw new acp.RequestError(-32000, authErrorMessage || 'Authentication required.');
195
- }
196
- if (this.clientCapabilities?.fs) {
197
- const acpFileSystemService = new AcpFileSystemService(this.connection, sessionId, this.clientCapabilities.fs, config.getFileSystemService(), cwd);
198
- config.setFileSystemService(acpFileSystemService);
199
- }
200
- await config.initialize();
201
- startupProfiler.flush(config);
202
- startAutoMemoryIfEnabled(config);
203
- const geminiClient = config.getGeminiClient();
204
- const chat = await geminiClient.startChat();
205
- const session = new Session(sessionId, chat, config, this.connection, this.settings);
206
- this.sessions.set(sessionId, session);
207
- setTimeout(() => {
208
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
209
- session.sendAvailableCommands();
210
- }, 0);
211
- const { availableModels, currentModelId } = buildAvailableModels(config, loadedSettings);
212
- const response = {
213
- sessionId,
214
- modes: {
215
- availableModes: buildAvailableModes(config.isPlanEnabled()),
216
- currentModeId: config.getApprovalMode(),
217
- },
218
- models: {
219
- availableModels,
220
- currentModelId,
221
- },
222
- };
223
- return response;
224
- }
225
- async loadSession({ sessionId, cwd, mcpServers, }) {
226
- const config = await this.initializeSessionConfig(sessionId, cwd, mcpServers);
227
- const sessionSelector = new SessionSelector(config.storage);
228
- const { sessionData, sessionPath } = await sessionSelector.resolveSession(sessionId);
229
- const clientHistory = convertSessionToClientHistory(sessionData.messages);
230
- const geminiClient = config.getGeminiClient();
231
- await geminiClient.initialize();
232
- await geminiClient.resumeChat(clientHistory, {
233
- conversation: sessionData,
234
- filePath: sessionPath,
235
- });
236
- const session = new Session(sessionId, geminiClient.getChat(), config, this.connection, this.settings);
237
- this.sessions.set(sessionId, session);
238
- // Stream history back to client
239
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
240
- session.streamHistory(sessionData.messages);
241
- setTimeout(() => {
242
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
243
- session.sendAvailableCommands();
244
- }, 0);
245
- const { availableModels, currentModelId } = buildAvailableModels(config, this.settings);
246
- const response = {
247
- modes: {
248
- availableModes: buildAvailableModes(config.isPlanEnabled()),
249
- currentModeId: config.getApprovalMode(),
250
- },
251
- models: {
252
- availableModels,
253
- currentModelId,
254
- },
255
- };
256
- return response;
257
- }
258
- async initializeSessionConfig(sessionId, cwd, mcpServers) {
259
- const selectedAuthType = this.settings.merged.security.auth.selectedType;
260
- if (!selectedAuthType) {
261
- throw acp.RequestError.authRequired();
262
- }
263
- // 1. Create config WITHOUT initializing it (no MCP servers started yet)
264
- const config = await this.newSessionConfig(sessionId, cwd, mcpServers);
265
- // 2. Authenticate BEFORE initializing configuration or starting MCP servers.
266
- // This satisfies the security requirement to verify the user before executing
267
- // potentially unsafe server definitions.
268
- try {
269
- await config.refreshAuth(selectedAuthType, undefined, this.apiKey, this.baseUrl, this.customHeaders);
270
- }
271
- catch (e) {
272
- debugLogger.error(`Authentication failed: ${e}`);
273
- throw acp.RequestError.authRequired();
274
- }
275
- // 3. Set the ACP FileSystemService (if supported) before config initialization
276
- if (this.clientCapabilities?.fs) {
277
- const acpFileSystemService = new AcpFileSystemService(this.connection, sessionId, this.clientCapabilities.fs, config.getFileSystemService(), cwd);
278
- config.setFileSystemService(acpFileSystemService);
279
- }
280
- // 4. Now that we are authenticated, it is safe to initialize the config
281
- // which starts the MCP servers and other heavy resources.
282
- await config.initialize();
283
- startupProfiler.flush(config);
284
- startAutoMemoryIfEnabled(config);
285
- return config;
286
- }
287
- async newSessionConfig(sessionId, cwd, mcpServers, loadedSettings) {
288
- const currentSettings = loadedSettings || this.settings;
289
- const mergedMcpServers = { ...currentSettings.merged.mcpServers };
290
- for (const server of mcpServers) {
291
- if ('type' in server &&
292
- (server.type === 'sse' || server.type === 'http')) {
293
- // HTTP or SSE MCP server
294
- const headers = Object.fromEntries(server.headers.map(({ name, value }) => [name, value]));
295
- mergedMcpServers[server.name] = new MCPServerConfig(undefined, // command
296
- undefined, // args
297
- undefined, // env
298
- undefined, // cwd
299
- server.type === 'sse', // isSse
300
- server.type === 'sse' ? server.url : undefined, // url (sse)
301
- server.type === 'http' ? server.url : undefined, // httpUrl
302
- headers);
303
- }
304
- else if ('command' in server) {
305
- // Stdio MCP server
306
- const env = {};
307
- for (const { name: envName, value } of server.env) {
308
- env[envName] = value;
309
- }
310
- mergedMcpServers[server.name] = new MCPServerConfig(server.command, server.args, env, cwd);
311
- }
312
- }
313
- const settings = {
314
- ...currentSettings.merged,
315
- mcpServers: mergedMcpServers,
316
- };
317
- const config = await loadCliConfig(settings, sessionId, this.argv, { cwd });
318
- createPolicyUpdater(config.getPolicyEngine(), config.messageBus, config.storage);
319
- return config;
320
- }
321
- async cancel(params) {
322
- const session = this.sessions.get(params.sessionId);
323
- if (!session) {
324
- throw new Error(`Session not found: ${params.sessionId}`);
325
- }
326
- await session.cancelPendingPrompt();
327
- }
328
- async prompt(params) {
329
- const session = this.sessions.get(params.sessionId);
330
- if (!session) {
331
- throw new Error(`Session not found: ${params.sessionId}`);
332
- }
333
- return session.prompt(params);
334
- }
335
- async setSessionMode(params) {
336
- const session = this.sessions.get(params.sessionId);
337
- if (!session) {
338
- throw new Error(`Session not found: ${params.sessionId}`);
339
- }
340
- return session.setMode(params.modeId);
341
- }
342
- async unstable_setSessionModel(params) {
343
- const session = this.sessions.get(params.sessionId);
344
- if (!session) {
345
- throw new Error(`Session not found: ${params.sessionId}`);
346
- }
347
- return session.setModel(params.modelId);
348
- }
349
- }
350
19
  export class Session {
351
20
  id;
352
21
  chat;
@@ -355,12 +24,97 @@ export class Session {
355
24
  settings;
356
25
  pendingPrompt = null;
357
26
  commandHandler = new CommandHandler();
27
+ callIdCounter = 0;
28
+ disposeController = new AbortController();
29
+ generateCallId(name) {
30
+ return `${name}-${Date.now()}-${++this.callIdCounter}`;
31
+ }
358
32
  constructor(id, chat, context, connection, settings) {
359
33
  this.id = id;
360
34
  this.chat = chat;
361
35
  this.context = context;
362
36
  this.connection = connection;
363
37
  this.settings = settings;
38
+ coreEvents.on(CoreEvent.ApprovalModeChanged, this.handleApprovalModeChanged);
39
+ // Subscribe to tool confirmation requests to handle policy checks (e.g. auto-allowing safe shell commands)
40
+ this.context.config
41
+ .getMessageBus()
42
+ ?.subscribe(MessageBusType.TOOL_CONFIRMATION_REQUEST, this.handleToolConfirmationRequest, { signal: this.disposeController.signal });
43
+ }
44
+ handleToolConfirmationRequest = async (request) => {
45
+ try {
46
+ const policyEngine = this.context.config.getPolicyEngine?.();
47
+ const messageBus = this.context.config.getMessageBus();
48
+ if (!messageBus) {
49
+ return;
50
+ }
51
+ if (!policyEngine) {
52
+ debugLogger.warn('Policy engine missing. Denying tool confirmation request.');
53
+ await messageBus.publish({
54
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
55
+ correlationId: request.correlationId,
56
+ confirmed: false,
57
+ requiresUserConfirmation: false,
58
+ });
59
+ return;
60
+ }
61
+ const toolName = request.toolCall.name?.trim();
62
+ if (!toolName) {
63
+ debugLogger.warn('Tool confirmation request missing tool name. Denying.');
64
+ await messageBus.publish({
65
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
66
+ correlationId: request.correlationId,
67
+ confirmed: false,
68
+ requiresUserConfirmation: false,
69
+ });
70
+ return;
71
+ }
72
+ const tool = this.context.toolRegistry.getTool(toolName);
73
+ if (!tool) {
74
+ debugLogger.warn(`Tool confirmation request for unknown tool: ${toolName}. Denying.`);
75
+ await messageBus.publish({
76
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
77
+ correlationId: request.correlationId,
78
+ confirmed: false,
79
+ requiresUserConfirmation: false,
80
+ });
81
+ return;
82
+ }
83
+ const serverName = tool instanceof DiscoveredMCPTool ? tool.serverName : undefined;
84
+ const toolAnnotations = tool.toolAnnotations;
85
+ const result = await policyEngine.check(request.toolCall, serverName, toolAnnotations, request.subagent);
86
+ await messageBus.publish({
87
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
88
+ correlationId: request.correlationId,
89
+ confirmed: result.decision === PolicyDecision.ALLOW,
90
+ requiresUserConfirmation: result.decision === PolicyDecision.ASK_USER,
91
+ });
92
+ }
93
+ catch (error) {
94
+ debugLogger.error('Error handling tool confirmation request:', error);
95
+ // Fail closed on exception
96
+ await this.context.config.getMessageBus()?.publish({
97
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
98
+ correlationId: request.correlationId,
99
+ confirmed: false,
100
+ requiresUserConfirmation: false,
101
+ });
102
+ }
103
+ };
104
+ handleApprovalModeChanged = (payload) => {
105
+ if (payload.sessionId === this.id) {
106
+ void this.sendUpdate({
107
+ sessionUpdate: 'agent_message_chunk',
108
+ content: {
109
+ type: 'text',
110
+ text: `[MODE_UPDATE] ${payload.mode}`,
111
+ },
112
+ });
113
+ }
114
+ };
115
+ dispose() {
116
+ coreEvents.off(CoreEvent.ApprovalModeChanged, this.handleApprovalModeChanged);
117
+ this.disposeController.abort();
364
118
  }
365
119
  async cancelPendingPrompt() {
366
120
  if (!this.pendingPrompt) {
@@ -467,19 +221,15 @@ export class Session {
467
221
  this.pendingPrompt = pendingSend;
468
222
  await this.context.config.waitForMcpInit();
469
223
  const promptId = Math.random().toString(16).slice(2);
470
- const chat = this.chat;
471
224
  const parts = await this.#resolvePrompt(params.prompt, pendingSend.signal);
472
225
  // Command interception
473
226
  let commandText = '';
474
227
  for (const part of parts) {
475
228
  if (typeof part === 'object' && part !== null) {
476
- if ('text' in part) {
229
+ if (isTextPart(part)) {
477
230
  // It is a text part
478
- // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-unsafe-type-assertion
479
231
  const text = part.text;
480
- if (typeof text === 'string') {
481
- commandText += text;
482
- }
232
+ commandText += text;
483
233
  }
484
234
  else {
485
235
  // Non-text part (image, embedded resource)
@@ -510,78 +260,97 @@ export class Session {
510
260
  let totalInputTokens = 0;
511
261
  let totalOutputTokens = 0;
512
262
  const modelUsageMap = new Map();
513
- let nextMessage = { role: 'user', parts };
514
- while (nextMessage !== null) {
263
+ let currentParts = parts;
264
+ let turnCount = 0;
265
+ const maxTurns = this.context.config.getMaxSessionTurns();
266
+ while (true) {
267
+ turnCount++;
268
+ if (maxTurns >= 0 && turnCount > maxTurns) {
269
+ return {
270
+ stopReason: 'max_turn_requests',
271
+ _meta: {
272
+ quota: {
273
+ token_count: {
274
+ input_tokens: totalInputTokens,
275
+ output_tokens: totalOutputTokens,
276
+ },
277
+ model_usage: Array.from(modelUsageMap.entries()).map(([modelName, counts]) => ({
278
+ model: modelName,
279
+ token_count: {
280
+ input_tokens: counts.input,
281
+ output_tokens: counts.output,
282
+ },
283
+ })),
284
+ },
285
+ },
286
+ };
287
+ }
515
288
  if (pendingSend.signal.aborted) {
516
- chat.addHistory(nextMessage);
517
- return { stopReason: CoreToolCallStatus.Cancelled };
289
+ return { stopReason: 'cancelled' };
518
290
  }
519
- const functionCalls = [];
291
+ const toolCallRequests = [];
292
+ let stopReason = 'end_turn';
293
+ let turnModelId = this.context.config.getModel();
294
+ let turnInputTokens = 0;
295
+ let turnOutputTokens = 0;
520
296
  try {
521
- const routingContext = {
522
- history: chat.getHistory(/*curated=*/ true),
523
- request: nextMessage?.parts ?? [],
524
- signal: pendingSend.signal,
525
- requestedModel: this.context.config.getModel(),
526
- };
527
- const router = this.context.config.getModelRouterService();
528
- const { model } = await router.route(routingContext);
529
- const responseStream = await chat.sendMessageStream({ model }, nextMessage?.parts ?? [], promptId, pendingSend.signal, LlmRole.MAIN);
530
- nextMessage = null;
531
- let turnInputTokens = 0;
532
- let turnOutputTokens = 0;
533
- let turnModelId = model;
534
- for await (const resp of responseStream) {
297
+ const responseStream = this.context.geminiClient.sendMessageStream(currentParts, pendingSend.signal, promptId);
298
+ for await (const event of responseStream) {
535
299
  if (pendingSend.signal.aborted) {
536
- return { stopReason: CoreToolCallStatus.Cancelled };
537
- }
538
- if (resp.type === StreamEventType.CHUNK && resp.value.usageMetadata) {
539
- turnInputTokens =
540
- resp.value.usageMetadata.promptTokenCount ?? turnInputTokens;
541
- turnOutputTokens =
542
- resp.value.usageMetadata.candidatesTokenCount ?? turnOutputTokens;
543
- if (resp.value.modelVersion) {
544
- turnModelId = resp.value.modelVersion;
545
- }
300
+ return { stopReason: 'cancelled' };
546
301
  }
547
- if (resp.type === StreamEventType.CHUNK &&
548
- resp.value.candidates &&
549
- resp.value.candidates.length > 0) {
550
- const candidate = resp.value.candidates[0];
551
- for (const part of candidate.content?.parts ?? []) {
552
- if (!part.text) {
553
- continue;
554
- }
302
+ switch (event.type) {
303
+ case GeminiEventType.Content: {
555
304
  const content = {
556
305
  type: 'text',
557
- text: part.text,
306
+ text: event.value,
558
307
  };
559
- // eslint-disable-next-line @typescript-eslint/no-floating-promises
560
- this.sendUpdate({
561
- sessionUpdate: part.thought
562
- ? 'agent_thought_chunk'
563
- : 'agent_message_chunk',
308
+ await this.sendUpdate({
309
+ sessionUpdate: 'agent_message_chunk',
564
310
  content,
565
311
  });
312
+ break;
566
313
  }
314
+ case GeminiEventType.Thought: {
315
+ const thoughtText = `**${event.value.subject}**\n${event.value.description}`;
316
+ await this.sendUpdate({
317
+ sessionUpdate: 'agent_thought_chunk',
318
+ content: { type: 'text', text: thoughtText },
319
+ });
320
+ break;
321
+ }
322
+ case GeminiEventType.ToolCallRequest:
323
+ toolCallRequests.push(event.value);
324
+ break;
325
+ case GeminiEventType.Finished: {
326
+ const usage = event.value.usageMetadata;
327
+ if (usage) {
328
+ turnInputTokens = usage.promptTokenCount ?? turnInputTokens;
329
+ turnOutputTokens =
330
+ usage.candidatesTokenCount ?? turnOutputTokens;
331
+ }
332
+ break;
333
+ }
334
+ case GeminiEventType.ModelInfo:
335
+ turnModelId = event.value;
336
+ break;
337
+ case GeminiEventType.MaxSessionTurns:
338
+ stopReason = 'max_turn_requests';
339
+ break;
340
+ case GeminiEventType.LoopDetected:
341
+ stopReason = 'max_turn_requests';
342
+ break;
343
+ case GeminiEventType.ContextWindowWillOverflow:
344
+ stopReason = 'max_tokens';
345
+ break;
346
+ case GeminiEventType.Error: {
347
+ const parseResult = StructuredErrorSchema.safeParse(event.value.error);
348
+ const errData = parseResult.success ? parseResult.data : {};
349
+ throw new acp.RequestError(errData.status ?? 500, errData.message ?? 'Unknown stream execution error.');
350
+ }
351
+ default:
352
+ break;
567
353
  }
568
- if (resp.type === StreamEventType.CHUNK && resp.value.functionCalls) {
569
- functionCalls.push(...resp.value.functionCalls);
570
- }
571
- }
572
- totalInputTokens += turnInputTokens;
573
- totalOutputTokens += turnOutputTokens;
574
- if (turnInputTokens > 0 || turnOutputTokens > 0) {
575
- const existing = modelUsageMap.get(turnModelId) ?? {
576
- input: 0,
577
- output: 0,
578
- };
579
- existing.input += turnInputTokens;
580
- existing.output += turnOutputTokens;
581
- modelUsageMap.set(turnModelId, existing);
582
- }
583
- if (pendingSend.signal.aborted) {
584
- return { stopReason: CoreToolCallStatus.Cancelled };
585
354
  }
586
355
  }
587
356
  catch (error) {
@@ -590,7 +359,10 @@ export class Session {
590
359
  }
591
360
  if (pendingSend.signal.aborted ||
592
361
  (error instanceof Error && error.name === 'AbortError')) {
593
- return { stopReason: CoreToolCallStatus.Cancelled };
362
+ return { stopReason: 'cancelled' };
363
+ }
364
+ if (error instanceof acp.RequestError) {
365
+ throw error;
594
366
  }
595
367
  if (error instanceof InvalidStreamError ||
596
368
  (error &&
@@ -623,14 +395,51 @@ export class Session {
623
395
  }
624
396
  throw new acp.RequestError(getErrorStatus(error) || 500, getAcpErrorMessage(error));
625
397
  }
626
- if (functionCalls.length > 0) {
627
- const toolResponseParts = [];
628
- for (const fc of functionCalls) {
629
- const response = await this.runTool(pendingSend.signal, promptId, fc);
630
- toolResponseParts.push(...response);
631
- }
632
- nextMessage = { role: 'user', parts: toolResponseParts };
398
+ totalInputTokens += turnInputTokens;
399
+ totalOutputTokens += turnOutputTokens;
400
+ if (turnInputTokens > 0 || turnOutputTokens > 0) {
401
+ const existing = modelUsageMap.get(turnModelId) ?? {
402
+ input: 0,
403
+ output: 0,
404
+ };
405
+ existing.input += turnInputTokens;
406
+ existing.output += turnOutputTokens;
407
+ modelUsageMap.set(turnModelId, existing);
408
+ }
409
+ if (stopReason !== 'end_turn') {
410
+ return {
411
+ stopReason,
412
+ _meta: {
413
+ quota: {
414
+ token_count: {
415
+ input_tokens: totalInputTokens,
416
+ output_tokens: totalOutputTokens,
417
+ },
418
+ model_usage: Array.from(modelUsageMap.entries()).map(([modelName, counts]) => ({
419
+ model: modelName,
420
+ token_count: {
421
+ input_tokens: counts.input,
422
+ output_tokens: counts.output,
423
+ },
424
+ })),
425
+ },
426
+ },
427
+ };
428
+ }
429
+ if (toolCallRequests.length === 0) {
430
+ break;
633
431
  }
432
+ const toolResponseParts = [];
433
+ for (const tReq of toolCallRequests) {
434
+ const fc = {
435
+ id: tReq.callId,
436
+ name: tReq.name,
437
+ args: tReq.args,
438
+ };
439
+ const response = await this.runTool(pendingSend.signal, promptId, fc);
440
+ toolResponseParts.push(...response);
441
+ }
442
+ currentParts = toolResponseParts;
634
443
  }
635
444
  const modelUsageArray = Array.from(modelUsageMap.entries()).map(([modelName, counts]) => ({
636
445
  model: modelName,
@@ -677,7 +486,7 @@ export class Session {
677
486
  await this.connection.sessionUpdate(params);
678
487
  }
679
488
  async runTool(abortSignal, promptId, fc) {
680
- const callId = fc.id ?? GeminiAgent.generateCallId(fc.name || 'unknown');
489
+ const callId = fc.id ?? this.generateCallId(fc.name || 'unknown');
681
490
  const args = fc.args ?? {};
682
491
  const startTime = Date.now();
683
492
  const errorResponse = (error) => {
@@ -711,12 +520,6 @@ export class Session {
711
520
  const explanation = typeof invocation.getExplanation === 'function'
712
521
  ? invocation.getExplanation()
713
522
  : '';
714
- if (explanation) {
715
- await this.sendUpdate({
716
- sessionUpdate: 'agent_thought_chunk',
717
- content: { type: 'text', text: explanation },
718
- });
719
- }
720
523
  const confirmationDetails = await invocation.shouldConfirmExecute(abortSignal);
721
524
  if (confirmationDetails) {
722
525
  const content = [];
@@ -735,6 +538,12 @@ export class Session {
735
538
  },
736
539
  });
737
540
  }
541
+ if (content.length === 0 && explanation) {
542
+ content.push({
543
+ type: 'content',
544
+ content: { type: 'text', text: explanation },
545
+ });
546
+ }
738
547
  const params = {
739
548
  sessionId: this.id,
740
549
  options: toPermissionOptions(confirmationDetails, this.context.config, this.settings.merged.security.enablePermanentToolApproval),
@@ -774,6 +583,12 @@ export class Session {
774
583
  }
775
584
  else {
776
585
  const content = [];
586
+ if (explanation) {
587
+ content.push({
588
+ type: 'content',
589
+ content: { type: 'text', text: explanation },
590
+ });
591
+ }
777
592
  await this.sendUpdate({
778
593
  sessionUpdate: 'tool_call',
779
594
  toolCallId: callId,
@@ -935,80 +750,101 @@ export class Session {
935
750
  let currentPathSpec = pathName;
936
751
  let resolvedSuccessfully = false;
937
752
  let readDirectly = false;
938
- try {
939
- const absolutePath = path.resolve(this.context.config.getTargetDir(), pathName);
940
- let validationError = this.context.config.validatePathAccess(absolutePath, 'read');
941
- // We ask the user for explicit permission to read them if outside sandboxed workspace boundaries (and not already authorized).
942
- if (validationError &&
943
- !isWithinRoot(absolutePath, this.context.config.getTargetDir())) {
944
- try {
945
- const stats = await fs.stat(absolutePath);
946
- if (stats.isFile()) {
947
- const syntheticCallId = `resolve-prompt-${pathName}-${randomUUID()}`;
948
- const params = {
949
- sessionId: this.id,
950
- options: [
951
- {
952
- optionId: ToolConfirmationOutcome.ProceedOnce,
953
- name: 'Allow once',
954
- kind: 'allow_once',
955
- },
753
+ const result = await resolveAtCommandPath(pathName, this.context.config, (msg) => this.debug(msg));
754
+ let validationError = null;
755
+ let absolutePath;
756
+ let resolved;
757
+ if (result.status === 'resolved') {
758
+ resolved = result.resolved;
759
+ absolutePath = resolved.absolutePath;
760
+ }
761
+ else if (result.status === 'unauthorized') {
762
+ absolutePath = result.absolutePath;
763
+ validationError = result.error;
764
+ }
765
+ else if (result.status === 'invalid') {
766
+ // Already logged in resolveAtCommandPath
767
+ continue;
768
+ }
769
+ else {
770
+ // Result is not_found.
771
+ // We still check if it's an unauthorized absolute path that we can ask permission for,
772
+ // specifically for paths that are completely outside the root and not even in any workspace directory.
773
+ // For relative paths not found anywhere, we resolve relative to targetDir for permission check.
774
+ absolutePath = path.resolve(this.context.config.getTargetDir(), pathName);
775
+ }
776
+ if (!resolved &&
777
+ validationError &&
778
+ !isWithinRoot(absolutePath, this.context.config.getTargetDir())) {
779
+ try {
780
+ const stats = await fs.stat(absolutePath);
781
+ if (stats.isFile()) {
782
+ const syntheticCallId = `resolve-prompt-${pathName}-${randomUUID()}`;
783
+ const params = {
784
+ sessionId: this.id,
785
+ options: [
786
+ {
787
+ optionId: ToolConfirmationOutcome.ProceedOnce,
788
+ name: 'Allow once',
789
+ kind: 'allow_once',
790
+ },
791
+ {
792
+ optionId: ToolConfirmationOutcome.Cancel,
793
+ name: 'Deny',
794
+ kind: 'reject_once',
795
+ },
796
+ ],
797
+ toolCall: {
798
+ toolCallId: syntheticCallId,
799
+ status: 'pending',
800
+ title: `Allow access to absolute path: ${pathName}`,
801
+ content: [
956
802
  {
957
- optionId: ToolConfirmationOutcome.Cancel,
958
- name: 'Deny',
959
- kind: 'reject_once',
803
+ type: 'content',
804
+ content: {
805
+ type: 'text',
806
+ text: `The Agent needs access to read an attached file outside your workspace: ${pathName}`,
807
+ },
960
808
  },
961
809
  ],
962
- toolCall: {
963
- toolCallId: syntheticCallId,
964
- status: 'pending',
965
- title: `Allow access to absolute path: ${pathName}`,
966
- content: [
967
- {
968
- type: 'content',
969
- content: {
970
- type: 'text',
971
- text: `The Agent needs access to read an attached file outside your workspace: ${pathName}`,
972
- },
973
- },
974
- ],
975
- locations: [],
976
- kind: 'read',
977
- },
978
- };
979
- const output = RequestPermissionResponseSchema.parse(await this.connection.requestPermission(params));
980
- const outcome = output.outcome.outcome === 'cancelled'
981
- ? ToolConfirmationOutcome.Cancel
982
- : z
983
- .nativeEnum(ToolConfirmationOutcome)
984
- .parse(output.outcome.optionId);
985
- if (outcome === ToolConfirmationOutcome.ProceedOnce) {
986
- this.context.config
987
- .getWorkspaceContext()
988
- .addReadOnlyPath(absolutePath);
989
- validationError = null;
990
- }
991
- else {
992
- this.debug(`Direct read authorization denied for absolute path ${pathName}`);
993
- directContents.push({
994
- spec: pathName,
995
- content: `[Warning: Access to absolute path \`${pathName}\` denied by user.]`,
996
- });
997
- continue;
998
- }
999
- }
1000
- }
1001
- catch (error) {
1002
- this.debug(`Failed to request permission for absolute attachment ${pathName}: ${getErrorMessage(error)}`);
1003
- await this.sendUpdate({
1004
- sessionUpdate: 'agent_thought_chunk',
1005
- content: {
1006
- type: 'text',
1007
- text: `Warning: Failed to display permission dialog for \`${absolutePath}\`. Error: ${getErrorMessage(error)}`,
810
+ locations: [],
811
+ kind: 'read',
1008
812
  },
1009
- });
813
+ };
814
+ const output = RequestPermissionResponseSchema.parse(await this.connection.requestPermission(params));
815
+ const outcome = output.outcome.outcome === 'cancelled'
816
+ ? ToolConfirmationOutcome.Cancel
817
+ : z
818
+ .nativeEnum(ToolConfirmationOutcome)
819
+ .parse(output.outcome.optionId);
820
+ if (outcome === ToolConfirmationOutcome.ProceedOnce) {
821
+ this.context.config
822
+ .getWorkspaceContext()
823
+ .addReadOnlyPath(absolutePath);
824
+ validationError = null;
825
+ }
826
+ else {
827
+ this.debug(`Direct read authorization denied for absolute path ${pathName}`);
828
+ directContents.push({
829
+ spec: pathName,
830
+ content: `[Warning: Access to absolute path \`${pathName}\` denied by user.]`,
831
+ });
832
+ continue;
833
+ }
1010
834
  }
1011
835
  }
836
+ catch (error) {
837
+ this.debug(`Failed to request permission for absolute attachment ${pathName}: ${getErrorMessage(error)}`);
838
+ await this.sendUpdate({
839
+ sessionUpdate: 'agent_thought_chunk',
840
+ content: {
841
+ type: 'text',
842
+ text: `Warning: Failed to display permission dialog for \`${absolutePath}\`. Error: ${getErrorMessage(error)}`,
843
+ },
844
+ });
845
+ }
846
+ }
847
+ try {
1012
848
  if (!validationError) {
1013
849
  // If it's an absolute path that is authorized (e.g. added via readOnlyPaths),
1014
850
  // read it directly to avoid ReadManyFilesTool absolute path resolution issues.
@@ -1016,7 +852,9 @@ export class Session {
1016
852
  !isWithinRoot(absolutePath, this.context.config.getTargetDir())) &&
1017
853
  !readDirectly) {
1018
854
  try {
1019
- const stats = await fs.stat(absolutePath);
855
+ const stats = resolved
856
+ ? resolved.stats
857
+ : await fs.stat(absolutePath);
1020
858
  if (stats.isFile()) {
1021
859
  const fileReadResult = await processSingleFileContent(absolutePath, this.context.config.getTargetDir(), this.context.config.getFileSystemService());
1022
860
  if (!fileReadResult.error) {
@@ -1066,7 +904,9 @@ export class Session {
1066
904
  }
1067
905
  }
1068
906
  if (!readDirectly) {
1069
- const stats = await fs.stat(absolutePath);
907
+ const stats = resolved
908
+ ? resolved.stats
909
+ : await fs.stat(absolutePath);
1070
910
  if (stats.isDirectory()) {
1071
911
  currentPathSpec = pathName.endsWith('/')
1072
912
  ? `${pathName}**`
@@ -1195,7 +1035,7 @@ export class Session {
1195
1035
  const toolArgs = {
1196
1036
  include: pathSpecsToRead,
1197
1037
  };
1198
- const callId = GeminiAgent.generateCallId(readManyFilesTool.name);
1038
+ const callId = this.generateCallId(readManyFilesTool.name);
1199
1039
  try {
1200
1040
  const invocation = readManyFilesTool.build(toolArgs);
1201
1041
  await this.sendUpdate({
@@ -1325,285 +1165,4 @@ export class Session {
1325
1165
  }
1326
1166
  }
1327
1167
  }
1328
- function toToolCallContent(toolResult) {
1329
- if (toolResult.error?.message) {
1330
- throw new Error(toolResult.error.message);
1331
- }
1332
- if (toolResult.returnDisplay) {
1333
- if (typeof toolResult.returnDisplay === 'string') {
1334
- return {
1335
- type: 'content',
1336
- content: { type: 'text', text: toolResult.returnDisplay },
1337
- };
1338
- }
1339
- else {
1340
- if ('fileName' in toolResult.returnDisplay) {
1341
- return {
1342
- type: 'diff',
1343
- path: toolResult.returnDisplay.filePath ??
1344
- toolResult.returnDisplay.fileName,
1345
- oldText: toolResult.returnDisplay.originalContent,
1346
- newText: toolResult.returnDisplay.newContent,
1347
- _meta: {
1348
- kind: !toolResult.returnDisplay.originalContent
1349
- ? 'add'
1350
- : toolResult.returnDisplay.newContent === ''
1351
- ? 'delete'
1352
- : 'modify',
1353
- },
1354
- };
1355
- }
1356
- return null;
1357
- }
1358
- }
1359
- else {
1360
- return null;
1361
- }
1362
- }
1363
- const basicPermissionOptions = [
1364
- {
1365
- optionId: ToolConfirmationOutcome.ProceedOnce,
1366
- name: 'Allow',
1367
- kind: 'allow_once',
1368
- },
1369
- {
1370
- optionId: ToolConfirmationOutcome.Cancel,
1371
- name: 'Reject',
1372
- kind: 'reject_once',
1373
- },
1374
- ];
1375
- function toPermissionOptions(confirmation, config, enablePermanentToolApproval = false) {
1376
- const disableAlwaysAllow = config.getDisableAlwaysAllow();
1377
- const options = [];
1378
- if (!disableAlwaysAllow) {
1379
- switch (confirmation.type) {
1380
- case 'edit':
1381
- options.push({
1382
- optionId: ToolConfirmationOutcome.ProceedAlways,
1383
- name: 'Allow for this session',
1384
- kind: 'allow_always',
1385
- });
1386
- if (enablePermanentToolApproval) {
1387
- options.push({
1388
- optionId: ToolConfirmationOutcome.ProceedAlwaysAndSave,
1389
- name: 'Allow for this file in all future sessions',
1390
- kind: 'allow_always',
1391
- });
1392
- }
1393
- break;
1394
- case 'exec':
1395
- options.push({
1396
- optionId: ToolConfirmationOutcome.ProceedAlways,
1397
- name: 'Allow for this session',
1398
- kind: 'allow_always',
1399
- });
1400
- if (enablePermanentToolApproval) {
1401
- options.push({
1402
- optionId: ToolConfirmationOutcome.ProceedAlwaysAndSave,
1403
- name: 'Allow this command for all future sessions',
1404
- kind: 'allow_always',
1405
- });
1406
- }
1407
- break;
1408
- case 'mcp':
1409
- options.push({
1410
- optionId: ToolConfirmationOutcome.ProceedAlwaysServer,
1411
- name: 'Allow all server tools for this session',
1412
- kind: 'allow_always',
1413
- }, {
1414
- optionId: ToolConfirmationOutcome.ProceedAlwaysTool,
1415
- name: 'Allow tool for this session',
1416
- kind: 'allow_always',
1417
- });
1418
- if (enablePermanentToolApproval) {
1419
- options.push({
1420
- optionId: ToolConfirmationOutcome.ProceedAlwaysAndSave,
1421
- name: 'Allow tool for all future sessions',
1422
- kind: 'allow_always',
1423
- });
1424
- }
1425
- break;
1426
- case 'info':
1427
- options.push({
1428
- optionId: ToolConfirmationOutcome.ProceedAlways,
1429
- name: 'Allow for this session',
1430
- kind: 'allow_always',
1431
- });
1432
- if (enablePermanentToolApproval) {
1433
- options.push({
1434
- optionId: ToolConfirmationOutcome.ProceedAlwaysAndSave,
1435
- name: 'Allow for all future sessions',
1436
- kind: 'allow_always',
1437
- });
1438
- }
1439
- break;
1440
- case 'ask_user':
1441
- case 'exit_plan_mode':
1442
- // askuser and exit_plan_mode don't need "always allow" options
1443
- break;
1444
- default:
1445
- // No "always allow" options for other types
1446
- break;
1447
- }
1448
- }
1449
- options.push(...basicPermissionOptions);
1450
- // Exhaustive check
1451
- switch (confirmation.type) {
1452
- case 'edit':
1453
- case 'exec':
1454
- case 'mcp':
1455
- case 'info':
1456
- case 'ask_user':
1457
- case 'exit_plan_mode':
1458
- case 'sandbox_expansion':
1459
- break;
1460
- default: {
1461
- const unreachable = confirmation;
1462
- throw new Error(`Unexpected: ${unreachable}`);
1463
- }
1464
- }
1465
- return options;
1466
- }
1467
- /**
1468
- * Maps our internal tool kind to the ACP ToolKind.
1469
- * Fallback to 'other' for kinds that are not supported by the ACP protocol.
1470
- */
1471
- function toAcpToolKind(kind) {
1472
- switch (kind) {
1473
- case Kind.Read:
1474
- case Kind.Edit:
1475
- case Kind.Execute:
1476
- case Kind.Search:
1477
- case Kind.Delete:
1478
- case Kind.Move:
1479
- case Kind.Think:
1480
- case Kind.Fetch:
1481
- case Kind.SwitchMode:
1482
- case Kind.Other:
1483
- return kind;
1484
- case Kind.Agent:
1485
- return 'think';
1486
- case Kind.Plan:
1487
- case Kind.Communicate:
1488
- default:
1489
- return 'other';
1490
- }
1491
- }
1492
- function buildAvailableModes(isPlanEnabled) {
1493
- const modes = [
1494
- {
1495
- id: ApprovalMode.DEFAULT,
1496
- name: 'Default',
1497
- description: 'Prompts for approval',
1498
- },
1499
- {
1500
- id: ApprovalMode.AUTO_EDIT,
1501
- name: 'Auto Edit',
1502
- description: 'Auto-approves edit tools',
1503
- },
1504
- {
1505
- id: ApprovalMode.YOLO,
1506
- name: 'YOLO',
1507
- description: 'Auto-approves all tools',
1508
- },
1509
- ];
1510
- if (isPlanEnabled) {
1511
- modes.push({
1512
- id: ApprovalMode.PLAN,
1513
- name: 'Plan',
1514
- description: 'Read-only mode',
1515
- });
1516
- }
1517
- return modes;
1518
- }
1519
- function buildAvailableModels(config, settings) {
1520
- const preferredModel = config.getModel() || DEFAULT_GEMINI_MODEL_AUTO;
1521
- const shouldShowPreviewModels = config.getHasAccessToPreviewModel();
1522
- const useGemini31 = config.getGemini31LaunchedSync?.() ?? false;
1523
- const useGemini31FlashLite = config.getGemini31FlashLiteLaunchedSync?.() ?? false;
1524
- const selectedAuthType = settings.merged.security.auth.selectedType;
1525
- const useCustomToolModel = useGemini31 && selectedAuthType === AuthType.USE_GEMINI;
1526
- // --- DYNAMIC PATH ---
1527
- if (config.getExperimentalDynamicModelConfiguration?.() === true &&
1528
- config.getModelConfigService) {
1529
- const options = config.getModelConfigService().getAvailableModelOptions({
1530
- useGemini3_1: useGemini31,
1531
- useGemini3_1FlashLite: useGemini31FlashLite,
1532
- useCustomTools: useCustomToolModel,
1533
- hasAccessToPreview: shouldShowPreviewModels,
1534
- });
1535
- return {
1536
- availableModels: options,
1537
- currentModelId: preferredModel,
1538
- };
1539
- }
1540
- // --- LEGACY PATH ---
1541
- const mainOptions = [
1542
- {
1543
- value: DEFAULT_GEMINI_MODEL_AUTO,
1544
- title: getDisplayString(DEFAULT_GEMINI_MODEL_AUTO),
1545
- description: 'Let Cell CLI decide the best model for the task: gemini-2.5-pro, gemini-2.5-flash',
1546
- },
1547
- ];
1548
- if (shouldShowPreviewModels) {
1549
- mainOptions.unshift({
1550
- value: PREVIEW_GEMINI_MODEL_AUTO,
1551
- title: getDisplayString(PREVIEW_GEMINI_MODEL_AUTO),
1552
- description: useGemini31
1553
- ? 'Let Cell CLI decide the best model for the task: gemini-3.1-pro, gemini-3-flash'
1554
- : 'Let Cell CLI decide the best model for the task: gemini-3-pro, gemini-3-flash',
1555
- });
1556
- }
1557
- const manualOptions = [
1558
- {
1559
- value: DEFAULT_GEMINI_MODEL,
1560
- title: getDisplayString(DEFAULT_GEMINI_MODEL),
1561
- },
1562
- {
1563
- value: DEFAULT_GEMINI_FLASH_MODEL,
1564
- title: getDisplayString(DEFAULT_GEMINI_FLASH_MODEL),
1565
- },
1566
- {
1567
- value: DEFAULT_GEMINI_FLASH_LITE_MODEL,
1568
- title: getDisplayString(DEFAULT_GEMINI_FLASH_LITE_MODEL),
1569
- },
1570
- ];
1571
- if (shouldShowPreviewModels) {
1572
- const previewProModel = useGemini31
1573
- ? PREVIEW_GEMINI_3_1_MODEL
1574
- : PREVIEW_GEMINI_MODEL;
1575
- const previewProValue = useCustomToolModel
1576
- ? PREVIEW_GEMINI_3_1_CUSTOM_TOOLS_MODEL
1577
- : previewProModel;
1578
- const previewOptions = [
1579
- {
1580
- value: previewProValue,
1581
- title: getDisplayString(previewProModel),
1582
- },
1583
- {
1584
- value: PREVIEW_GEMINI_FLASH_MODEL,
1585
- title: getDisplayString(PREVIEW_GEMINI_FLASH_MODEL),
1586
- },
1587
- ];
1588
- if (useGemini31FlashLite) {
1589
- previewOptions.push({
1590
- value: PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL,
1591
- title: getDisplayString(PREVIEW_GEMINI_3_1_FLASH_LITE_MODEL),
1592
- });
1593
- }
1594
- manualOptions.unshift(...previewOptions);
1595
- }
1596
- const scaleOptions = (options) => options.map((o) => ({
1597
- modelId: o.value,
1598
- name: o.title,
1599
- description: o.description,
1600
- }));
1601
- return {
1602
- availableModels: [
1603
- ...scaleOptions(mainOptions),
1604
- ...scaleOptions(manualOptions),
1605
- ],
1606
- currentModelId: preferredModel,
1607
- };
1608
- }
1609
- //# sourceMappingURL=acpClient.js.map
1168
+ //# sourceMappingURL=acpSession.js.map