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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (637) hide show
  1. package/dist/index.js +5 -5
  2. package/dist/index.js.map +1 -1
  3. package/dist/package.json +8 -7
  4. package/dist/src/commands/extensions/disable.js +8 -5
  5. package/dist/src/commands/extensions/disable.js.map +1 -1
  6. package/dist/src/commands/extensions/enable.js +8 -6
  7. package/dist/src/commands/extensions/enable.js.map +1 -1
  8. package/dist/src/commands/extensions/examples/context/GEMINI.md +9 -3
  9. package/dist/src/commands/extensions/examples/mcp-server/example.d.ts +6 -0
  10. package/dist/src/commands/extensions/examples/mcp-server/example.js +46 -0
  11. package/dist/src/commands/extensions/examples/mcp-server/example.js.map +1 -0
  12. package/dist/src/commands/extensions/install.d.ts +2 -0
  13. package/dist/src/commands/extensions/install.js +25 -5
  14. package/dist/src/commands/extensions/install.js.map +1 -1
  15. package/dist/src/commands/extensions/install.test.js +9 -9
  16. package/dist/src/commands/extensions/install.test.js.map +1 -1
  17. package/dist/src/commands/extensions/link.js +5 -4
  18. package/dist/src/commands/extensions/link.js.map +1 -1
  19. package/dist/src/commands/extensions/list.js +7 -5
  20. package/dist/src/commands/extensions/list.js.map +1 -1
  21. package/dist/src/commands/extensions/new.js +14 -20
  22. package/dist/src/commands/extensions/new.js.map +1 -1
  23. package/dist/src/commands/extensions/uninstall.js +4 -3
  24. package/dist/src/commands/extensions/uninstall.js.map +1 -1
  25. package/dist/src/commands/extensions/update.js +18 -22
  26. package/dist/src/commands/extensions/update.js.map +1 -1
  27. package/dist/src/commands/mcp/add.js +7 -4
  28. package/dist/src/commands/mcp/add.js.map +1 -1
  29. package/dist/src/commands/mcp/add.test.d.ts +6 -0
  30. package/dist/src/commands/mcp/add.test.js +244 -0
  31. package/dist/src/commands/mcp/add.test.js.map +1 -0
  32. package/dist/src/commands/mcp/list.js +11 -9
  33. package/dist/src/commands/mcp/list.js.map +1 -1
  34. package/dist/src/commands/mcp/list.test.d.ts +6 -0
  35. package/dist/src/commands/mcp/list.test.js +118 -0
  36. package/dist/src/commands/mcp/list.test.js.map +1 -0
  37. package/dist/src/commands/mcp/remove.js +3 -2
  38. package/dist/src/commands/mcp/remove.js.map +1 -1
  39. package/dist/src/commands/mcp/remove.test.d.ts +6 -0
  40. package/dist/src/commands/mcp/remove.test.js +175 -0
  41. package/dist/src/commands/mcp/remove.test.js.map +1 -0
  42. package/dist/src/commands/mcp.test.d.ts +6 -0
  43. package/dist/src/commands/mcp.test.js +62 -0
  44. package/dist/src/commands/mcp.test.js.map +1 -0
  45. package/dist/src/config/auth.js +3 -1
  46. package/dist/src/config/auth.js.map +1 -1
  47. package/dist/src/config/config.d.ts +4 -16
  48. package/dist/src/config/config.integration.test.d.ts +6 -0
  49. package/dist/src/config/config.integration.test.js +321 -0
  50. package/dist/src/config/config.integration.test.js.map +1 -0
  51. package/dist/src/config/config.js +80 -105
  52. package/dist/src/config/config.js.map +1 -1
  53. package/dist/src/config/config.test.d.ts +6 -0
  54. package/dist/src/config/config.test.js +1949 -0
  55. package/dist/src/config/config.test.js.map +1 -0
  56. package/dist/src/config/extension.d.ts +19 -27
  57. package/dist/src/config/extension.js +159 -139
  58. package/dist/src/config/extension.js.map +1 -1
  59. package/dist/src/config/extension.test.d.ts +6 -0
  60. package/dist/src/config/extension.test.js +1088 -0
  61. package/dist/src/config/extension.test.js.map +1 -0
  62. package/dist/src/config/extensions/extensionEnablement.d.ts +3 -3
  63. package/dist/src/config/extensions/extensionEnablement.js +5 -5
  64. package/dist/src/config/extensions/extensionEnablement.js.map +1 -1
  65. package/dist/src/config/extensions/extensionEnablement.test.js +26 -22
  66. package/dist/src/config/extensions/extensionEnablement.test.js.map +1 -1
  67. package/dist/src/config/extensions/github.d.ts +23 -7
  68. package/dist/src/config/extensions/github.js +139 -88
  69. package/dist/src/config/extensions/github.js.map +1 -1
  70. package/dist/src/config/extensions/github.test.js +74 -22
  71. package/dist/src/config/extensions/github.test.js.map +1 -1
  72. package/dist/src/config/extensions/github_fetch.d.ts +7 -0
  73. package/dist/src/config/extensions/github_fetch.js +34 -0
  74. package/dist/src/config/extensions/github_fetch.js.map +1 -0
  75. package/dist/src/config/extensions/update.d.ts +5 -4
  76. package/dist/src/config/extensions/update.js +23 -16
  77. package/dist/src/config/extensions/update.js.map +1 -1
  78. package/dist/src/config/extensions/update.test.js +57 -57
  79. package/dist/src/config/extensions/update.test.js.map +1 -1
  80. package/dist/src/config/extensions/variableSchema.d.ts +2 -0
  81. package/dist/src/config/extensions/variableSchema.js.map +1 -1
  82. package/dist/src/config/keyBindings.d.ts +2 -1
  83. package/dist/src/config/keyBindings.js +5 -3
  84. package/dist/src/config/keyBindings.js.map +1 -1
  85. package/dist/src/config/policy.d.ts +3 -2
  86. package/dist/src/config/policy.js +33 -24
  87. package/dist/src/config/policy.js.map +1 -1
  88. package/dist/src/config/policy.test.js +60 -36
  89. package/dist/src/config/policy.test.js.map +1 -1
  90. package/dist/src/config/sandboxConfig.d.ts +0 -1
  91. package/dist/src/config/sandboxConfig.js +1 -3
  92. package/dist/src/config/sandboxConfig.js.map +1 -1
  93. package/dist/src/config/settings.d.ts +10 -1
  94. package/dist/src/config/settings.js +24 -9
  95. package/dist/src/config/settings.js.map +1 -1
  96. package/dist/src/config/settings.test.d.ts +6 -0
  97. package/dist/src/config/settings.test.js +1941 -0
  98. package/dist/src/config/settings.test.js.map +1 -0
  99. package/dist/src/config/settingsSchema.d.ts +124 -3
  100. package/dist/src/config/settingsSchema.js +125 -4
  101. package/dist/src/config/settingsSchema.js.map +1 -1
  102. package/dist/src/config/trustedFolders.d.ts +0 -1
  103. package/dist/src/config/trustedFolders.js +2 -3
  104. package/dist/src/config/trustedFolders.js.map +1 -1
  105. package/dist/src/gemini.js +46 -33
  106. package/dist/src/gemini.js.map +1 -1
  107. package/dist/src/gemini.test.js +62 -19
  108. package/dist/src/gemini.test.js.map +1 -1
  109. package/dist/src/generated/git-commit.d.ts +2 -2
  110. package/dist/src/generated/git-commit.js +2 -2
  111. package/dist/src/generated/git-commit.js.map +1 -1
  112. package/dist/src/nonInteractiveCli.js +105 -4
  113. package/dist/src/nonInteractiveCli.js.map +1 -1
  114. package/dist/src/nonInteractiveCli.test.d.ts +6 -0
  115. package/dist/src/nonInteractiveCli.test.js +741 -0
  116. package/dist/src/nonInteractiveCli.test.js.map +1 -0
  117. package/dist/src/nonInteractiveCliCommands.js +2 -3
  118. package/dist/src/nonInteractiveCliCommands.js.map +1 -1
  119. package/dist/src/services/BuiltinCommandLoader.js +3 -0
  120. package/dist/src/services/BuiltinCommandLoader.js.map +1 -1
  121. package/dist/src/services/BuiltinCommandLoader.test.js +37 -0
  122. package/dist/src/services/BuiltinCommandLoader.test.js.map +1 -1
  123. package/dist/src/services/CommandService.js +2 -1
  124. package/dist/src/services/CommandService.js.map +1 -1
  125. package/dist/src/services/FileCommandLoader.d.ts +1 -1
  126. package/dist/src/services/FileCommandLoader.js +4 -4
  127. package/dist/src/services/FileCommandLoader.js.map +1 -1
  128. package/dist/src/services/FileCommandLoader.test.d.ts +6 -0
  129. package/dist/src/services/FileCommandLoader.test.js +971 -0
  130. package/dist/src/services/FileCommandLoader.test.js.map +1 -0
  131. package/dist/src/services/prompt-processors/argumentProcessor.test.d.ts +6 -0
  132. package/dist/src/services/prompt-processors/argumentProcessor.test.js +40 -0
  133. package/dist/src/services/prompt-processors/argumentProcessor.test.js.map +1 -0
  134. package/dist/src/services/prompt-processors/atFileProcessor.js +3 -2
  135. package/dist/src/services/prompt-processors/atFileProcessor.js.map +1 -1
  136. package/dist/src/services/prompt-processors/shellProcessor.js +1 -1
  137. package/dist/src/services/prompt-processors/shellProcessor.js.map +1 -1
  138. package/dist/src/services/prompt-processors/shellProcessor.test.d.ts +6 -0
  139. package/dist/src/services/prompt-processors/shellProcessor.test.js +482 -0
  140. package/dist/src/services/prompt-processors/shellProcessor.test.js.map +1 -0
  141. package/dist/src/test-utils/render.d.ts +12 -4
  142. package/dist/src/test-utils/render.js +56 -2
  143. package/dist/src/test-utils/render.js.map +1 -1
  144. package/dist/src/ui/App.js +1 -17
  145. package/dist/src/ui/App.js.map +1 -1
  146. package/dist/src/ui/App.test.d.ts +6 -0
  147. package/dist/src/ui/App.test.js +110 -0
  148. package/dist/src/ui/App.test.js.map +1 -0
  149. package/dist/src/ui/AppContainer.js +69 -39
  150. package/dist/src/ui/AppContainer.js.map +1 -1
  151. package/dist/src/ui/AppContainer.test.js +35 -9
  152. package/dist/src/ui/AppContainer.test.js.map +1 -1
  153. package/dist/src/ui/auth/AuthDialog.d.ts +1 -1
  154. package/dist/src/ui/auth/AuthDialog.js +5 -3
  155. package/dist/src/ui/auth/AuthDialog.js.map +1 -1
  156. package/dist/src/ui/auth/AuthInProgress.js +2 -2
  157. package/dist/src/ui/auth/AuthInProgress.js.map +1 -1
  158. package/dist/src/ui/auth/useAuth.d.ts +1 -1
  159. package/dist/src/ui/auth/useAuth.js +5 -3
  160. package/dist/src/ui/auth/useAuth.js.map +1 -1
  161. package/dist/src/ui/commands/aboutCommand.js +1 -1
  162. package/dist/src/ui/commands/aboutCommand.test.d.ts +6 -0
  163. package/dist/src/ui/commands/aboutCommand.test.js +130 -0
  164. package/dist/src/ui/commands/aboutCommand.test.js.map +1 -0
  165. package/dist/src/ui/commands/authCommand.js +1 -1
  166. package/dist/src/ui/commands/authCommand.test.d.ts +6 -0
  167. package/dist/src/ui/commands/authCommand.test.js +30 -0
  168. package/dist/src/ui/commands/authCommand.test.js.map +1 -0
  169. package/dist/src/ui/commands/bugCommand.js +1 -1
  170. package/dist/src/ui/commands/bugCommand.test.d.ts +6 -0
  171. package/dist/src/ui/commands/bugCommand.test.js +105 -0
  172. package/dist/src/ui/commands/bugCommand.test.js.map +1 -0
  173. package/dist/src/ui/commands/chatCommand.js +8 -25
  174. package/dist/src/ui/commands/chatCommand.js.map +1 -1
  175. package/dist/src/ui/commands/chatCommand.test.d.ts +6 -0
  176. package/dist/src/ui/commands/chatCommand.test.js +555 -0
  177. package/dist/src/ui/commands/chatCommand.test.js.map +1 -0
  178. package/dist/src/ui/commands/clearCommand.js +1 -1
  179. package/dist/src/ui/commands/clearCommand.test.d.ts +6 -0
  180. package/dist/src/ui/commands/clearCommand.test.js +76 -0
  181. package/dist/src/ui/commands/clearCommand.test.js.map +1 -0
  182. package/dist/src/ui/commands/compressCommand.js +1 -1
  183. package/dist/src/ui/commands/compressCommand.js.map +1 -1
  184. package/dist/src/ui/commands/compressCommand.test.d.ts +6 -0
  185. package/dist/src/ui/commands/compressCommand.test.js +98 -0
  186. package/dist/src/ui/commands/compressCommand.test.js.map +1 -0
  187. package/dist/src/ui/commands/copyCommand.js +2 -1
  188. package/dist/src/ui/commands/copyCommand.js.map +1 -1
  189. package/dist/src/ui/commands/copyCommand.test.d.ts +6 -0
  190. package/dist/src/ui/commands/copyCommand.test.js +242 -0
  191. package/dist/src/ui/commands/copyCommand.test.js.map +1 -0
  192. package/dist/src/ui/commands/corgiCommand.js +1 -1
  193. package/dist/src/ui/commands/corgiCommand.js.map +1 -1
  194. package/dist/src/ui/commands/corgiCommand.test.d.ts +6 -0
  195. package/dist/src/ui/commands/corgiCommand.test.js +28 -0
  196. package/dist/src/ui/commands/corgiCommand.test.js.map +1 -0
  197. package/dist/src/ui/commands/directoryCommand.js +1 -1
  198. package/dist/src/ui/commands/directoryCommand.js.map +1 -1
  199. package/dist/src/ui/commands/directoryCommand.test.d.ts +6 -0
  200. package/dist/src/ui/commands/directoryCommand.test.js +144 -0
  201. package/dist/src/ui/commands/directoryCommand.test.js.map +1 -0
  202. package/dist/src/ui/commands/docsCommand.js +1 -1
  203. package/dist/src/ui/commands/docsCommand.test.d.ts +6 -0
  204. package/dist/src/ui/commands/docsCommand.test.js +72 -0
  205. package/dist/src/ui/commands/docsCommand.test.js.map +1 -0
  206. package/dist/src/ui/commands/editorCommand.js +1 -1
  207. package/dist/src/ui/commands/editorCommand.test.d.ts +6 -0
  208. package/dist/src/ui/commands/editorCommand.test.js +27 -0
  209. package/dist/src/ui/commands/editorCommand.test.js.map +1 -0
  210. package/dist/src/ui/commands/extensionsCommand.js +30 -32
  211. package/dist/src/ui/commands/extensionsCommand.js.map +1 -1
  212. package/dist/src/ui/commands/extensionsCommand.test.d.ts +6 -0
  213. package/dist/src/ui/commands/extensionsCommand.test.js +244 -0
  214. package/dist/src/ui/commands/extensionsCommand.test.js.map +1 -0
  215. package/dist/src/ui/commands/helpCommand.js +1 -1
  216. package/dist/src/ui/commands/helpCommand.test.d.ts +6 -0
  217. package/dist/src/ui/commands/helpCommand.test.js +42 -0
  218. package/dist/src/ui/commands/helpCommand.test.js.map +1 -0
  219. package/dist/src/ui/commands/ideCommand.js +6 -6
  220. package/dist/src/ui/commands/ideCommand.test.d.ts +6 -0
  221. package/dist/src/ui/commands/ideCommand.test.js +205 -0
  222. package/dist/src/ui/commands/ideCommand.test.js.map +1 -0
  223. package/dist/src/ui/commands/initCommand.js +1 -1
  224. package/dist/src/ui/commands/initCommand.js.map +1 -1
  225. package/dist/src/ui/commands/initCommand.test.d.ts +6 -0
  226. package/dist/src/ui/commands/initCommand.test.js +80 -0
  227. package/dist/src/ui/commands/initCommand.test.js.map +1 -0
  228. package/dist/src/ui/commands/mcpCommand.js +98 -88
  229. package/dist/src/ui/commands/mcpCommand.js.map +1 -1
  230. package/dist/src/ui/commands/mcpCommand.test.d.ts +6 -0
  231. package/dist/src/ui/commands/mcpCommand.test.js +148 -0
  232. package/dist/src/ui/commands/mcpCommand.test.js.map +1 -0
  233. package/dist/src/ui/commands/memoryCommand.js +27 -9
  234. package/dist/src/ui/commands/memoryCommand.js.map +1 -1
  235. package/dist/src/ui/commands/memoryCommand.test.d.ts +6 -0
  236. package/dist/src/ui/commands/memoryCommand.test.js +266 -0
  237. package/dist/src/ui/commands/memoryCommand.test.js.map +1 -0
  238. package/dist/src/ui/commands/privacyCommand.js +1 -1
  239. package/dist/src/ui/commands/privacyCommand.test.d.ts +6 -0
  240. package/dist/src/ui/commands/privacyCommand.test.js +32 -0
  241. package/dist/src/ui/commands/privacyCommand.test.js.map +1 -0
  242. package/dist/src/ui/commands/profileCommand.d.ts +7 -0
  243. package/dist/src/ui/commands/profileCommand.js +23 -0
  244. package/dist/src/ui/commands/profileCommand.js.map +1 -0
  245. package/dist/src/ui/commands/quitCommand.js +1 -1
  246. package/dist/src/ui/commands/quitCommand.test.d.ts +6 -0
  247. package/dist/src/ui/commands/quitCommand.test.js +50 -0
  248. package/dist/src/ui/commands/quitCommand.test.js.map +1 -0
  249. package/dist/src/ui/commands/restoreCommand.test.d.ts +6 -0
  250. package/dist/src/ui/commands/restoreCommand.test.js +190 -0
  251. package/dist/src/ui/commands/restoreCommand.test.js.map +1 -0
  252. package/dist/src/ui/commands/settingsCommand.test.d.ts +6 -0
  253. package/dist/src/ui/commands/settingsCommand.test.js +30 -0
  254. package/dist/src/ui/commands/settingsCommand.test.js.map +1 -0
  255. package/dist/src/ui/commands/setupGithubCommand.js +4 -3
  256. package/dist/src/ui/commands/setupGithubCommand.js.map +1 -1
  257. package/dist/src/ui/commands/statsCommand.js +3 -3
  258. package/dist/src/ui/commands/statsCommand.js.map +1 -1
  259. package/dist/src/ui/commands/statsCommand.test.d.ts +6 -0
  260. package/dist/src/ui/commands/statsCommand.test.js +53 -0
  261. package/dist/src/ui/commands/statsCommand.test.js.map +1 -0
  262. package/dist/src/ui/commands/terminalSetupCommand.test.d.ts +6 -0
  263. package/dist/src/ui/commands/terminalSetupCommand.test.js +66 -0
  264. package/dist/src/ui/commands/terminalSetupCommand.test.js.map +1 -0
  265. package/dist/src/ui/commands/themeCommand.js +1 -1
  266. package/dist/src/ui/commands/themeCommand.test.d.ts +6 -0
  267. package/dist/src/ui/commands/themeCommand.test.js +32 -0
  268. package/dist/src/ui/commands/themeCommand.test.js.map +1 -0
  269. package/dist/src/ui/commands/toolsCommand.js +1 -1
  270. package/dist/src/ui/commands/toolsCommand.test.d.ts +6 -0
  271. package/dist/src/ui/commands/toolsCommand.test.js +100 -0
  272. package/dist/src/ui/commands/toolsCommand.test.js.map +1 -0
  273. package/dist/src/ui/commands/types.d.ts +2 -0
  274. package/dist/src/ui/commands/types.js.map +1 -1
  275. package/dist/src/ui/commands/vimCommand.js +1 -1
  276. package/dist/src/ui/components/AnsiOutput.d.ts +1 -0
  277. package/dist/src/ui/components/AnsiOutput.js +5 -5
  278. package/dist/src/ui/components/AnsiOutput.js.map +1 -1
  279. package/dist/src/ui/components/AnsiOutput.test.js +6 -6
  280. package/dist/src/ui/components/AnsiOutput.test.js.map +1 -1
  281. package/dist/src/ui/components/AsciiArt.d.ts +3 -3
  282. package/dist/src/ui/components/AsciiArt.js +3 -3
  283. package/dist/src/ui/components/CliSpinner.d.ts +10 -0
  284. package/dist/src/ui/components/CliSpinner.js +20 -0
  285. package/dist/src/ui/components/CliSpinner.js.map +1 -0
  286. package/dist/src/ui/components/Composer.js +8 -9
  287. package/dist/src/ui/components/Composer.js.map +1 -1
  288. package/dist/src/ui/components/Composer.test.js +16 -1
  289. package/dist/src/ui/components/Composer.test.js.map +1 -1
  290. package/dist/src/ui/components/ContextSummaryDisplay.d.ts +0 -1
  291. package/dist/src/ui/components/ContextSummaryDisplay.js +4 -14
  292. package/dist/src/ui/components/ContextSummaryDisplay.js.map +1 -1
  293. package/dist/src/ui/components/ContextSummaryDisplay.test.d.ts +6 -0
  294. package/dist/src/ui/components/ContextSummaryDisplay.test.js +66 -0
  295. package/dist/src/ui/components/ContextSummaryDisplay.test.js.map +1 -0
  296. package/dist/src/ui/components/DebugProfiler.d.ts +18 -0
  297. package/dist/src/ui/components/DebugProfiler.js +158 -12
  298. package/dist/src/ui/components/DebugProfiler.js.map +1 -1
  299. package/dist/src/ui/components/DebugProfiler.test.d.ts +6 -0
  300. package/dist/src/ui/components/DebugProfiler.test.js +140 -0
  301. package/dist/src/ui/components/DebugProfiler.test.js.map +1 -0
  302. package/dist/src/ui/components/DialogManager.js +1 -5
  303. package/dist/src/ui/components/DialogManager.js.map +1 -1
  304. package/dist/src/ui/components/EditorSettingsDialog.js +1 -1
  305. package/dist/src/ui/components/EditorSettingsDialog.js.map +1 -1
  306. package/dist/src/ui/components/FolderTrustDialog.js +9 -5
  307. package/dist/src/ui/components/FolderTrustDialog.js.map +1 -1
  308. package/dist/src/ui/components/FolderTrustDialog.test.js +14 -14
  309. package/dist/src/ui/components/FolderTrustDialog.test.js.map +1 -1
  310. package/dist/src/ui/components/Footer.js +7 -6
  311. package/dist/src/ui/components/Footer.js.map +1 -1
  312. package/dist/src/ui/components/Footer.test.d.ts +6 -0
  313. package/dist/src/ui/components/Footer.test.js +231 -0
  314. package/dist/src/ui/components/Footer.test.js.map +1 -0
  315. package/dist/src/ui/components/GeminiRespondingSpinner.js +2 -2
  316. package/dist/src/ui/components/GeminiRespondingSpinner.js.map +1 -1
  317. package/dist/src/ui/components/Help.js +1 -1
  318. package/dist/src/ui/components/Help.js.map +1 -1
  319. package/dist/src/ui/components/HistoryItemDisplay.js +2 -1
  320. package/dist/src/ui/components/HistoryItemDisplay.js.map +1 -1
  321. package/dist/src/ui/components/InputPrompt.d.ts +11 -1
  322. package/dist/src/ui/components/InputPrompt.js +103 -29
  323. package/dist/src/ui/components/InputPrompt.js.map +1 -1
  324. package/dist/src/ui/components/InputPrompt.test.d.ts +6 -0
  325. package/dist/src/ui/components/InputPrompt.test.js +1737 -0
  326. package/dist/src/ui/components/InputPrompt.test.js.map +1 -0
  327. package/dist/src/ui/components/MainContent.js +1 -1
  328. package/dist/src/ui/components/MainContent.js.map +1 -1
  329. package/dist/src/ui/components/ModelStatsDisplay.test.d.ts +6 -0
  330. package/dist/src/ui/components/ModelStatsDisplay.test.js +285 -0
  331. package/dist/src/ui/components/ModelStatsDisplay.test.js.map +1 -0
  332. package/dist/src/ui/components/Notifications.js +12 -4
  333. package/dist/src/ui/components/Notifications.js.map +1 -1
  334. package/dist/src/ui/components/PermissionsModifyTrustDialog.js +22 -18
  335. package/dist/src/ui/components/PermissionsModifyTrustDialog.js.map +1 -1
  336. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js +10 -2
  337. package/dist/src/ui/components/PermissionsModifyTrustDialog.test.js.map +1 -1
  338. package/dist/src/ui/components/QueuedMessageDisplay.js +3 -3
  339. package/dist/src/ui/components/QueuedMessageDisplay.js.map +1 -1
  340. package/dist/src/ui/components/QueuedMessageDisplay.test.js +4 -0
  341. package/dist/src/ui/components/QueuedMessageDisplay.test.js.map +1 -1
  342. package/dist/src/ui/components/RawMarkdownIndicator.d.ts +7 -0
  343. package/dist/src/ui/components/RawMarkdownIndicator.js +8 -0
  344. package/dist/src/ui/components/RawMarkdownIndicator.js.map +1 -0
  345. package/dist/src/ui/components/SessionSummaryDisplay.test.d.ts +6 -0
  346. package/dist/src/ui/components/SessionSummaryDisplay.test.js +74 -0
  347. package/dist/src/ui/components/SessionSummaryDisplay.test.js.map +1 -0
  348. package/dist/src/ui/components/SettingsDialog.js +12 -11
  349. package/dist/src/ui/components/SettingsDialog.js.map +1 -1
  350. package/dist/src/ui/components/SettingsDialog.test.js +190 -77
  351. package/dist/src/ui/components/SettingsDialog.test.js.map +1 -1
  352. package/dist/src/ui/components/StatsDisplay.test.d.ts +6 -0
  353. package/dist/src/ui/components/StatsDisplay.test.js +351 -0
  354. package/dist/src/ui/components/StatsDisplay.test.js.map +1 -0
  355. package/dist/src/ui/components/ThemeDialog.d.ts +4 -2
  356. package/dist/src/ui/components/ThemeDialog.js +3 -3
  357. package/dist/src/ui/components/ThemeDialog.js.map +1 -1
  358. package/dist/src/ui/components/ThemeDialog.test.js +13 -0
  359. package/dist/src/ui/components/ThemeDialog.test.js.map +1 -1
  360. package/dist/src/ui/components/ToolStatsDisplay.test.d.ts +6 -0
  361. package/dist/src/ui/components/ToolStatsDisplay.test.js +227 -0
  362. package/dist/src/ui/components/ToolStatsDisplay.test.js.map +1 -0
  363. package/dist/src/ui/components/messages/CompressionMessage.js +3 -3
  364. package/dist/src/ui/components/messages/CompressionMessage.js.map +1 -1
  365. package/dist/src/ui/components/messages/GeminiMessage.js +3 -1
  366. package/dist/src/ui/components/messages/GeminiMessage.js.map +1 -1
  367. package/dist/src/ui/components/messages/GeminiMessage.test.d.ts +6 -0
  368. package/dist/src/ui/components/messages/GeminiMessage.test.js +35 -0
  369. package/dist/src/ui/components/messages/GeminiMessage.test.js.map +1 -0
  370. package/dist/src/ui/components/messages/GeminiMessageContent.js +3 -1
  371. package/dist/src/ui/components/messages/GeminiMessageContent.js.map +1 -1
  372. package/dist/src/ui/components/messages/Todo.d.ts +7 -0
  373. package/dist/src/ui/components/messages/Todo.js +69 -0
  374. package/dist/src/ui/components/messages/Todo.js.map +1 -0
  375. package/dist/src/ui/components/messages/Todo.test.d.ts +6 -0
  376. package/dist/src/ui/components/messages/Todo.test.js +102 -0
  377. package/dist/src/ui/components/messages/Todo.test.js.map +1 -0
  378. package/dist/src/ui/components/messages/ToolConfirmationMessage.js +1 -1
  379. package/dist/src/ui/components/messages/ToolConfirmationMessage.js.map +1 -1
  380. package/dist/src/ui/components/messages/ToolGroupMessage.js +2 -2
  381. package/dist/src/ui/components/messages/ToolGroupMessage.js.map +1 -1
  382. package/dist/src/ui/components/messages/ToolMessage.js +9 -4
  383. package/dist/src/ui/components/messages/ToolMessage.js.map +1 -1
  384. package/dist/src/ui/components/messages/ToolMessage.test.js +2 -2
  385. package/dist/src/ui/components/messages/ToolMessage.test.js.map +1 -1
  386. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.d.ts +6 -0
  387. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js +30 -0
  388. package/dist/src/ui/components/messages/ToolMessageRawMarkdown.test.js.map +1 -0
  389. package/dist/src/ui/components/messages/UserShellMessage.js +1 -1
  390. package/dist/src/ui/components/messages/UserShellMessage.js.map +1 -1
  391. package/dist/src/ui/components/shared/BaseSelectionList.test.js +33 -24
  392. package/dist/src/ui/components/shared/BaseSelectionList.test.js.map +1 -1
  393. package/dist/src/ui/components/shared/text-buffer.js +1 -1
  394. package/dist/src/ui/components/shared/text-buffer.js.map +1 -1
  395. package/dist/src/ui/components/shared/text-buffer.test.d.ts +6 -0
  396. package/dist/src/ui/components/shared/text-buffer.test.js +1578 -0
  397. package/dist/src/ui/components/shared/text-buffer.test.js.map +1 -0
  398. package/dist/src/ui/components/shared/vim-buffer-actions.test.d.ts +6 -0
  399. package/dist/src/ui/components/shared/vim-buffer-actions.test.js +951 -0
  400. package/dist/src/ui/components/shared/vim-buffer-actions.test.js.map +1 -0
  401. package/dist/src/ui/components/views/ChatList.d.ts +12 -0
  402. package/dist/src/ui/components/views/ChatList.js +17 -0
  403. package/dist/src/ui/components/views/ChatList.js.map +1 -0
  404. package/dist/src/ui/components/views/ChatList.test.d.ts +6 -0
  405. package/dist/src/ui/components/views/ChatList.test.js +42 -0
  406. package/dist/src/ui/components/views/ChatList.test.js.map +1 -0
  407. package/dist/src/ui/components/views/ExtensionsList.js +3 -4
  408. package/dist/src/ui/components/views/ExtensionsList.js.map +1 -1
  409. package/dist/src/ui/components/views/ExtensionsList.test.js +2 -9
  410. package/dist/src/ui/components/views/ExtensionsList.test.js.map +1 -1
  411. package/dist/src/ui/components/views/McpStatus.d.ts +0 -1
  412. package/dist/src/ui/components/views/McpStatus.js +4 -4
  413. package/dist/src/ui/components/views/McpStatus.js.map +1 -1
  414. package/dist/src/ui/components/views/McpStatus.test.js +0 -5
  415. package/dist/src/ui/components/views/McpStatus.test.js.map +1 -1
  416. package/dist/src/ui/components/views/ToolsList.test.js +4 -4
  417. package/dist/src/ui/components/views/ToolsList.test.js.map +1 -1
  418. package/dist/src/ui/contexts/KeypressContext.d.ts +1 -0
  419. package/dist/src/ui/contexts/KeypressContext.js +219 -53
  420. package/dist/src/ui/contexts/KeypressContext.js.map +1 -1
  421. package/dist/src/ui/contexts/KeypressContext.test.js +536 -10
  422. package/dist/src/ui/contexts/KeypressContext.test.js.map +1 -1
  423. package/dist/src/ui/contexts/SessionContext.test.d.ts +6 -0
  424. package/dist/src/ui/contexts/SessionContext.test.js +177 -0
  425. package/dist/src/ui/contexts/SessionContext.test.js.map +1 -0
  426. package/dist/src/ui/contexts/UIActionsContext.d.ts +5 -4
  427. package/dist/src/ui/contexts/UIActionsContext.js.map +1 -1
  428. package/dist/src/ui/contexts/UIStateContext.d.ts +6 -4
  429. package/dist/src/ui/contexts/UIStateContext.js.map +1 -1
  430. package/dist/src/ui/hooks/atCommandProcessor.js +2 -2
  431. package/dist/src/ui/hooks/atCommandProcessor.js.map +1 -1
  432. package/dist/src/ui/hooks/shellCommandProcessor.js +5 -7
  433. package/dist/src/ui/hooks/shellCommandProcessor.js.map +1 -1
  434. package/dist/src/ui/hooks/shellCommandProcessor.test.js +19 -32
  435. package/dist/src/ui/hooks/shellCommandProcessor.test.js.map +1 -1
  436. package/dist/src/ui/hooks/slashCommandProcessor.d.ts +2 -1
  437. package/dist/src/ui/hooks/slashCommandProcessor.js +11 -7
  438. package/dist/src/ui/hooks/slashCommandProcessor.js.map +1 -1
  439. package/dist/src/ui/hooks/slashCommandProcessor.test.d.ts +6 -0
  440. package/dist/src/ui/hooks/slashCommandProcessor.test.js +779 -0
  441. package/dist/src/ui/hooks/slashCommandProcessor.test.js.map +1 -0
  442. package/dist/src/ui/hooks/useAtCompletion.js +2 -2
  443. package/dist/src/ui/hooks/useAtCompletion.js.map +1 -1
  444. package/dist/src/ui/hooks/useAtCompletion.test.d.ts +6 -0
  445. package/dist/src/ui/hooks/useAtCompletion.test.js +385 -0
  446. package/dist/src/ui/hooks/useAtCompletion.test.js.map +1 -0
  447. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js +0 -1
  448. package/dist/src/ui/hooks/useAutoAcceptIndicator.test.js.map +1 -1
  449. package/dist/src/ui/hooks/useCommandCompletion.d.ts +1 -1
  450. package/dist/src/ui/hooks/useCommandCompletion.js +5 -3
  451. package/dist/src/ui/hooks/useCommandCompletion.js.map +1 -1
  452. package/dist/src/ui/hooks/useCommandCompletion.test.d.ts +6 -0
  453. package/dist/src/ui/hooks/useCommandCompletion.test.js +375 -0
  454. package/dist/src/ui/hooks/useCommandCompletion.test.js.map +1 -0
  455. package/dist/src/ui/hooks/useConsoleMessages.test.d.ts +6 -0
  456. package/dist/src/ui/hooks/useConsoleMessages.test.js +110 -0
  457. package/dist/src/ui/hooks/useConsoleMessages.test.js.map +1 -0
  458. package/dist/src/ui/hooks/useExtensionUpdates.d.ts +2 -1
  459. package/dist/src/ui/hooks/useExtensionUpdates.js +71 -19
  460. package/dist/src/ui/hooks/useExtensionUpdates.js.map +1 -1
  461. package/dist/src/ui/hooks/useExtensionUpdates.test.js +28 -13
  462. package/dist/src/ui/hooks/useExtensionUpdates.test.js.map +1 -1
  463. package/dist/src/ui/hooks/useFlickerDetector.d.ts +14 -0
  464. package/dist/src/ui/hooks/useFlickerDetector.js +37 -0
  465. package/dist/src/ui/hooks/useFlickerDetector.js.map +1 -0
  466. package/dist/src/ui/hooks/useFlickerDetector.test.d.ts +6 -0
  467. package/dist/src/ui/hooks/useFlickerDetector.test.js +102 -0
  468. package/dist/src/ui/hooks/useFlickerDetector.test.js.map +1 -0
  469. package/dist/src/ui/hooks/useFocus.test.d.ts +6 -0
  470. package/dist/src/ui/hooks/useFocus.test.js +115 -0
  471. package/dist/src/ui/hooks/useFocus.test.js.map +1 -0
  472. package/dist/src/ui/hooks/useFolderTrust.d.ts +2 -1
  473. package/dist/src/ui/hooks/useFolderTrust.js +12 -3
  474. package/dist/src/ui/hooks/useFolderTrust.js.map +1 -1
  475. package/dist/src/ui/hooks/useFolderTrust.test.d.ts +6 -0
  476. package/dist/src/ui/hooks/useFolderTrust.test.js +164 -0
  477. package/dist/src/ui/hooks/useFolderTrust.test.js.map +1 -0
  478. package/dist/src/ui/hooks/useGeminiStream.js +95 -56
  479. package/dist/src/ui/hooks/useGeminiStream.js.map +1 -1
  480. package/dist/src/ui/hooks/useGeminiStream.test.d.ts +6 -0
  481. package/dist/src/ui/hooks/useGeminiStream.test.js +1971 -0
  482. package/dist/src/ui/hooks/useGeminiStream.test.js.map +1 -0
  483. package/dist/src/ui/hooks/useHistoryManager.js +3 -3
  484. package/dist/src/ui/hooks/useHistoryManager.js.map +1 -1
  485. package/dist/src/ui/hooks/useInputHistoryStore.js +2 -1
  486. package/dist/src/ui/hooks/useInputHistoryStore.js.map +1 -1
  487. package/dist/src/ui/hooks/useKeypress.test.d.ts +6 -0
  488. package/dist/src/ui/hooks/useKeypress.test.js +234 -0
  489. package/dist/src/ui/hooks/useKeypress.test.js.map +1 -0
  490. package/dist/src/ui/hooks/useLoadingIndicator.test.js +5 -0
  491. package/dist/src/ui/hooks/useLoadingIndicator.test.js.map +1 -1
  492. package/dist/src/ui/hooks/useMessageQueue.d.ts +1 -0
  493. package/dist/src/ui/hooks/useMessageQueue.js +14 -0
  494. package/dist/src/ui/hooks/useMessageQueue.js.map +1 -1
  495. package/dist/src/ui/hooks/useMessageQueue.test.js +121 -0
  496. package/dist/src/ui/hooks/useMessageQueue.test.js.map +1 -1
  497. package/dist/src/ui/hooks/usePhraseCycler.d.ts +1 -0
  498. package/dist/src/ui/hooks/usePhraseCycler.js +157 -5
  499. package/dist/src/ui/hooks/usePhraseCycler.js.map +1 -1
  500. package/dist/src/ui/hooks/usePhraseCycler.test.d.ts +6 -0
  501. package/dist/src/ui/hooks/usePhraseCycler.test.js +155 -0
  502. package/dist/src/ui/hooks/usePhraseCycler.test.js.map +1 -0
  503. package/dist/src/ui/hooks/useReactToolScheduler.js +2 -2
  504. package/dist/src/ui/hooks/useReactToolScheduler.js.map +1 -1
  505. package/dist/src/ui/hooks/useSelectionList.js +50 -23
  506. package/dist/src/ui/hooks/useSelectionList.js.map +1 -1
  507. package/dist/src/ui/hooks/useSelectionList.test.js +24 -0
  508. package/dist/src/ui/hooks/useSelectionList.test.js.map +1 -1
  509. package/dist/src/ui/hooks/useShellHistory.test.js +16 -10
  510. package/dist/src/ui/hooks/useShellHistory.test.js.map +1 -1
  511. package/dist/src/ui/hooks/useShowMemoryCommand.d.ts +1 -1
  512. package/dist/src/ui/hooks/useShowMemoryCommand.js +4 -3
  513. package/dist/src/ui/hooks/useShowMemoryCommand.js.map +1 -1
  514. package/dist/src/ui/hooks/useSlashCompletion.js +2 -1
  515. package/dist/src/ui/hooks/useSlashCompletion.js.map +1 -1
  516. package/dist/src/ui/hooks/useTerminalSize.js +2 -3
  517. package/dist/src/ui/hooks/useTerminalSize.js.map +1 -1
  518. package/dist/src/ui/hooks/useThemeCommand.d.ts +2 -1
  519. package/dist/src/ui/hooks/useThemeCommand.js +6 -0
  520. package/dist/src/ui/hooks/useThemeCommand.js.map +1 -1
  521. package/dist/src/ui/hooks/useToolScheduler.test.js +3 -0
  522. package/dist/src/ui/hooks/useToolScheduler.test.js.map +1 -1
  523. package/dist/src/ui/hooks/vim.js +2 -1
  524. package/dist/src/ui/hooks/vim.js.map +1 -1
  525. package/dist/src/ui/hooks/vim.test.d.ts +6 -0
  526. package/dist/src/ui/hooks/vim.test.js +1389 -0
  527. package/dist/src/ui/hooks/vim.test.js.map +1 -0
  528. package/dist/src/ui/keyMatchers.test.js +9 -3
  529. package/dist/src/ui/keyMatchers.test.js.map +1 -1
  530. package/dist/src/ui/layouts/DefaultAppLayout.d.ts +1 -3
  531. package/dist/src/ui/layouts/DefaultAppLayout.js +5 -2
  532. package/dist/src/ui/layouts/DefaultAppLayout.js.map +1 -1
  533. package/dist/src/ui/layouts/ScreenReaderAppLayout.js +4 -1
  534. package/dist/src/ui/layouts/ScreenReaderAppLayout.js.map +1 -1
  535. package/dist/src/ui/noninteractive/nonInteractiveUi.js +1 -0
  536. package/dist/src/ui/noninteractive/nonInteractiveUi.js.map +1 -1
  537. package/dist/src/ui/state/extensions.d.ts +22 -3
  538. package/dist/src/ui/state/extensions.js +26 -4
  539. package/dist/src/ui/state/extensions.js.map +1 -1
  540. package/dist/src/ui/themes/color-utils.js +2 -1
  541. package/dist/src/ui/themes/color-utils.js.map +1 -1
  542. package/dist/src/ui/themes/theme-manager.js +8 -7
  543. package/dist/src/ui/themes/theme-manager.js.map +1 -1
  544. package/dist/src/ui/themes/theme.test.d.ts +6 -0
  545. package/dist/src/ui/themes/theme.test.js +85 -0
  546. package/dist/src/ui/themes/theme.test.js.map +1 -0
  547. package/dist/src/ui/types.d.ts +11 -3
  548. package/dist/src/ui/types.js +1 -0
  549. package/dist/src/ui/types.js.map +1 -1
  550. package/dist/src/ui/utils/CodeColorizer.d.ts +1 -1
  551. package/dist/src/ui/utils/CodeColorizer.js +4 -2
  552. package/dist/src/ui/utils/CodeColorizer.js.map +1 -1
  553. package/dist/src/ui/utils/MarkdownDisplay.d.ts +1 -0
  554. package/dist/src/ui/utils/MarkdownDisplay.js +8 -1
  555. package/dist/src/ui/utils/MarkdownDisplay.js.map +1 -1
  556. package/dist/src/ui/utils/commandUtils.js +20 -3
  557. package/dist/src/ui/utils/commandUtils.js.map +1 -1
  558. package/dist/src/ui/utils/commandUtils.test.js +61 -6
  559. package/dist/src/ui/utils/commandUtils.test.js.map +1 -1
  560. package/dist/src/ui/utils/computeStats.js +5 -2
  561. package/dist/src/ui/utils/computeStats.js.map +1 -1
  562. package/dist/src/ui/utils/computeStats.test.d.ts +6 -0
  563. package/dist/src/ui/utils/computeStats.test.js +262 -0
  564. package/dist/src/ui/utils/computeStats.test.js.map +1 -0
  565. package/dist/src/ui/utils/terminalSetup.js +3 -2
  566. package/dist/src/ui/utils/terminalSetup.js.map +1 -1
  567. package/dist/src/ui/utils/ui-sizing.d.ts +7 -0
  568. package/dist/src/ui/utils/ui-sizing.js +23 -0
  569. package/dist/src/ui/utils/ui-sizing.js.map +1 -0
  570. package/dist/src/ui/utils/updateCheck.d.ts +2 -1
  571. package/dist/src/ui/utils/updateCheck.js +6 -2
  572. package/dist/src/ui/utils/updateCheck.js.map +1 -1
  573. package/dist/src/ui/utils/updateCheck.test.js +25 -10
  574. package/dist/src/ui/utils/updateCheck.test.js.map +1 -1
  575. package/dist/src/utils/cleanup.test.d.ts +6 -0
  576. package/dist/src/utils/cleanup.test.js +49 -0
  577. package/dist/src/utils/cleanup.test.js.map +1 -0
  578. package/dist/src/utils/commentJson.js +95 -13
  579. package/dist/src/utils/commentJson.js.map +1 -1
  580. package/dist/src/utils/commentJson.test.js +161 -0
  581. package/dist/src/utils/commentJson.test.js.map +1 -1
  582. package/dist/src/utils/errors.d.ts +9 -3
  583. package/dist/src/utils/errors.js +87 -16
  584. package/dist/src/utils/errors.js.map +1 -1
  585. package/dist/src/utils/errors.test.js +40 -46
  586. package/dist/src/utils/errors.test.js.map +1 -1
  587. package/dist/src/utils/events.d.ts +2 -1
  588. package/dist/src/utils/events.js +1 -0
  589. package/dist/src/utils/events.js.map +1 -1
  590. package/dist/src/utils/gitUtils.js +3 -2
  591. package/dist/src/utils/gitUtils.js.map +1 -1
  592. package/dist/src/utils/handleAutoUpdate.js +4 -1
  593. package/dist/src/utils/handleAutoUpdate.js.map +1 -1
  594. package/dist/src/utils/handleAutoUpdate.test.d.ts +6 -0
  595. package/dist/src/utils/handleAutoUpdate.test.js +225 -0
  596. package/dist/src/utils/handleAutoUpdate.test.js.map +1 -0
  597. package/dist/src/utils/installationInfo.d.ts +1 -0
  598. package/dist/src/utils/installationInfo.js +4 -2
  599. package/dist/src/utils/installationInfo.js.map +1 -1
  600. package/dist/src/utils/installationInfo.test.js +8 -4
  601. package/dist/src/utils/installationInfo.test.js.map +1 -1
  602. package/dist/src/utils/readStdin.js +2 -1
  603. package/dist/src/utils/readStdin.js.map +1 -1
  604. package/dist/src/utils/sandbox-macos-permissive-open.sb +2 -0
  605. package/dist/src/utils/sandbox.js +20 -20
  606. package/dist/src/utils/sandbox.js.map +1 -1
  607. package/dist/src/utils/sessionCleanup.d.ts +22 -0
  608. package/dist/src/utils/sessionCleanup.integration.test.d.ts +6 -0
  609. package/dist/src/utils/sessionCleanup.integration.test.js +182 -0
  610. package/dist/src/utils/sessionCleanup.integration.test.js.map +1 -0
  611. package/dist/src/utils/sessionCleanup.js +214 -0
  612. package/dist/src/utils/sessionCleanup.js.map +1 -0
  613. package/dist/src/utils/sessionCleanup.test.d.ts +6 -0
  614. package/dist/src/utils/sessionCleanup.test.js +1232 -0
  615. package/dist/src/utils/sessionCleanup.test.js.map +1 -0
  616. package/dist/src/utils/sessionUtils.d.ts +37 -0
  617. package/dist/src/utils/sessionUtils.js +71 -0
  618. package/dist/src/utils/sessionUtils.js.map +1 -0
  619. package/dist/src/utils/startupWarnings.test.d.ts +6 -0
  620. package/dist/src/utils/startupWarnings.test.js +61 -0
  621. package/dist/src/utils/startupWarnings.test.js.map +1 -0
  622. package/dist/src/validateNonInterActiveAuth.js +8 -9
  623. package/dist/src/validateNonInterActiveAuth.js.map +1 -1
  624. package/dist/src/zed-integration/acp.js +1 -2
  625. package/dist/src/zed-integration/acp.js.map +1 -1
  626. package/dist/src/zed-integration/schema.d.ts +176 -176
  627. package/dist/src/zed-integration/zedIntegration.d.ts +2 -3
  628. package/dist/src/zed-integration/zedIntegration.js +12 -33
  629. package/dist/src/zed-integration/zedIntegration.js.map +1 -1
  630. package/dist/tsconfig.tsbuildinfo +1 -1
  631. package/package.json +7 -6
  632. package/dist/src/ui/components/WorkspaceMigrationDialog.d.ts +0 -11
  633. package/dist/src/ui/components/WorkspaceMigrationDialog.js +0 -44
  634. package/dist/src/ui/components/WorkspaceMigrationDialog.js.map +0 -1
  635. package/dist/src/ui/hooks/useWorkspaceMigration.d.ts +0 -13
  636. package/dist/src/ui/hooks/useWorkspaceMigration.js +0 -54
  637. package/dist/src/ui/hooks/useWorkspaceMigration.js.map +0 -1
@@ -0,0 +1,115 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { renderHook, act } from '@testing-library/react';
7
+ import { EventEmitter } from 'node:events';
8
+ import { useFocus } from './useFocus.js';
9
+ import { vi } from 'vitest';
10
+ import { useStdin, useStdout } from 'ink';
11
+ import { KeypressProvider } from '../contexts/KeypressContext.js';
12
+ import React from 'react';
13
+ // Mock the ink hooks
14
+ vi.mock('ink', async (importOriginal) => {
15
+ const original = await importOriginal();
16
+ return {
17
+ ...original,
18
+ useStdin: vi.fn(),
19
+ useStdout: vi.fn(),
20
+ };
21
+ });
22
+ const mockedUseStdin = vi.mocked(useStdin);
23
+ const mockedUseStdout = vi.mocked(useStdout);
24
+ const wrapper = ({ children }) => React.createElement(KeypressProvider, null, children);
25
+ describe('useFocus', () => {
26
+ let stdin;
27
+ let stdout;
28
+ beforeEach(() => {
29
+ stdin = Object.assign(new EventEmitter(), {
30
+ resume: vi.fn(),
31
+ pause: vi.fn(),
32
+ });
33
+ stdout = { write: vi.fn() };
34
+ mockedUseStdin.mockReturnValue({ stdin });
35
+ mockedUseStdout.mockReturnValue({ stdout });
36
+ });
37
+ afterEach(() => {
38
+ vi.clearAllMocks();
39
+ stdin.removeAllListeners();
40
+ });
41
+ it('should initialize with focus and enable focus reporting', () => {
42
+ const { result } = renderHook(() => useFocus(), { wrapper });
43
+ expect(result.current).toBe(true);
44
+ expect(stdout.write).toHaveBeenCalledWith('\x1b[?1004h');
45
+ });
46
+ it('should set isFocused to false when a focus-out event is received', () => {
47
+ const { result } = renderHook(() => useFocus(), { wrapper });
48
+ // Initial state is focused
49
+ expect(result.current).toBe(true);
50
+ // Simulate focus-out event
51
+ act(() => {
52
+ stdin.emit('data', Buffer.from('\x1b[O'));
53
+ });
54
+ // State should now be unfocused
55
+ expect(result.current).toBe(false);
56
+ });
57
+ it('should set isFocused to true when a focus-in event is received', () => {
58
+ const { result } = renderHook(() => useFocus(), { wrapper });
59
+ // Simulate focus-out to set initial state to false
60
+ act(() => {
61
+ stdin.emit('data', Buffer.from('\x1b[O'));
62
+ });
63
+ expect(result.current).toBe(false);
64
+ // Simulate focus-in event
65
+ act(() => {
66
+ stdin.emit('data', Buffer.from('\x1b[I'));
67
+ });
68
+ // State should now be focused
69
+ expect(result.current).toBe(true);
70
+ });
71
+ it('should clean up and disable focus reporting on unmount', () => {
72
+ const { unmount } = renderHook(() => useFocus(), { wrapper });
73
+ // At this point we should have listeners from both KeypressProvider and useFocus
74
+ const listenerCountAfterMount = stdin.listenerCount('data');
75
+ expect(listenerCountAfterMount).toBeGreaterThanOrEqual(1);
76
+ unmount();
77
+ // Assert that the cleanup function was called
78
+ expect(stdout.write).toHaveBeenCalledWith('\x1b[?1004l');
79
+ // Ensure useFocus listener was removed (but KeypressProvider listeners may remain)
80
+ expect(stdin.listenerCount('data')).toBeLessThan(listenerCountAfterMount);
81
+ });
82
+ it('should handle multiple focus events correctly', () => {
83
+ const { result } = renderHook(() => useFocus(), { wrapper });
84
+ act(() => {
85
+ stdin.emit('data', Buffer.from('\x1b[O'));
86
+ });
87
+ expect(result.current).toBe(false);
88
+ act(() => {
89
+ stdin.emit('data', Buffer.from('\x1b[O'));
90
+ });
91
+ expect(result.current).toBe(false);
92
+ act(() => {
93
+ stdin.emit('data', Buffer.from('\x1b[I'));
94
+ });
95
+ expect(result.current).toBe(true);
96
+ act(() => {
97
+ stdin.emit('data', Buffer.from('\x1b[I'));
98
+ });
99
+ expect(result.current).toBe(true);
100
+ });
101
+ it('restores focus on keypress after focus is lost', () => {
102
+ const { result } = renderHook(() => useFocus(), { wrapper });
103
+ // Simulate focus-out event
104
+ act(() => {
105
+ stdin.emit('data', Buffer.from('\x1b[O'));
106
+ });
107
+ expect(result.current).toBe(false);
108
+ // Simulate a keypress
109
+ act(() => {
110
+ stdin.emit('data', Buffer.from('a'));
111
+ });
112
+ expect(result.current).toBe(true);
113
+ });
114
+ });
115
+ //# sourceMappingURL=useFocus.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFocus.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useFocus.test.ts"],"names":[],"mappings":"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"}
@@ -5,7 +5,8 @@
5
5
  */
6
6
  import type { LoadedSettings } from '../../config/settings.js';
7
7
  import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
8
- export declare const useFolderTrust: (settings: LoadedSettings, onTrustChange: (isTrusted: boolean | undefined) => void) => {
8
+ import { type HistoryItemWithoutId } from '../types.js';
9
+ export declare const useFolderTrust: (settings: LoadedSettings, onTrustChange: (isTrusted: boolean | undefined) => void, addItem: (item: HistoryItemWithoutId, timestamp: number) => number) => {
9
10
  isTrusted: boolean | undefined;
10
11
  isFolderTrustDialogOpen: boolean;
11
12
  handleFolderTrustSelect: (choice: FolderTrustChoice) => void;
@@ -3,21 +3,30 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { useState, useCallback, useEffect } from 'react';
6
+ import { useState, useCallback, useEffect, useRef } from 'react';
7
7
  import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
8
8
  import { loadTrustedFolders, TrustLevel, isWorkspaceTrusted, } from '../../config/trustedFolders.js';
9
9
  import * as process from 'node:process';
10
- export const useFolderTrust = (settings, onTrustChange) => {
10
+ import { MessageType } from '../types.js';
11
+ export const useFolderTrust = (settings, onTrustChange, addItem) => {
11
12
  const [isTrusted, setIsTrusted] = useState(undefined);
12
13
  const [isFolderTrustDialogOpen, setIsFolderTrustDialogOpen] = useState(false);
13
14
  const [isRestarting, setIsRestarting] = useState(false);
15
+ const startupMessageSent = useRef(false);
14
16
  const folderTrust = settings.merged.security?.folderTrust?.enabled;
15
17
  useEffect(() => {
16
18
  const { isTrusted: trusted } = isWorkspaceTrusted(settings.merged);
17
19
  setIsTrusted(trusted);
18
20
  setIsFolderTrustDialogOpen(trusted === undefined);
19
21
  onTrustChange(trusted);
20
- }, [folderTrust, onTrustChange, settings.merged]);
22
+ if (trusted === false && !startupMessageSent.current) {
23
+ addItem({
24
+ type: MessageType.INFO,
25
+ text: 'This folder is not trusted. Some features may be disabled. Use the `/permissions` command to change the trust level.',
26
+ }, Date.now());
27
+ startupMessageSent.current = true;
28
+ }
29
+ }, [folderTrust, onTrustChange, settings.merged, addItem]);
21
30
  const handleFolderTrustSelect = useCallback((choice) => {
22
31
  const trustedFolders = loadTrustedFolders();
23
32
  const cwd = process.cwd();
@@ -1 +1 @@
1
- {"version":3,"file":"useFolderTrust.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useFolderTrust.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,oCAAoC,CAAC;AACvE,OAAO,EACL,kBAAkB,EAClB,UAAU,EACV,kBAAkB,GACnB,MAAM,gCAAgC,CAAC;AACxC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,QAAwB,EACxB,aAAuD,EACvD,EAAE;IACF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAsB,SAAS,CAAC,CAAC;IAC3E,MAAM,CAAC,uBAAuB,EAAE,0BAA0B,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9E,MAAM,CAAC,YAAY,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExD,MAAM,WAAW,GAAG,QAAQ,CAAC,MAAM,CAAC,QAAQ,EAAE,WAAW,EAAE,OAAO,CAAC;IAEnE,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;QACnE,YAAY,CAAC,OAAO,CAAC,CAAC;QACtB,0BAA0B,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC;QAClD,aAAa,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC,EAAE,CAAC,WAAW,EAAE,aAAa,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC;IAElD,MAAM,uBAAuB,GAAG,WAAW,CACzC,CAAC,MAAyB,EAAE,EAAE;QAC5B,MAAM,cAAc,GAAG,kBAAkB,EAAE,CAAC;QAC5C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC1B,IAAI,UAAsB,CAAC;QAE3B,MAAM,UAAU,GAAG,SAAS,IAAI,IAAI,CAAC;QAErC,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,iBAAiB,CAAC,YAAY;gBACjC,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC;gBACrC,MAAM;YACR,KAAK,iBAAiB,CAAC,YAAY;gBACjC,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC;gBACrC,MAAM;YACR,KAAK,iBAAiB,CAAC,YAAY;gBACjC,UAAU,GAAG,UAAU,CAAC,YAAY,CAAC;gBACrC,MAAM;YACR;gBACE,OAAO;QACX,CAAC;QAED,cAAc,CAAC,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC;QACzC,MAAM,gBAAgB,GACpB,UAAU,KAAK,UAAU,CAAC,YAAY;YACtC,UAAU,KAAK,UAAU,CAAC,YAAY,CAAC;QACzC,YAAY,CAAC,gBAAgB,CAAC,CAAC;QAC/B,aAAa,CAAC,gBAAgB,CAAC,CAAC;QAEhC,MAAM,YAAY,GAAG,UAAU,KAAK,gBAAgB,CAAC;QACrD,IAAI,YAAY,EAAE,CAAC;YACjB,eAAe,CAAC,IAAI,CAAC,CAAC;YACtB,0BAA0B,CAAC,IAAI,CAAC,CAAC;QACnC,CAAC;aAAM,CAAC;YACN,0BAA0B,CAAC,KAAK,CAAC,CAAC;QACpC,CAAC;IACH,CAAC,EACD,CAAC,aAAa,EAAE,SAAS,CAAC,CAC3B,CAAC;IAEF,OAAO;QACL,SAAS;QACT,uBAAuB;QACvB,uBAAuB;QACvB,YAAY;KACb,CAAC;AACJ,CAAC,CAAC"}
1
+ {"version":3,"file":"useFolderTrust.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useFolderTrust.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ export {};
@@ -0,0 +1,164 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { vi } from 'vitest';
7
+ import { renderHook, act } from '@testing-library/react';
8
+ import { useFolderTrust } from './useFolderTrust.js';
9
+ import { FolderTrustChoice } from '../components/FolderTrustDialog.js';
10
+ import { TrustLevel } from '../../config/trustedFolders.js';
11
+ import * as trustedFolders from '../../config/trustedFolders.js';
12
+ const mockedCwd = vi.hoisted(() => vi.fn());
13
+ vi.mock('node:process', async () => {
14
+ const actual = await vi.importActual('node:process');
15
+ return {
16
+ ...actual,
17
+ cwd: mockedCwd,
18
+ platform: 'linux',
19
+ };
20
+ });
21
+ describe('useFolderTrust', () => {
22
+ let mockSettings;
23
+ let mockTrustedFolders;
24
+ let loadTrustedFoldersSpy;
25
+ let isWorkspaceTrustedSpy;
26
+ let onTrustChange;
27
+ let addItem;
28
+ beforeEach(() => {
29
+ mockSettings = {
30
+ merged: {
31
+ security: {
32
+ folderTrust: {
33
+ enabled: true,
34
+ },
35
+ },
36
+ },
37
+ setValue: vi.fn(),
38
+ };
39
+ mockTrustedFolders = {
40
+ setValue: vi.fn(),
41
+ };
42
+ loadTrustedFoldersSpy = vi
43
+ .spyOn(trustedFolders, 'loadTrustedFolders')
44
+ .mockReturnValue(mockTrustedFolders);
45
+ isWorkspaceTrustedSpy = vi.spyOn(trustedFolders, 'isWorkspaceTrusted');
46
+ mockedCwd.mockReturnValue('/test/path');
47
+ onTrustChange = vi.fn();
48
+ addItem = vi.fn();
49
+ });
50
+ afterEach(() => {
51
+ vi.clearAllMocks();
52
+ });
53
+ it('should not open dialog when folder is already trusted', () => {
54
+ isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: true, source: 'file' });
55
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
56
+ expect(result.current.isFolderTrustDialogOpen).toBe(false);
57
+ expect(onTrustChange).toHaveBeenCalledWith(true);
58
+ });
59
+ it('should not open dialog when folder is already untrusted', () => {
60
+ isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' });
61
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
62
+ expect(result.current.isFolderTrustDialogOpen).toBe(false);
63
+ expect(onTrustChange).toHaveBeenCalledWith(false);
64
+ });
65
+ it('should open dialog when folder trust is undefined', () => {
66
+ isWorkspaceTrustedSpy.mockReturnValue({
67
+ isTrusted: undefined,
68
+ source: undefined,
69
+ });
70
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
71
+ expect(result.current.isFolderTrustDialogOpen).toBe(true);
72
+ expect(onTrustChange).toHaveBeenCalledWith(undefined);
73
+ });
74
+ it('should send a message if the folder is untrusted', () => {
75
+ isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' });
76
+ renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
77
+ expect(addItem).toHaveBeenCalledWith({
78
+ text: 'This folder is not trusted. Some features may be disabled. Use the `/permissions` command to change the trust level.',
79
+ type: 'info',
80
+ }, expect.any(Number));
81
+ });
82
+ it('should not send a message if the folder is trusted', () => {
83
+ isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: true, source: 'file' });
84
+ renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
85
+ expect(addItem).not.toHaveBeenCalled();
86
+ });
87
+ it('should handle TRUST_FOLDER choice', () => {
88
+ isWorkspaceTrustedSpy.mockReturnValue({
89
+ isTrusted: undefined,
90
+ source: undefined,
91
+ });
92
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
93
+ act(() => {
94
+ result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_FOLDER);
95
+ });
96
+ expect(loadTrustedFoldersSpy).toHaveBeenCalled();
97
+ expect(mockTrustedFolders.setValue).toHaveBeenCalledWith('/test/path', TrustLevel.TRUST_FOLDER);
98
+ expect(result.current.isFolderTrustDialogOpen).toBe(false);
99
+ expect(onTrustChange).toHaveBeenLastCalledWith(true);
100
+ });
101
+ it('should handle TRUST_PARENT choice', () => {
102
+ isWorkspaceTrustedSpy.mockReturnValue({
103
+ isTrusted: undefined,
104
+ source: undefined,
105
+ });
106
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
107
+ act(() => {
108
+ result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_PARENT);
109
+ });
110
+ expect(mockTrustedFolders.setValue).toHaveBeenCalledWith('/test/path', TrustLevel.TRUST_PARENT);
111
+ expect(result.current.isFolderTrustDialogOpen).toBe(false);
112
+ expect(onTrustChange).toHaveBeenLastCalledWith(true);
113
+ });
114
+ it('should handle DO_NOT_TRUST choice and trigger restart', () => {
115
+ isWorkspaceTrustedSpy.mockReturnValue({
116
+ isTrusted: undefined,
117
+ source: undefined,
118
+ });
119
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
120
+ act(() => {
121
+ result.current.handleFolderTrustSelect(FolderTrustChoice.DO_NOT_TRUST);
122
+ });
123
+ expect(mockTrustedFolders.setValue).toHaveBeenCalledWith('/test/path', TrustLevel.DO_NOT_TRUST);
124
+ expect(onTrustChange).toHaveBeenLastCalledWith(false);
125
+ expect(result.current.isRestarting).toBe(true);
126
+ expect(result.current.isFolderTrustDialogOpen).toBe(true);
127
+ });
128
+ it('should do nothing for default choice', () => {
129
+ isWorkspaceTrustedSpy.mockReturnValue({
130
+ isTrusted: undefined,
131
+ source: undefined,
132
+ });
133
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
134
+ act(() => {
135
+ result.current.handleFolderTrustSelect('invalid_choice');
136
+ });
137
+ expect(mockTrustedFolders.setValue).not.toHaveBeenCalled();
138
+ expect(mockSettings.setValue).not.toHaveBeenCalled();
139
+ expect(result.current.isFolderTrustDialogOpen).toBe(true);
140
+ expect(onTrustChange).toHaveBeenCalledWith(undefined);
141
+ });
142
+ it('should set isRestarting to true when trust status changes from false to true', () => {
143
+ isWorkspaceTrustedSpy.mockReturnValue({ isTrusted: false, source: 'file' }); // Initially untrusted
144
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
145
+ act(() => {
146
+ result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_FOLDER);
147
+ });
148
+ expect(result.current.isRestarting).toBe(true);
149
+ expect(result.current.isFolderTrustDialogOpen).toBe(true); // Dialog should stay open
150
+ });
151
+ it('should not set isRestarting to true when trust status does not change', () => {
152
+ isWorkspaceTrustedSpy.mockReturnValue({
153
+ isTrusted: undefined,
154
+ source: undefined,
155
+ });
156
+ const { result } = renderHook(() => useFolderTrust(mockSettings, onTrustChange, addItem));
157
+ act(() => {
158
+ result.current.handleFolderTrustSelect(FolderTrustChoice.TRUST_FOLDER);
159
+ });
160
+ expect(result.current.isRestarting).toBe(false);
161
+ expect(result.current.isFolderTrustDialogOpen).toBe(false); // Dialog should close
162
+ });
163
+ });
164
+ //# sourceMappingURL=useFolderTrust.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useFolderTrust.test.js","sourceRoot":"","sources":["../../../../src/ui/hooks/useFolderTrust.test.ts"],"names":[],"mappings":"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"}
@@ -4,7 +4,7 @@
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
6
  import { useState, useRef, useCallback, useEffect, useMemo } from 'react';
7
- import { GeminiEventType as ServerGeminiEventType, getErrorMessage, isNodeError, MessageSenderType, logUserPrompt, GitService, UnauthorizedError, UserPromptEvent, DEFAULT_GEMINI_FLASH_MODEL, logConversationFinishedEvent, ConversationFinishedEvent, ApprovalMode, parseAndFormatApiError, ToolConfirmationOutcome, promptIdContext, } from '@google/gemini-cli-core';
7
+ import { GeminiEventType as ServerGeminiEventType, getErrorMessage, isNodeError, MessageSenderType, logUserPrompt, GitService, UnauthorizedError, UserPromptEvent, DEFAULT_GEMINI_FLASH_MODEL, logConversationFinishedEvent, ConversationFinishedEvent, ApprovalMode, parseAndFormatApiError, ToolConfirmationOutcome, promptIdContext, WRITE_FILE_TOOL_NAME, tokenLimit, } from '@google/gemini-cli-core';
8
8
  import { FinishReason } from '@google/genai';
9
9
  import { StreamingState, MessageType, ToolCallStatus } from '../types.js';
10
10
  import { isAtCommand, isSlashCommand } from '../utils/commandUtils.js';
@@ -24,7 +24,7 @@ var StreamProcessingStatus;
24
24
  StreamProcessingStatus[StreamProcessingStatus["UserCancelled"] = 1] = "UserCancelled";
25
25
  StreamProcessingStatus[StreamProcessingStatus["Error"] = 2] = "Error";
26
26
  })(StreamProcessingStatus || (StreamProcessingStatus = {}));
27
- const EDIT_TOOL_NAMES = new Set(['replace', 'write_file']);
27
+ const EDIT_TOOL_NAMES = new Set(['replace', WRITE_FILE_TOOL_NAME]);
28
28
  function showCitations(settings) {
29
29
  const enabled = settings?.merged?.ui?.showCitations;
30
30
  if (enabled !== undefined) {
@@ -58,6 +58,18 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
58
58
  if (completedToolCallsFromScheduler.length > 0) {
59
59
  // Add the final state of these tools to the history for display.
60
60
  addItem(mapTrackedToolCallsToDisplay(completedToolCallsFromScheduler), Date.now());
61
+ // Record tool calls with full metadata before sending responses.
62
+ try {
63
+ const currentModel = config.getGeminiClient().getCurrentSequenceModel() ??
64
+ config.getModel();
65
+ config
66
+ .getGeminiClient()
67
+ .getChat()
68
+ .recordCompletedToolCalls(currentModel, completedToolCallsFromScheduler);
69
+ }
70
+ catch (error) {
71
+ console.error(`Error recording completed tool call information: ${error}`);
72
+ }
61
73
  // Handle tool response submission immediately when tools complete
62
74
  await handleCompletedTools(completedToolCallsFromScheduler);
63
75
  }
@@ -70,6 +82,8 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
70
82
  }
71
83
  return undefined;
72
84
  }, [toolCalls]);
85
+ const lastQueryRef = useRef(null);
86
+ const lastPromptIdRef = useRef(null);
73
87
  const loopDetectedRef = useRef(false);
74
88
  const [loopDetectionConfirmationRequest, setLoopDetectionConfirmationRequest,] = useState(null);
75
89
  const onExec = useCallback(async (done) => {
@@ -156,37 +170,39 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
156
170
  const trimmedQuery = query.trim();
157
171
  onDebugMessage(`User query: '${trimmedQuery}'`);
158
172
  await logger?.logMessage(MessageSenderType.USER, trimmedQuery);
159
- // Handle UI-only commands first
160
- const slashCommandResult = isSlashCommand(trimmedQuery)
161
- ? await handleSlashCommand(trimmedQuery)
162
- : false;
163
- if (slashCommandResult) {
164
- switch (slashCommandResult.type) {
165
- case 'schedule_tool': {
166
- const { toolName, toolArgs } = slashCommandResult;
167
- const toolCallRequest = {
168
- callId: `${toolName}-${Date.now()}-${Math.random().toString(16).slice(2)}`,
169
- name: toolName,
170
- args: toolArgs,
171
- isClientInitiated: true,
172
- prompt_id,
173
- };
174
- scheduleToolCalls([toolCallRequest], abortSignal);
175
- return { queryToSend: null, shouldProceed: false };
176
- }
177
- case 'submit_prompt': {
178
- localQueryToSendToGemini = slashCommandResult.content;
179
- return {
180
- queryToSend: localQueryToSendToGemini,
181
- shouldProceed: true,
182
- };
183
- }
184
- case 'handled': {
185
- return { queryToSend: null, shouldProceed: false };
186
- }
187
- default: {
188
- const unreachable = slashCommandResult;
189
- throw new Error(`Unhandled slash command result type: ${unreachable}`);
173
+ if (!shellModeActive) {
174
+ // Handle UI-only commands first
175
+ const slashCommandResult = isSlashCommand(trimmedQuery)
176
+ ? await handleSlashCommand(trimmedQuery)
177
+ : false;
178
+ if (slashCommandResult) {
179
+ switch (slashCommandResult.type) {
180
+ case 'schedule_tool': {
181
+ const { toolName, toolArgs } = slashCommandResult;
182
+ const toolCallRequest = {
183
+ callId: `${toolName}-${Date.now()}-${Math.random().toString(16).slice(2)}`,
184
+ name: toolName,
185
+ args: toolArgs,
186
+ isClientInitiated: true,
187
+ prompt_id,
188
+ };
189
+ scheduleToolCalls([toolCallRequest], abortSignal);
190
+ return { queryToSend: null, shouldProceed: false };
191
+ }
192
+ case 'submit_prompt': {
193
+ localQueryToSendToGemini = slashCommandResult.content;
194
+ return {
195
+ queryToSend: localQueryToSendToGemini,
196
+ shouldProceed: true,
197
+ };
198
+ }
199
+ case 'handled': {
200
+ return { queryToSend: null, shouldProceed: false };
201
+ }
202
+ default: {
203
+ const unreachable = slashCommandResult;
204
+ throw new Error(`Unhandled slash command result type: ${unreachable}`);
205
+ }
190
206
  }
191
207
  }
192
208
  }
@@ -373,28 +389,20 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
373
389
  text: `The session has reached the maximum number of turns: ${config.getMaxSessionTurns()}. ` +
374
390
  `Please update this limit in your setting.json file.`,
375
391
  }, Date.now()), [addItem, config]);
376
- const handleLoopDetectionConfirmation = useCallback((result) => {
377
- setLoopDetectionConfirmationRequest(null);
378
- if (result.userSelection === 'disable') {
379
- config.getGeminiClient().getLoopDetectionService().disableForSession();
380
- addItem({
381
- type: 'info',
382
- text: `Loop detection has been disabled for this session. Please try your request again.`,
383
- }, Date.now());
392
+ const handleContextWindowWillOverflowEvent = useCallback((estimatedRequestTokenCount, remainingTokenCount) => {
393
+ onCancelSubmit();
394
+ const limit = tokenLimit(config.getModel());
395
+ const isLessThan75Percent = limit > 0 && remainingTokenCount < limit * 0.75;
396
+ let text = `Sending this message (${estimatedRequestTokenCount} tokens) might exceed the remaining context window limit (${remainingTokenCount} tokens).`;
397
+ if (isLessThan75Percent) {
398
+ text +=
399
+ ' Please try reducing the size of your message or use the `/compress` command to compress the chat history.';
384
400
  }
385
- else {
386
- addItem({
387
- type: 'info',
388
- text: `A potential loop was detected. This can happen due to repetitive tool calls or other model behavior. The request has been halted.`,
389
- }, Date.now());
390
- }
391
- }, [config, addItem]);
392
- const handleLoopDetectedEvent = useCallback(() => {
393
- // Show the confirmation dialog to choose whether to disable loop detection
394
- setLoopDetectionConfirmationRequest({
395
- onComplete: handleLoopDetectionConfirmation,
396
- });
397
- }, [handleLoopDetectionConfirmation]);
401
+ addItem({
402
+ type: 'info',
403
+ text,
404
+ }, Date.now());
405
+ }, [addItem, onCancelSubmit, config]);
398
406
  const processGeminiStreamEvents = useCallback(async (stream, userMessageTimestamp, signal) => {
399
407
  let geminiMessageBuffer = '';
400
408
  const toolCallRequests = [];
@@ -425,6 +433,9 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
425
433
  case ServerGeminiEventType.MaxSessionTurns:
426
434
  handleMaxSessionTurnsEvent();
427
435
  break;
436
+ case ServerGeminiEventType.ContextWindowWillOverflow:
437
+ handleContextWindowWillOverflowEvent(event.value.estimatedRequestTokenCount, event.value.remainingTokenCount);
438
+ break;
428
439
  case ServerGeminiEventType.Finished:
429
440
  handleFinishedEvent(event, userMessageTimestamp);
430
441
  break;
@@ -437,6 +448,7 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
437
448
  loopDetectedRef.current = true;
438
449
  break;
439
450
  case ServerGeminiEventType.Retry:
451
+ case ServerGeminiEventType.InvalidStream:
440
452
  // Will add the missing logic later
441
453
  break;
442
454
  default: {
@@ -458,6 +470,7 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
458
470
  handleChatCompressionEvent,
459
471
  handleFinishedEvent,
460
472
  handleMaxSessionTurnsEvent,
473
+ handleContextWindowWillOverflowEvent,
461
474
  handleCitationEvent,
462
475
  ]);
463
476
  const submitQuery = useCallback(async (query, options, prompt_id) => {
@@ -493,6 +506,9 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
493
506
  }
494
507
  setIsResponding(true);
495
508
  setInitError(null);
509
+ // Store query and prompt_id for potential retry on loop detection
510
+ lastQueryRef.current = queryToSend;
511
+ lastPromptIdRef.current = prompt_id;
496
512
  try {
497
513
  const stream = geminiClient.sendMessageStream(queryToSend, abortSignal, prompt_id);
498
514
  const processingStatus = await processGeminiStreamEvents(stream, userMessageTimestamp, abortSignal);
@@ -505,7 +521,31 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
505
521
  }
506
522
  if (loopDetectedRef.current) {
507
523
  loopDetectedRef.current = false;
508
- handleLoopDetectedEvent();
524
+ // Show the confirmation dialog to choose whether to disable loop detection
525
+ setLoopDetectionConfirmationRequest({
526
+ onComplete: (result) => {
527
+ setLoopDetectionConfirmationRequest(null);
528
+ if (result.userSelection === 'disable') {
529
+ config
530
+ .getGeminiClient()
531
+ .getLoopDetectionService()
532
+ .disableForSession();
533
+ addItem({
534
+ type: 'info',
535
+ text: `Loop detection has been disabled for this session. Retrying request...`,
536
+ }, Date.now());
537
+ if (lastQueryRef.current && lastPromptIdRef.current) {
538
+ submitQuery(lastQueryRef.current, { isContinuation: true }, lastPromptIdRef.current);
539
+ }
540
+ }
541
+ else {
542
+ addItem({
543
+ type: 'info',
544
+ text: `A potential loop was detected. This can happen due to repetitive tool calls or other model behavior. The request has been halted.`,
545
+ }, Date.now());
546
+ }
547
+ },
548
+ });
509
549
  }
510
550
  }
511
551
  catch (error) {
@@ -537,7 +577,6 @@ export const useGeminiStream = (geminiClient, history, addItem, config, settings
537
577
  config,
538
578
  startNewPrompt,
539
579
  getPromptCount,
540
- handleLoopDetectedEvent,
541
580
  ]);
542
581
  const handleApprovalModeChange = useCallback(async (newApprovalMode) => {
543
582
  // Auto-approve pending tool calls when switching to auto-approval modes