@machina.ai/cell-cli-core 1.0.21-rc4 → 1.2.2-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 (479) hide show
  1. package/dist/index.d.ts +3 -1
  2. package/dist/index.js +3 -1
  3. package/dist/index.js.map +1 -1
  4. package/dist/package.json +24 -11
  5. package/dist/src/code_assist/codeAssist.d.ts +4 -3
  6. package/dist/src/code_assist/codeAssist.js.map +1 -1
  7. package/dist/src/code_assist/converter.d.ts +2 -1
  8. package/dist/src/code_assist/converter.js +36 -4
  9. package/dist/src/code_assist/converter.js.map +1 -1
  10. package/dist/src/code_assist/converter.test.js +83 -0
  11. package/dist/src/code_assist/converter.test.js.map +1 -1
  12. package/dist/src/code_assist/oauth2.d.ts +2 -1
  13. package/dist/src/code_assist/oauth2.js +29 -24
  14. package/dist/src/code_assist/oauth2.js.map +1 -1
  15. package/dist/src/code_assist/oauth2.test.js +65 -15
  16. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  17. package/dist/src/code_assist/server.d.ts +5 -5
  18. package/dist/src/code_assist/server.js +1 -1
  19. package/dist/src/code_assist/server.js.map +1 -1
  20. package/dist/src/code_assist/setup.d.ts +1 -1
  21. package/dist/src/code_assist/setup.js +1 -1
  22. package/dist/src/code_assist/setup.js.map +1 -1
  23. package/dist/src/code_assist/setup.test.js.map +1 -1
  24. package/dist/src/config/config.d.ts +53 -11
  25. package/dist/src/config/config.js +113 -29
  26. package/dist/src/config/config.js.map +1 -1
  27. package/dist/src/config/config.test.js +103 -5
  28. package/dist/src/config/config.test.js.map +1 -1
  29. package/dist/src/config/models.d.ts +1 -0
  30. package/dist/src/config/models.js +2 -0
  31. package/dist/src/config/models.js.map +1 -1
  32. package/dist/src/config/storage.d.ts +32 -0
  33. package/dist/src/config/storage.js +90 -0
  34. package/dist/src/config/storage.js.map +1 -0
  35. package/dist/src/config/storage.test.js +43 -0
  36. package/dist/src/config/storage.test.js.map +1 -0
  37. package/dist/src/core/client.d.ts +17 -9
  38. package/dist/src/core/client.js +76 -19
  39. package/dist/src/core/client.js.map +1 -1
  40. package/dist/src/core/client.test.js +366 -84
  41. package/dist/src/core/client.test.js.map +1 -1
  42. package/dist/src/core/contentGenerator.d.ts +6 -6
  43. package/dist/src/core/contentGenerator.js +4 -3
  44. package/dist/src/core/contentGenerator.js.map +1 -1
  45. package/dist/src/core/contentGenerator.test.js.map +1 -1
  46. package/dist/src/core/coreToolScheduler.d.ts +14 -5
  47. package/dist/src/core/coreToolScheduler.js +120 -49
  48. package/dist/src/core/coreToolScheduler.js.map +1 -1
  49. package/dist/src/core/coreToolScheduler.test.js +365 -72
  50. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  51. package/dist/src/core/geminiChat.d.ts +18 -14
  52. package/dist/src/core/geminiChat.js +223 -156
  53. package/dist/src/core/geminiChat.js.map +1 -1
  54. package/dist/src/core/geminiChat.test.js +862 -257
  55. package/dist/src/core/geminiChat.test.js.map +1 -1
  56. package/dist/src/core/geminiRequest.js +1 -0
  57. package/dist/src/core/geminiRequest.js.map +1 -1
  58. package/dist/src/core/logger.d.ts +4 -2
  59. package/dist/src/core/logger.js +4 -3
  60. package/dist/src/core/logger.js.map +1 -1
  61. package/dist/src/core/logger.test.js +19 -18
  62. package/dist/src/core/logger.test.js.map +1 -1
  63. package/dist/src/core/loggingContentGenerator.d.ts +3 -3
  64. package/dist/src/core/loggingContentGenerator.js +3 -1
  65. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  66. package/dist/src/core/nonInteractiveToolExecutor.d.ts +3 -5
  67. package/dist/src/core/nonInteractiveToolExecutor.js +15 -123
  68. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  69. package/dist/src/core/nonInteractiveToolExecutor.test.js +114 -90
  70. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  71. package/dist/src/core/prompts.js +8 -7
  72. package/dist/src/core/prompts.js.map +1 -1
  73. package/dist/src/core/prompts.test.js +21 -21
  74. package/dist/src/core/prompts.test.js.map +1 -1
  75. package/dist/src/core/subagent.d.ts +24 -18
  76. package/dist/src/core/subagent.js +125 -87
  77. package/dist/src/core/subagent.js.map +1 -1
  78. package/dist/src/core/subagent.test.js +31 -26
  79. package/dist/src/core/subagent.test.js.map +1 -1
  80. package/dist/src/core/turn.d.ts +24 -7
  81. package/dist/src/core/turn.js +41 -11
  82. package/dist/src/core/turn.js.map +1 -1
  83. package/dist/src/core/turn.test.js +157 -1
  84. package/dist/src/core/turn.test.js.map +1 -1
  85. package/dist/src/generated/git-commit.d.ts +2 -2
  86. package/dist/src/generated/git-commit.js +2 -2
  87. package/dist/src/generated/git-commit.js.map +1 -1
  88. package/dist/src/ide/constants.d.ts +1 -1
  89. package/dist/src/ide/constants.js +1 -1
  90. package/dist/src/ide/constants.js.map +1 -1
  91. package/dist/src/ide/detect-ide.d.ts +8 -3
  92. package/dist/src/ide/detect-ide.js +29 -11
  93. package/dist/src/ide/detect-ide.js.map +1 -1
  94. package/dist/src/ide/detect-ide.test.js +96 -52
  95. package/dist/src/ide/detect-ide.test.js.map +1 -1
  96. package/dist/src/ide/ide-client.d.ts +11 -7
  97. package/dist/src/ide/ide-client.js +127 -29
  98. package/dist/src/ide/ide-client.js.map +1 -1
  99. package/dist/src/ide/ide-client.test.js +147 -25
  100. package/dist/src/ide/ide-client.test.js.map +1 -1
  101. package/dist/src/ide/ide-installer.d.ts +1 -1
  102. package/dist/src/ide/ide-installer.js +31 -22
  103. package/dist/src/ide/ide-installer.js.map +1 -1
  104. package/dist/src/ide/ide-installer.test.js +82 -22
  105. package/dist/src/ide/ide-installer.test.js.map +1 -1
  106. package/dist/src/ide/process-utils.d.ts +14 -6
  107. package/dist/src/ide/process-utils.js +136 -34
  108. package/dist/src/ide/process-utils.js.map +1 -1
  109. package/dist/src/ide/process-utils.test.js +158 -0
  110. package/dist/src/ide/process-utils.test.js.map +1 -0
  111. package/dist/src/index.d.ts +11 -2
  112. package/dist/src/index.js +10 -1
  113. package/dist/src/index.js.map +1 -1
  114. package/dist/src/mcp/google-auth-provider.d.ts +3 -3
  115. package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
  116. package/dist/src/mcp/oauth-provider.d.ts +2 -2
  117. package/dist/src/mcp/oauth-provider.js.map +1 -1
  118. package/dist/src/mcp/oauth-provider.test.js +1 -1
  119. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  120. package/dist/src/mcp/oauth-token-storage.d.ts +5 -27
  121. package/dist/src/mcp/oauth-token-storage.js +2 -5
  122. package/dist/src/mcp/oauth-token-storage.js.map +1 -1
  123. package/dist/src/mcp/oauth-token-storage.test.js +7 -6
  124. package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
  125. package/dist/src/mcp/oauth-utils.d.ts +9 -1
  126. package/dist/src/mcp/oauth-utils.js +41 -27
  127. package/dist/src/mcp/oauth-utils.js.map +1 -1
  128. package/dist/src/mcp/oauth-utils.test.js +41 -1
  129. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  130. package/dist/src/mcp/token-storage/base-token-storage.d.ts +19 -0
  131. package/dist/src/mcp/token-storage/base-token-storage.js +36 -0
  132. package/dist/src/mcp/token-storage/base-token-storage.js.map +1 -0
  133. package/dist/src/mcp/token-storage/base-token-storage.test.d.ts +6 -0
  134. package/dist/src/mcp/token-storage/base-token-storage.test.js +160 -0
  135. package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -0
  136. package/dist/src/mcp/token-storage/file-token-storage.d.ts +24 -0
  137. package/dist/src/mcp/token-storage/file-token-storage.js +144 -0
  138. package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -0
  139. package/dist/src/mcp/token-storage/file-token-storage.test.d.ts +6 -0
  140. package/dist/src/mcp/token-storage/file-token-storage.test.js +235 -0
  141. package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -0
  142. package/dist/src/mcp/token-storage/types.d.ts +34 -0
  143. package/dist/src/mcp/token-storage/types.js +7 -0
  144. package/dist/src/mcp/token-storage/types.js.map +1 -0
  145. package/dist/src/prompts/mcp-prompts.d.ts +2 -2
  146. package/dist/src/prompts/prompt-registry.d.ts +1 -1
  147. package/dist/src/services/chatRecordingService.d.ts +2 -2
  148. package/dist/src/services/chatRecordingService.js +6 -3
  149. package/dist/src/services/chatRecordingService.js.map +1 -1
  150. package/dist/src/services/chatRecordingService.test.js +10 -8
  151. package/dist/src/services/chatRecordingService.test.js.map +1 -1
  152. package/dist/src/services/fileDiscoveryService.js +1 -1
  153. package/dist/src/services/fileDiscoveryService.js.map +1 -1
  154. package/dist/src/services/fileDiscoveryService.test.js +3 -3
  155. package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
  156. package/dist/src/services/fileSystemService.js +1 -1
  157. package/dist/src/services/fileSystemService.js.map +1 -1
  158. package/dist/src/services/fileSystemService.test.js +1 -1
  159. package/dist/src/services/fileSystemService.test.js.map +1 -1
  160. package/dist/src/services/gitService.d.ts +3 -1
  161. package/dist/src/services/gitService.js +21 -12
  162. package/dist/src/services/gitService.js.map +1 -1
  163. package/dist/src/services/gitService.test.js +22 -19
  164. package/dist/src/services/gitService.test.js.map +1 -1
  165. package/dist/src/services/loopDetectionService.d.ts +2 -2
  166. package/dist/src/services/loopDetectionService.js +9 -3
  167. package/dist/src/services/loopDetectionService.js.map +1 -1
  168. package/dist/src/services/loopDetectionService.test.js +23 -1
  169. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  170. package/dist/src/services/shellExecutionService.d.ts +8 -10
  171. package/dist/src/services/shellExecutionService.js +292 -135
  172. package/dist/src/services/shellExecutionService.js.map +1 -1
  173. package/dist/src/services/shellExecutionService.test.js +277 -42
  174. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  175. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +16 -4
  176. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +140 -9
  177. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  178. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +84 -11
  179. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  180. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +26 -1
  181. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +62 -0
  182. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  183. package/dist/src/telemetry/constants.d.ts +8 -0
  184. package/dist/src/telemetry/constants.js +8 -0
  185. package/dist/src/telemetry/constants.js.map +1 -1
  186. package/dist/src/telemetry/file-exporters.d.ts +5 -4
  187. package/dist/src/telemetry/file-exporters.js +1 -1
  188. package/dist/src/telemetry/file-exporters.js.map +1 -1
  189. package/dist/src/telemetry/index.d.ts +5 -2
  190. package/dist/src/telemetry/index.js +3 -2
  191. package/dist/src/telemetry/index.js.map +1 -1
  192. package/dist/src/telemetry/loggers.d.ts +8 -2
  193. package/dist/src/telemetry/loggers.js +105 -2
  194. package/dist/src/telemetry/loggers.js.map +1 -1
  195. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  196. package/dist/src/telemetry/loggers.test.js +69 -9
  197. package/dist/src/telemetry/loggers.test.js.map +1 -1
  198. package/dist/src/telemetry/metrics.d.ts +15 -4
  199. package/dist/src/telemetry/metrics.js +46 -8
  200. package/dist/src/telemetry/metrics.js.map +1 -1
  201. package/dist/src/telemetry/metrics.test.js +5 -25
  202. package/dist/src/telemetry/metrics.test.js.map +1 -1
  203. package/dist/src/telemetry/sdk.d.ts +1 -1
  204. package/dist/src/telemetry/sdk.js +3 -3
  205. package/dist/src/telemetry/sdk.js.map +1 -1
  206. package/dist/src/telemetry/telemetry-utils.d.ts +6 -0
  207. package/dist/src/telemetry/telemetry-utils.js +14 -0
  208. package/dist/src/telemetry/telemetry-utils.js.map +1 -0
  209. package/dist/src/telemetry/telemetry-utils.test.d.ts +6 -0
  210. package/dist/src/telemetry/telemetry-utils.test.js +40 -0
  211. package/dist/src/telemetry/telemetry-utils.test.js.map +1 -0
  212. package/dist/src/telemetry/types.d.ts +52 -6
  213. package/dist/src/telemetry/types.js +87 -2
  214. package/dist/src/telemetry/types.js.map +1 -1
  215. package/dist/src/telemetry/uiTelemetry.d.ts +2 -2
  216. package/dist/src/telemetry/uiTelemetry.js +1 -1
  217. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  218. package/dist/src/telemetry/uiTelemetry.test.js +16 -12
  219. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  220. package/dist/src/test-utils/config.d.ts +2 -1
  221. package/dist/src/test-utils/config.js.map +1 -1
  222. package/dist/src/test-utils/index.d.ts +6 -0
  223. package/dist/src/test-utils/index.js +7 -0
  224. package/dist/src/test-utils/index.js.map +1 -0
  225. package/dist/src/test-utils/mock-tool.d.ts +41 -0
  226. package/dist/src/test-utils/mock-tool.js +51 -0
  227. package/dist/src/test-utils/mock-tool.js.map +1 -0
  228. package/dist/src/test-utils/mockWorkspaceContext.d.ts +1 -1
  229. package/dist/src/test-utils/tools.d.ts +3 -2
  230. package/dist/src/test-utils/tools.js.map +1 -1
  231. package/dist/src/tools/diffOptions.d.ts +1 -1
  232. package/dist/src/tools/edit.d.ts +6 -5
  233. package/dist/src/tools/edit.js +36 -17
  234. package/dist/src/tools/edit.js.map +1 -1
  235. package/dist/src/tools/edit.test.js +45 -8
  236. package/dist/src/tools/edit.test.js.map +1 -1
  237. package/dist/src/tools/glob.d.ts +3 -2
  238. package/dist/src/tools/glob.js +17 -6
  239. package/dist/src/tools/glob.js.map +1 -1
  240. package/dist/src/tools/glob.test.js +29 -4
  241. package/dist/src/tools/glob.test.js.map +1 -1
  242. package/dist/src/tools/grep.d.ts +3 -2
  243. package/dist/src/tools/grep.js +35 -15
  244. package/dist/src/tools/grep.js.map +1 -1
  245. package/dist/src/tools/grep.test.js +26 -3
  246. package/dist/src/tools/grep.test.js.map +1 -1
  247. package/dist/src/tools/ls.d.ts +3 -2
  248. package/dist/src/tools/ls.js +12 -7
  249. package/dist/src/tools/ls.js.map +1 -1
  250. package/dist/src/tools/ls.test.js +7 -2
  251. package/dist/src/tools/ls.test.js.map +1 -1
  252. package/dist/src/tools/mcp-client-manager.d.ts +8 -6
  253. package/dist/src/tools/mcp-client-manager.js +30 -5
  254. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  255. package/dist/src/tools/mcp-client-manager.test.js +20 -1
  256. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  257. package/dist/src/tools/mcp-client.d.ts +18 -11
  258. package/dist/src/tools/mcp-client.js +38 -33
  259. package/dist/src/tools/mcp-client.js.map +1 -1
  260. package/dist/src/tools/mcp-client.test.js +29 -4
  261. package/dist/src/tools/mcp-client.test.js.map +1 -1
  262. package/dist/src/tools/mcp-tool.d.ts +6 -3
  263. package/dist/src/tools/mcp-tool.js +21 -7
  264. package/dist/src/tools/mcp-tool.js.map +1 -1
  265. package/dist/src/tools/mcp-tool.test.js +49 -6
  266. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  267. package/dist/src/tools/memoryTool.d.ts +4 -3
  268. package/dist/src/tools/memoryTool.js +15 -38
  269. package/dist/src/tools/memoryTool.js.map +1 -1
  270. package/dist/src/tools/memoryTool.test.js +24 -12
  271. package/dist/src/tools/memoryTool.test.js.map +1 -1
  272. package/dist/src/tools/modifiable-tool.d.ts +2 -2
  273. package/dist/src/tools/modifiable-tool.js +3 -3
  274. package/dist/src/tools/modifiable-tool.js.map +1 -1
  275. package/dist/src/tools/modifiable-tool.test.js +4 -4
  276. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  277. package/dist/src/tools/read-file.d.ts +3 -2
  278. package/dist/src/tools/read-file.js +12 -34
  279. package/dist/src/tools/read-file.js.map +1 -1
  280. package/dist/src/tools/read-file.test.js +9 -6
  281. package/dist/src/tools/read-file.test.js.map +1 -1
  282. package/dist/src/tools/read-many-files.d.ts +3 -2
  283. package/dist/src/tools/read-many-files.js +35 -58
  284. package/dist/src/tools/read-many-files.js.map +1 -1
  285. package/dist/src/tools/read-many-files.test.js +60 -7
  286. package/dist/src/tools/read-many-files.test.js.map +1 -1
  287. package/dist/src/tools/ripGrep.d.ts +47 -0
  288. package/dist/src/tools/ripGrep.js +368 -0
  289. package/dist/src/tools/ripGrep.js.map +1 -0
  290. package/dist/src/tools/ripGrep.test.d.ts +6 -0
  291. package/dist/src/tools/ripGrep.test.js +874 -0
  292. package/dist/src/tools/ripGrep.test.js.map +1 -0
  293. package/dist/src/tools/shell.d.ts +3 -2
  294. package/dist/src/tools/shell.js +26 -24
  295. package/dist/src/tools/shell.js.map +1 -1
  296. package/dist/src/tools/shell.test.js +33 -24
  297. package/dist/src/tools/shell.test.js.map +1 -1
  298. package/dist/src/tools/smart-edit.d.ts +73 -0
  299. package/dist/src/tools/smart-edit.js +607 -0
  300. package/dist/src/tools/smart-edit.js.map +1 -0
  301. package/dist/src/tools/smart-edit.test.d.ts +6 -0
  302. package/dist/src/tools/smart-edit.test.js +397 -0
  303. package/dist/src/tools/smart-edit.test.js.map +1 -0
  304. package/dist/src/tools/tool-error.d.ts +17 -1
  305. package/dist/src/tools/tool-error.js +26 -0
  306. package/dist/src/tools/tool-error.js.map +1 -1
  307. package/dist/src/tools/tool-registry.d.ts +10 -4
  308. package/dist/src/tools/tool-registry.js +19 -7
  309. package/dist/src/tools/tool-registry.js.map +1 -1
  310. package/dist/src/tools/tool-registry.test.js +86 -3
  311. package/dist/src/tools/tool-registry.test.js.map +1 -1
  312. package/dist/src/tools/tools.d.ts +9 -7
  313. package/dist/src/tools/tools.js +12 -0
  314. package/dist/src/tools/tools.js.map +1 -1
  315. package/dist/src/tools/tools.test.js +1 -2
  316. package/dist/src/tools/tools.test.js.map +1 -1
  317. package/dist/src/tools/web-fetch.d.ts +3 -2
  318. package/dist/src/tools/web-fetch.js +10 -7
  319. package/dist/src/tools/web-fetch.js.map +1 -1
  320. package/dist/src/tools/web-fetch.test.js +55 -16
  321. package/dist/src/tools/web-fetch.test.js.map +1 -1
  322. package/dist/src/tools/web-search.d.ts +4 -3
  323. package/dist/src/tools/web-search.js +28 -7
  324. package/dist/src/tools/web-search.js.map +1 -1
  325. package/dist/src/tools/web-search.test.js +69 -1
  326. package/dist/src/tools/web-search.test.js.map +1 -1
  327. package/dist/src/tools/write-file.d.ts +4 -3
  328. package/dist/src/tools/write-file.js +13 -13
  329. package/dist/src/tools/write-file.js.map +1 -1
  330. package/dist/src/tools/write-file.test.js +9 -5
  331. package/dist/src/tools/write-file.test.js.map +1 -1
  332. package/dist/src/utils/bfsFileSearch.d.ts +2 -2
  333. package/dist/src/utils/bfsFileSearch.js +2 -2
  334. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  335. package/dist/src/utils/bfsFileSearch.test.js +3 -3
  336. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  337. package/dist/src/utils/editCorrector.d.ts +2 -2
  338. package/dist/src/utils/editCorrector.js +1 -1
  339. package/dist/src/utils/editCorrector.js.map +1 -1
  340. package/dist/src/utils/editCorrector.test.js +3 -3
  341. package/dist/src/utils/editCorrector.test.js.map +1 -1
  342. package/dist/src/utils/editor.js +2 -2
  343. package/dist/src/utils/editor.js.map +1 -1
  344. package/dist/src/utils/editor.test.js +2 -2
  345. package/dist/src/utils/editor.test.js.map +1 -1
  346. package/dist/src/utils/environmentContext.d.ts +2 -2
  347. package/dist/src/utils/environmentContext.js +1 -1
  348. package/dist/src/utils/environmentContext.js.map +1 -1
  349. package/dist/src/utils/environmentContext.test.js +1 -1
  350. package/dist/src/utils/environmentContext.test.js.map +1 -1
  351. package/dist/src/utils/errorReporting.d.ts +1 -1
  352. package/dist/src/utils/errors.d.ts +19 -0
  353. package/dist/src/utils/errors.js +32 -0
  354. package/dist/src/utils/errors.js.map +1 -1
  355. package/dist/src/utils/fetch.js +1 -1
  356. package/dist/src/utils/fetch.js.map +1 -1
  357. package/dist/src/utils/fileUtils.d.ts +23 -12
  358. package/dist/src/utils/fileUtils.js +155 -75
  359. package/dist/src/utils/fileUtils.js.map +1 -1
  360. package/dist/src/utils/fileUtils.test.js +293 -1
  361. package/dist/src/utils/fileUtils.test.js.map +1 -1
  362. package/dist/src/utils/filesearch/crawler.d.ts +1 -1
  363. package/dist/src/utils/filesearch/crawler.test.js +2 -2
  364. package/dist/src/utils/filesearch/crawler.test.js.map +1 -1
  365. package/dist/src/utils/filesearch/fileSearch.d.ts +1 -0
  366. package/dist/src/utils/filesearch/fileSearch.js +14 -9
  367. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  368. package/dist/src/utils/filesearch/fileSearch.test.js +90 -0
  369. package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
  370. package/dist/src/utils/generateContentResponseUtilities.d.ts +1 -2
  371. package/dist/src/utils/generateContentResponseUtilities.js +1 -13
  372. package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
  373. package/dist/src/utils/generateContentResponseUtilities.test.js +2 -40
  374. package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
  375. package/dist/src/utils/getFolderStructure.d.ts +2 -2
  376. package/dist/src/utils/getFolderStructure.js +2 -2
  377. package/dist/src/utils/getFolderStructure.js.map +1 -1
  378. package/dist/src/utils/getFolderStructure.test.js +13 -13
  379. package/dist/src/utils/getFolderStructure.test.js.map +1 -1
  380. package/dist/src/utils/getPty.d.ts +19 -0
  381. package/dist/src/utils/getPty.js +23 -0
  382. package/dist/src/utils/getPty.js.map +1 -0
  383. package/dist/src/utils/gitIgnoreParser.js +3 -3
  384. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  385. package/dist/src/utils/gitIgnoreParser.test.js +3 -3
  386. package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
  387. package/dist/src/utils/gitUtils.js +2 -2
  388. package/dist/src/utils/gitUtils.js.map +1 -1
  389. package/dist/src/utils/ignorePatterns.d.ts +103 -0
  390. package/dist/src/utils/ignorePatterns.js +220 -0
  391. package/dist/src/utils/ignorePatterns.js.map +1 -0
  392. package/dist/src/utils/ignorePatterns.test.d.ts +6 -0
  393. package/dist/src/utils/ignorePatterns.test.js +250 -0
  394. package/dist/src/utils/ignorePatterns.test.js.map +1 -0
  395. package/dist/src/utils/installationManager.d.ts +16 -0
  396. package/dist/src/utils/installationManager.js +50 -0
  397. package/dist/src/utils/installationManager.js.map +1 -0
  398. package/dist/src/utils/installationManager.test.d.ts +6 -0
  399. package/dist/src/utils/installationManager.test.js +83 -0
  400. package/dist/src/utils/installationManager.test.js.map +1 -0
  401. package/dist/src/utils/language-detection.d.ts +6 -0
  402. package/dist/src/utils/language-detection.js +101 -0
  403. package/dist/src/utils/language-detection.js.map +1 -0
  404. package/dist/src/utils/llm-edit-fixer.d.ts +25 -0
  405. package/dist/src/utils/llm-edit-fixer.js +112 -0
  406. package/dist/src/utils/llm-edit-fixer.js.map +1 -0
  407. package/dist/src/utils/memoryDiscovery.d.ts +7 -6
  408. package/dist/src/utils/memoryDiscovery.js +68 -33
  409. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  410. package/dist/src/utils/memoryDiscovery.test.js +76 -20
  411. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  412. package/dist/src/utils/memoryImportProcessor.js +2 -2
  413. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  414. package/dist/src/utils/memoryImportProcessor.test.js +2 -141
  415. package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
  416. package/dist/src/utils/messageInspectors.d.ts +1 -1
  417. package/dist/src/utils/nextSpeakerChecker.d.ts +2 -2
  418. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  419. package/dist/src/utils/partUtils.d.ts +22 -1
  420. package/dist/src/utils/partUtils.js +68 -0
  421. package/dist/src/utils/partUtils.js.map +1 -1
  422. package/dist/src/utils/partUtils.test.js +112 -1
  423. package/dist/src/utils/partUtils.test.js.map +1 -1
  424. package/dist/src/utils/pathReader.d.ts +17 -0
  425. package/dist/src/utils/pathReader.js +92 -0
  426. package/dist/src/utils/pathReader.js.map +1 -0
  427. package/dist/src/utils/pathReader.test.d.ts +6 -0
  428. package/dist/src/utils/pathReader.test.js +363 -0
  429. package/dist/src/utils/pathReader.test.js.map +1 -0
  430. package/dist/src/utils/paths.d.ts +1 -18
  431. package/dist/src/utils/paths.js +3 -29
  432. package/dist/src/utils/paths.js.map +1 -1
  433. package/dist/src/utils/quotaErrorDetection.d.ts +1 -1
  434. package/dist/src/utils/retry.test.js +4 -1
  435. package/dist/src/utils/retry.test.js.map +1 -1
  436. package/dist/src/utils/schemaValidator.js +4 -0
  437. package/dist/src/utils/schemaValidator.js.map +1 -1
  438. package/dist/src/utils/session.js +1 -1
  439. package/dist/src/utils/session.js.map +1 -1
  440. package/dist/src/utils/shell-utils.d.ts +1 -1
  441. package/dist/src/utils/shell-utils.js +23 -29
  442. package/dist/src/utils/shell-utils.js.map +1 -1
  443. package/dist/src/utils/shell-utils.test.js +8 -1
  444. package/dist/src/utils/shell-utils.test.js.map +1 -1
  445. package/dist/src/utils/summarizer.d.ts +2 -2
  446. package/dist/src/utils/summarizer.test.js.map +1 -1
  447. package/dist/src/utils/systemEncoding.js +2 -2
  448. package/dist/src/utils/systemEncoding.js.map +1 -1
  449. package/dist/src/utils/systemEncoding.test.js +2 -2
  450. package/dist/src/utils/systemEncoding.test.js.map +1 -1
  451. package/dist/src/utils/tool-utils.d.ts +19 -0
  452. package/dist/src/utils/tool-utils.js +58 -0
  453. package/dist/src/utils/tool-utils.js.map +1 -0
  454. package/dist/src/utils/tool-utils.test.d.ts +6 -0
  455. package/dist/src/utils/tool-utils.test.js +61 -0
  456. package/dist/src/utils/tool-utils.test.js.map +1 -0
  457. package/dist/src/utils/userAccountManager.d.ts +20 -0
  458. package/dist/src/utils/userAccountManager.js +114 -0
  459. package/dist/src/utils/userAccountManager.js.map +1 -0
  460. package/dist/src/utils/userAccountManager.test.d.ts +6 -0
  461. package/dist/src/utils/{user_account.test.js → userAccountManager.test.js} +33 -30
  462. package/dist/src/utils/userAccountManager.test.js.map +1 -0
  463. package/dist/src/utils/workspaceContext.js +13 -7
  464. package/dist/src/utils/workspaceContext.js.map +1 -1
  465. package/dist/src/utils/workspaceContext.test.js +41 -16
  466. package/dist/src/utils/workspaceContext.test.js.map +1 -1
  467. package/dist/tsconfig.tsbuildinfo +1 -1
  468. package/package.json +25 -12
  469. package/dist/src/utils/user_account.d.ts +0 -9
  470. package/dist/src/utils/user_account.js +0 -109
  471. package/dist/src/utils/user_account.js.map +0 -1
  472. package/dist/src/utils/user_account.test.js.map +0 -1
  473. package/dist/src/utils/user_id.d.ts +0 -11
  474. package/dist/src/utils/user_id.js +0 -49
  475. package/dist/src/utils/user_id.js.map +0 -1
  476. package/dist/src/utils/user_id.test.js +0 -21
  477. package/dist/src/utils/user_id.test.js.map +0 -1
  478. /package/dist/src/{utils/user_account.test.d.ts → config/storage.test.d.ts} +0 -0
  479. /package/dist/src/{utils/user_id.test.d.ts → ide/process-utils.test.d.ts} +0 -0
@@ -3,12 +3,13 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
7
- import { GoogleGenAI, } from '@google/genai';
8
- import { findIndexAfterFraction, GeminiClient } from './client.js';
9
- import { AuthType } from './contentGenerator.js';
6
+ import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
7
+ import { GoogleGenAI } from '@google/genai';
8
+ import { findIndexAfterFraction, isThinkingDefault, isThinkingSupported, GeminiClient, } from './client.js';
9
+ import { AuthType, } from './contentGenerator.js';
10
+ import {} from './geminiChat.js';
10
11
  import { Config } from '../config/config.js';
11
- import { GeminiEventType, Turn } from './turn.js';
12
+ import { CompressionStatus, GeminiEventType, Turn, } from './turn.js';
12
13
  import { getCoreSystemPrompt } from './prompts.js';
13
14
  import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
14
15
  import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
@@ -22,7 +23,8 @@ const mockGenerateContentFn = vi.fn();
22
23
  const mockEmbedContentFn = vi.fn();
23
24
  const mockTurnRunFn = vi.fn();
24
25
  vi.mock('@google/genai');
25
- vi.mock('./turn', () => {
26
+ vi.mock('./turn', async (importOriginal) => {
27
+ const actual = await importOriginal();
26
28
  // Define a mock class that has the same shape as the real Turn
27
29
  class MockTurn {
28
30
  pendingToolCalls = [];
@@ -34,11 +36,8 @@ vi.mock('./turn', () => {
34
36
  }
35
37
  // Export the mock class as 'Turn'
36
38
  return {
39
+ ...actual,
37
40
  Turn: MockTurn,
38
- GeminiEventType: {
39
- MaxSessionTurns: 'MaxSessionTurns',
40
- ChatCompressed: 'ChatCompressed',
41
- },
42
41
  };
43
42
  });
44
43
  vi.mock('../config/config.js');
@@ -60,6 +59,18 @@ vi.mock('../telemetry/index.js', () => ({
60
59
  logApiError: vi.fn(),
61
60
  }));
62
61
  vi.mock('../ide/ideContext.js');
62
+ /**
63
+ * Array.fromAsync ponyfill, which will be available in es 2024.
64
+ *
65
+ * Buffers an async generator into an array and returns the result.
66
+ */
67
+ async function fromAsync(promise) {
68
+ const results = [];
69
+ for await (const result of promise) {
70
+ results.push(result);
71
+ }
72
+ return results;
73
+ }
63
74
  describe('findIndexAfterFraction', () => {
64
75
  const history = [
65
76
  { role: 'user', parts: [{ text: 'This is the first message.' }] }, // JSON length: 66
@@ -106,6 +117,33 @@ describe('findIndexAfterFraction', () => {
106
117
  expect(findIndexAfterFraction(historyWithEmptyParts, 0.5)).toBe(1);
107
118
  });
108
119
  });
120
+ describe('isThinkingSupported', () => {
121
+ it('should return true for gemini-2.5', () => {
122
+ expect(isThinkingSupported('gemini-2.5')).toBe(true);
123
+ });
124
+ it('should return true for gemini-2.5-pro', () => {
125
+ expect(isThinkingSupported('gemini-2.5-pro')).toBe(true);
126
+ });
127
+ it('should return false for other models', () => {
128
+ expect(isThinkingSupported('gemini-1.5-flash')).toBe(false);
129
+ expect(isThinkingSupported('some-other-model')).toBe(false);
130
+ });
131
+ });
132
+ describe('isThinkingDefault', () => {
133
+ it('should return false for gemini-2.5-flash-lite', () => {
134
+ expect(isThinkingDefault('gemini-2.5-flash-lite')).toBe(false);
135
+ });
136
+ it('should return true for gemini-2.5', () => {
137
+ expect(isThinkingDefault('gemini-2.5')).toBe(true);
138
+ });
139
+ it('should return true for gemini-2.5-pro', () => {
140
+ expect(isThinkingDefault('gemini-2.5-pro')).toBe(true);
141
+ });
142
+ it('should return false for other models', () => {
143
+ expect(isThinkingDefault('gemini-1.5-flash')).toBe(false);
144
+ expect(isThinkingDefault('some-other-model')).toBe(false);
145
+ });
146
+ });
109
147
  describe('Gemini Client (client.ts)', () => {
110
148
  let client;
111
149
  beforeEach(async () => {
@@ -152,7 +190,7 @@ describe('Gemini Client (client.ts)', () => {
152
190
  getContentGeneratorConfig: vi
153
191
  .fn()
154
192
  .mockReturnValue(contentGeneratorConfig),
155
- getToolRegistry: vi.fn().mockResolvedValue(mockToolRegistry),
193
+ getToolRegistry: vi.fn().mockReturnValue(mockToolRegistry),
156
194
  getModel: vi.fn().mockReturnValue('test-model'),
157
195
  getEmbeddingModel: vi.fn().mockReturnValue('test-embedding-model'),
158
196
  getApiKey: vi.fn().mockReturnValue('test-key'),
@@ -178,6 +216,7 @@ describe('Gemini Client (client.ts)', () => {
178
216
  getGeminiClient: vi.fn(),
179
217
  setFallbackMode: vi.fn(),
180
218
  getChatCompression: vi.fn().mockReturnValue(undefined),
219
+ getSkipNextSpeakerCheck: vi.fn().mockReturnValue(false),
181
220
  };
182
221
  const MockedConfig = vi.mocked(Config, true);
183
222
  MockedConfig.mockImplementation(() => mockConfigObject);
@@ -274,30 +313,6 @@ describe('Gemini Client (client.ts)', () => {
274
313
  await expect(client.generateEmbedding(texts)).rejects.toThrow('API Failure');
275
314
  });
276
315
  });
277
- describe('generateContent', () => {
278
- it('should call generateContent with the correct parameters', async () => {
279
- const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
280
- const generationConfig = { temperature: 0.5 };
281
- const abortSignal = new AbortController().signal;
282
- // Mock countTokens
283
- const mockGenerator = {
284
- countTokens: vi.fn().mockResolvedValue({ totalTokens: 1 }),
285
- generateContent: mockGenerateContentFn,
286
- };
287
- client['contentGenerator'] = mockGenerator;
288
- await client.generateContent(contents, generationConfig, abortSignal);
289
- expect(mockGenerateContentFn).toHaveBeenCalledWith({
290
- model: 'test-model',
291
- config: {
292
- abortSignal,
293
- systemInstruction: getCoreSystemPrompt(''),
294
- temperature: 0.5,
295
- topP: 1,
296
- },
297
- contents,
298
- }, 'test-session-id');
299
- });
300
- });
301
316
  describe('generateJson', () => {
302
317
  it('should call generateContent with the correct parameters', async () => {
303
318
  const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
@@ -324,7 +339,9 @@ describe('Gemini Client (client.ts)', () => {
324
339
  }, 'test-session-id');
325
340
  });
326
341
  it('should allow overriding model and config', async () => {
327
- const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
342
+ const contents = [
343
+ { role: 'user', parts: [{ text: 'hello' }] },
344
+ ];
328
345
  const schema = { type: 'string' };
329
346
  const abortSignal = new AbortController().signal;
330
347
  const customModel = 'custom-json-model';
@@ -404,6 +421,106 @@ describe('Gemini Client (client.ts)', () => {
404
421
  sendMessage: mockSendMessage,
405
422
  };
406
423
  });
424
+ function setup({ chatHistory = [
425
+ { role: 'user', parts: [{ text: 'Long conversation' }] },
426
+ { role: 'model', parts: [{ text: 'Long response' }] },
427
+ ], } = {}) {
428
+ const mockChat = {
429
+ getHistory: vi.fn().mockReturnValue(chatHistory),
430
+ setHistory: vi.fn(),
431
+ sendMessage: vi.fn().mockResolvedValue({ text: 'Summary' }),
432
+ };
433
+ const mockCountTokens = vi
434
+ .fn()
435
+ .mockResolvedValueOnce({ totalTokens: 1000 })
436
+ .mockResolvedValueOnce({ totalTokens: 5000 });
437
+ const mockGenerator = {
438
+ countTokens: mockCountTokens,
439
+ };
440
+ client['chat'] = mockChat;
441
+ client['contentGenerator'] = mockGenerator;
442
+ client['startChat'] = vi.fn().mockResolvedValue({ ...mockChat });
443
+ return { client, mockChat, mockGenerator };
444
+ }
445
+ describe('when compression inflates the token count', () => {
446
+ it('uses the truncated history for compression');
447
+ it('allows compression to be forced/manual after a failure', async () => {
448
+ const { client, mockGenerator } = setup();
449
+ mockGenerator.countTokens?.mockResolvedValue({
450
+ totalTokens: 1000,
451
+ });
452
+ await client.tryCompressChat('prompt-id-4'); // Fails
453
+ const result = await client.tryCompressChat('prompt-id-4', true);
454
+ expect(result).toEqual({
455
+ compressionStatus: CompressionStatus.COMPRESSED,
456
+ newTokenCount: 1000,
457
+ originalTokenCount: 1000,
458
+ });
459
+ });
460
+ it('yields the result even if the compression inflated the tokens', async () => {
461
+ const { client } = setup();
462
+ const result = await client.tryCompressChat('prompt-id-4', true);
463
+ expect(result).toEqual({
464
+ compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
465
+ newTokenCount: 5000,
466
+ originalTokenCount: 1000,
467
+ });
468
+ });
469
+ it('does not manipulate the source chat', async () => {
470
+ const { client, mockChat } = setup();
471
+ await client.tryCompressChat('prompt-id-4', true);
472
+ expect(client['chat']).toBe(mockChat); // a new chat session was not created
473
+ });
474
+ it('restores the history back to the original', async () => {
475
+ vi.mocked(tokenLimit).mockReturnValue(1000);
476
+ mockCountTokens.mockResolvedValue({
477
+ totalTokens: 999,
478
+ });
479
+ const originalHistory = [
480
+ { role: 'user', parts: [{ text: 'what is your wisdom?' }] },
481
+ { role: 'model', parts: [{ text: 'some wisdom' }] },
482
+ { role: 'user', parts: [{ text: 'ahh that is a good a wisdom' }] },
483
+ ];
484
+ const { client } = setup({
485
+ chatHistory: originalHistory,
486
+ });
487
+ const { compressionStatus } = await client.tryCompressChat('prompt-id-4');
488
+ expect(compressionStatus).toBe(CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT);
489
+ expect(client['chat']?.setHistory).toHaveBeenCalledWith(originalHistory);
490
+ });
491
+ it('will not attempt to compress context after a failure', async () => {
492
+ const { client, mockGenerator } = setup();
493
+ await client.tryCompressChat('prompt-id-4');
494
+ const result = await client.tryCompressChat('prompt-id-5');
495
+ // it counts tokens for {original, compressed} and then never again
496
+ expect(mockGenerator.countTokens).toHaveBeenCalledTimes(2);
497
+ expect(result).toEqual({
498
+ compressionStatus: CompressionStatus.NOOP,
499
+ newTokenCount: 0,
500
+ originalTokenCount: 0,
501
+ });
502
+ });
503
+ });
504
+ it('attempts to compress with a maxOutputTokens set to the original token count', async () => {
505
+ vi.mocked(tokenLimit).mockReturnValue(1000);
506
+ mockCountTokens.mockResolvedValue({
507
+ totalTokens: 999,
508
+ });
509
+ mockGetHistory.mockReturnValue([
510
+ { role: 'user', parts: [{ text: '...history...' }] },
511
+ ]);
512
+ // Mock the summary response from the chat
513
+ mockSendMessage.mockResolvedValue({
514
+ role: 'model',
515
+ parts: [{ text: 'This is a summary.' }],
516
+ });
517
+ await client.tryCompressChat('prompt-id-2', true);
518
+ expect(mockSendMessage).toHaveBeenCalledWith(expect.objectContaining({
519
+ config: expect.objectContaining({
520
+ maxOutputTokens: 999,
521
+ }),
522
+ }), 'prompt-id-2');
523
+ });
407
524
  it('should not trigger summarization if token count is below threshold', async () => {
408
525
  const MOCKED_TOKEN_LIMIT = 1000;
409
526
  vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
@@ -417,7 +534,11 @@ describe('Gemini Client (client.ts)', () => {
417
534
  const result = await client.tryCompressChat('prompt-id-2');
418
535
  const newChat = client.getChat();
419
536
  expect(tokenLimit).toHaveBeenCalled();
420
- expect(result).toBeNull();
537
+ expect(result).toEqual({
538
+ compressionStatus: CompressionStatus.NOOP,
539
+ newTokenCount: 699,
540
+ originalTokenCount: 699,
541
+ });
421
542
  expect(newChat).toBe(initialChat);
422
543
  });
423
544
  it('logs a telemetry event when compressing', async () => {
@@ -474,6 +595,7 @@ describe('Gemini Client (client.ts)', () => {
474
595
  expect(mockSendMessage).toHaveBeenCalled();
475
596
  // Assert that summarization happened and returned the correct stats
476
597
  expect(result).toEqual({
598
+ compressionStatus: CompressionStatus.COMPRESSED,
477
599
  originalTokenCount,
478
600
  newTokenCount,
479
601
  });
@@ -518,6 +640,7 @@ describe('Gemini Client (client.ts)', () => {
518
640
  expect(mockSendMessage).toHaveBeenCalled();
519
641
  // Assert that summarization happened and returned the correct stats
520
642
  expect(result).toEqual({
643
+ compressionStatus: CompressionStatus.COMPRESSED,
521
644
  originalTokenCount,
522
645
  newTokenCount,
523
646
  });
@@ -549,14 +672,129 @@ describe('Gemini Client (client.ts)', () => {
549
672
  const newChat = client.getChat();
550
673
  expect(mockSendMessage).toHaveBeenCalled();
551
674
  expect(result).toEqual({
675
+ compressionStatus: CompressionStatus.COMPRESSED,
552
676
  originalTokenCount,
553
677
  newTokenCount,
554
678
  });
555
679
  // Assert that the chat was reset
556
680
  expect(newChat).not.toBe(initialChat);
557
681
  });
682
+ it('should use current model from config for token counting after sendMessage', async () => {
683
+ const initialModel = client['config'].getModel();
684
+ const mockCountTokens = vi
685
+ .fn()
686
+ .mockResolvedValueOnce({ totalTokens: 100000 })
687
+ .mockResolvedValueOnce({ totalTokens: 5000 });
688
+ const mockSendMessage = vi.fn().mockResolvedValue({ text: 'Summary' });
689
+ const mockChatHistory = [
690
+ { role: 'user', parts: [{ text: 'Long conversation' }] },
691
+ { role: 'model', parts: [{ text: 'Long response' }] },
692
+ ];
693
+ const mockChat = {
694
+ getHistory: vi.fn().mockReturnValue(mockChatHistory),
695
+ setHistory: vi.fn(),
696
+ sendMessage: mockSendMessage,
697
+ };
698
+ const mockGenerator = {
699
+ countTokens: mockCountTokens,
700
+ };
701
+ // mock the model has been changed between calls of `countTokens`
702
+ const firstCurrentModel = initialModel + '-changed-1';
703
+ const secondCurrentModel = initialModel + '-changed-2';
704
+ vi.spyOn(client['config'], 'getModel')
705
+ .mockReturnValueOnce(firstCurrentModel)
706
+ .mockReturnValueOnce(secondCurrentModel);
707
+ client['chat'] = mockChat;
708
+ client['contentGenerator'] = mockGenerator;
709
+ client['startChat'] = vi.fn().mockResolvedValue(mockChat);
710
+ const result = await client.tryCompressChat('prompt-id-4', true);
711
+ expect(mockCountTokens).toHaveBeenCalledTimes(2);
712
+ expect(mockCountTokens).toHaveBeenNthCalledWith(1, {
713
+ model: firstCurrentModel,
714
+ contents: mockChatHistory,
715
+ });
716
+ expect(mockCountTokens).toHaveBeenNthCalledWith(2, {
717
+ model: secondCurrentModel,
718
+ contents: expect.any(Array),
719
+ });
720
+ expect(result).toEqual({
721
+ compressionStatus: CompressionStatus.COMPRESSED,
722
+ originalTokenCount: 100000,
723
+ newTokenCount: 5000,
724
+ });
725
+ });
558
726
  });
559
727
  describe('sendMessageStream', () => {
728
+ it('emits a compression event when the context was automatically compressed', async () => {
729
+ // Arrange
730
+ const mockStream = (async function* () {
731
+ yield { type: 'content', value: 'Hello' };
732
+ })();
733
+ mockTurnRunFn.mockReturnValue(mockStream);
734
+ const mockChat = {
735
+ addHistory: vi.fn(),
736
+ getHistory: vi.fn().mockReturnValue([]),
737
+ };
738
+ client['chat'] = mockChat;
739
+ const mockGenerator = {
740
+ countTokens: vi.fn().mockResolvedValue({ totalTokens: 0 }),
741
+ generateContent: mockGenerateContentFn,
742
+ };
743
+ client['contentGenerator'] = mockGenerator;
744
+ const compressionInfo = {
745
+ compressionStatus: CompressionStatus.COMPRESSED,
746
+ originalTokenCount: 1000,
747
+ newTokenCount: 500,
748
+ };
749
+ vi.spyOn(client, 'tryCompressChat').mockResolvedValueOnce(compressionInfo);
750
+ // Act
751
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-id-1');
752
+ const events = await fromAsync(stream);
753
+ // Assert
754
+ expect(events).toContainEqual({
755
+ type: GeminiEventType.ChatCompressed,
756
+ value: compressionInfo,
757
+ });
758
+ });
759
+ it.each([
760
+ {
761
+ compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
762
+ },
763
+ { compressionStatus: CompressionStatus.NOOP },
764
+ {
765
+ compressionStatus: CompressionStatus.COMPRESSION_FAILED_TOKEN_COUNT_ERROR,
766
+ },
767
+ ])('does not emit a compression event when the status is $compressionStatus', async ({ compressionStatus }) => {
768
+ // Arrange
769
+ const mockStream = (async function* () {
770
+ yield { type: 'content', value: 'Hello' };
771
+ })();
772
+ mockTurnRunFn.mockReturnValue(mockStream);
773
+ const mockChat = {
774
+ addHistory: vi.fn(),
775
+ getHistory: vi.fn().mockReturnValue([]),
776
+ };
777
+ client['chat'] = mockChat;
778
+ const mockGenerator = {
779
+ countTokens: vi.fn().mockResolvedValue({ totalTokens: 0 }),
780
+ generateContent: mockGenerateContentFn,
781
+ };
782
+ client['contentGenerator'] = mockGenerator;
783
+ const compressionInfo = {
784
+ compressionStatus,
785
+ originalTokenCount: 1000,
786
+ newTokenCount: 500,
787
+ };
788
+ vi.spyOn(client, 'tryCompressChat').mockResolvedValueOnce(compressionInfo);
789
+ // Act
790
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-id-1');
791
+ const events = await fromAsync(stream);
792
+ // Assert
793
+ expect(events).not.toContainEqual({
794
+ type: GeminiEventType.ChatCompressed,
795
+ value: expect.anything(),
796
+ });
797
+ });
560
798
  it('should include editor context when ideMode is enabled', async () => {
561
799
  // Arrange
562
800
  vi.mocked(ideContext.getIdeContext).mockReturnValue({
@@ -976,7 +1214,11 @@ ${JSON.stringify({
976
1214
  })();
977
1215
  beforeEach(() => {
978
1216
  client['forceFullIdeContext'] = false; // Reset before each delta test
979
- vi.spyOn(client, 'tryCompressChat').mockResolvedValue(null);
1217
+ vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
1218
+ originalTokenCount: 0,
1219
+ newTokenCount: 0,
1220
+ compressionStatus: CompressionStatus.COMPRESSED,
1221
+ });
980
1222
  vi.spyOn(client['config'], 'getIdeMode').mockReturnValue(true);
981
1223
  mockTurnRunFn.mockReturnValue(mockStream);
982
1224
  const mockChat = {
@@ -1189,7 +1431,11 @@ ${JSON.stringify({
1189
1431
  describe('IDE context with pending tool calls', () => {
1190
1432
  let mockChat;
1191
1433
  beforeEach(() => {
1192
- vi.spyOn(client, 'tryCompressChat').mockResolvedValue(null);
1434
+ vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
1435
+ originalTokenCount: 0,
1436
+ newTokenCount: 0,
1437
+ compressionStatus: CompressionStatus.COMPRESSED,
1438
+ });
1193
1439
  const mockStream = (async function* () {
1194
1440
  yield { type: 'content', value: 'response' };
1195
1441
  })();
@@ -1452,8 +1698,89 @@ ${JSON.stringify({
1452
1698
  expect(JSON.stringify(finalCall)).toContain('fileC.ts');
1453
1699
  });
1454
1700
  });
1701
+ it('should not call checkNextSpeaker when turn.run() yields an error', async () => {
1702
+ // Arrange
1703
+ const { checkNextSpeaker } = await import('../utils/nextSpeakerChecker.js');
1704
+ const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
1705
+ const mockStream = (async function* () {
1706
+ yield {
1707
+ type: GeminiEventType.Error,
1708
+ value: { error: { message: 'test error' } },
1709
+ };
1710
+ })();
1711
+ mockTurnRunFn.mockReturnValue(mockStream);
1712
+ const mockChat = {
1713
+ addHistory: vi.fn(),
1714
+ getHistory: vi.fn().mockReturnValue([]),
1715
+ };
1716
+ client['chat'] = mockChat;
1717
+ const mockGenerator = {
1718
+ countTokens: vi.fn().mockResolvedValue({ totalTokens: 0 }),
1719
+ generateContent: mockGenerateContentFn,
1720
+ };
1721
+ client['contentGenerator'] = mockGenerator;
1722
+ // Act
1723
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-id-error');
1724
+ for await (const _ of stream) {
1725
+ // consume stream
1726
+ }
1727
+ // Assert
1728
+ expect(mockCheckNextSpeaker).not.toHaveBeenCalled();
1729
+ });
1730
+ it('should not call checkNextSpeaker when turn.run() yields a value then an error', async () => {
1731
+ // Arrange
1732
+ const { checkNextSpeaker } = await import('../utils/nextSpeakerChecker.js');
1733
+ const mockCheckNextSpeaker = vi.mocked(checkNextSpeaker);
1734
+ const mockStream = (async function* () {
1735
+ yield { type: GeminiEventType.Content, value: 'some content' };
1736
+ yield {
1737
+ type: GeminiEventType.Error,
1738
+ value: { error: { message: 'test error' } },
1739
+ };
1740
+ })();
1741
+ mockTurnRunFn.mockReturnValue(mockStream);
1742
+ const mockChat = {
1743
+ addHistory: vi.fn(),
1744
+ getHistory: vi.fn().mockReturnValue([]),
1745
+ };
1746
+ client['chat'] = mockChat;
1747
+ const mockGenerator = {
1748
+ countTokens: vi.fn().mockResolvedValue({ totalTokens: 0 }),
1749
+ generateContent: mockGenerateContentFn,
1750
+ };
1751
+ client['contentGenerator'] = mockGenerator;
1752
+ // Act
1753
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-id-error');
1754
+ for await (const _ of stream) {
1755
+ // consume stream
1756
+ }
1757
+ // Assert
1758
+ expect(mockCheckNextSpeaker).not.toHaveBeenCalled();
1759
+ });
1455
1760
  });
1456
1761
  describe('generateContent', () => {
1762
+ it('should call generateContent with the correct parameters', async () => {
1763
+ const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
1764
+ const generationConfig = { temperature: 0.5 };
1765
+ const abortSignal = new AbortController().signal;
1766
+ // Mock countTokens
1767
+ const mockGenerator = {
1768
+ countTokens: vi.fn().mockResolvedValue({ totalTokens: 1 }),
1769
+ generateContent: mockGenerateContentFn,
1770
+ };
1771
+ client['contentGenerator'] = mockGenerator;
1772
+ await client.generateContent(contents, generationConfig, abortSignal);
1773
+ expect(mockGenerateContentFn).toHaveBeenCalledWith({
1774
+ model: 'test-model',
1775
+ config: {
1776
+ abortSignal,
1777
+ systemInstruction: getCoreSystemPrompt(''),
1778
+ temperature: 0.5,
1779
+ topP: 1,
1780
+ },
1781
+ contents,
1782
+ }, 'test-session-id');
1783
+ });
1457
1784
  it('should use current model from config for content generation', async () => {
1458
1785
  const initialModel = client['config'].getModel();
1459
1786
  const contents = [{ role: 'user', parts: [{ text: 'test' }] }];
@@ -1477,51 +1804,6 @@ ${JSON.stringify({
1477
1804
  }, 'test-session-id');
1478
1805
  });
1479
1806
  });
1480
- describe('tryCompressChat', () => {
1481
- it('should use current model from config for token counting after sendMessage', async () => {
1482
- const initialModel = client['config'].getModel();
1483
- const mockCountTokens = vi
1484
- .fn()
1485
- .mockResolvedValueOnce({ totalTokens: 100000 })
1486
- .mockResolvedValueOnce({ totalTokens: 5000 });
1487
- const mockSendMessage = vi.fn().mockResolvedValue({ text: 'Summary' });
1488
- const mockChatHistory = [
1489
- { role: 'user', parts: [{ text: 'Long conversation' }] },
1490
- { role: 'model', parts: [{ text: 'Long response' }] },
1491
- ];
1492
- const mockChat = {
1493
- getHistory: vi.fn().mockReturnValue(mockChatHistory),
1494
- setHistory: vi.fn(),
1495
- sendMessage: mockSendMessage,
1496
- };
1497
- const mockGenerator = {
1498
- countTokens: mockCountTokens,
1499
- };
1500
- // mock the model has been changed between calls of `countTokens`
1501
- const firstCurrentModel = initialModel + '-changed-1';
1502
- const secondCurrentModel = initialModel + '-changed-2';
1503
- vi.spyOn(client['config'], 'getModel')
1504
- .mockReturnValueOnce(firstCurrentModel)
1505
- .mockReturnValueOnce(secondCurrentModel);
1506
- client['chat'] = mockChat;
1507
- client['contentGenerator'] = mockGenerator;
1508
- client['startChat'] = vi.fn().mockResolvedValue(mockChat);
1509
- const result = await client.tryCompressChat('prompt-id-4', true);
1510
- expect(mockCountTokens).toHaveBeenCalledTimes(2);
1511
- expect(mockCountTokens).toHaveBeenNthCalledWith(1, {
1512
- model: firstCurrentModel,
1513
- contents: mockChatHistory,
1514
- });
1515
- expect(mockCountTokens).toHaveBeenNthCalledWith(2, {
1516
- model: secondCurrentModel,
1517
- contents: expect.any(Array),
1518
- });
1519
- expect(result).toEqual({
1520
- originalTokenCount: 100000,
1521
- newTokenCount: 5000,
1522
- });
1523
- });
1524
- });
1525
1807
  describe('handleFlashFallback', () => {
1526
1808
  it('should use current model from config when checking for fallback', async () => {
1527
1809
  const initialModel = client['config'].getModel();