@office-ai/aioncli-core 0.18.6 → 0.24.0-preview.1

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 (893) hide show
  1. package/dist/docs/CONTRIBUTING.md +546 -0
  2. package/dist/docs/architecture.md +80 -0
  3. package/dist/docs/assets/connected_devtools.png +0 -0
  4. package/dist/docs/assets/gemini-screenshot.png +0 -0
  5. package/dist/docs/assets/release_patch.png +0 -0
  6. package/dist/docs/assets/theme-ansi-light.png +0 -0
  7. package/dist/docs/assets/theme-ansi.png +0 -0
  8. package/dist/docs/assets/theme-atom-one.png +0 -0
  9. package/dist/docs/assets/theme-ayu-light.png +0 -0
  10. package/dist/docs/assets/theme-ayu.png +0 -0
  11. package/dist/docs/assets/theme-custom.png +0 -0
  12. package/dist/docs/assets/theme-default-light.png +0 -0
  13. package/dist/docs/assets/theme-default.png +0 -0
  14. package/dist/docs/assets/theme-dracula.png +0 -0
  15. package/dist/docs/assets/theme-github-light.png +0 -0
  16. package/dist/docs/assets/theme-github.png +0 -0
  17. package/dist/docs/assets/theme-google-light.png +0 -0
  18. package/dist/docs/assets/theme-xcode-light.png +0 -0
  19. package/dist/docs/changelogs/index.md +592 -0
  20. package/dist/docs/changelogs/latest.md +225 -0
  21. package/dist/docs/changelogs/preview.md +129 -0
  22. package/dist/docs/changelogs/releases.md +896 -0
  23. package/dist/docs/cli/authentication.md +3 -0
  24. package/dist/docs/cli/checkpointing.md +94 -0
  25. package/dist/docs/cli/commands.md +354 -0
  26. package/dist/docs/cli/configuration.md +780 -0
  27. package/dist/docs/cli/custom-commands.md +315 -0
  28. package/dist/docs/cli/enterprise.md +565 -0
  29. package/dist/docs/cli/gemini-ignore.md +71 -0
  30. package/dist/docs/cli/gemini-md.md +108 -0
  31. package/dist/docs/cli/generation-settings.md +210 -0
  32. package/dist/docs/cli/headless.md +388 -0
  33. package/dist/docs/cli/index.md +63 -0
  34. package/dist/docs/cli/keyboard-shortcuts.md +143 -0
  35. package/dist/docs/cli/model-routing.md +37 -0
  36. package/dist/docs/cli/model.md +62 -0
  37. package/dist/docs/cli/sandbox.md +171 -0
  38. package/dist/docs/cli/session-management.md +158 -0
  39. package/dist/docs/cli/settings.md +114 -0
  40. package/dist/docs/cli/skills.md +156 -0
  41. package/dist/docs/cli/system-prompt.md +93 -0
  42. package/dist/docs/cli/telemetry.md +791 -0
  43. package/dist/docs/cli/themes.md +237 -0
  44. package/dist/docs/cli/token-caching.md +20 -0
  45. package/dist/docs/cli/trusted-folders.md +95 -0
  46. package/dist/docs/cli/tutorials/skills-getting-started.md +124 -0
  47. package/dist/docs/cli/tutorials.md +87 -0
  48. package/dist/docs/cli/uninstall.md +47 -0
  49. package/dist/docs/core/index.md +101 -0
  50. package/dist/docs/core/memport.md +244 -0
  51. package/dist/docs/core/policy-engine.md +267 -0
  52. package/dist/docs/core/tools-api.md +131 -0
  53. package/dist/docs/examples/proxy-script.md +83 -0
  54. package/dist/docs/extension.md +160 -0
  55. package/dist/docs/extensions/extension-releasing.md +183 -0
  56. package/dist/docs/extensions/getting-started-extensions.md +245 -0
  57. package/dist/docs/extensions/index.md +293 -0
  58. package/dist/docs/faq.md +154 -0
  59. package/dist/docs/get-started/authentication.md +321 -0
  60. package/dist/docs/get-started/configuration-v1.md +888 -0
  61. package/dist/docs/get-started/configuration.md +1536 -0
  62. package/dist/docs/get-started/deployment.md +143 -0
  63. package/dist/docs/get-started/examples.md +219 -0
  64. package/dist/docs/get-started/gemini-3.md +116 -0
  65. package/dist/docs/get-started/index.md +71 -0
  66. package/dist/docs/get-started/installation.md +141 -0
  67. package/dist/docs/hooks/best-practices.md +856 -0
  68. package/dist/docs/hooks/index.md +687 -0
  69. package/dist/docs/hooks/reference.md +168 -0
  70. package/dist/docs/hooks/writing-hooks.md +1026 -0
  71. package/dist/docs/ide-integration/ide-companion-spec.md +267 -0
  72. package/dist/docs/ide-integration/index.md +202 -0
  73. package/dist/docs/index.md +147 -0
  74. package/dist/docs/integration-tests.md +211 -0
  75. package/dist/docs/issue-and-pr-automation.md +134 -0
  76. package/dist/docs/local-development.md +128 -0
  77. package/dist/docs/mermaid/context.mmd +103 -0
  78. package/dist/docs/mermaid/render-path.mmd +64 -0
  79. package/dist/docs/npm.md +62 -0
  80. package/dist/docs/quota-and-pricing.md +158 -0
  81. package/dist/docs/release-confidence.md +164 -0
  82. package/dist/docs/releases.md +540 -0
  83. package/dist/docs/sidebar.json +301 -0
  84. package/dist/docs/tools/file-system.md +217 -0
  85. package/dist/docs/tools/index.md +95 -0
  86. package/dist/docs/tools/mcp-server.md +1044 -0
  87. package/dist/docs/tools/memory.md +54 -0
  88. package/dist/docs/tools/shell.md +260 -0
  89. package/dist/docs/tools/todos.md +57 -0
  90. package/dist/docs/tools/web-fetch.md +59 -0
  91. package/dist/docs/tools/web-search.md +42 -0
  92. package/dist/docs/tos-privacy.md +96 -0
  93. package/dist/docs/troubleshooting.md +158 -0
  94. package/dist/index.d.ts +1 -1
  95. package/dist/index.js +1 -1
  96. package/dist/index.js.map +1 -1
  97. package/dist/src/agents/a2a-client-manager.d.ts +78 -0
  98. package/dist/src/agents/a2a-client-manager.js +295 -0
  99. package/dist/src/agents/a2a-client-manager.js.map +1 -0
  100. package/dist/src/agents/a2a-client-manager.test.d.ts +6 -0
  101. package/dist/src/agents/a2a-client-manager.test.js +237 -0
  102. package/dist/src/agents/a2a-client-manager.test.js.map +1 -0
  103. package/dist/src/agents/a2aUtils.d.ts +28 -0
  104. package/dist/src/agents/a2aUtils.js +111 -0
  105. package/dist/src/agents/a2aUtils.js.map +1 -0
  106. package/dist/src/agents/a2aUtils.test.d.ts +6 -0
  107. package/dist/src/agents/a2aUtils.test.js +147 -0
  108. package/dist/src/agents/a2aUtils.test.js.map +1 -0
  109. package/dist/src/agents/codebase-investigator.d.ts +2 -2
  110. package/dist/src/agents/codebase-investigator.js +5 -4
  111. package/dist/src/agents/codebase-investigator.js.map +1 -1
  112. package/dist/src/agents/delegate-to-agent-tool.d.ts +19 -0
  113. package/dist/src/agents/delegate-to-agent-tool.js +115 -0
  114. package/dist/src/agents/delegate-to-agent-tool.js.map +1 -0
  115. package/dist/src/agents/delegate-to-agent-tool.test.d.ts +6 -0
  116. package/dist/src/agents/delegate-to-agent-tool.test.js +165 -0
  117. package/dist/src/agents/delegate-to-agent-tool.test.js.map +1 -0
  118. package/dist/src/agents/introspection-agent.d.ts +23 -0
  119. package/dist/src/agents/introspection-agent.js +72 -0
  120. package/dist/src/agents/introspection-agent.js.map +1 -0
  121. package/dist/src/agents/introspection-agent.test.d.ts +6 -0
  122. package/dist/src/agents/introspection-agent.test.js +47 -0
  123. package/dist/src/agents/introspection-agent.test.js.map +1 -0
  124. package/dist/src/agents/local-executor.d.ts +108 -0
  125. package/dist/src/agents/local-executor.js +801 -0
  126. package/dist/src/agents/local-executor.js.map +1 -0
  127. package/dist/src/agents/local-executor.test.d.ts +6 -0
  128. package/dist/src/agents/local-executor.test.js +1380 -0
  129. package/dist/src/agents/local-executor.test.js.map +1 -0
  130. package/dist/src/agents/local-invocation.d.ts +45 -0
  131. package/dist/src/agents/local-invocation.js +101 -0
  132. package/dist/src/agents/local-invocation.js.map +1 -0
  133. package/dist/src/agents/local-invocation.test.d.ts +6 -0
  134. package/dist/src/agents/local-invocation.test.js +218 -0
  135. package/dist/src/agents/local-invocation.test.js.map +1 -0
  136. package/dist/src/agents/registry.d.ts +25 -1
  137. package/dist/src/agents/registry.js +149 -5
  138. package/dist/src/agents/registry.js.map +1 -1
  139. package/dist/src/agents/registry.test.js +247 -25
  140. package/dist/src/agents/registry.test.js.map +1 -1
  141. package/dist/src/agents/remote-invocation.d.ts +35 -0
  142. package/dist/src/agents/remote-invocation.js +129 -0
  143. package/dist/src/agents/remote-invocation.js.map +1 -0
  144. package/dist/src/agents/remote-invocation.test.d.ts +6 -0
  145. package/dist/src/agents/remote-invocation.test.js +201 -0
  146. package/dist/src/agents/remote-invocation.test.js.map +1 -0
  147. package/dist/src/agents/subagent-tool-wrapper.d.ts +2 -2
  148. package/dist/src/agents/subagent-tool-wrapper.js +11 -6
  149. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -1
  150. package/dist/src/agents/subagent-tool-wrapper.test.js +25 -17
  151. package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
  152. package/dist/src/agents/toml-loader.d.ts +74 -0
  153. package/dist/src/agents/toml-loader.js +248 -0
  154. package/dist/src/agents/toml-loader.js.map +1 -0
  155. package/dist/src/agents/toml-loader.test.d.ts +6 -0
  156. package/dist/src/agents/toml-loader.test.js +309 -0
  157. package/dist/src/agents/toml-loader.test.js.map +1 -0
  158. package/dist/src/agents/types.d.ts +18 -4
  159. package/dist/src/availability/errorClassification.d.ts +7 -0
  160. package/dist/src/availability/errorClassification.js +20 -0
  161. package/dist/src/availability/errorClassification.js.map +1 -0
  162. package/dist/src/availability/modelAvailabilityService.d.ts +36 -0
  163. package/dist/src/availability/modelAvailabilityService.js +87 -0
  164. package/dist/src/availability/modelAvailabilityService.js.map +1 -0
  165. package/dist/src/availability/modelAvailabilityService.test.d.ts +6 -0
  166. package/dist/src/availability/modelAvailabilityService.test.js +140 -0
  167. package/dist/src/availability/modelAvailabilityService.test.js.map +1 -0
  168. package/dist/src/availability/modelPolicy.d.ts +49 -0
  169. package/dist/src/availability/modelPolicy.js +7 -0
  170. package/dist/src/availability/modelPolicy.js.map +1 -0
  171. package/dist/src/availability/policyCatalog.d.ts +23 -0
  172. package/dist/src/availability/policyCatalog.js +82 -0
  173. package/dist/src/availability/policyCatalog.js.map +1 -0
  174. package/dist/src/availability/policyCatalog.test.d.ts +6 -0
  175. package/dist/src/availability/policyCatalog.test.js +70 -0
  176. package/dist/src/availability/policyCatalog.test.js.map +1 -0
  177. package/dist/src/availability/policyHelpers.d.ts +52 -0
  178. package/dist/src/availability/policyHelpers.js +136 -0
  179. package/dist/src/availability/policyHelpers.js.map +1 -0
  180. package/dist/src/availability/policyHelpers.test.d.ts +6 -0
  181. package/dist/src/availability/policyHelpers.test.js +182 -0
  182. package/dist/src/availability/policyHelpers.test.js.map +1 -0
  183. package/dist/src/availability/testUtils.d.ts +10 -0
  184. package/dist/src/availability/testUtils.js +22 -0
  185. package/dist/src/availability/testUtils.js.map +1 -0
  186. package/dist/src/code_assist/experiments/client_metadata.js +3 -2
  187. package/dist/src/code_assist/experiments/client_metadata.js.map +1 -1
  188. package/dist/src/code_assist/experiments/client_metadata.test.js +7 -10
  189. package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -1
  190. package/dist/src/code_assist/experiments/experiments.js +2 -2
  191. package/dist/src/code_assist/experiments/experiments.js.map +1 -1
  192. package/dist/src/code_assist/oauth2.d.ts +2 -0
  193. package/dist/src/code_assist/oauth2.js +73 -17
  194. package/dist/src/code_assist/oauth2.js.map +1 -1
  195. package/dist/src/code_assist/oauth2.test.js +195 -18
  196. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  197. package/dist/src/code_assist/server.d.ts +10 -1
  198. package/dist/src/code_assist/server.js +81 -15
  199. package/dist/src/code_assist/server.js.map +1 -1
  200. package/dist/src/code_assist/server.test.js +221 -25
  201. package/dist/src/code_assist/server.test.js.map +1 -1
  202. package/dist/src/code_assist/setup.js +6 -4
  203. package/dist/src/code_assist/setup.js.map +1 -1
  204. package/dist/src/code_assist/setup.test.js +63 -0
  205. package/dist/src/code_assist/setup.test.js.map +1 -1
  206. package/dist/src/code_assist/telemetry.d.ts +14 -0
  207. package/dist/src/code_assist/telemetry.js +156 -0
  208. package/dist/src/code_assist/telemetry.js.map +1 -0
  209. package/dist/src/code_assist/telemetry.test.d.ts +6 -0
  210. package/dist/src/code_assist/telemetry.test.js +300 -0
  211. package/dist/src/code_assist/telemetry.test.js.map +1 -0
  212. package/dist/src/code_assist/types.d.ts +84 -1
  213. package/dist/src/code_assist/types.js +21 -0
  214. package/dist/src/code_assist/types.js.map +1 -1
  215. package/dist/src/commands/init.d.ts +7 -0
  216. package/dist/src/commands/init.js +53 -0
  217. package/dist/src/commands/init.js.map +1 -0
  218. package/dist/src/commands/init.test.d.ts +6 -0
  219. package/dist/src/commands/init.test.js +25 -0
  220. package/dist/src/commands/init.test.js.map +1 -0
  221. package/dist/src/commands/restore.d.ts +9 -0
  222. package/dist/src/commands/restore.js +46 -0
  223. package/dist/src/commands/restore.js.map +1 -0
  224. package/dist/src/commands/restore.test.d.ts +6 -0
  225. package/dist/src/commands/restore.test.js +137 -0
  226. package/dist/src/commands/restore.test.js.map +1 -0
  227. package/dist/src/commands/types.d.ts +41 -0
  228. package/dist/src/commands/types.js +7 -0
  229. package/dist/src/commands/types.js.map +1 -0
  230. package/dist/src/config/config.d.ts +120 -23
  231. package/dist/src/config/config.js +336 -116
  232. package/dist/src/config/config.js.map +1 -1
  233. package/dist/src/config/config.test.js +373 -95
  234. package/dist/src/config/config.test.js.map +1 -1
  235. package/dist/src/config/defaultModelConfigs.js +46 -0
  236. package/dist/src/config/defaultModelConfigs.js.map +1 -1
  237. package/dist/src/config/flashFallback.test.js +11 -35
  238. package/dist/src/config/flashFallback.test.js.map +1 -1
  239. package/dist/src/config/models.d.ts +29 -15
  240. package/dist/src/config/models.js +78 -28
  241. package/dist/src/config/models.js.map +1 -1
  242. package/dist/src/config/models.test.js +91 -77
  243. package/dist/src/config/models.test.js.map +1 -1
  244. package/dist/src/config/storage.d.ts +4 -0
  245. package/dist/src/config/storage.js +12 -0
  246. package/dist/src/config/storage.js.map +1 -1
  247. package/dist/src/config/storage.test.js +16 -0
  248. package/dist/src/config/storage.test.js.map +1 -1
  249. package/dist/src/confirmation-bus/message-bus.d.ts +6 -0
  250. package/dist/src/confirmation-bus/message-bus.js +66 -3
  251. package/dist/src/confirmation-bus/message-bus.js.map +1 -1
  252. package/dist/src/confirmation-bus/types.d.ts +29 -2
  253. package/dist/src/confirmation-bus/types.js +3 -0
  254. package/dist/src/confirmation-bus/types.js.map +1 -1
  255. package/dist/src/core/baseLlmClient.d.ts +30 -2
  256. package/dist/src/core/baseLlmClient.js +107 -49
  257. package/dist/src/core/baseLlmClient.js.map +1 -1
  258. package/dist/src/core/baseLlmClient.test.js +271 -13
  259. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  260. package/dist/src/core/client.d.ts +5 -1
  261. package/dist/src/core/client.js +241 -63
  262. package/dist/src/core/client.js.map +1 -1
  263. package/dist/src/core/client.test.js +462 -72
  264. package/dist/src/core/client.test.js.map +1 -1
  265. package/dist/src/core/clientHookTriggers.d.ts +36 -0
  266. package/dist/src/core/clientHookTriggers.js +76 -0
  267. package/dist/src/core/clientHookTriggers.js.map +1 -0
  268. package/dist/src/core/contentGenerator.js +17 -4
  269. package/dist/src/core/contentGenerator.js.map +1 -1
  270. package/dist/src/core/contentGenerator.test.js +132 -3
  271. package/dist/src/core/contentGenerator.test.js.map +1 -1
  272. package/dist/src/core/coreToolHookTriggers.d.ts +55 -0
  273. package/dist/src/core/coreToolHookTriggers.js +304 -0
  274. package/dist/src/core/coreToolHookTriggers.js.map +1 -0
  275. package/dist/src/core/coreToolHookTriggers.test.d.ts +6 -0
  276. package/dist/src/core/coreToolHookTriggers.test.js +191 -0
  277. package/dist/src/core/coreToolHookTriggers.test.js.map +1 -0
  278. package/dist/src/core/coreToolScheduler.d.ts +6 -85
  279. package/dist/src/core/coreToolScheduler.js +69 -267
  280. package/dist/src/core/coreToolScheduler.js.map +1 -1
  281. package/dist/src/core/coreToolScheduler.test.js +161 -346
  282. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  283. package/dist/src/core/geminiChat.js +132 -76
  284. package/dist/src/core/geminiChat.js.map +1 -1
  285. package/dist/src/core/geminiChat.test.js +240 -257
  286. package/dist/src/core/geminiChat.test.js.map +1 -1
  287. package/dist/src/core/geminiChatHookTriggers.d.ts +64 -0
  288. package/dist/src/core/geminiChatHookTriggers.js +136 -0
  289. package/dist/src/core/geminiChatHookTriggers.js.map +1 -0
  290. package/dist/src/core/geminiChat_network_retry.test.d.ts +6 -0
  291. package/dist/src/core/geminiChat_network_retry.test.js +196 -0
  292. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -0
  293. package/dist/src/core/logger.js.map +1 -1
  294. package/dist/src/core/loggingContentGenerator.js +23 -6
  295. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  296. package/dist/src/core/nonInteractiveToolExecutor.test.js +13 -8
  297. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  298. package/dist/src/core/openaiContentGenerator.d.ts +25 -0
  299. package/dist/src/core/openaiContentGenerator.js +243 -14
  300. package/dist/src/core/openaiContentGenerator.js.map +1 -1
  301. package/dist/src/core/prompts.js +82 -26
  302. package/dist/src/core/prompts.js.map +1 -1
  303. package/dist/src/core/prompts.test.js +102 -3
  304. package/dist/src/core/prompts.test.js.map +1 -1
  305. package/dist/src/core/sessionHookTriggers.d.ts +29 -0
  306. package/dist/src/core/sessionHookTriggers.js +75 -0
  307. package/dist/src/core/sessionHookTriggers.js.map +1 -0
  308. package/dist/src/core/turn.d.ts +34 -21
  309. package/dist/src/core/turn.js +33 -13
  310. package/dist/src/core/turn.js.map +1 -1
  311. package/dist/src/core/turn.test.js +0 -5
  312. package/dist/src/core/turn.test.js.map +1 -1
  313. package/dist/src/fallback/handler.js +101 -93
  314. package/dist/src/fallback/handler.js.map +1 -1
  315. package/dist/src/fallback/handler.test.js +186 -173
  316. package/dist/src/fallback/handler.test.js.map +1 -1
  317. package/dist/src/fallback/types.d.ts +8 -0
  318. package/dist/src/generated/git-commit.d.ts +3 -3
  319. package/dist/src/generated/git-commit.js +3 -3
  320. package/dist/src/generated/git-commit.js.map +1 -1
  321. package/dist/src/hooks/hookAggregator.js +7 -0
  322. package/dist/src/hooks/hookAggregator.js.map +1 -1
  323. package/dist/src/hooks/hookEventHandler.d.ts +113 -0
  324. package/dist/src/hooks/hookEventHandler.js +571 -0
  325. package/dist/src/hooks/hookEventHandler.js.map +1 -0
  326. package/dist/src/hooks/hookEventHandler.test.d.ts +6 -0
  327. package/dist/src/hooks/hookEventHandler.test.js +461 -0
  328. package/dist/src/hooks/hookEventHandler.test.js.map +1 -0
  329. package/dist/src/hooks/hookPlanner.d.ts +1 -5
  330. package/dist/src/hooks/hookPlanner.js +2 -7
  331. package/dist/src/hooks/hookPlanner.js.map +1 -1
  332. package/dist/src/hooks/hookPlanner.test.js +62 -2
  333. package/dist/src/hooks/hookPlanner.test.js.map +1 -1
  334. package/dist/src/hooks/hookRegistry.d.ts +6 -18
  335. package/dist/src/hooks/hookRegistry.js +49 -35
  336. package/dist/src/hooks/hookRegistry.js.map +1 -1
  337. package/dist/src/hooks/hookRegistry.test.js +167 -8
  338. package/dist/src/hooks/hookRegistry.test.js.map +1 -1
  339. package/dist/src/hooks/hookRunner.d.ts +5 -3
  340. package/dist/src/hooks/hookRunner.js +74 -18
  341. package/dist/src/hooks/hookRunner.js.map +1 -1
  342. package/dist/src/hooks/hookRunner.test.js +174 -36
  343. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  344. package/dist/src/hooks/hookSystem.d.ts +40 -0
  345. package/dist/src/hooks/hookSystem.js +65 -0
  346. package/dist/src/hooks/hookSystem.js.map +1 -0
  347. package/dist/src/hooks/hookSystem.test.d.ts +6 -0
  348. package/dist/src/hooks/hookSystem.test.js +319 -0
  349. package/dist/src/hooks/hookSystem.test.js.map +1 -0
  350. package/dist/src/hooks/index.d.ts +17 -0
  351. package/dist/src/hooks/index.js +18 -0
  352. package/dist/src/hooks/index.js.map +1 -0
  353. package/dist/src/hooks/trustedHooks.d.ts +28 -0
  354. package/dist/src/hooks/trustedHooks.js +90 -0
  355. package/dist/src/hooks/trustedHooks.js.map +1 -0
  356. package/dist/src/hooks/trustedHooks.test.d.ts +6 -0
  357. package/dist/src/hooks/trustedHooks.test.js +154 -0
  358. package/dist/src/hooks/trustedHooks.test.js.map +1 -0
  359. package/dist/src/hooks/types.d.ts +21 -11
  360. package/dist/src/hooks/types.js +31 -27
  361. package/dist/src/hooks/types.js.map +1 -1
  362. package/dist/src/hooks/types.test.js +5 -24
  363. package/dist/src/hooks/types.test.js.map +1 -1
  364. package/dist/src/ide/detect-ide.test.js +32 -1
  365. package/dist/src/ide/detect-ide.test.js.map +1 -1
  366. package/dist/src/ide/ide-client.js +9 -4
  367. package/dist/src/ide/ide-client.js.map +1 -1
  368. package/dist/src/ide/ide-client.test.js +17 -0
  369. package/dist/src/ide/ide-client.test.js.map +1 -1
  370. package/dist/src/ide/ide-installer.test.js +1 -1
  371. package/dist/src/ide/ide-installer.test.js.map +1 -1
  372. package/dist/src/ide/types.d.ts +4 -4
  373. package/dist/src/index.d.ts +17 -1
  374. package/dist/src/index.js +18 -2
  375. package/dist/src/index.js.map +1 -1
  376. package/dist/src/mcp/auth-provider.d.ts +16 -0
  377. package/dist/src/mcp/auth-provider.js +7 -0
  378. package/dist/src/mcp/auth-provider.js.map +1 -0
  379. package/dist/src/mcp/google-auth-provider.d.ts +10 -2
  380. package/dist/src/mcp/google-auth-provider.js +28 -0
  381. package/dist/src/mcp/google-auth-provider.js.map +1 -1
  382. package/dist/src/mcp/google-auth-provider.test.js +45 -0
  383. package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
  384. package/dist/src/mcp/oauth-provider.js +6 -2
  385. package/dist/src/mcp/oauth-provider.js.map +1 -1
  386. package/dist/src/mcp/oauth-provider.test.js +4 -1
  387. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  388. package/dist/src/mcp/oauth-utils.d.ts +8 -1
  389. package/dist/src/mcp/oauth-utils.js +31 -2
  390. package/dist/src/mcp/oauth-utils.js.map +1 -1
  391. package/dist/src/mcp/oauth-utils.test.js +42 -0
  392. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  393. package/dist/src/mcp/sa-impersonation-provider.d.ts +2 -2
  394. package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
  395. package/dist/src/mcp/token-storage/hybrid-token-storage.js +1 -1
  396. package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -1
  397. package/dist/src/mcp/token-storage/keychain-token-storage.js +1 -1
  398. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  399. package/dist/src/output/json-formatter.d.ts +2 -2
  400. package/dist/src/output/json-formatter.js +6 -3
  401. package/dist/src/output/json-formatter.js.map +1 -1
  402. package/dist/src/output/json-formatter.test.js +37 -9
  403. package/dist/src/output/json-formatter.test.js.map +1 -1
  404. package/dist/src/output/stream-json-formatter.js +6 -0
  405. package/dist/src/output/stream-json-formatter.js.map +1 -1
  406. package/dist/src/output/stream-json-formatter.test.js +98 -100
  407. package/dist/src/output/stream-json-formatter.test.js.map +1 -1
  408. package/dist/src/output/types.d.ts +3 -0
  409. package/dist/src/output/types.js.map +1 -1
  410. package/dist/src/policy/config.js +140 -15
  411. package/dist/src/policy/config.js.map +1 -1
  412. package/dist/src/policy/config.test.js +21 -0
  413. package/dist/src/policy/config.test.js.map +1 -1
  414. package/dist/src/policy/persistence.test.d.ts +6 -0
  415. package/dist/src/policy/persistence.test.js +154 -0
  416. package/dist/src/policy/persistence.test.js.map +1 -0
  417. package/dist/src/policy/policies/agent.toml +31 -0
  418. package/dist/src/policy/policies/read-only.toml +5 -0
  419. package/dist/src/policy/policies/write.toml +5 -0
  420. package/dist/src/policy/policies/yolo.toml +1 -0
  421. package/dist/src/policy/policy-engine.d.ts +30 -1
  422. package/dist/src/policy/policy-engine.js +192 -5
  423. package/dist/src/policy/policy-engine.js.map +1 -1
  424. package/dist/src/policy/policy-engine.test.js +520 -3
  425. package/dist/src/policy/policy-engine.test.js.map +1 -1
  426. package/dist/src/policy/policy-updater.test.d.ts +6 -0
  427. package/dist/src/policy/policy-updater.test.js +116 -0
  428. package/dist/src/policy/policy-updater.test.js.map +1 -0
  429. package/dist/src/policy/shell-safety.test.d.ts +6 -0
  430. package/dist/src/policy/shell-safety.test.js +75 -0
  431. package/dist/src/policy/shell-safety.test.js.map +1 -0
  432. package/dist/src/policy/toml-loader.d.ts +3 -5
  433. package/dist/src/policy/toml-loader.js +12 -60
  434. package/dist/src/policy/toml-loader.js.map +1 -1
  435. package/dist/src/policy/toml-loader.test.js +38 -7
  436. package/dist/src/policy/toml-loader.test.js.map +1 -1
  437. package/dist/src/policy/types.d.ts +72 -1
  438. package/dist/src/policy/types.js +21 -0
  439. package/dist/src/policy/types.js.map +1 -1
  440. package/dist/src/policy/utils.d.ts +21 -0
  441. package/dist/src/policy/utils.js +42 -0
  442. package/dist/src/policy/utils.js.map +1 -0
  443. package/dist/src/policy/utils.test.d.ts +6 -0
  444. package/dist/src/policy/utils.test.js +64 -0
  445. package/dist/src/policy/utils.test.js.map +1 -0
  446. package/dist/src/resources/resource-registry.d.ts +30 -0
  447. package/dist/src/resources/resource-registry.js +57 -0
  448. package/dist/src/resources/resource-registry.js.map +1 -0
  449. package/dist/src/resources/resource-registry.test.d.ts +6 -0
  450. package/dist/src/resources/resource-registry.test.js +54 -0
  451. package/dist/src/resources/resource-registry.test.js.map +1 -0
  452. package/dist/src/routing/modelRouterService.js +0 -15
  453. package/dist/src/routing/modelRouterService.js.map +1 -1
  454. package/dist/src/routing/modelRouterService.test.js +0 -62
  455. package/dist/src/routing/modelRouterService.test.js.map +1 -1
  456. package/dist/src/routing/strategies/classifierStrategy.js +10 -21
  457. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -1
  458. package/dist/src/routing/strategies/classifierStrategy.test.js +2 -1
  459. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -1
  460. package/dist/src/routing/strategies/compositeStrategy.js +4 -2
  461. package/dist/src/routing/strategies/compositeStrategy.js.map +1 -1
  462. package/dist/src/routing/strategies/compositeStrategy.test.js +11 -10
  463. package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -1
  464. package/dist/src/routing/strategies/fallbackStrategy.js +20 -12
  465. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -1
  466. package/dist/src/routing/strategies/fallbackStrategy.test.js +63 -39
  467. package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -1
  468. package/dist/src/routing/strategies/overrideStrategy.js +3 -2
  469. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -1
  470. package/dist/src/safety/checker-runner.js +17 -6
  471. package/dist/src/safety/checker-runner.js.map +1 -1
  472. package/dist/src/scheduler/tool-executor.d.ts +22 -0
  473. package/dist/src/scheduler/tool-executor.js +198 -0
  474. package/dist/src/scheduler/tool-executor.js.map +1 -0
  475. package/dist/src/scheduler/tool-executor.test.d.ts +6 -0
  476. package/dist/src/scheduler/tool-executor.test.js +231 -0
  477. package/dist/src/scheduler/tool-executor.test.js.map +1 -0
  478. package/dist/src/scheduler/types.d.ts +95 -0
  479. package/dist/src/scheduler/types.js +7 -0
  480. package/dist/src/scheduler/types.js.map +1 -0
  481. package/dist/src/services/chatCompressionService.d.ts +1 -0
  482. package/dist/src/services/chatCompressionService.js +38 -8
  483. package/dist/src/services/chatCompressionService.js.map +1 -1
  484. package/dist/src/services/chatCompressionService.test.js +35 -31
  485. package/dist/src/services/chatCompressionService.test.js.map +1 -1
  486. package/dist/src/services/chatRecordingService.d.ts +14 -0
  487. package/dist/src/services/chatRecordingService.js +37 -0
  488. package/dist/src/services/chatRecordingService.js.map +1 -1
  489. package/dist/src/services/contextManager.d.ts +29 -0
  490. package/dist/src/services/contextManager.js +71 -0
  491. package/dist/src/services/contextManager.js.map +1 -0
  492. package/dist/src/services/contextManager.test.d.ts +6 -0
  493. package/dist/src/services/contextManager.test.js +104 -0
  494. package/dist/src/services/contextManager.test.js.map +1 -0
  495. package/dist/src/services/environmentSanitization.d.ts +15 -0
  496. package/dist/src/services/environmentSanitization.js +141 -0
  497. package/dist/src/services/environmentSanitization.js.map +1 -0
  498. package/dist/src/services/environmentSanitization.test.d.ts +6 -0
  499. package/dist/src/services/environmentSanitization.test.js +284 -0
  500. package/dist/src/services/environmentSanitization.test.js.map +1 -0
  501. package/dist/src/services/fileSystemService.d.ts +0 -9
  502. package/dist/src/services/fileSystemService.js +0 -11
  503. package/dist/src/services/fileSystemService.js.map +1 -1
  504. package/dist/src/services/gitService.js +18 -2
  505. package/dist/src/services/gitService.js.map +1 -1
  506. package/dist/src/services/gitService.test.js +56 -0
  507. package/dist/src/services/gitService.test.js.map +1 -1
  508. package/dist/src/services/loopDetectionService.js +5 -4
  509. package/dist/src/services/loopDetectionService.js.map +1 -1
  510. package/dist/src/services/loopDetectionService.test.js +14 -8
  511. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  512. package/dist/src/services/modelConfig.golden.test.js +32 -0
  513. package/dist/src/services/modelConfig.golden.test.js.map +1 -1
  514. package/dist/src/services/modelConfig.integration.test.js +1 -1
  515. package/dist/src/services/modelConfig.integration.test.js.map +1 -1
  516. package/dist/src/services/modelConfigService.d.ts +4 -0
  517. package/dist/src/services/modelConfigService.js +8 -3
  518. package/dist/src/services/modelConfigService.js.map +1 -1
  519. package/dist/src/services/modelConfigService.test.js +221 -0
  520. package/dist/src/services/modelConfigService.test.js.map +1 -1
  521. package/dist/src/services/modelConfigServiceTestUtils.d.ts +10 -0
  522. package/dist/src/services/modelConfigServiceTestUtils.js +17 -0
  523. package/dist/src/services/modelConfigServiceTestUtils.js.map +1 -0
  524. package/dist/src/services/sessionSummaryService.d.ts +28 -0
  525. package/dist/src/services/sessionSummaryService.js +131 -0
  526. package/dist/src/services/sessionSummaryService.js.map +1 -0
  527. package/dist/src/services/sessionSummaryService.test.d.ts +6 -0
  528. package/dist/src/services/sessionSummaryService.test.js +785 -0
  529. package/dist/src/services/sessionSummaryService.test.js.map +1 -0
  530. package/dist/src/services/sessionSummaryUtils.d.ts +16 -0
  531. package/dist/src/services/sessionSummaryUtils.js +129 -0
  532. package/dist/src/services/sessionSummaryUtils.js.map +1 -0
  533. package/dist/src/services/sessionSummaryUtils.test.d.ts +6 -0
  534. package/dist/src/services/sessionSummaryUtils.test.js +137 -0
  535. package/dist/src/services/sessionSummaryUtils.test.js.map +1 -0
  536. package/dist/src/services/shellExecutionService.d.ts +4 -0
  537. package/dist/src/services/shellExecutionService.js +45 -27
  538. package/dist/src/services/shellExecutionService.js.map +1 -1
  539. package/dist/src/services/shellExecutionService.test.js +240 -8
  540. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  541. package/dist/src/services/test-data/resolved-aliases-retry.golden.json +238 -0
  542. package/dist/src/services/test-data/resolved-aliases.golden.json +36 -0
  543. package/dist/src/skills/skillLoader.d.ts +28 -0
  544. package/dist/src/skills/skillLoader.js +77 -0
  545. package/dist/src/skills/skillLoader.js.map +1 -0
  546. package/dist/src/skills/skillLoader.test.d.ts +1 -0
  547. package/dist/src/skills/skillLoader.test.js +2 -0
  548. package/dist/src/skills/skillLoader.test.js.map +1 -0
  549. package/dist/src/skills/skillManager.d.ts +51 -0
  550. package/dist/src/skills/skillManager.js +89 -0
  551. package/dist/src/skills/skillManager.js.map +1 -0
  552. package/dist/src/skills/skillManager.test.d.ts +6 -0
  553. package/dist/src/skills/skillManager.test.js +128 -0
  554. package/dist/src/skills/skillManager.test.js.map +1 -0
  555. package/dist/src/telemetry/activity-detector.test.js.map +1 -1
  556. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +11 -7
  557. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +127 -47
  558. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  559. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +105 -18
  560. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  561. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +9 -3
  562. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +20 -5
  563. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  564. package/dist/src/telemetry/config.js +2 -0
  565. package/dist/src/telemetry/config.js.map +1 -1
  566. package/dist/src/telemetry/config.test.js +25 -0
  567. package/dist/src/telemetry/config.test.js.map +1 -1
  568. package/dist/src/telemetry/gcp-exporters.d.ts +4 -3
  569. package/dist/src/telemetry/gcp-exporters.js +8 -4
  570. package/dist/src/telemetry/gcp-exporters.js.map +1 -1
  571. package/dist/src/telemetry/index.d.ts +2 -1
  572. package/dist/src/telemetry/index.js +2 -1
  573. package/dist/src/telemetry/index.js.map +1 -1
  574. package/dist/src/telemetry/loggers.d.ts +5 -3
  575. package/dist/src/telemetry/loggers.js +353 -334
  576. package/dist/src/telemetry/loggers.js.map +1 -1
  577. package/dist/src/telemetry/loggers.test.circular.js +1 -0
  578. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  579. package/dist/src/telemetry/loggers.test.js +238 -31
  580. package/dist/src/telemetry/loggers.test.js.map +1 -1
  581. package/dist/src/telemetry/metrics.d.ts +22 -0
  582. package/dist/src/telemetry/metrics.js +32 -0
  583. package/dist/src/telemetry/metrics.js.map +1 -1
  584. package/dist/src/telemetry/metrics.test.js +64 -0
  585. package/dist/src/telemetry/metrics.test.js.map +1 -1
  586. package/dist/src/telemetry/sanitize.d.ts +25 -0
  587. package/dist/src/telemetry/sanitize.js +48 -0
  588. package/dist/src/telemetry/sanitize.js.map +1 -0
  589. package/dist/src/telemetry/sanitize.test.d.ts +6 -0
  590. package/dist/src/telemetry/sanitize.test.js +279 -0
  591. package/dist/src/telemetry/sanitize.test.js.map +1 -0
  592. package/dist/src/telemetry/sdk.d.ts +9 -2
  593. package/dist/src/telemetry/sdk.js +142 -17
  594. package/dist/src/telemetry/sdk.js.map +1 -1
  595. package/dist/src/telemetry/sdk.test.js +130 -28
  596. package/dist/src/telemetry/sdk.test.js.map +1 -1
  597. package/dist/src/telemetry/semantic.js +1 -1
  598. package/dist/src/telemetry/semantic.js.map +1 -1
  599. package/dist/src/telemetry/startupProfiler.d.ts +51 -0
  600. package/dist/src/telemetry/startupProfiler.js +170 -0
  601. package/dist/src/telemetry/startupProfiler.js.map +1 -0
  602. package/dist/src/telemetry/startupProfiler.test.d.ts +6 -0
  603. package/dist/src/telemetry/startupProfiler.test.js +285 -0
  604. package/dist/src/telemetry/startupProfiler.test.js.map +1 -0
  605. package/dist/src/telemetry/telemetry.test.js +10 -3
  606. package/dist/src/telemetry/telemetry.test.js.map +1 -1
  607. package/dist/src/telemetry/trace.js +2 -2
  608. package/dist/src/telemetry/trace.js.map +1 -1
  609. package/dist/src/telemetry/types.d.ts +62 -16
  610. package/dist/src/telemetry/types.js +157 -27
  611. package/dist/src/telemetry/types.js.map +1 -1
  612. package/dist/src/telemetry/uiTelemetry.d.ts +1 -0
  613. package/dist/src/telemetry/uiTelemetry.js +2 -0
  614. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  615. package/dist/src/telemetry/uiTelemetry.test.js +4 -0
  616. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  617. package/dist/src/test-utils/mock-message-bus.d.ts +61 -0
  618. package/dist/src/test-utils/mock-message-bus.js +160 -0
  619. package/dist/src/test-utils/mock-message-bus.js.map +1 -0
  620. package/dist/src/test-utils/mock-tool.d.ts +5 -3
  621. package/dist/src/test-utils/mock-tool.js +12 -11
  622. package/dist/src/test-utils/mock-tool.js.map +1 -1
  623. package/dist/src/tools/activate-skill.d.ts +27 -0
  624. package/dist/src/tools/activate-skill.js +120 -0
  625. package/dist/src/tools/activate-skill.js.map +1 -0
  626. package/dist/src/tools/activate-skill.test.d.ts +6 -0
  627. package/dist/src/tools/activate-skill.test.js +95 -0
  628. package/dist/src/tools/activate-skill.test.js.map +1 -0
  629. package/dist/src/tools/confirmation-policy.test.d.ts +6 -0
  630. package/dist/src/tools/confirmation-policy.test.js +142 -0
  631. package/dist/src/tools/confirmation-policy.test.js.map +1 -0
  632. package/dist/src/tools/edit.d.ts +27 -5
  633. package/dist/src/tools/edit.js +449 -137
  634. package/dist/src/tools/edit.js.map +1 -1
  635. package/dist/src/tools/edit.test.js +258 -526
  636. package/dist/src/tools/edit.test.js.map +1 -1
  637. package/dist/src/tools/get-internal-docs.d.ts +27 -0
  638. package/dist/src/tools/get-internal-docs.js +129 -0
  639. package/dist/src/tools/get-internal-docs.js.map +1 -0
  640. package/dist/src/tools/get-internal-docs.test.d.ts +6 -0
  641. package/dist/src/tools/get-internal-docs.test.js +57 -0
  642. package/dist/src/tools/get-internal-docs.test.js.map +1 -0
  643. package/dist/src/tools/glob.d.ts +2 -2
  644. package/dist/src/tools/glob.js +1 -1
  645. package/dist/src/tools/glob.js.map +1 -1
  646. package/dist/src/tools/glob.test.js +2 -1
  647. package/dist/src/tools/glob.test.js.map +1 -1
  648. package/dist/src/tools/grep.d.ts +2 -2
  649. package/dist/src/tools/grep.js +1 -1
  650. package/dist/src/tools/grep.js.map +1 -1
  651. package/dist/src/tools/grep.test.js +5 -4
  652. package/dist/src/tools/grep.test.js.map +1 -1
  653. package/dist/src/tools/ls.d.ts +2 -2
  654. package/dist/src/tools/ls.js +2 -2
  655. package/dist/src/tools/ls.js.map +1 -1
  656. package/dist/src/tools/ls.test.js +2 -1
  657. package/dist/src/tools/ls.test.js.map +1 -1
  658. package/dist/src/tools/mcp-client-manager.d.ts +3 -1
  659. package/dist/src/tools/mcp-client-manager.js +42 -9
  660. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  661. package/dist/src/tools/mcp-client-manager.test.js +66 -10
  662. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  663. package/dist/src/tools/mcp-client.d.ts +44 -6
  664. package/dist/src/tools/mcp-client.js +476 -176
  665. package/dist/src/tools/mcp-client.js.map +1 -1
  666. package/dist/src/tools/mcp-client.test.js +633 -36
  667. package/dist/src/tools/mcp-client.test.js.map +1 -1
  668. package/dist/src/tools/mcp-tool.d.ts +2 -2
  669. package/dist/src/tools/mcp-tool.js +20 -7
  670. package/dist/src/tools/mcp-tool.js.map +1 -1
  671. package/dist/src/tools/mcp-tool.test.js +35 -5
  672. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  673. package/dist/src/tools/memoryTool.d.ts +3 -3
  674. package/dist/src/tools/memoryTool.js +3 -4
  675. package/dist/src/tools/memoryTool.js.map +1 -1
  676. package/dist/src/tools/memoryTool.test.js +5 -2
  677. package/dist/src/tools/memoryTool.test.js.map +1 -1
  678. package/dist/src/tools/message-bus-integration.test.js +10 -37
  679. package/dist/src/tools/message-bus-integration.test.js.map +1 -1
  680. package/dist/src/tools/modifiable-tool.js.map +1 -1
  681. package/dist/src/tools/modifiable-tool.test.js +22 -13
  682. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  683. package/dist/src/tools/read-file.d.ts +2 -2
  684. package/dist/src/tools/read-file.js +2 -2
  685. package/dist/src/tools/read-file.js.map +1 -1
  686. package/dist/src/tools/read-file.test.js +3 -2
  687. package/dist/src/tools/read-file.test.js.map +1 -1
  688. package/dist/src/tools/read-many-files.d.ts +2 -2
  689. package/dist/src/tools/read-many-files.js +7 -6
  690. package/dist/src/tools/read-many-files.js.map +1 -1
  691. package/dist/src/tools/read-many-files.test.js +4 -3
  692. package/dist/src/tools/read-many-files.test.js.map +1 -1
  693. package/dist/src/tools/ripGrep.d.ts +3 -2
  694. package/dist/src/tools/ripGrep.js +18 -7
  695. package/dist/src/tools/ripGrep.js.map +1 -1
  696. package/dist/src/tools/ripGrep.test.js +60 -4
  697. package/dist/src/tools/ripGrep.test.js.map +1 -1
  698. package/dist/src/tools/shell.d.ts +5 -7
  699. package/dist/src/tools/shell.js +77 -51
  700. package/dist/src/tools/shell.js.map +1 -1
  701. package/dist/src/tools/shell.test.js +59 -63
  702. package/dist/src/tools/shell.test.js.map +1 -1
  703. package/dist/src/tools/tool-error.d.ts +2 -1
  704. package/dist/src/tools/tool-error.js +2 -0
  705. package/dist/src/tools/tool-error.js.map +1 -1
  706. package/dist/src/tools/tool-names.d.ts +17 -0
  707. package/dist/src/tools/tool-names.js +59 -0
  708. package/dist/src/tools/tool-names.js.map +1 -1
  709. package/dist/src/tools/tool-names.test.d.ts +6 -0
  710. package/dist/src/tools/tool-names.test.js +43 -0
  711. package/dist/src/tools/tool-names.test.js.map +1 -0
  712. package/dist/src/tools/tool-registry.d.ts +11 -7
  713. package/dist/src/tools/tool-registry.js +15 -10
  714. package/dist/src/tools/tool-registry.js.map +1 -1
  715. package/dist/src/tools/tool-registry.test.js +16 -11
  716. package/dist/src/tools/tool-registry.test.js.map +1 -1
  717. package/dist/src/tools/tools.d.ts +25 -6
  718. package/dist/src/tools/tools.js +44 -25
  719. package/dist/src/tools/tools.js.map +1 -1
  720. package/dist/src/tools/tools.test.js +3 -1
  721. package/dist/src/tools/tools.test.js.map +1 -1
  722. package/dist/src/tools/web-fetch.d.ts +2 -2
  723. package/dist/src/tools/web-fetch.js +22 -9
  724. package/dist/src/tools/web-fetch.js.map +1 -1
  725. package/dist/src/tools/web-fetch.test.js +18 -19
  726. package/dist/src/tools/web-fetch.test.js.map +1 -1
  727. package/dist/src/tools/web-search.d.ts +2 -2
  728. package/dist/src/tools/web-search.js +5 -5
  729. package/dist/src/tools/web-search.js.map +1 -1
  730. package/dist/src/tools/web-search.test.js +2 -1
  731. package/dist/src/tools/web-search.test.js.map +1 -1
  732. package/dist/src/tools/write-file.d.ts +2 -2
  733. package/dist/src/tools/write-file.js +10 -4
  734. package/dist/src/tools/write-file.js.map +1 -1
  735. package/dist/src/tools/write-file.test.js +4 -1
  736. package/dist/src/tools/write-file.test.js.map +1 -1
  737. package/dist/src/tools/write-todos.d.ts +2 -2
  738. package/dist/src/tools/write-todos.js +5 -4
  739. package/dist/src/tools/write-todos.js.map +1 -1
  740. package/dist/src/tools/write-todos.test.js +2 -1
  741. package/dist/src/tools/write-todos.test.js.map +1 -1
  742. package/dist/src/utils/bfsFileSearch.d.ts +8 -0
  743. package/dist/src/utils/bfsFileSearch.js +63 -23
  744. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  745. package/dist/src/utils/bfsFileSearch.test.js +65 -1
  746. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  747. package/dist/src/utils/checkpointUtils.d.ts +82 -0
  748. package/dist/src/utils/checkpointUtils.js +117 -0
  749. package/dist/src/utils/checkpointUtils.js.map +1 -0
  750. package/dist/src/utils/checkpointUtils.test.d.ts +6 -0
  751. package/dist/src/utils/checkpointUtils.test.js +229 -0
  752. package/dist/src/utils/checkpointUtils.test.js.map +1 -0
  753. package/dist/src/utils/customHeaderUtils.d.ts +9 -0
  754. package/dist/src/utils/customHeaderUtils.js +34 -0
  755. package/dist/src/utils/customHeaderUtils.js.map +1 -0
  756. package/dist/src/utils/customHeaderUtils.test.d.ts +6 -0
  757. package/dist/src/utils/customHeaderUtils.test.js +77 -0
  758. package/dist/src/utils/customHeaderUtils.test.js.map +1 -0
  759. package/dist/src/utils/debugLogger.d.ts +3 -0
  760. package/dist/src/utils/debugLogger.js +28 -0
  761. package/dist/src/utils/debugLogger.js.map +1 -1
  762. package/dist/src/utils/editCorrector.js +6 -5
  763. package/dist/src/utils/editCorrector.js.map +1 -1
  764. package/dist/src/utils/editCorrector.test.js +7 -3
  765. package/dist/src/utils/editCorrector.test.js.map +1 -1
  766. package/dist/src/utils/editor.d.ts +9 -1
  767. package/dist/src/utils/editor.js +23 -14
  768. package/dist/src/utils/editor.js.map +1 -1
  769. package/dist/src/utils/environmentContext.d.ts +1 -0
  770. package/dist/src/utils/environmentContext.js +4 -0
  771. package/dist/src/utils/environmentContext.js.map +1 -1
  772. package/dist/src/utils/environmentContext.test.js +2 -0
  773. package/dist/src/utils/environmentContext.test.js.map +1 -1
  774. package/dist/src/utils/errorReporting.d.ts +1 -1
  775. package/dist/src/utils/errorReporting.js +13 -12
  776. package/dist/src/utils/errorReporting.js.map +1 -1
  777. package/dist/src/utils/errorReporting.test.js +17 -14
  778. package/dist/src/utils/errorReporting.test.js.map +1 -1
  779. package/dist/src/utils/errors.d.ts +8 -0
  780. package/dist/src/utils/errors.js +39 -2
  781. package/dist/src/utils/errors.js.map +1 -1
  782. package/dist/src/utils/errors.test.d.ts +6 -0
  783. package/dist/src/utils/errors.test.js +155 -0
  784. package/dist/src/utils/errors.test.js.map +1 -0
  785. package/dist/src/utils/events.d.ts +49 -19
  786. package/dist/src/utils/events.js +21 -9
  787. package/dist/src/utils/events.js.map +1 -1
  788. package/dist/src/utils/events.test.js +25 -0
  789. package/dist/src/utils/events.test.js.map +1 -1
  790. package/dist/src/utils/exitCodes.d.ts +12 -0
  791. package/dist/src/utils/exitCodes.js +13 -0
  792. package/dist/src/utils/exitCodes.js.map +1 -0
  793. package/dist/src/utils/extensionLoader.d.ts +2 -2
  794. package/dist/src/utils/extensionLoader.js +5 -6
  795. package/dist/src/utils/extensionLoader.js.map +1 -1
  796. package/dist/src/utils/extensionLoader.test.js +11 -0
  797. package/dist/src/utils/extensionLoader.test.js.map +1 -1
  798. package/dist/src/utils/fetch.d.ts +1 -1
  799. package/dist/src/utils/fetch.js +3 -3
  800. package/dist/src/utils/fetch.js.map +1 -1
  801. package/dist/src/utils/fileUtils.d.ts +4 -0
  802. package/dist/src/utils/fileUtils.js +53 -0
  803. package/dist/src/utils/fileUtils.js.map +1 -1
  804. package/dist/src/utils/fileUtils.test.js +127 -1
  805. package/dist/src/utils/fileUtils.test.js.map +1 -1
  806. package/dist/src/utils/filesearch/crawlCache.js.map +1 -1
  807. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  808. package/dist/src/utils/flashFallback.test.js +1 -1
  809. package/dist/src/utils/flashFallback.test.js.map +1 -1
  810. package/dist/src/utils/geminiIgnoreParser.d.ts +11 -0
  811. package/dist/src/utils/geminiIgnoreParser.js +20 -0
  812. package/dist/src/utils/geminiIgnoreParser.js.map +1 -1
  813. package/dist/src/utils/geminiIgnoreParser.test.js +48 -0
  814. package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -1
  815. package/dist/src/utils/generateContentResponseUtilities.d.ts +3 -1
  816. package/dist/src/utils/generateContentResponseUtilities.js +106 -0
  817. package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
  818. package/dist/src/utils/generateContentResponseUtilities.test.js +279 -2
  819. package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
  820. package/dist/src/utils/getFolderStructure.js +7 -2
  821. package/dist/src/utils/getFolderStructure.js.map +1 -1
  822. package/dist/src/utils/googleErrors.js +31 -18
  823. package/dist/src/utils/googleErrors.js.map +1 -1
  824. package/dist/src/utils/googleErrors.test.js +10 -2
  825. package/dist/src/utils/googleErrors.test.js.map +1 -1
  826. package/dist/src/utils/googleQuotaErrors.d.ts +3 -3
  827. package/dist/src/utils/googleQuotaErrors.js +32 -6
  828. package/dist/src/utils/googleQuotaErrors.js.map +1 -1
  829. package/dist/src/utils/googleQuotaErrors.test.js +94 -2
  830. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -1
  831. package/dist/src/utils/memoryDiscovery.d.ts +5 -0
  832. package/dist/src/utils/memoryDiscovery.js +9 -5
  833. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  834. package/dist/src/utils/memoryDiscovery.test.js +31 -1
  835. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  836. package/dist/src/utils/nextSpeakerChecker.test.js +4 -0
  837. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  838. package/dist/src/utils/package.d.ts +14 -0
  839. package/dist/src/utils/package.js +15 -2
  840. package/dist/src/utils/package.js.map +1 -1
  841. package/dist/src/utils/pathCorrector.js +12 -2
  842. package/dist/src/utils/pathCorrector.js.map +1 -1
  843. package/dist/src/utils/pathCorrector.test.js +6 -2
  844. package/dist/src/utils/pathCorrector.test.js.map +1 -1
  845. package/dist/src/utils/retry.d.ts +11 -0
  846. package/dist/src/utils/retry.js +62 -21
  847. package/dist/src/utils/retry.js.map +1 -1
  848. package/dist/src/utils/retry.test.js +170 -10
  849. package/dist/src/utils/retry.test.js.map +1 -1
  850. package/dist/src/utils/schemaValidator.d.ts +1 -1
  851. package/dist/src/utils/schemaValidator.js +1 -1
  852. package/dist/src/utils/shell-permissions.d.ts +52 -0
  853. package/dist/src/utils/shell-permissions.js +188 -0
  854. package/dist/src/utils/shell-permissions.js.map +1 -0
  855. package/dist/src/utils/shell-permissions.test.d.ts +6 -0
  856. package/dist/src/utils/shell-permissions.test.js +369 -0
  857. package/dist/src/utils/shell-permissions.test.js.map +1 -0
  858. package/dist/src/utils/shell-utils.d.ts +16 -47
  859. package/dist/src/utils/shell-utils.js +99 -195
  860. package/dist/src/utils/shell-utils.js.map +1 -1
  861. package/dist/src/utils/shell-utils.test.js +99 -288
  862. package/dist/src/utils/shell-utils.test.js.map +1 -1
  863. package/dist/src/utils/stdio.d.ts +2 -2
  864. package/dist/src/utils/stdio.js +2 -2
  865. package/dist/src/utils/stdio.js.map +1 -1
  866. package/dist/src/utils/stdio.test.js +5 -5
  867. package/dist/src/utils/stdio.test.js.map +1 -1
  868. package/dist/src/utils/summarizer.test.js +3 -2
  869. package/dist/src/utils/summarizer.test.js.map +1 -1
  870. package/dist/src/utils/terminal.d.ts +4 -0
  871. package/dist/src/utils/terminal.js +12 -0
  872. package/dist/src/utils/terminal.js.map +1 -1
  873. package/dist/src/utils/terminalSerializer.test.js +17 -0
  874. package/dist/src/utils/terminalSerializer.test.js.map +1 -1
  875. package/dist/src/utils/tokenCalculation.d.ts +19 -0
  876. package/dist/src/utils/tokenCalculation.js +85 -0
  877. package/dist/src/utils/tokenCalculation.js.map +1 -0
  878. package/dist/src/utils/tokenCalculation.test.d.ts +6 -0
  879. package/dist/src/utils/tokenCalculation.test.js +87 -0
  880. package/dist/src/utils/tokenCalculation.test.js.map +1 -0
  881. package/dist/src/utils/tool-utils.d.ts +9 -0
  882. package/dist/src/utils/tool-utils.js +29 -0
  883. package/dist/src/utils/tool-utils.js.map +1 -1
  884. package/dist/src/utils/tool-utils.test.js +17 -2
  885. package/dist/src/utils/tool-utils.test.js.map +1 -1
  886. package/dist/src/utils/version.d.ts +6 -0
  887. package/dist/src/utils/version.js +15 -0
  888. package/dist/src/utils/version.js.map +1 -0
  889. package/dist/src/utils/version.test.d.ts +6 -0
  890. package/dist/src/utils/version.test.js +39 -0
  891. package/dist/src/utils/version.test.js.map +1 -0
  892. package/dist/tsconfig.tsbuildinfo +1 -1
  893. package/package.json +8 -7
@@ -9,14 +9,17 @@ import { AuthType, } from './contentGenerator.js';
9
9
  import {} from './geminiChat.js';
10
10
  import { CompressionStatus, GeminiEventType, Turn, } from './turn.js';
11
11
  import { getCoreSystemPrompt } from './prompts.js';
12
- import { DEFAULT_GEMINI_FLASH_MODEL } from '../config/models.js';
12
+ import { DEFAULT_GEMINI_MODEL_AUTO } from '../config/models.js';
13
13
  import { FileDiscoveryService } from '../services/fileDiscoveryService.js';
14
14
  import { setSimulate429 } from '../utils/testUtils.js';
15
15
  import { tokenLimit } from './tokenLimits.js';
16
16
  import { ideContextStore } from '../ide/ideContext.js';
17
17
  import { uiTelemetryService } from '../telemetry/uiTelemetry.js';
18
18
  import { ChatCompressionService } from '../services/chatCompressionService.js';
19
+ import { createAvailabilityServiceMock } from '../availability/testUtils.js';
19
20
  import { ClearcutLogger } from '../telemetry/clearcut-logger/clearcut-logger.js';
21
+ import { HookSystem } from '../hooks/hookSystem.js';
22
+ import * as policyCatalog from '../availability/policyCatalog.js';
20
23
  vi.mock('../services/chatCompressionService.js');
21
24
  // Mock fs module to prevent actual file system operations during tests
22
25
  const mockFileSystem = new Map();
@@ -35,13 +38,16 @@ vi.mock('node:fs', () => {
35
38
  });
36
39
  }),
37
40
  existsSync: vi.fn((path) => mockFileSystem.has(path)),
41
+ createWriteStream: vi.fn(() => ({
42
+ write: vi.fn(),
43
+ on: vi.fn(),
44
+ })),
38
45
  };
39
46
  return {
40
47
  default: fsModule,
41
48
  ...fsModule,
42
49
  };
43
50
  });
44
- // --- Mocks ---
45
51
  const mockTurnRunFn = vi.fn();
46
52
  vi.mock('./turn', async (importOriginal) => {
47
53
  const actual = await importOriginal();
@@ -53,6 +59,7 @@ vi.mock('./turn', async (importOriginal) => {
53
59
  constructor() {
54
60
  // The constructor can be empty or do some mock setup
55
61
  }
62
+ getResponseText = vi.fn().mockReturnValue('Mock Response');
56
63
  }
57
64
  // Export the mock class as 'Turn'
58
65
  return {
@@ -85,6 +92,16 @@ vi.mock('../telemetry/uiTelemetry.js', () => ({
85
92
  getLastPromptTokenCount: vi.fn(),
86
93
  },
87
94
  }));
95
+ vi.mock('../hooks/hookSystem.js');
96
+ vi.mock('./clientHookTriggers.js', () => ({
97
+ fireBeforeAgentHook: vi.fn(),
98
+ fireAfterAgentHook: vi.fn().mockResolvedValue({
99
+ decision: 'allow',
100
+ continue: false,
101
+ suppressOutput: false,
102
+ systemMessage: undefined,
103
+ }),
104
+ }));
88
105
  /**
89
106
  * Array.fromAsync ponyfill, which will be available in es 2024.
90
107
  *
@@ -102,6 +119,7 @@ describe('Gemini Client (client.ts)', () => {
102
119
  let mockConfig;
103
120
  let client;
104
121
  let mockGenerateContentFn;
122
+ let mockRouterService;
105
123
  beforeEach(async () => {
106
124
  vi.resetAllMocks();
107
125
  ClearcutLogger.clearInstance();
@@ -119,10 +137,16 @@ describe('Gemini Client (client.ts)', () => {
119
137
  });
120
138
  // Disable 429 simulation for tests
121
139
  setSimulate429(false);
140
+ mockRouterService = {
141
+ route: vi
142
+ .fn()
143
+ .mockResolvedValue({ model: 'default-routed-model', reason: 'test' }),
144
+ };
122
145
  mockContentGenerator = {
123
146
  generateContent: mockGenerateContentFn,
124
147
  generateContentStream: vi.fn(),
125
148
  batchEmbedContents: vi.fn(),
149
+ countTokens: vi.fn().mockResolvedValue({ totalTokens: 100 }),
126
150
  };
127
151
  // Because the GeminiClient constructor kicks off an async process (startChat)
128
152
  // that depends on a fully-formed Config object, we need to mock the
@@ -143,11 +167,15 @@ describe('Gemini Client (client.ts)', () => {
143
167
  .mockReturnValue(contentGeneratorConfig),
144
168
  getToolRegistry: vi.fn().mockReturnValue(mockToolRegistry),
145
169
  getModel: vi.fn().mockReturnValue('test-model'),
170
+ getUserTier: vi.fn().mockReturnValue(undefined),
146
171
  getEmbeddingModel: vi.fn().mockReturnValue('test-embedding-model'),
147
172
  getApiKey: vi.fn().mockReturnValue('test-key'),
148
173
  getVertexAI: vi.fn().mockReturnValue(false),
149
174
  getUserAgent: vi.fn().mockReturnValue('test-agent'),
150
175
  getUserMemory: vi.fn().mockReturnValue(''),
176
+ getGlobalMemory: vi.fn().mockReturnValue(''),
177
+ getEnvironmentMemory: vi.fn().mockReturnValue(''),
178
+ isJitContextEnabled: vi.fn().mockReturnValue(false),
151
179
  getSessionId: vi.fn().mockReturnValue('test-session-id'),
152
180
  getProxy: vi.fn().mockReturnValue(undefined),
153
181
  getWorkingDir: vi.fn().mockReturnValue('/test/dir'),
@@ -165,15 +193,13 @@ describe('Gemini Client (client.ts)', () => {
165
193
  getDirectories: vi.fn().mockReturnValue(['/test/dir']),
166
194
  }),
167
195
  getGeminiClient: vi.fn(),
168
- getModelRouterService: vi.fn().mockReturnValue({
169
- route: vi.fn().mockResolvedValue({ model: 'default-routed-model' }),
170
- }),
171
- isInFallbackMode: vi.fn().mockReturnValue(false),
172
- setFallbackMode: vi.fn(),
196
+ getModelRouterService: vi
197
+ .fn()
198
+ .mockReturnValue(mockRouterService),
199
+ getMessageBus: vi.fn().mockReturnValue(undefined),
200
+ getEnableHooks: vi.fn().mockReturnValue(false),
173
201
  getChatCompression: vi.fn().mockReturnValue(undefined),
174
202
  getSkipNextSpeakerCheck: vi.fn().mockReturnValue(false),
175
- getUseSmartEdit: vi.fn().mockReturnValue(false),
176
- getUseModelRouter: vi.fn().mockReturnValue(false),
177
203
  getShowModelInfoInChat: vi.fn().mockReturnValue(false),
178
204
  getContinueOnFailedApiCall: vi.fn(),
179
205
  getProjectRoot: vi.fn().mockReturnValue('/test/project/root'),
@@ -199,7 +225,17 @@ describe('Gemini Client (client.ts)', () => {
199
225
  },
200
226
  },
201
227
  isInteractive: vi.fn().mockReturnValue(false),
228
+ getExperiments: () => { },
229
+ getActiveModel: vi.fn().mockReturnValue('test-model'),
230
+ setActiveModel: vi.fn(),
231
+ resetTurn: vi.fn(),
232
+ getModelAvailabilityService: vi
233
+ .fn()
234
+ .mockReturnValue(createAvailabilityServiceMock()),
202
235
  };
236
+ mockConfig.getHookSystem = vi
237
+ .fn()
238
+ .mockReturnValue(new HookSystem(mockConfig));
203
239
  client = new GeminiClient(mockConfig);
204
240
  await client.initialize();
205
241
  vi.mocked(mockConfig.getGeminiClient).mockReturnValue(client);
@@ -226,18 +262,18 @@ describe('Gemini Client (client.ts)', () => {
226
262
  it('should create a new chat session, clearing the old history', async () => {
227
263
  // 1. Get the initial chat instance and add some history.
228
264
  const initialChat = client.getChat();
229
- const initialHistory = await client.getHistory();
265
+ const initialHistory = client.getHistory();
230
266
  await client.addHistory({
231
267
  role: 'user',
232
268
  parts: [{ text: 'some old message' }],
233
269
  });
234
- const historyWithOldMessage = await client.getHistory();
270
+ const historyWithOldMessage = client.getHistory();
235
271
  expect(historyWithOldMessage.length).toBeGreaterThan(initialHistory.length);
236
272
  // 2. Call resetChat.
237
273
  await client.resetChat();
238
274
  // 3. Get the new chat instance and its history.
239
275
  const newChat = client.getChat();
240
- const newHistory = await client.getHistory();
276
+ const newHistory = client.getHistory();
241
277
  // 4. Assert that the chat instance is new and the history is reset.
242
278
  expect(newChat).not.toBe(initialChat);
243
279
  expect(newHistory.length).toBe(initialHistory.length);
@@ -384,6 +420,27 @@ describe('Gemini Client (client.ts)', () => {
384
420
  expect(ChatCompressionService.prototype.compress).toHaveBeenLastCalledWith(expect.anything(), 'prompt-id-5', false, expect.anything(), expect.anything(), true);
385
421
  });
386
422
  });
423
+ it('should correctly latch hasFailedCompressionAttempt flag', async () => {
424
+ // 1. Setup: Call setup() from this test file
425
+ // This helper function mocks the compression service for us.
426
+ const { client } = setup({
427
+ originalTokenCount: 100,
428
+ newTokenCount: 200, // Inflated
429
+ compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
430
+ });
431
+ // 2. Test Step 1: Trigger a non-forced failure
432
+ await client.tryCompressChat('prompt-1', false); // force = false
433
+ // 3. Assert Step 1: Check that the flag became true
434
+ // 3. Assert Step 1: Check that the flag became true
435
+ expect(client
436
+ .hasFailedCompressionAttempt).toBe(true);
437
+ // 4. Test Step 2: Trigger a forced failure
438
+ await client.tryCompressChat('prompt-2', true); // force = true
439
+ // 5. Assert Step 2: Check that the flag REMAINS true
440
+ // 5. Assert Step 2: Check that the flag REMAINS true
441
+ expect(client
442
+ .hasFailedCompressionAttempt).toBe(true);
443
+ });
387
444
  it('should not trigger summarization if token count is below threshold', async () => {
388
445
  const MOCKED_TOKEN_LIMIT = 1000;
389
446
  const originalTokenCount = MOCKED_TOKEN_LIMIT * 0.699;
@@ -677,6 +734,50 @@ ${JSON.stringify({
677
734
  parts: expectedRequest,
678
735
  });
679
736
  });
737
+ it('should use local estimation for text-only requests and NOT call countTokens', async () => {
738
+ const request = [{ text: 'Hello world' }];
739
+ const generator = client['getContentGeneratorOrFail']();
740
+ const countTokensSpy = vi.spyOn(generator, 'countTokens');
741
+ const stream = client.sendMessageStream(request, new AbortController().signal, 'test-prompt-id');
742
+ await stream.next(); // Trigger the generator
743
+ expect(countTokensSpy).not.toHaveBeenCalled();
744
+ });
745
+ it('should use countTokens API for requests with non-text parts', async () => {
746
+ const request = [
747
+ { text: 'Describe this image' },
748
+ { inlineData: { mimeType: 'image/png', data: 'base64...' } },
749
+ ];
750
+ const generator = client['getContentGeneratorOrFail']();
751
+ const countTokensSpy = vi
752
+ .spyOn(generator, 'countTokens')
753
+ .mockResolvedValue({ totalTokens: 123 });
754
+ const stream = client.sendMessageStream(request, new AbortController().signal, 'test-prompt-id');
755
+ await stream.next(); // Trigger the generator
756
+ expect(countTokensSpy).toHaveBeenCalledWith(expect.objectContaining({
757
+ contents: expect.arrayContaining([
758
+ expect.objectContaining({
759
+ parts: expect.arrayContaining([
760
+ { text: 'Describe this image' },
761
+ { inlineData: { mimeType: 'image/png', data: 'base64...' } },
762
+ ]),
763
+ }),
764
+ ]),
765
+ }));
766
+ });
767
+ it('should estimate CJK characters more conservatively (closer to 1 token/char)', async () => {
768
+ const request = [{ text: '你好世界' }]; // 4 chars
769
+ const generator = client['getContentGeneratorOrFail']();
770
+ const countTokensSpy = vi.spyOn(generator, 'countTokens');
771
+ // 4 chars.
772
+ // Old logic: 4/4 = 1.
773
+ // New logic (heuristic): 4 * 1 = 4. (Or at least > 1).
774
+ // Let's assert it's roughly accurate.
775
+ const stream = client.sendMessageStream(request, new AbortController().signal, 'test-prompt-id');
776
+ await stream.next();
777
+ // Should NOT call countTokens (it's text only)
778
+ expect(countTokensSpy).not.toHaveBeenCalled();
779
+ // The actual token calculation is unit tested in tokenCalculation.test.ts
780
+ });
680
781
  it('should return the turn instance after the stream is complete', async () => {
681
782
  // Arrange
682
783
  const mockStream = (async function* () {
@@ -859,7 +960,8 @@ ${JSON.stringify({
859
960
  // A string of length 400 is roughly 100 tokens.
860
961
  const longText = 'a'.repeat(400);
861
962
  const request = [{ text: longText }];
862
- const estimatedRequestTokenCount = Math.floor(JSON.stringify(request).length / 4);
963
+ // estimateTextOnlyLength counts only text content (400 chars), not JSON structure
964
+ const estimatedRequestTokenCount = Math.floor(longText.length / 4);
863
965
  const remainingTokenCount = MOCKED_TOKEN_LIMIT - lastPromptTokenCount;
864
966
  // Mock tryCompressChat to not compress
865
967
  vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
@@ -905,7 +1007,8 @@ ${JSON.stringify({
905
1007
  // We need a request > 95 tokens.
906
1008
  const longText = 'a'.repeat(400);
907
1009
  const request = [{ text: longText }];
908
- const estimatedRequestTokenCount = Math.floor(JSON.stringify(request).length / 4);
1010
+ // estimateTextOnlyLength counts only text content (400 chars), not JSON structure
1011
+ const estimatedRequestTokenCount = Math.floor(longText.length / 4);
909
1012
  const remainingTokenCount = STICKY_MODEL_LIMIT - lastPromptTokenCount;
910
1013
  vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
911
1014
  originalTokenCount: lastPromptTokenCount,
@@ -927,6 +1030,51 @@ ${JSON.stringify({
927
1030
  expect(tokenLimit).toHaveBeenCalledWith(STICKY_MODEL);
928
1031
  expect(mockTurnRunFn).not.toHaveBeenCalled();
929
1032
  });
1033
+ it('should not trigger overflow warning for requests with large binary data (PDFs/images)', async () => {
1034
+ // Arrange
1035
+ const MOCKED_TOKEN_LIMIT = 1000000; // 1M tokens
1036
+ vi.mocked(tokenLimit).mockReturnValue(MOCKED_TOKEN_LIMIT);
1037
+ const lastPromptTokenCount = 10000;
1038
+ const mockChat = {
1039
+ getLastPromptTokenCount: vi.fn().mockReturnValue(lastPromptTokenCount),
1040
+ getHistory: vi.fn().mockReturnValue([]),
1041
+ };
1042
+ client['chat'] = mockChat;
1043
+ // Simulate a PDF file with large base64 data (11MB when encoded)
1044
+ // In the old implementation, this would incorrectly estimate ~2.7M tokens
1045
+ // In the new implementation, only the text part is counted
1046
+ const largePdfBase64 = 'A'.repeat(11 * 1024 * 1024);
1047
+ const request = [
1048
+ { text: 'Please analyze this PDF document' }, // ~35 chars = ~8 tokens
1049
+ {
1050
+ inlineData: {
1051
+ mimeType: 'application/pdf',
1052
+ data: largePdfBase64, // This should be ignored in token estimation
1053
+ },
1054
+ },
1055
+ ];
1056
+ // Mock tryCompressChat to not compress
1057
+ vi.spyOn(client, 'tryCompressChat').mockResolvedValue({
1058
+ originalTokenCount: lastPromptTokenCount,
1059
+ newTokenCount: lastPromptTokenCount,
1060
+ compressionStatus: CompressionStatus.NOOP,
1061
+ });
1062
+ // Mock Turn.run to simulate successful processing
1063
+ const mockStream = (async function* () {
1064
+ yield { type: 'content', value: 'Analysis complete' };
1065
+ })();
1066
+ mockTurnRunFn.mockReturnValue(mockStream);
1067
+ // Act
1068
+ const stream = client.sendMessageStream(request, new AbortController().signal, 'prompt-id-pdf-test');
1069
+ const events = await fromAsync(stream);
1070
+ // Assert
1071
+ // Should NOT contain overflow warning
1072
+ expect(events).not.toContainEqual(expect.objectContaining({
1073
+ type: GeminiEventType.ContextWindowWillOverflow,
1074
+ }));
1075
+ // Turn.run should be called (processing should continue)
1076
+ expect(mockTurnRunFn).toHaveBeenCalled();
1077
+ });
930
1078
  describe('Model Routing', () => {
931
1079
  let mockRouterService;
932
1080
  beforeEach(() => {
@@ -985,37 +1133,23 @@ ${JSON.stringify({
985
1133
  // Should use the newly routed model
986
1134
  expect(mockTurnRunFn).toHaveBeenCalledWith({ model: 'new-routed-model' }, [{ text: 'A new topic' }], expect.any(AbortSignal));
987
1135
  });
988
- it('should use the fallback model and bypass routing when in fallback mode', async () => {
989
- vi.mocked(mockConfig.isInFallbackMode).mockReturnValue(true);
990
- mockRouterService.route.mockResolvedValue({
991
- model: DEFAULT_GEMINI_FLASH_MODEL,
992
- reason: 'fallback',
993
- });
994
- const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-1');
995
- await fromAsync(stream);
996
- expect(mockTurnRunFn).toHaveBeenCalledWith({ model: DEFAULT_GEMINI_FLASH_MODEL }, [{ text: 'Hi' }], expect.any(AbortSignal));
997
- });
998
- it('should stick to the fallback model for the entire sequence even if fallback mode ends', async () => {
999
- // Start the sequence in fallback mode
1000
- vi.mocked(mockConfig.isInFallbackMode).mockReturnValue(true);
1001
- mockRouterService.route.mockResolvedValue({
1002
- model: DEFAULT_GEMINI_FLASH_MODEL,
1003
- reason: 'fallback',
1004
- });
1005
- let stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-fallback-stickiness');
1006
- await fromAsync(stream);
1007
- // First call should use fallback model
1008
- expect(mockTurnRunFn).toHaveBeenCalledWith({ model: DEFAULT_GEMINI_FLASH_MODEL }, [{ text: 'Hi' }], expect.any(AbortSignal));
1009
- // End fallback mode
1010
- vi.mocked(mockConfig.isInFallbackMode).mockReturnValue(false);
1011
- // Second call in the same sequence
1012
- stream = client.sendMessageStream([{ text: 'Continue' }], new AbortController().signal, 'prompt-fallback-stickiness');
1013
- await fromAsync(stream);
1014
- // Router should still not be called, and it should stick to the fallback model
1015
- expect(mockTurnRunFn).toHaveBeenCalledTimes(2); // Ensure it was called again
1016
- expect(mockTurnRunFn).toHaveBeenLastCalledWith({ model: DEFAULT_GEMINI_FLASH_MODEL }, // Still the fallback model
1017
- [{ text: 'Continue' }], expect.any(AbortSignal));
1018
- });
1136
+ });
1137
+ it('should use getGlobalMemory for system instruction when JIT is enabled', async () => {
1138
+ vi.mocked(mockConfig.isJitContextEnabled).mockReturnValue(true);
1139
+ vi.mocked(mockConfig.getGlobalMemory).mockReturnValue('Global JIT Memory');
1140
+ vi.mocked(mockConfig.getUserMemory).mockReturnValue('Full JIT Memory');
1141
+ const { getCoreSystemPrompt } = await import('./prompts.js');
1142
+ const mockGetCoreSystemPrompt = vi.mocked(getCoreSystemPrompt);
1143
+ await client.updateSystemInstruction();
1144
+ expect(mockGetCoreSystemPrompt).toHaveBeenCalledWith(mockConfig, 'Global JIT Memory');
1145
+ });
1146
+ it('should use getUserMemory for system instruction when JIT is disabled', async () => {
1147
+ vi.mocked(mockConfig.isJitContextEnabled).mockReturnValue(false);
1148
+ vi.mocked(mockConfig.getUserMemory).mockReturnValue('Legacy Memory');
1149
+ const { getCoreSystemPrompt } = await import('./prompts.js');
1150
+ const mockGetCoreSystemPrompt = vi.mocked(getCoreSystemPrompt);
1151
+ await client.updateSystemInstruction();
1152
+ expect(mockGetCoreSystemPrompt).toHaveBeenCalledWith(mockConfig, 'Legacy Memory');
1019
1153
  });
1020
1154
  it('should recursively call sendMessageStream with "Please continue." when InvalidStream event is received', async () => {
1021
1155
  vi.spyOn(client['config'], 'getContinueOnFailedApiCall').mockReturnValue(true);
@@ -1045,6 +1179,7 @@ ${JSON.stringify({
1045
1179
  expect(events).toEqual([
1046
1180
  { type: GeminiEventType.ModelInfo, value: 'default-routed-model' },
1047
1181
  { type: GeminiEventType.InvalidStream },
1182
+ { type: GeminiEventType.ModelInfo, value: 'default-routed-model' },
1048
1183
  { type: GeminiEventType.Content, value: 'Continued content' },
1049
1184
  ]);
1050
1185
  // Verify that turn.run was called twice
@@ -1101,8 +1236,8 @@ ${JSON.stringify({
1101
1236
  const stream = client.sendMessageStream(initialRequest, signal, promptId);
1102
1237
  const events = await fromAsync(stream);
1103
1238
  // Assert
1104
- // We expect 3 events (model_info + original + 1 retry)
1105
- expect(events.length).toBe(3);
1239
+ // We expect 4 events (model_info + original + model_info + 1 retry)
1240
+ expect(events.length).toBe(4);
1106
1241
  expect(events
1107
1242
  .filter((e) => e.type !== GeminiEventType.ModelInfo)
1108
1243
  .every((e) => e.type === GeminiEventType.InvalidStream)).toBe(true);
@@ -1328,6 +1463,94 @@ ${JSON.stringify({
1328
1463
  expect(contextJson.activeFile.path).toBe('/path/to/active/file.ts');
1329
1464
  });
1330
1465
  });
1466
+ describe('Availability Service Integration', () => {
1467
+ let mockAvailabilityService;
1468
+ beforeEach(() => {
1469
+ mockAvailabilityService = createAvailabilityServiceMock();
1470
+ vi.mocked(mockConfig.getModelAvailabilityService).mockReturnValue(mockAvailabilityService);
1471
+ vi.mocked(mockConfig.setActiveModel).mockClear();
1472
+ mockRouterService.route.mockResolvedValue({
1473
+ model: 'model-a',
1474
+ reason: 'test',
1475
+ });
1476
+ vi.mocked(mockConfig.getModelRouterService).mockReturnValue(mockRouterService);
1477
+ vi.spyOn(policyCatalog, 'getModelPolicyChain').mockReturnValue([
1478
+ {
1479
+ model: 'model-a',
1480
+ isLastResort: false,
1481
+ actions: {},
1482
+ stateTransitions: {},
1483
+ },
1484
+ {
1485
+ model: 'model-b',
1486
+ isLastResort: true,
1487
+ actions: {},
1488
+ stateTransitions: {},
1489
+ },
1490
+ ]);
1491
+ mockTurnRunFn.mockReturnValue((async function* () {
1492
+ yield { type: 'content', value: 'Hello' };
1493
+ })());
1494
+ });
1495
+ it('should select first available model, set active, and not consume sticky attempt (done lower in chain)', async () => {
1496
+ vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
1497
+ selectedModel: 'model-a',
1498
+ attempts: 1,
1499
+ skipped: [],
1500
+ });
1501
+ vi.mocked(mockConfig.getModel).mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO);
1502
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-avail');
1503
+ await fromAsync(stream);
1504
+ expect(mockAvailabilityService.selectFirstAvailable).toHaveBeenCalledWith(['model-a', 'model-b']);
1505
+ expect(mockConfig.setActiveModel).toHaveBeenCalledWith('model-a');
1506
+ expect(mockAvailabilityService.consumeStickyAttempt).not.toHaveBeenCalled();
1507
+ // Ensure turn.run used the selected model
1508
+ expect(mockTurnRunFn).toHaveBeenCalledWith(expect.objectContaining({ model: 'model-a' }), expect.anything(), expect.anything());
1509
+ });
1510
+ it('should default to last resort model if selection returns null', async () => {
1511
+ vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
1512
+ selectedModel: null,
1513
+ skipped: [],
1514
+ });
1515
+ vi.mocked(mockConfig.getModel).mockReturnValue(DEFAULT_GEMINI_MODEL_AUTO);
1516
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-avail-fallback');
1517
+ await fromAsync(stream);
1518
+ expect(mockConfig.setActiveModel).toHaveBeenCalledWith('model-b'); // Last resort
1519
+ expect(mockAvailabilityService.consumeStickyAttempt).not.toHaveBeenCalled();
1520
+ });
1521
+ it('should reset turn on new message stream', async () => {
1522
+ vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
1523
+ selectedModel: 'model-a',
1524
+ skipped: [],
1525
+ });
1526
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-reset');
1527
+ await fromAsync(stream);
1528
+ expect(mockConfig.resetTurn).toHaveBeenCalled();
1529
+ });
1530
+ it('should NOT reset turn on invalid stream retry', async () => {
1531
+ vi.mocked(mockAvailabilityService.selectFirstAvailable).mockReturnValue({
1532
+ selectedModel: 'model-a',
1533
+ skipped: [],
1534
+ });
1535
+ // We simulate a retry by calling sendMessageStream with isInvalidStreamRetry=true
1536
+ // But the public API doesn't expose that argument directly unless we use the private method or simulate the recursion.
1537
+ // We can simulate recursion by mocking turn run to return invalid stream once.
1538
+ vi.spyOn(client['config'], 'getContinueOnFailedApiCall').mockReturnValue(true);
1539
+ const mockStream1 = (async function* () {
1540
+ yield { type: GeminiEventType.InvalidStream };
1541
+ })();
1542
+ const mockStream2 = (async function* () {
1543
+ yield { type: 'content', value: 'ok' };
1544
+ })();
1545
+ mockTurnRunFn
1546
+ .mockReturnValueOnce(mockStream1)
1547
+ .mockReturnValueOnce(mockStream2);
1548
+ const stream = client.sendMessageStream([{ text: 'Hi' }], new AbortController().signal, 'prompt-retry');
1549
+ await fromAsync(stream);
1550
+ // resetTurn should be called once (for the initial call) but NOT for the recursive call
1551
+ expect(mockConfig.resetTurn).toHaveBeenCalledTimes(1);
1552
+ });
1553
+ });
1331
1554
  describe('IDE context with pending tool calls', () => {
1332
1555
  let mockChat;
1333
1556
  beforeEach(() => {
@@ -1680,9 +1903,9 @@ ${JSON.stringify({
1680
1903
  it('should call generateContent with the correct parameters', async () => {
1681
1904
  const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
1682
1905
  const abortSignal = new AbortController().signal;
1683
- await client.generateContent({ model: DEFAULT_GEMINI_FLASH_MODEL }, contents, abortSignal);
1906
+ await client.generateContent({ model: 'test-model' }, contents, abortSignal);
1684
1907
  expect(mockContentGenerator.generateContent).toHaveBeenCalledWith({
1685
- model: DEFAULT_GEMINI_FLASH_MODEL,
1908
+ model: 'test-model',
1686
1909
  config: {
1687
1910
  abortSignal,
1688
1911
  systemInstruction: getCoreSystemPrompt({}, ''),
@@ -1693,33 +1916,200 @@ ${JSON.stringify({
1693
1916
  }, 'test-session-id');
1694
1917
  });
1695
1918
  it('should use current model from config for content generation', async () => {
1696
- const initialModel = client['config'].getModel();
1919
+ const initialModel = 'test-model';
1697
1920
  const contents = [{ role: 'user', parts: [{ text: 'test' }] }];
1698
- const currentModel = initialModel + '-changed';
1699
- vi.spyOn(client['config'], 'getModel').mockReturnValueOnce(currentModel);
1700
- await client.generateContent({ model: DEFAULT_GEMINI_FLASH_MODEL }, contents, new AbortController().signal);
1701
- expect(mockContentGenerator.generateContent).not.toHaveBeenCalledWith({
1921
+ await client.generateContent({ model: initialModel }, contents, new AbortController().signal);
1922
+ expect(mockContentGenerator.generateContent).toHaveBeenCalledWith(expect.objectContaining({
1702
1923
  model: initialModel,
1703
- config: expect.any(Object),
1704
- contents,
1705
- });
1706
- expect(mockContentGenerator.generateContent).toHaveBeenCalledWith({
1707
- model: DEFAULT_GEMINI_FLASH_MODEL,
1708
- config: expect.any(Object),
1709
- contents,
1710
- }, 'test-session-id');
1711
- });
1712
- it('should use the Flash model when fallback mode is active', async () => {
1713
- const contents = [{ role: 'user', parts: [{ text: 'hello' }] }];
1714
- const abortSignal = new AbortController().signal;
1715
- const requestedModel = 'gemini-2.5-pro'; // A non-flash model
1716
- // Mock config to be in fallback mode
1717
- vi.spyOn(client['config'], 'isInFallbackMode').mockReturnValue(true);
1718
- await client.generateContent({ model: requestedModel }, contents, abortSignal);
1719
- expect(mockGenerateContentFn).toHaveBeenCalledWith(expect.objectContaining({
1720
- model: DEFAULT_GEMINI_FLASH_MODEL,
1721
1924
  }), 'test-session-id');
1722
1925
  });
1926
+ describe('Hook System', () => {
1927
+ let mockMessageBus;
1928
+ beforeEach(() => {
1929
+ vi.clearAllMocks();
1930
+ mockMessageBus = { publish: vi.fn(), subscribe: vi.fn() };
1931
+ // Force override config methods on the client instance
1932
+ client['config'].getEnableHooks = vi.fn().mockReturnValue(true);
1933
+ client['config'].getMessageBus = vi
1934
+ .fn()
1935
+ .mockReturnValue(mockMessageBus);
1936
+ });
1937
+ it('should fire BeforeAgent and AfterAgent exactly once for a simple turn', async () => {
1938
+ const promptId = 'test-prompt-hook-1';
1939
+ const request = { text: 'Hello Hooks' };
1940
+ const signal = new AbortController().signal;
1941
+ const { fireBeforeAgentHook, fireAfterAgentHook } = await import('./clientHookTriggers.js');
1942
+ mockTurnRunFn.mockImplementation(async function* () {
1943
+ this.getResponseText.mockReturnValue('Hook Response');
1944
+ yield { type: GeminiEventType.Content, value: 'Hook Response' };
1945
+ });
1946
+ const stream = client.sendMessageStream(request, signal, promptId);
1947
+ while (!(await stream.next()).done)
1948
+ ;
1949
+ expect(fireBeforeAgentHook).toHaveBeenCalledTimes(1);
1950
+ expect(fireAfterAgentHook).toHaveBeenCalledTimes(1);
1951
+ expect(fireAfterAgentHook).toHaveBeenCalledWith(expect.anything(), request, 'Hook Response');
1952
+ // Map should be empty
1953
+ expect(client['hookStateMap'].size).toBe(0);
1954
+ });
1955
+ it('should fire BeforeAgent once and AfterAgent once even with recursion', async () => {
1956
+ const { checkNextSpeaker } = await import('../utils/nextSpeakerChecker.js');
1957
+ vi.mocked(checkNextSpeaker)
1958
+ .mockResolvedValueOnce({ next_speaker: 'model', reasoning: 'more' })
1959
+ .mockResolvedValueOnce(null);
1960
+ const promptId = 'test-prompt-hook-recursive';
1961
+ const request = { text: 'Recursion Test' };
1962
+ const signal = new AbortController().signal;
1963
+ const { fireBeforeAgentHook, fireAfterAgentHook } = await import('./clientHookTriggers.js');
1964
+ let callCount = 0;
1965
+ mockTurnRunFn.mockImplementation(async function* () {
1966
+ callCount++;
1967
+ const response = `Response ${callCount}`;
1968
+ this.getResponseText.mockReturnValue(response);
1969
+ yield { type: GeminiEventType.Content, value: response };
1970
+ });
1971
+ const stream = client.sendMessageStream(request, signal, promptId);
1972
+ while (!(await stream.next()).done)
1973
+ ;
1974
+ // BeforeAgent should fire ONLY once despite multiple internal turns
1975
+ expect(fireBeforeAgentHook).toHaveBeenCalledTimes(1);
1976
+ // AfterAgent should fire ONLY when the stack unwinds
1977
+ expect(fireAfterAgentHook).toHaveBeenCalledTimes(1);
1978
+ // Check cumulative response (separated by newline)
1979
+ expect(fireAfterAgentHook).toHaveBeenCalledWith(expect.anything(), request, 'Response 1\nResponse 2');
1980
+ expect(client['hookStateMap'].size).toBe(0);
1981
+ });
1982
+ it('should use original request in AfterAgent hook even when continuation happened', async () => {
1983
+ const { checkNextSpeaker } = await import('../utils/nextSpeakerChecker.js');
1984
+ vi.mocked(checkNextSpeaker)
1985
+ .mockResolvedValueOnce({ next_speaker: 'model', reasoning: 'more' })
1986
+ .mockResolvedValueOnce(null);
1987
+ const promptId = 'test-prompt-hook-original-req';
1988
+ const request = { text: 'Do something' };
1989
+ const signal = new AbortController().signal;
1990
+ const { fireAfterAgentHook } = await import('./clientHookTriggers.js');
1991
+ mockTurnRunFn.mockImplementation(async function* () {
1992
+ this.getResponseText.mockReturnValue('Ok');
1993
+ yield { type: GeminiEventType.Content, value: 'Ok' };
1994
+ });
1995
+ const stream = client.sendMessageStream(request, signal, promptId);
1996
+ while (!(await stream.next()).done)
1997
+ ;
1998
+ expect(fireAfterAgentHook).toHaveBeenCalledWith(expect.anything(), request, // Should be 'Do something'
1999
+ expect.stringContaining('Ok'));
2000
+ });
2001
+ it('should cleanup state when prompt_id changes', async () => {
2002
+ const signal = new AbortController().signal;
2003
+ mockTurnRunFn.mockImplementation(async function* () {
2004
+ this.getResponseText.mockReturnValue('Ok');
2005
+ yield { type: GeminiEventType.Content, value: 'Ok' };
2006
+ });
2007
+ client['hookStateMap'].set('old-id', {
2008
+ hasFiredBeforeAgent: true,
2009
+ cumulativeResponse: 'Old',
2010
+ activeCalls: 0,
2011
+ originalRequest: { text: 'Old' },
2012
+ });
2013
+ client['lastPromptId'] = 'old-id';
2014
+ const stream = client.sendMessageStream({ text: 'New' }, signal, 'new-id');
2015
+ await stream.next();
2016
+ expect(client['hookStateMap'].has('old-id')).toBe(false);
2017
+ expect(client['hookStateMap'].has('new-id')).toBe(true);
2018
+ });
2019
+ it('should stop execution in BeforeAgent when hook returns continue: false', async () => {
2020
+ const { fireBeforeAgentHook } = await import('./clientHookTriggers.js');
2021
+ vi.mocked(fireBeforeAgentHook).mockResolvedValue({
2022
+ shouldStopExecution: () => true,
2023
+ getEffectiveReason: () => 'Stopped by hook',
2024
+ });
2025
+ const mockChat = {
2026
+ addHistory: vi.fn(),
2027
+ getHistory: vi.fn().mockReturnValue([]),
2028
+ getLastPromptTokenCount: vi.fn(),
2029
+ };
2030
+ client['chat'] = mockChat;
2031
+ const request = [{ text: 'Hello' }];
2032
+ const stream = client.sendMessageStream(request, new AbortController().signal, 'test-prompt');
2033
+ const events = await fromAsync(stream);
2034
+ expect(events).toContainEqual({
2035
+ type: GeminiEventType.AgentExecutionStopped,
2036
+ value: { reason: 'Stopped by hook' },
2037
+ });
2038
+ expect(mockChat.addHistory).toHaveBeenCalledWith({
2039
+ role: 'user',
2040
+ parts: request,
2041
+ });
2042
+ expect(mockTurnRunFn).not.toHaveBeenCalled();
2043
+ });
2044
+ it('should block execution in BeforeAgent when hook returns decision: block', async () => {
2045
+ const { fireBeforeAgentHook } = await import('./clientHookTriggers.js');
2046
+ vi.mocked(fireBeforeAgentHook).mockResolvedValue({
2047
+ shouldStopExecution: () => false,
2048
+ isBlockingDecision: () => true,
2049
+ getEffectiveReason: () => 'Blocked by hook',
2050
+ });
2051
+ const mockChat = {
2052
+ addHistory: vi.fn(),
2053
+ getHistory: vi.fn().mockReturnValue([]),
2054
+ getLastPromptTokenCount: vi.fn(),
2055
+ };
2056
+ client['chat'] = mockChat;
2057
+ const request = [{ text: 'Hello' }];
2058
+ const stream = client.sendMessageStream(request, new AbortController().signal, 'test-prompt');
2059
+ const events = await fromAsync(stream);
2060
+ expect(events).toContainEqual({
2061
+ type: GeminiEventType.AgentExecutionBlocked,
2062
+ value: {
2063
+ reason: 'Blocked by hook',
2064
+ },
2065
+ });
2066
+ expect(mockChat.addHistory).not.toHaveBeenCalled();
2067
+ expect(mockTurnRunFn).not.toHaveBeenCalled();
2068
+ });
2069
+ it('should stop execution in AfterAgent when hook returns continue: false', async () => {
2070
+ const { fireAfterAgentHook } = await import('./clientHookTriggers.js');
2071
+ vi.mocked(fireAfterAgentHook).mockResolvedValue({
2072
+ shouldStopExecution: () => true,
2073
+ getEffectiveReason: () => 'Stopped after agent',
2074
+ });
2075
+ mockTurnRunFn.mockImplementation(async function* () {
2076
+ yield { type: GeminiEventType.Content, value: 'Hello' };
2077
+ });
2078
+ const stream = client.sendMessageStream({ text: 'Hi' }, new AbortController().signal, 'test-prompt');
2079
+ const events = await fromAsync(stream);
2080
+ expect(events).toContainEqual({
2081
+ type: GeminiEventType.AgentExecutionStopped,
2082
+ value: { reason: 'Stopped after agent' },
2083
+ });
2084
+ // sendMessageStream should not recurse
2085
+ expect(mockTurnRunFn).toHaveBeenCalledTimes(1);
2086
+ });
2087
+ it('should yield AgentExecutionBlocked and recurse in AfterAgent when hook returns decision: block', async () => {
2088
+ const { fireAfterAgentHook } = await import('./clientHookTriggers.js');
2089
+ vi.mocked(fireAfterAgentHook)
2090
+ .mockResolvedValueOnce({
2091
+ shouldStopExecution: () => false,
2092
+ isBlockingDecision: () => true,
2093
+ getEffectiveReason: () => 'Please explain',
2094
+ })
2095
+ .mockResolvedValueOnce({
2096
+ shouldStopExecution: () => false,
2097
+ isBlockingDecision: () => false,
2098
+ });
2099
+ mockTurnRunFn.mockImplementation(async function* () {
2100
+ yield { type: GeminiEventType.Content, value: 'Response' };
2101
+ });
2102
+ const stream = client.sendMessageStream({ text: 'Hi' }, new AbortController().signal, 'test-prompt');
2103
+ const events = await fromAsync(stream);
2104
+ expect(events).toContainEqual({
2105
+ type: GeminiEventType.AgentExecutionBlocked,
2106
+ value: { reason: 'Please explain' },
2107
+ });
2108
+ // Should have called turn run twice (original + re-prompt)
2109
+ expect(mockTurnRunFn).toHaveBeenCalledTimes(2);
2110
+ expect(mockTurnRunFn).toHaveBeenNthCalledWith(2, expect.anything(), [{ text: 'Please explain' }], expect.anything());
2111
+ });
2112
+ });
1723
2113
  });
1724
2114
  });
1725
2115
  //# sourceMappingURL=client.test.js.map