@office-ai/aioncli-core 0.2.3 → 0.18.4

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 (1051) hide show
  1. package/dist/index.d.ts +16 -3
  2. package/dist/index.js +15 -3
  3. package/dist/index.js.map +1 -1
  4. package/dist/src/agents/codebase-investigator.d.ts +46 -0
  5. package/dist/src/agents/codebase-investigator.js +132 -0
  6. package/dist/src/agents/codebase-investigator.js.map +1 -0
  7. package/dist/src/agents/codebase-investigator.test.js +35 -0
  8. package/dist/src/agents/codebase-investigator.test.js.map +1 -0
  9. package/dist/src/agents/executor.d.ts +114 -0
  10. package/dist/src/agents/executor.js +779 -0
  11. package/dist/src/agents/executor.js.map +1 -0
  12. package/dist/src/agents/executor.test.js +1362 -0
  13. package/dist/src/agents/executor.test.js.map +1 -0
  14. package/dist/src/agents/invocation.d.ts +46 -0
  15. package/dist/src/agents/invocation.js +102 -0
  16. package/dist/src/agents/invocation.js.map +1 -0
  17. package/dist/src/agents/invocation.test.js +215 -0
  18. package/dist/src/agents/invocation.test.js.map +1 -0
  19. package/dist/src/agents/registry.d.ts +40 -0
  20. package/dist/src/agents/registry.js +105 -0
  21. package/dist/src/agents/registry.js.map +1 -0
  22. package/dist/src/agents/registry.test.d.ts +6 -0
  23. package/dist/src/agents/registry.test.js +160 -0
  24. package/dist/src/agents/registry.test.js.map +1 -0
  25. package/dist/src/agents/schema-utils.d.ts +39 -0
  26. package/dist/src/agents/schema-utils.js +57 -0
  27. package/dist/src/agents/schema-utils.js.map +1 -0
  28. package/dist/src/agents/schema-utils.test.d.ts +6 -0
  29. package/dist/src/agents/schema-utils.test.js +144 -0
  30. package/dist/src/agents/schema-utils.test.js.map +1 -0
  31. package/dist/src/agents/subagent-tool-wrapper.d.ts +38 -0
  32. package/dist/src/agents/subagent-tool-wrapper.js +48 -0
  33. package/dist/src/agents/subagent-tool-wrapper.js.map +1 -0
  34. package/dist/src/agents/subagent-tool-wrapper.test.d.ts +6 -0
  35. package/dist/src/agents/subagent-tool-wrapper.test.js +110 -0
  36. package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -0
  37. package/dist/src/agents/types.d.ts +146 -0
  38. package/dist/src/agents/types.js +19 -0
  39. package/dist/src/agents/types.js.map +1 -0
  40. package/dist/src/agents/utils.d.ts +15 -0
  41. package/dist/src/agents/utils.js +29 -0
  42. package/dist/src/agents/utils.js.map +1 -0
  43. package/dist/src/agents/utils.test.d.ts +6 -0
  44. package/dist/src/agents/utils.test.js +87 -0
  45. package/dist/src/agents/utils.test.js.map +1 -0
  46. package/dist/src/code_assist/codeAssist.d.ts +6 -3
  47. package/dist/src/code_assist/codeAssist.js +13 -1
  48. package/dist/src/code_assist/codeAssist.js.map +1 -1
  49. package/dist/src/code_assist/codeAssist.test.d.ts +6 -0
  50. package/dist/src/code_assist/codeAssist.test.js +99 -0
  51. package/dist/src/code_assist/codeAssist.test.js.map +1 -0
  52. package/dist/src/code_assist/converter.d.ts +5 -1
  53. package/dist/src/code_assist/converter.js +39 -5
  54. package/dist/src/code_assist/converter.js.map +1 -1
  55. package/dist/src/code_assist/converter.test.js +112 -0
  56. package/dist/src/code_assist/converter.test.js.map +1 -1
  57. package/dist/src/code_assist/experiments/client_metadata.d.ts +12 -0
  58. package/dist/src/code_assist/experiments/client_metadata.js +50 -0
  59. package/dist/src/code_assist/experiments/client_metadata.js.map +1 -0
  60. package/dist/src/code_assist/experiments/client_metadata.test.d.ts +6 -0
  61. package/dist/src/code_assist/experiments/client_metadata.test.js +99 -0
  62. package/dist/src/code_assist/experiments/client_metadata.test.js.map +1 -0
  63. package/dist/src/code_assist/experiments/experiments.d.ts +17 -0
  64. package/dist/src/code_assist/experiments/experiments.js +36 -0
  65. package/dist/src/code_assist/experiments/experiments.js.map +1 -0
  66. package/dist/src/code_assist/experiments/experiments.test.d.ts +6 -0
  67. package/dist/src/code_assist/experiments/experiments.test.js +92 -0
  68. package/dist/src/code_assist/experiments/experiments.test.js.map +1 -0
  69. package/dist/src/code_assist/experiments/flagNames.d.ts +13 -0
  70. package/dist/src/code_assist/experiments/flagNames.js +13 -0
  71. package/dist/src/code_assist/experiments/flagNames.js.map +1 -0
  72. package/dist/src/code_assist/experiments/types.d.ts +35 -0
  73. package/dist/src/code_assist/experiments/types.js +7 -0
  74. package/dist/src/code_assist/experiments/types.js.map +1 -0
  75. package/dist/src/code_assist/oauth-credential-storage.d.ts +25 -0
  76. package/dist/src/code_assist/oauth-credential-storage.js +110 -0
  77. package/dist/src/code_assist/oauth-credential-storage.js.map +1 -0
  78. package/dist/src/code_assist/oauth-credential-storage.test.d.ts +6 -0
  79. package/dist/src/code_assist/oauth-credential-storage.test.js +198 -0
  80. package/dist/src/code_assist/oauth-credential-storage.test.js.map +1 -0
  81. package/dist/src/code_assist/oauth2.d.ts +3 -3
  82. package/dist/src/code_assist/oauth2.js +252 -125
  83. package/dist/src/code_assist/oauth2.js.map +1 -1
  84. package/dist/src/code_assist/oauth2.test.js +788 -350
  85. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  86. package/dist/src/code_assist/server.d.ts +8 -6
  87. package/dist/src/code_assist/server.js +41 -10
  88. package/dist/src/code_assist/server.js.map +1 -1
  89. package/dist/src/code_assist/server.test.js +151 -28
  90. package/dist/src/code_assist/server.test.js.map +1 -1
  91. package/dist/src/code_assist/setup.d.ts +2 -2
  92. package/dist/src/code_assist/setup.js +5 -3
  93. package/dist/src/code_assist/setup.js.map +1 -1
  94. package/dist/src/code_assist/setup.test.js.map +1 -1
  95. package/dist/src/code_assist/types.d.ts +18 -3
  96. package/dist/src/code_assist/types.js.map +1 -1
  97. package/dist/src/commands/extensions.d.ts +7 -0
  98. package/dist/src/commands/extensions.js +9 -0
  99. package/dist/src/commands/extensions.js.map +1 -0
  100. package/dist/src/commands/extensions.test.d.ts +6 -0
  101. package/dist/src/commands/extensions.test.js +19 -0
  102. package/dist/src/commands/extensions.test.js.map +1 -0
  103. package/dist/src/config/config.d.ts +282 -60
  104. package/dist/src/config/config.js +677 -129
  105. package/dist/src/config/config.js.map +1 -1
  106. package/dist/src/config/config.test.js +1020 -146
  107. package/dist/src/config/config.test.js.map +1 -1
  108. package/dist/src/config/constants.d.ts +11 -0
  109. package/dist/src/config/constants.js +16 -0
  110. package/dist/src/config/constants.js.map +1 -0
  111. package/dist/src/config/defaultModelConfigs.d.ts +7 -0
  112. package/dist/src/config/defaultModelConfigs.js +185 -0
  113. package/dist/src/config/defaultModelConfigs.js.map +1 -0
  114. package/dist/src/config/models.d.ts +37 -0
  115. package/dist/src/config/models.js +72 -0
  116. package/dist/src/config/models.js.map +1 -1
  117. package/dist/src/config/models.test.d.ts +6 -0
  118. package/dist/src/config/models.test.js +116 -0
  119. package/dist/src/config/models.test.js.map +1 -0
  120. package/dist/src/config/storage.d.ts +36 -0
  121. package/dist/src/config/storage.js +115 -0
  122. package/dist/src/config/storage.js.map +1 -0
  123. package/dist/src/config/storage.test.d.ts +6 -0
  124. package/dist/src/config/storage.test.js +48 -0
  125. package/dist/src/config/storage.test.js.map +1 -0
  126. package/dist/src/confirmation-bus/index.d.ts +7 -0
  127. package/dist/src/confirmation-bus/index.js +8 -0
  128. package/dist/src/confirmation-bus/index.js.map +1 -0
  129. package/dist/src/confirmation-bus/message-bus.d.ts +18 -0
  130. package/dist/src/confirmation-bus/message-bus.js +87 -0
  131. package/dist/src/confirmation-bus/message-bus.js.map +1 -0
  132. package/dist/src/confirmation-bus/message-bus.test.d.ts +6 -0
  133. package/dist/src/confirmation-bus/message-bus.test.js +170 -0
  134. package/dist/src/confirmation-bus/message-bus.test.js.map +1 -0
  135. package/dist/src/confirmation-bus/types.d.ts +49 -0
  136. package/dist/src/confirmation-bus/types.js +16 -0
  137. package/dist/src/confirmation-bus/types.js.map +1 -0
  138. package/dist/src/core/apiKeyCredentialStorage.d.ts +17 -0
  139. package/dist/src/core/apiKeyCredentialStorage.js +64 -0
  140. package/dist/src/core/apiKeyCredentialStorage.js.map +1 -0
  141. package/dist/src/core/apiKeyCredentialStorage.test.d.ts +6 -0
  142. package/dist/src/core/apiKeyCredentialStorage.test.js +71 -0
  143. package/dist/src/core/apiKeyCredentialStorage.test.js.map +1 -0
  144. package/dist/src/core/baseLlmClient.d.ts +50 -0
  145. package/dist/src/core/baseLlmClient.js +185 -0
  146. package/dist/src/core/baseLlmClient.js.map +1 -0
  147. package/dist/src/core/baseLlmClient.test.d.ts +6 -0
  148. package/dist/src/core/baseLlmClient.test.js +311 -0
  149. package/dist/src/core/baseLlmClient.test.js.map +1 -0
  150. package/dist/src/core/client.d.ts +30 -42
  151. package/dist/src/core/client.js +178 -477
  152. package/dist/src/core/client.js.map +1 -1
  153. package/dist/src/core/client.test.js +739 -617
  154. package/dist/src/core/client.test.js.map +1 -1
  155. package/dist/src/core/contentGenerator.d.ts +7 -6
  156. package/dist/src/core/contentGenerator.js +59 -45
  157. package/dist/src/core/contentGenerator.js.map +1 -1
  158. package/dist/src/core/contentGenerator.test.js +50 -4
  159. package/dist/src/core/contentGenerator.test.js.map +1 -1
  160. package/dist/src/core/coreToolScheduler.d.ts +28 -11
  161. package/dist/src/core/coreToolScheduler.js +493 -161
  162. package/dist/src/core/coreToolScheduler.js.map +1 -1
  163. package/dist/src/core/coreToolScheduler.test.js +995 -163
  164. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  165. package/dist/src/core/fakeContentGenerator.d.ts +33 -0
  166. package/dist/src/core/fakeContentGenerator.js +58 -0
  167. package/dist/src/core/fakeContentGenerator.js.map +1 -0
  168. package/dist/src/core/fakeContentGenerator.test.d.ts +6 -0
  169. package/dist/src/core/fakeContentGenerator.test.js +127 -0
  170. package/dist/src/core/fakeContentGenerator.test.js.map +1 -0
  171. package/dist/src/core/geminiChat.d.ts +61 -55
  172. package/dist/src/core/geminiChat.js +388 -366
  173. package/dist/src/core/geminiChat.js.map +1 -1
  174. package/dist/src/core/geminiChat.test.js +1600 -355
  175. package/dist/src/core/geminiChat.test.js.map +1 -1
  176. package/dist/src/core/geminiRequest.js +1 -0
  177. package/dist/src/core/geminiRequest.js.map +1 -1
  178. package/dist/src/core/logger.d.ts +11 -4
  179. package/dist/src/core/logger.js +39 -30
  180. package/dist/src/core/logger.js.map +1 -1
  181. package/dist/src/core/logger.test.js +62 -45
  182. package/dist/src/core/logger.test.js.map +1 -1
  183. package/dist/src/core/loggingContentGenerator.d.ts +4 -3
  184. package/dist/src/core/loggingContentGenerator.js +116 -37
  185. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  186. package/dist/src/core/loggingContentGenerator.test.d.ts +6 -0
  187. package/dist/src/core/loggingContentGenerator.test.js +180 -0
  188. package/dist/src/core/loggingContentGenerator.test.js.map +1 -0
  189. package/dist/src/core/nonInteractiveToolExecutor.d.ts +4 -5
  190. package/dist/src/core/nonInteractiveToolExecutor.js +17 -120
  191. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  192. package/dist/src/core/nonInteractiveToolExecutor.test.js +168 -84
  193. package/dist/src/core/nonInteractiveToolExecutor.test.js.map +1 -1
  194. package/dist/src/core/openaiContentGenerator.d.ts +4 -3
  195. package/dist/src/core/openaiContentGenerator.js +49 -19
  196. package/dist/src/core/openaiContentGenerator.js.map +1 -1
  197. package/dist/src/core/openaiContentGenerator.test.js +1 -0
  198. package/dist/src/core/openaiContentGenerator.test.js.map +1 -1
  199. package/dist/src/core/prompts.d.ts +7 -1
  200. package/dist/src/core/prompts.js +198 -195
  201. package/dist/src/core/prompts.js.map +1 -1
  202. package/dist/src/core/prompts.test.js +172 -104
  203. package/dist/src/core/prompts.test.js.map +1 -1
  204. package/dist/src/core/recordingContentGenerator.d.ts +18 -0
  205. package/dist/src/core/recordingContentGenerator.js +77 -0
  206. package/dist/src/core/recordingContentGenerator.js.map +1 -0
  207. package/dist/src/core/recordingContentGenerator.test.d.ts +6 -0
  208. package/dist/src/core/recordingContentGenerator.test.js +101 -0
  209. package/dist/src/core/recordingContentGenerator.test.js.map +1 -0
  210. package/dist/src/core/subagent.d.ts +24 -18
  211. package/dist/src/core/subagent.js +125 -90
  212. package/dist/src/core/subagent.js.map +1 -1
  213. package/dist/src/core/subagent.test.js +59 -44
  214. package/dist/src/core/subagent.test.js.map +1 -1
  215. package/dist/src/core/tokenLimits.test.d.ts +6 -0
  216. package/dist/src/core/tokenLimits.test.js +26 -0
  217. package/dist/src/core/tokenLimits.test.js.map +1 -0
  218. package/dist/src/core/turn.d.ts +57 -13
  219. package/dist/src/core/turn.js +79 -35
  220. package/dist/src/core/turn.js.map +1 -1
  221. package/dist/src/core/turn.test.js +373 -120
  222. package/dist/src/core/turn.test.js.map +1 -1
  223. package/dist/src/fallback/handler.d.ts +7 -0
  224. package/dist/src/fallback/handler.js +181 -0
  225. package/dist/src/fallback/handler.js.map +1 -0
  226. package/dist/src/fallback/handler.test.d.ts +6 -0
  227. package/dist/src/fallback/handler.test.js +245 -0
  228. package/dist/src/fallback/handler.test.js.map +1 -0
  229. package/dist/src/fallback/types.d.ts +14 -0
  230. package/dist/src/fallback/types.js +7 -0
  231. package/dist/src/fallback/types.js.map +1 -0
  232. package/dist/src/generated/git-commit.d.ts +2 -2
  233. package/dist/src/generated/git-commit.js +2 -2
  234. package/dist/src/generated/git-commit.js.map +1 -1
  235. package/dist/src/hooks/hookAggregator.d.ts +68 -0
  236. package/dist/src/hooks/hookAggregator.js +262 -0
  237. package/dist/src/hooks/hookAggregator.js.map +1 -0
  238. package/dist/src/hooks/hookAggregator.test.d.ts +6 -0
  239. package/dist/src/hooks/hookAggregator.test.js +387 -0
  240. package/dist/src/hooks/hookAggregator.test.js.map +1 -0
  241. package/dist/src/hooks/hookPlanner.d.ts +46 -0
  242. package/dist/src/hooks/hookPlanner.js +108 -0
  243. package/dist/src/hooks/hookPlanner.js.map +1 -0
  244. package/dist/src/hooks/hookPlanner.test.d.ts +6 -0
  245. package/dist/src/hooks/hookPlanner.test.js +255 -0
  246. package/dist/src/hooks/hookPlanner.test.js.map +1 -0
  247. package/dist/src/hooks/hookRegistry.d.ts +87 -0
  248. package/dist/src/hooks/hookRegistry.js +198 -0
  249. package/dist/src/hooks/hookRegistry.js.map +1 -0
  250. package/dist/src/hooks/hookRegistry.test.d.ts +6 -0
  251. package/dist/src/hooks/hookRegistry.test.js +341 -0
  252. package/dist/src/hooks/hookRegistry.test.js.map +1 -0
  253. package/dist/src/hooks/hookRunner.d.ts +42 -0
  254. package/dist/src/hooks/hookRunner.js +272 -0
  255. package/dist/src/hooks/hookRunner.js.map +1 -0
  256. package/dist/src/hooks/hookRunner.test.d.ts +6 -0
  257. package/dist/src/hooks/hookRunner.test.js +468 -0
  258. package/dist/src/hooks/hookRunner.test.js.map +1 -0
  259. package/dist/src/hooks/hookTranslator.d.ts +113 -0
  260. package/dist/src/hooks/hookTranslator.js +232 -0
  261. package/dist/src/hooks/hookTranslator.js.map +1 -0
  262. package/dist/src/hooks/hookTranslator.test.d.ts +6 -0
  263. package/dist/src/hooks/hookTranslator.test.js +192 -0
  264. package/dist/src/hooks/hookTranslator.test.js.map +1 -0
  265. package/dist/src/hooks/types.d.ts +384 -0
  266. package/dist/src/hooks/types.js +284 -0
  267. package/dist/src/hooks/types.js.map +1 -0
  268. package/dist/src/hooks/types.test.d.ts +6 -0
  269. package/dist/src/hooks/types.test.js +313 -0
  270. package/dist/src/hooks/types.test.js.map +1 -0
  271. package/dist/src/ide/constants.d.ts +3 -0
  272. package/dist/src/ide/constants.js +3 -0
  273. package/dist/src/ide/constants.js.map +1 -1
  274. package/dist/src/ide/detect-ide.d.ts +52 -12
  275. package/dist/src/ide/detect-ide.js +51 -65
  276. package/dist/src/ide/detect-ide.js.map +1 -1
  277. package/dist/src/ide/detect-ide.test.js +95 -52
  278. package/dist/src/ide/detect-ide.test.js.map +1 -1
  279. package/dist/src/ide/ide-client.d.ts +72 -24
  280. package/dist/src/ide/ide-client.js +380 -84
  281. package/dist/src/ide/ide-client.js.map +1 -1
  282. package/dist/src/ide/ide-client.test.js +539 -35
  283. package/dist/src/ide/ide-client.test.js.map +1 -1
  284. package/dist/src/ide/ide-installer.d.ts +2 -2
  285. package/dist/src/ide/ide-installer.js +93 -35
  286. package/dist/src/ide/ide-installer.js.map +1 -1
  287. package/dist/src/ide/ide-installer.test.js +157 -26
  288. package/dist/src/ide/ide-installer.test.js.map +1 -1
  289. package/dist/src/ide/ideContext.d.ts +35 -365
  290. package/dist/src/ide/ideContext.js +60 -106
  291. package/dist/src/ide/ideContext.js.map +1 -1
  292. package/dist/src/ide/ideContext.test.js +152 -24
  293. package/dist/src/ide/ideContext.test.js.map +1 -1
  294. package/dist/src/ide/process-utils.d.ts +7 -5
  295. package/dist/src/ide/process-utils.js +108 -67
  296. package/dist/src/ide/process-utils.js.map +1 -1
  297. package/dist/src/ide/process-utils.test.d.ts +6 -0
  298. package/dist/src/ide/process-utils.test.js +151 -0
  299. package/dist/src/ide/process-utils.test.js.map +1 -0
  300. package/dist/src/ide/types.d.ts +486 -0
  301. package/dist/src/ide/types.js +138 -0
  302. package/dist/src/ide/types.js.map +1 -0
  303. package/dist/src/index.d.ts +41 -2
  304. package/dist/src/index.js +44 -2
  305. package/dist/src/index.js.map +1 -1
  306. package/dist/src/mcp/google-auth-provider.d.ts +5 -3
  307. package/dist/src/mcp/google-auth-provider.js +21 -3
  308. package/dist/src/mcp/google-auth-provider.js.map +1 -1
  309. package/dist/src/mcp/google-auth-provider.test.js +42 -9
  310. package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
  311. package/dist/src/mcp/oauth-provider.d.ts +25 -18
  312. package/dist/src/mcp/oauth-provider.js +194 -97
  313. package/dist/src/mcp/oauth-provider.js.map +1 -1
  314. package/dist/src/mcp/oauth-provider.test.js +581 -39
  315. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  316. package/dist/src/mcp/oauth-token-storage.d.ts +14 -32
  317. package/dist/src/mcp/oauth-token-storage.js +58 -28
  318. package/dist/src/mcp/oauth-token-storage.js.map +1 -1
  319. package/dist/src/mcp/oauth-token-storage.test.js +262 -162
  320. package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
  321. package/dist/src/mcp/oauth-utils.d.ts +16 -1
  322. package/dist/src/mcp/oauth-utils.js +68 -33
  323. package/dist/src/mcp/oauth-utils.js.map +1 -1
  324. package/dist/src/mcp/oauth-utils.test.js +86 -3
  325. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  326. package/dist/src/mcp/sa-impersonation-provider.d.ts +27 -0
  327. package/dist/src/mcp/sa-impersonation-provider.js +113 -0
  328. package/dist/src/mcp/sa-impersonation-provider.js.map +1 -0
  329. package/dist/src/mcp/sa-impersonation-provider.test.d.ts +6 -0
  330. package/dist/src/mcp/sa-impersonation-provider.test.js +117 -0
  331. package/dist/src/mcp/sa-impersonation-provider.test.js.map +1 -0
  332. package/dist/src/mcp/token-storage/base-token-storage.d.ts +19 -0
  333. package/dist/src/mcp/token-storage/base-token-storage.js +36 -0
  334. package/dist/src/mcp/token-storage/base-token-storage.js.map +1 -0
  335. package/dist/src/mcp/token-storage/base-token-storage.test.d.ts +6 -0
  336. package/dist/src/mcp/token-storage/base-token-storage.test.js +151 -0
  337. package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -0
  338. package/dist/src/mcp/token-storage/file-token-storage.d.ts +24 -0
  339. package/dist/src/mcp/token-storage/file-token-storage.js +145 -0
  340. package/dist/src/mcp/token-storage/file-token-storage.js.map +1 -0
  341. package/dist/src/mcp/token-storage/file-token-storage.test.d.ts +6 -0
  342. package/dist/src/mcp/token-storage/file-token-storage.test.js +238 -0
  343. package/dist/src/mcp/token-storage/file-token-storage.test.js.map +1 -0
  344. package/dist/src/mcp/token-storage/hybrid-token-storage.d.ts +23 -0
  345. package/dist/src/mcp/token-storage/hybrid-token-storage.js +78 -0
  346. package/dist/src/mcp/token-storage/hybrid-token-storage.js.map +1 -0
  347. package/dist/src/mcp/token-storage/hybrid-token-storage.test.d.ts +6 -0
  348. package/dist/src/mcp/token-storage/hybrid-token-storage.test.js +193 -0
  349. package/dist/src/mcp/token-storage/hybrid-token-storage.test.js.map +1 -0
  350. package/dist/src/mcp/token-storage/index.d.ts +11 -0
  351. package/dist/src/mcp/token-storage/index.js +12 -0
  352. package/dist/src/mcp/token-storage/index.js.map +1 -0
  353. package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +35 -0
  354. package/dist/src/mcp/token-storage/keychain-token-storage.js +246 -0
  355. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -0
  356. package/dist/src/mcp/token-storage/keychain-token-storage.test.d.ts +6 -0
  357. package/dist/src/mcp/token-storage/keychain-token-storage.test.js +305 -0
  358. package/dist/src/mcp/token-storage/keychain-token-storage.test.js.map +1 -0
  359. package/dist/src/mcp/token-storage/types.d.ts +44 -0
  360. package/dist/src/mcp/token-storage/types.js +11 -0
  361. package/dist/src/mcp/token-storage/types.js.map +1 -0
  362. package/dist/src/output/json-formatter.d.ts +11 -0
  363. package/dist/src/output/json-formatter.js +30 -0
  364. package/dist/src/output/json-formatter.js.map +1 -0
  365. package/dist/src/output/json-formatter.test.d.ts +6 -0
  366. package/dist/src/output/json-formatter.test.js +266 -0
  367. package/dist/src/output/json-formatter.test.js.map +1 -0
  368. package/dist/src/output/stream-json-formatter.d.ts +32 -0
  369. package/dist/src/output/stream-json-formatter.js +52 -0
  370. package/dist/src/output/stream-json-formatter.js.map +1 -0
  371. package/dist/src/output/stream-json-formatter.test.d.ts +6 -0
  372. package/dist/src/output/stream-json-formatter.test.js +479 -0
  373. package/dist/src/output/stream-json-formatter.test.js.map +1 -0
  374. package/dist/src/output/types.d.ts +82 -0
  375. package/dist/src/output/types.js +22 -0
  376. package/dist/src/output/types.js.map +1 -0
  377. package/dist/src/policy/config.d.ts +31 -0
  378. package/dist/src/policy/config.js +199 -0
  379. package/dist/src/policy/config.js.map +1 -0
  380. package/dist/src/policy/config.test.d.ts +6 -0
  381. package/dist/src/policy/config.test.js +538 -0
  382. package/dist/src/policy/config.test.js.map +1 -0
  383. package/dist/src/policy/index.d.ts +9 -0
  384. package/dist/src/policy/index.js +10 -0
  385. package/dist/src/policy/index.js.map +1 -0
  386. package/dist/src/policy/policies/discovered.toml +8 -0
  387. package/dist/src/policy/policies/read-only.toml +56 -0
  388. package/dist/src/policy/policies/write.toml +73 -0
  389. package/dist/src/policy/policies/yolo.toml +31 -0
  390. package/dist/src/policy/policy-engine.d.ts +39 -0
  391. package/dist/src/policy/policy-engine.js +158 -0
  392. package/dist/src/policy/policy-engine.js.map +1 -0
  393. package/dist/src/policy/policy-engine.test.d.ts +6 -0
  394. package/dist/src/policy/policy-engine.test.js +899 -0
  395. package/dist/src/policy/policy-engine.test.js.map +1 -0
  396. package/dist/src/policy/stable-stringify.d.ts +58 -0
  397. package/dist/src/policy/stable-stringify.js +122 -0
  398. package/dist/src/policy/stable-stringify.js.map +1 -0
  399. package/dist/src/policy/toml-loader.d.ts +47 -0
  400. package/dist/src/policy/toml-loader.js +411 -0
  401. package/dist/src/policy/toml-loader.js.map +1 -0
  402. package/dist/src/policy/toml-loader.test.d.ts +6 -0
  403. package/dist/src/policy/toml-loader.test.js +376 -0
  404. package/dist/src/policy/toml-loader.test.js.map +1 -0
  405. package/dist/src/policy/types.d.ts +130 -0
  406. package/dist/src/policy/types.js +22 -0
  407. package/dist/src/policy/types.js.map +1 -0
  408. package/dist/src/prompts/mcp-prompts.d.ts +2 -2
  409. package/dist/src/prompts/mcp-prompts.test.d.ts +6 -0
  410. package/dist/src/prompts/mcp-prompts.test.js +39 -0
  411. package/dist/src/prompts/mcp-prompts.test.js.map +1 -0
  412. package/dist/src/prompts/prompt-registry.d.ts +1 -1
  413. package/dist/src/prompts/prompt-registry.js +2 -1
  414. package/dist/src/prompts/prompt-registry.js.map +1 -1
  415. package/dist/src/prompts/prompt-registry.test.d.ts +6 -0
  416. package/dist/src/prompts/prompt-registry.test.js +96 -0
  417. package/dist/src/prompts/prompt-registry.test.js.map +1 -0
  418. package/dist/src/routing/modelRouterService.d.ts +23 -0
  419. package/dist/src/routing/modelRouterService.js +85 -0
  420. package/dist/src/routing/modelRouterService.js.map +1 -0
  421. package/dist/src/routing/modelRouterService.test.d.ts +6 -0
  422. package/dist/src/routing/modelRouterService.test.js +160 -0
  423. package/dist/src/routing/modelRouterService.test.js.map +1 -0
  424. package/dist/src/routing/routingStrategy.d.ts +62 -0
  425. package/dist/src/routing/routingStrategy.js +7 -0
  426. package/dist/src/routing/routingStrategy.js.map +1 -0
  427. package/dist/src/routing/strategies/classifierStrategy.d.ts +12 -0
  428. package/dist/src/routing/strategies/classifierStrategy.js +166 -0
  429. package/dist/src/routing/strategies/classifierStrategy.js.map +1 -0
  430. package/dist/src/routing/strategies/classifierStrategy.test.d.ts +6 -0
  431. package/dist/src/routing/strategies/classifierStrategy.test.js +196 -0
  432. package/dist/src/routing/strategies/classifierStrategy.test.js.map +1 -0
  433. package/dist/src/routing/strategies/compositeStrategy.d.ts +26 -0
  434. package/dist/src/routing/strategies/compositeStrategy.js +68 -0
  435. package/dist/src/routing/strategies/compositeStrategy.js.map +1 -0
  436. package/dist/src/routing/strategies/compositeStrategy.test.d.ts +6 -0
  437. package/dist/src/routing/strategies/compositeStrategy.test.js +123 -0
  438. package/dist/src/routing/strategies/compositeStrategy.test.js.map +1 -0
  439. package/dist/src/routing/strategies/defaultStrategy.d.ts +12 -0
  440. package/dist/src/routing/strategies/defaultStrategy.js +20 -0
  441. package/dist/src/routing/strategies/defaultStrategy.js.map +1 -0
  442. package/dist/src/routing/strategies/defaultStrategy.test.d.ts +6 -0
  443. package/dist/src/routing/strategies/defaultStrategy.test.js +26 -0
  444. package/dist/src/routing/strategies/defaultStrategy.test.js.map +1 -0
  445. package/dist/src/routing/strategies/fallbackStrategy.d.ts +12 -0
  446. package/dist/src/routing/strategies/fallbackStrategy.js +25 -0
  447. package/dist/src/routing/strategies/fallbackStrategy.js.map +1 -0
  448. package/dist/src/routing/strategies/fallbackStrategy.test.d.ts +6 -0
  449. package/dist/src/routing/strategies/fallbackStrategy.test.js +59 -0
  450. package/dist/src/routing/strategies/fallbackStrategy.test.js.map +1 -0
  451. package/dist/src/routing/strategies/overrideStrategy.d.ts +15 -0
  452. package/dist/src/routing/strategies/overrideStrategy.js +28 -0
  453. package/dist/src/routing/strategies/overrideStrategy.js.map +1 -0
  454. package/dist/src/routing/strategies/overrideStrategy.test.d.ts +6 -0
  455. package/dist/src/routing/strategies/overrideStrategy.test.js +45 -0
  456. package/dist/src/routing/strategies/overrideStrategy.test.js.map +1 -0
  457. package/dist/src/safety/built-in.d.ts +21 -0
  458. package/dist/src/safety/built-in.js +106 -0
  459. package/dist/src/safety/built-in.js.map +1 -0
  460. package/dist/src/safety/built-in.test.d.ts +6 -0
  461. package/dist/src/safety/built-in.test.js +199 -0
  462. package/dist/src/safety/built-in.test.js.map +1 -0
  463. package/dist/src/safety/checker-runner.d.ts +48 -0
  464. package/dist/src/safety/checker-runner.js +208 -0
  465. package/dist/src/safety/checker-runner.js.map +1 -0
  466. package/dist/src/safety/checker-runner.test.d.ts +6 -0
  467. package/dist/src/safety/checker-runner.test.js +238 -0
  468. package/dist/src/safety/checker-runner.test.js.map +1 -0
  469. package/dist/src/safety/context-builder.d.ts +23 -0
  470. package/dist/src/safety/context-builder.js +47 -0
  471. package/dist/src/safety/context-builder.js.map +1 -0
  472. package/dist/src/safety/context-builder.test.d.ts +6 -0
  473. package/dist/src/safety/context-builder.test.js +49 -0
  474. package/dist/src/safety/context-builder.test.js.map +1 -0
  475. package/dist/src/safety/protocol.d.ts +88 -0
  476. package/dist/src/safety/protocol.js +15 -0
  477. package/dist/src/safety/protocol.js.map +1 -0
  478. package/dist/src/safety/registry.d.ts +26 -0
  479. package/dist/src/safety/registry.js +65 -0
  480. package/dist/src/safety/registry.js.map +1 -0
  481. package/dist/src/safety/registry.test.d.ts +6 -0
  482. package/dist/src/safety/registry.test.js +31 -0
  483. package/dist/src/safety/registry.test.js.map +1 -0
  484. package/dist/src/services/chatCompressionService.d.ts +32 -0
  485. package/dist/src/services/chatCompressionService.js +162 -0
  486. package/dist/src/services/chatCompressionService.js.map +1 -0
  487. package/dist/src/services/chatCompressionService.test.d.ts +6 -0
  488. package/dist/src/services/chatCompressionService.test.js +210 -0
  489. package/dist/src/services/chatCompressionService.test.js.map +1 -0
  490. package/dist/src/services/chatRecordingService.d.ts +10 -15
  491. package/dist/src/services/chatRecordingService.js +43 -29
  492. package/dist/src/services/chatRecordingService.js.map +1 -1
  493. package/dist/src/services/chatRecordingService.test.js +69 -25
  494. package/dist/src/services/chatRecordingService.test.js.map +1 -1
  495. package/dist/src/services/fileDiscoveryService.d.ts +8 -10
  496. package/dist/src/services/fileDiscoveryService.js +31 -53
  497. package/dist/src/services/fileDiscoveryService.js.map +1 -1
  498. package/dist/src/services/fileDiscoveryService.test.js +94 -14
  499. package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
  500. package/dist/src/services/fileSystemService.d.ts +9 -0
  501. package/dist/src/services/fileSystemService.js +12 -1
  502. package/dist/src/services/fileSystemService.js.map +1 -1
  503. package/dist/src/services/fileSystemService.test.js +1 -1
  504. package/dist/src/services/fileSystemService.test.js.map +1 -1
  505. package/dist/src/services/gitService.d.ts +3 -1
  506. package/dist/src/services/gitService.js +30 -24
  507. package/dist/src/services/gitService.js.map +1 -1
  508. package/dist/src/services/gitService.test.js +30 -37
  509. package/dist/src/services/gitService.test.js.map +1 -1
  510. package/dist/src/services/loopDetectionService.d.ts +12 -3
  511. package/dist/src/services/loopDetectionService.js +148 -55
  512. package/dist/src/services/loopDetectionService.js.map +1 -1
  513. package/dist/src/services/loopDetectionService.test.js +280 -21
  514. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  515. package/dist/src/services/modelConfig.golden.test.d.ts +6 -0
  516. package/dist/src/services/modelConfig.golden.test.js +42 -0
  517. package/dist/src/services/modelConfig.golden.test.js.map +1 -0
  518. package/dist/src/services/modelConfig.integration.test.d.ts +6 -0
  519. package/dist/src/services/modelConfig.integration.test.js +247 -0
  520. package/dist/src/services/modelConfig.integration.test.js.map +1 -0
  521. package/dist/src/services/modelConfigService.d.ts +48 -0
  522. package/dist/src/services/modelConfigService.js +151 -0
  523. package/dist/src/services/modelConfigService.js.map +1 -0
  524. package/dist/src/services/modelConfigService.test.d.ts +6 -0
  525. package/dist/src/services/modelConfigService.test.js +531 -0
  526. package/dist/src/services/modelConfigService.test.js.map +1 -0
  527. package/dist/src/services/shellExecutionService.d.ts +37 -2
  528. package/dist/src/services/shellExecutionService.js +361 -67
  529. package/dist/src/services/shellExecutionService.js.map +1 -1
  530. package/dist/src/services/shellExecutionService.test.js +333 -71
  531. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  532. package/dist/src/services/test-data/resolved-aliases.golden.json +202 -0
  533. package/dist/src/telemetry/activity-detector.d.ts +41 -0
  534. package/dist/src/telemetry/activity-detector.js +61 -0
  535. package/dist/src/telemetry/activity-detector.js.map +1 -0
  536. package/dist/src/telemetry/activity-detector.test.d.ts +6 -0
  537. package/dist/src/telemetry/activity-detector.test.js +136 -0
  538. package/dist/src/telemetry/activity-detector.test.js.map +1 -0
  539. package/dist/src/telemetry/activity-monitor.d.ts +116 -0
  540. package/dist/src/telemetry/activity-monitor.js +209 -0
  541. package/dist/src/telemetry/activity-monitor.js.map +1 -0
  542. package/dist/src/telemetry/activity-monitor.test.d.ts +6 -0
  543. package/dist/src/telemetry/activity-monitor.test.js +251 -0
  544. package/dist/src/telemetry/activity-monitor.test.js.map +1 -0
  545. package/dist/src/telemetry/activity-types.d.ts +19 -0
  546. package/dist/src/telemetry/activity-types.js +21 -0
  547. package/dist/src/telemetry/activity-types.js.map +1 -0
  548. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +53 -5
  549. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +581 -56
  550. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  551. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.d.ts +2 -0
  552. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +467 -31
  553. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  554. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +75 -4
  555. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +182 -6
  556. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  557. package/dist/src/telemetry/config.d.ts +31 -0
  558. package/dist/src/telemetry/config.js +76 -0
  559. package/dist/src/telemetry/config.js.map +1 -0
  560. package/dist/src/telemetry/config.test.d.ts +6 -0
  561. package/dist/src/telemetry/config.test.js +124 -0
  562. package/dist/src/telemetry/config.test.js.map +1 -0
  563. package/dist/src/telemetry/constants.d.ts +0 -18
  564. package/dist/src/telemetry/constants.js +0 -18
  565. package/dist/src/telemetry/constants.js.map +1 -1
  566. package/dist/src/telemetry/file-exporters.d.ts +5 -4
  567. package/dist/src/telemetry/file-exporters.js +1 -1
  568. package/dist/src/telemetry/file-exporters.js.map +1 -1
  569. package/dist/src/telemetry/gcp-exporters.d.ts +34 -0
  570. package/dist/src/telemetry/gcp-exporters.js +116 -0
  571. package/dist/src/telemetry/gcp-exporters.js.map +1 -0
  572. package/dist/src/telemetry/gcp-exporters.test.d.ts +6 -0
  573. package/dist/src/telemetry/gcp-exporters.test.js +318 -0
  574. package/dist/src/telemetry/gcp-exporters.test.js.map +1 -0
  575. package/dist/src/telemetry/high-water-mark-tracker.d.ts +43 -0
  576. package/dist/src/telemetry/high-water-mark-tracker.js +88 -0
  577. package/dist/src/telemetry/high-water-mark-tracker.js.map +1 -0
  578. package/dist/src/telemetry/high-water-mark-tracker.test.d.ts +6 -0
  579. package/dist/src/telemetry/high-water-mark-tracker.test.js +152 -0
  580. package/dist/src/telemetry/high-water-mark-tracker.test.js.map +1 -0
  581. package/dist/src/telemetry/index.d.ts +16 -2
  582. package/dist/src/telemetry/index.js +25 -2
  583. package/dist/src/telemetry/index.js.map +1 -1
  584. package/dist/src/telemetry/loggers.d.ts +25 -3
  585. package/dist/src/telemetry/loggers.js +333 -154
  586. package/dist/src/telemetry/loggers.js.map +1 -1
  587. package/dist/src/telemetry/loggers.test.circular.js +3 -4
  588. package/dist/src/telemetry/loggers.test.circular.js.map +1 -1
  589. package/dist/src/telemetry/loggers.test.js +868 -63
  590. package/dist/src/telemetry/loggers.test.js.map +1 -1
  591. package/dist/src/telemetry/memory-monitor.d.ts +149 -0
  592. package/dist/src/telemetry/memory-monitor.js +335 -0
  593. package/dist/src/telemetry/memory-monitor.js.map +1 -0
  594. package/dist/src/telemetry/memory-monitor.test.d.ts +6 -0
  595. package/dist/src/telemetry/memory-monitor.test.js +472 -0
  596. package/dist/src/telemetry/memory-monitor.test.js.map +1 -0
  597. package/dist/src/telemetry/metrics.d.ts +498 -11
  598. package/dist/src/telemetry/metrics.js +729 -84
  599. package/dist/src/telemetry/metrics.js.map +1 -1
  600. package/dist/src/telemetry/metrics.test.js +964 -101
  601. package/dist/src/telemetry/metrics.test.js.map +1 -1
  602. package/dist/src/telemetry/rate-limiter.d.ts +48 -0
  603. package/dist/src/telemetry/rate-limiter.js +100 -0
  604. package/dist/src/telemetry/rate-limiter.js.map +1 -0
  605. package/dist/src/telemetry/rate-limiter.test.d.ts +6 -0
  606. package/dist/src/telemetry/rate-limiter.test.js +207 -0
  607. package/dist/src/telemetry/rate-limiter.test.js.map +1 -0
  608. package/dist/src/telemetry/sdk.d.ts +1 -1
  609. package/dist/src/telemetry/sdk.js +23 -4
  610. package/dist/src/telemetry/sdk.js.map +1 -1
  611. package/dist/src/telemetry/sdk.test.js +108 -0
  612. package/dist/src/telemetry/sdk.test.js.map +1 -1
  613. package/dist/src/telemetry/semantic.d.ts +82 -0
  614. package/dist/src/telemetry/semantic.js +269 -0
  615. package/dist/src/telemetry/semantic.js.map +1 -0
  616. package/dist/src/telemetry/semantic.test.d.ts +6 -0
  617. package/dist/src/telemetry/semantic.test.js +387 -0
  618. package/dist/src/telemetry/semantic.test.js.map +1 -0
  619. package/dist/src/telemetry/telemetry-utils.d.ts +6 -0
  620. package/dist/src/telemetry/telemetry-utils.js +14 -0
  621. package/dist/src/telemetry/telemetry-utils.js.map +1 -0
  622. package/dist/src/telemetry/telemetry-utils.test.d.ts +6 -0
  623. package/dist/src/telemetry/telemetry-utils.test.js +41 -0
  624. package/dist/src/telemetry/telemetry-utils.test.js.map +1 -0
  625. package/dist/src/telemetry/telemetryAttributes.d.ts +8 -0
  626. package/dist/src/telemetry/telemetryAttributes.js +19 -0
  627. package/dist/src/telemetry/telemetryAttributes.js.map +1 -0
  628. package/dist/src/telemetry/trace.d.ts +46 -0
  629. package/dist/src/telemetry/trace.js +121 -0
  630. package/dist/src/telemetry/trace.js.map +1 -0
  631. package/dist/src/telemetry/types.d.ts +351 -25
  632. package/dist/src/telemetry/types.js +1071 -63
  633. package/dist/src/telemetry/types.js.map +1 -1
  634. package/dist/src/telemetry/uiTelemetry.d.ts +4 -4
  635. package/dist/src/telemetry/uiTelemetry.js +14 -15
  636. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  637. package/dist/src/telemetry/uiTelemetry.test.js +122 -96
  638. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  639. package/dist/src/test-utils/config.d.ts +3 -2
  640. package/dist/src/test-utils/config.js +1 -1
  641. package/dist/src/test-utils/config.js.map +1 -1
  642. package/dist/src/test-utils/index.d.ts +6 -0
  643. package/dist/src/test-utils/index.js +7 -0
  644. package/dist/src/test-utils/index.js.map +1 -0
  645. package/dist/src/test-utils/mock-tool.d.ts +66 -0
  646. package/dist/src/test-utils/{tools.js → mock-tool.js} +45 -29
  647. package/dist/src/test-utils/mock-tool.js.map +1 -0
  648. package/dist/src/test-utils/mockWorkspaceContext.d.ts +1 -1
  649. package/dist/src/tools/base-tool-invocation.test.d.ts +6 -0
  650. package/dist/src/tools/base-tool-invocation.test.js +85 -0
  651. package/dist/src/tools/base-tool-invocation.test.js.map +1 -0
  652. package/dist/src/tools/diffOptions.d.ts +1 -1
  653. package/dist/src/tools/diffOptions.js +21 -13
  654. package/dist/src/tools/diffOptions.js.map +1 -1
  655. package/dist/src/tools/diffOptions.test.js +58 -22
  656. package/dist/src/tools/diffOptions.test.js.map +1 -1
  657. package/dist/src/tools/edit.d.ts +10 -8
  658. package/dist/src/tools/edit.js +100 -79
  659. package/dist/src/tools/edit.js.map +1 -1
  660. package/dist/src/tools/edit.test.js +429 -163
  661. package/dist/src/tools/edit.test.js.map +1 -1
  662. package/dist/src/tools/glob.d.ts +11 -5
  663. package/dist/src/tools/glob.js +58 -42
  664. package/dist/src/tools/glob.js.map +1 -1
  665. package/dist/src/tools/glob.test.js +249 -166
  666. package/dist/src/tools/glob.test.js.map +1 -1
  667. package/dist/src/tools/grep.d.ts +7 -5
  668. package/dist/src/tools/grep.js +66 -40
  669. package/dist/src/tools/grep.js.map +1 -1
  670. package/dist/src/tools/grep.test.js +41 -15
  671. package/dist/src/tools/grep.test.js.map +1 -1
  672. package/dist/src/tools/ls.d.ts +7 -5
  673. package/dist/src/tools/ls.js +54 -68
  674. package/dist/src/tools/ls.js.map +1 -1
  675. package/dist/src/tools/ls.test.js +150 -293
  676. package/dist/src/tools/ls.test.js.map +1 -1
  677. package/dist/src/tools/mcp-client-manager.d.ts +52 -12
  678. package/dist/src/tools/mcp-client-manager.js +196 -27
  679. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  680. package/dist/src/tools/mcp-client-manager.test.js +139 -13
  681. package/dist/src/tools/mcp-client-manager.test.js.map +1 -1
  682. package/dist/src/tools/mcp-client.d.ts +28 -24
  683. package/dist/src/tools/mcp-client.js +338 -351
  684. package/dist/src/tools/mcp-client.js.map +1 -1
  685. package/dist/src/tools/mcp-client.test.js +380 -193
  686. package/dist/src/tools/mcp-client.test.js.map +1 -1
  687. package/dist/src/tools/mcp-tool.d.ts +11 -5
  688. package/dist/src/tools/mcp-tool.js +66 -17
  689. package/dist/src/tools/mcp-tool.js.map +1 -1
  690. package/dist/src/tools/mcp-tool.test.js +278 -211
  691. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  692. package/dist/src/tools/memoryTool.d.ts +10 -7
  693. package/dist/src/tools/memoryTool.js +28 -49
  694. package/dist/src/tools/memoryTool.js.map +1 -1
  695. package/dist/src/tools/memoryTool.test.js +26 -13
  696. package/dist/src/tools/memoryTool.test.js.map +1 -1
  697. package/dist/src/tools/message-bus-integration.test.d.ts +6 -0
  698. package/dist/src/tools/message-bus-integration.test.js +196 -0
  699. package/dist/src/tools/message-bus-integration.test.js.map +1 -0
  700. package/dist/src/tools/modifiable-tool.d.ts +7 -3
  701. package/dist/src/tools/modifiable-tool.js +41 -19
  702. package/dist/src/tools/modifiable-tool.js.map +1 -1
  703. package/dist/src/tools/modifiable-tool.test.js +70 -35
  704. package/dist/src/tools/modifiable-tool.test.js.map +1 -1
  705. package/dist/src/tools/read-file.d.ts +9 -7
  706. package/dist/src/tools/read-file.js +39 -60
  707. package/dist/src/tools/read-file.js.map +1 -1
  708. package/dist/src/tools/read-file.test.js +103 -36
  709. package/dist/src/tools/read-file.test.js.map +1 -1
  710. package/dist/src/tools/read-many-files.d.ts +9 -14
  711. package/dist/src/tools/read-many-files.js +71 -155
  712. package/dist/src/tools/read-many-files.js.map +1 -1
  713. package/dist/src/tools/read-many-files.test.js +98 -44
  714. package/dist/src/tools/read-many-files.test.js.map +1 -1
  715. package/dist/src/tools/ripGrep.d.ts +73 -0
  716. package/dist/src/tools/ripGrep.js +395 -0
  717. package/dist/src/tools/ripGrep.js.map +1 -0
  718. package/dist/src/tools/ripGrep.test.d.ts +6 -0
  719. package/dist/src/tools/ripGrep.test.js +1305 -0
  720. package/dist/src/tools/ripGrep.test.js.map +1 -0
  721. package/dist/src/tools/shell.d.ts +19 -6
  722. package/dist/src/tools/shell.js +92 -56
  723. package/dist/src/tools/shell.js.map +1 -1
  724. package/dist/src/tools/shell.test.js +176 -103
  725. package/dist/src/tools/shell.test.js.map +1 -1
  726. package/dist/src/tools/smart-edit.d.ts +78 -0
  727. package/dist/src/tools/smart-edit.js +717 -0
  728. package/dist/src/tools/smart-edit.js.map +1 -0
  729. package/dist/src/tools/smart-edit.test.d.ts +6 -0
  730. package/dist/src/tools/smart-edit.test.js +592 -0
  731. package/dist/src/tools/smart-edit.test.js.map +1 -0
  732. package/dist/src/tools/tool-error.d.ts +39 -1
  733. package/dist/src/tools/tool-error.js +54 -0
  734. package/dist/src/tools/tool-error.js.map +1 -1
  735. package/dist/src/tools/tool-names.d.ts +17 -0
  736. package/dist/src/tools/tool-names.js +21 -0
  737. package/dist/src/tools/tool-names.js.map +1 -0
  738. package/dist/src/tools/tool-registry.d.ts +38 -20
  739. package/dist/src/tools/tool-registry.js +134 -77
  740. package/dist/src/tools/tool-registry.js.map +1 -1
  741. package/dist/src/tools/tool-registry.test.js +218 -58
  742. package/dist/src/tools/tool-registry.test.js.map +1 -1
  743. package/dist/src/tools/tools.d.ts +49 -17
  744. package/dist/src/tools/tools.js +150 -8
  745. package/dist/src/tools/tools.js.map +1 -1
  746. package/dist/src/tools/tools.test.js +1 -2
  747. package/dist/src/tools/tools.test.js.map +1 -1
  748. package/dist/src/tools/web-fetch.d.ts +14 -5
  749. package/dist/src/tools/web-fetch.js +90 -44
  750. package/dist/src/tools/web-fetch.js.map +1 -1
  751. package/dist/src/tools/web-fetch.test.js +388 -20
  752. package/dist/src/tools/web-fetch.test.js.map +1 -1
  753. package/dist/src/tools/web-search.d.ts +8 -6
  754. package/dist/src/tools/web-search.js +40 -15
  755. package/dist/src/tools/web-search.js.map +1 -1
  756. package/dist/src/tools/web-search.test.js +75 -1
  757. package/dist/src/tools/web-search.test.js.map +1 -1
  758. package/dist/src/tools/write-file.d.ts +7 -5
  759. package/dist/src/tools/write-file.js +54 -54
  760. package/dist/src/tools/write-file.js.map +1 -1
  761. package/dist/src/tools/write-file.test.js +237 -146
  762. package/dist/src/tools/write-file.test.js.map +1 -1
  763. package/dist/src/tools/write-todos.d.ts +50 -0
  764. package/dist/src/tools/write-todos.js +193 -0
  765. package/dist/src/tools/write-todos.js.map +1 -0
  766. package/dist/src/tools/write-todos.test.d.ts +6 -0
  767. package/dist/src/tools/write-todos.test.js +89 -0
  768. package/dist/src/tools/write-todos.test.js.map +1 -0
  769. package/dist/src/utils/bfsFileSearch.d.ts +2 -2
  770. package/dist/src/utils/bfsFileSearch.js +16 -9
  771. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  772. package/dist/src/utils/bfsFileSearch.test.js +3 -3
  773. package/dist/src/utils/bfsFileSearch.test.js.map +1 -1
  774. package/dist/src/utils/channel.d.ts +19 -0
  775. package/dist/src/utils/channel.js +49 -0
  776. package/dist/src/utils/channel.js.map +1 -0
  777. package/dist/src/utils/channel.test.d.ts +6 -0
  778. package/dist/src/utils/channel.test.js +170 -0
  779. package/dist/src/utils/channel.test.js.map +1 -0
  780. package/dist/src/utils/debugLogger.d.ts +25 -0
  781. package/dist/src/utils/debugLogger.js +33 -0
  782. package/dist/src/utils/debugLogger.js.map +1 -0
  783. package/dist/src/utils/debugLogger.test.d.ts +6 -0
  784. package/dist/src/utils/debugLogger.test.js +69 -0
  785. package/dist/src/utils/debugLogger.test.js.map +1 -0
  786. package/dist/src/utils/delay.d.ts +16 -0
  787. package/dist/src/utils/delay.js +43 -0
  788. package/dist/src/utils/delay.js.map +1 -0
  789. package/dist/src/utils/delay.test.d.ts +6 -0
  790. package/dist/src/utils/delay.test.js +88 -0
  791. package/dist/src/utils/delay.test.js.map +1 -0
  792. package/dist/src/utils/editCorrector.d.ts +9 -8
  793. package/dist/src/utils/editCorrector.js +62 -34
  794. package/dist/src/utils/editCorrector.js.map +1 -1
  795. package/dist/src/utils/editCorrector.test.js +52 -87
  796. package/dist/src/utils/editCorrector.test.js.map +1 -1
  797. package/dist/src/utils/editor.d.ts +4 -2
  798. package/dist/src/utils/editor.js +56 -55
  799. package/dist/src/utils/editor.js.map +1 -1
  800. package/dist/src/utils/editor.test.js +47 -88
  801. package/dist/src/utils/editor.test.js.map +1 -1
  802. package/dist/src/utils/environmentContext.d.ts +3 -2
  803. package/dist/src/utils/environmentContext.js +20 -33
  804. package/dist/src/utils/environmentContext.js.map +1 -1
  805. package/dist/src/utils/environmentContext.test.js +6 -34
  806. package/dist/src/utils/environmentContext.test.js.map +1 -1
  807. package/dist/src/utils/errorParsing.d.ts +1 -1
  808. package/dist/src/utils/errorParsing.js +5 -33
  809. package/dist/src/utils/errorParsing.js.map +1 -1
  810. package/dist/src/utils/errorParsing.test.js +0 -88
  811. package/dist/src/utils/errorParsing.test.js.map +1 -1
  812. package/dist/src/utils/errorReporting.d.ts +1 -1
  813. package/dist/src/utils/errors.d.ts +28 -0
  814. package/dist/src/utils/errors.js +48 -0
  815. package/dist/src/utils/errors.js.map +1 -1
  816. package/dist/src/utils/events.d.ts +121 -0
  817. package/dist/src/utils/events.js +84 -0
  818. package/dist/src/utils/events.js.map +1 -0
  819. package/dist/src/utils/events.test.d.ts +6 -0
  820. package/dist/src/utils/events.test.js +212 -0
  821. package/dist/src/utils/events.test.js.map +1 -0
  822. package/dist/src/utils/extensionLoader.d.ts +86 -0
  823. package/dist/src/utils/extensionLoader.js +208 -0
  824. package/dist/src/utils/extensionLoader.js.map +1 -0
  825. package/dist/src/utils/extensionLoader.test.d.ts +6 -0
  826. package/dist/src/utils/extensionLoader.test.js +154 -0
  827. package/dist/src/utils/extensionLoader.test.js.map +1 -0
  828. package/dist/src/utils/fetch.d.ts +1 -0
  829. package/dist/src/utils/fetch.js +5 -1
  830. package/dist/src/utils/fetch.js.map +1 -1
  831. package/dist/src/utils/fileUtils.d.ts +28 -12
  832. package/dist/src/utils/fileUtils.js +204 -81
  833. package/dist/src/utils/fileUtils.js.map +1 -1
  834. package/dist/src/utils/fileUtils.test.js +426 -82
  835. package/dist/src/utils/fileUtils.test.js.map +1 -1
  836. package/dist/src/utils/filesearch/crawler.d.ts +1 -1
  837. package/dist/src/utils/filesearch/crawler.test.js +2 -2
  838. package/dist/src/utils/filesearch/crawler.test.js.map +1 -1
  839. package/dist/src/utils/filesearch/fileSearch.d.ts +1 -0
  840. package/dist/src/utils/filesearch/fileSearch.js +14 -9
  841. package/dist/src/utils/filesearch/fileSearch.js.map +1 -1
  842. package/dist/src/utils/filesearch/fileSearch.test.js +90 -0
  843. package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
  844. package/dist/src/utils/flashFallback.test.d.ts +6 -0
  845. package/dist/src/utils/flashFallback.test.js +103 -0
  846. package/dist/src/utils/flashFallback.test.js.map +1 -0
  847. package/dist/src/utils/formatters.d.ts +1 -0
  848. package/dist/src/utils/formatters.js +2 -1
  849. package/dist/src/utils/formatters.js.map +1 -1
  850. package/dist/src/utils/formatters.test.d.ts +6 -0
  851. package/dist/src/utils/formatters.test.js +26 -0
  852. package/dist/src/utils/formatters.test.js.map +1 -0
  853. package/dist/src/utils/geminiIgnoreParser.d.ts +18 -0
  854. package/dist/src/utils/geminiIgnoreParser.js +61 -0
  855. package/dist/src/utils/geminiIgnoreParser.js.map +1 -0
  856. package/dist/src/utils/geminiIgnoreParser.test.d.ts +6 -0
  857. package/dist/src/utils/geminiIgnoreParser.test.js +50 -0
  858. package/dist/src/utils/geminiIgnoreParser.test.js.map +1 -0
  859. package/dist/src/utils/generateContentResponseUtilities.d.ts +1 -2
  860. package/dist/src/utils/generateContentResponseUtilities.js +1 -13
  861. package/dist/src/utils/generateContentResponseUtilities.js.map +1 -1
  862. package/dist/src/utils/generateContentResponseUtilities.test.js +2 -40
  863. package/dist/src/utils/generateContentResponseUtilities.test.js.map +1 -1
  864. package/dist/src/utils/getFolderStructure.d.ts +2 -2
  865. package/dist/src/utils/getFolderStructure.js +12 -20
  866. package/dist/src/utils/getFolderStructure.js.map +1 -1
  867. package/dist/src/utils/getFolderStructure.test.js +11 -10
  868. package/dist/src/utils/getFolderStructure.test.js.map +1 -1
  869. package/dist/src/utils/gitIgnoreParser.d.ts +7 -8
  870. package/dist/src/utils/gitIgnoreParser.js +145 -36
  871. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  872. package/dist/src/utils/gitIgnoreParser.test.js +127 -38
  873. package/dist/src/utils/gitIgnoreParser.test.js.map +1 -1
  874. package/dist/src/utils/gitUtils.js +2 -2
  875. package/dist/src/utils/gitUtils.js.map +1 -1
  876. package/dist/src/utils/googleErrors.d.ts +104 -0
  877. package/dist/src/utils/googleErrors.js +152 -0
  878. package/dist/src/utils/googleErrors.js.map +1 -0
  879. package/dist/src/utils/googleErrors.test.d.ts +6 -0
  880. package/dist/src/utils/googleErrors.test.js +301 -0
  881. package/dist/src/utils/googleErrors.test.js.map +1 -0
  882. package/dist/src/utils/googleQuotaErrors.d.ts +37 -0
  883. package/dist/src/utils/googleQuotaErrors.js +157 -0
  884. package/dist/src/utils/googleQuotaErrors.js.map +1 -0
  885. package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
  886. package/dist/src/utils/googleQuotaErrors.test.js +311 -0
  887. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
  888. package/dist/src/utils/httpErrors.d.ts +18 -0
  889. package/dist/src/utils/httpErrors.js +36 -0
  890. package/dist/src/utils/httpErrors.js.map +1 -0
  891. package/dist/src/utils/ignorePatterns.d.ts +103 -0
  892. package/dist/src/utils/ignorePatterns.js +220 -0
  893. package/dist/src/utils/ignorePatterns.js.map +1 -0
  894. package/dist/src/utils/ignorePatterns.test.d.ts +6 -0
  895. package/dist/src/utils/ignorePatterns.test.js +246 -0
  896. package/dist/src/utils/ignorePatterns.test.js.map +1 -0
  897. package/dist/src/utils/installationManager.d.ts +16 -0
  898. package/dist/src/utils/installationManager.js +51 -0
  899. package/dist/src/utils/installationManager.js.map +1 -0
  900. package/dist/src/utils/installationManager.test.d.ts +6 -0
  901. package/dist/src/utils/installationManager.test.js +85 -0
  902. package/dist/src/utils/installationManager.test.js.map +1 -0
  903. package/dist/src/utils/language-detection.d.ts +6 -0
  904. package/dist/src/utils/language-detection.js +101 -0
  905. package/dist/src/utils/language-detection.js.map +1 -0
  906. package/dist/src/utils/llm-edit-fixer.d.ts +26 -0
  907. package/dist/src/utils/llm-edit-fixer.js +155 -0
  908. package/dist/src/utils/llm-edit-fixer.js.map +1 -0
  909. package/dist/src/utils/llm-edit-fixer.test.d.ts +6 -0
  910. package/dist/src/utils/llm-edit-fixer.test.js +223 -0
  911. package/dist/src/utils/llm-edit-fixer.test.js.map +1 -0
  912. package/dist/src/utils/memoryDiscovery.d.ts +26 -6
  913. package/dist/src/utils/memoryDiscovery.js +239 -40
  914. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  915. package/dist/src/utils/memoryDiscovery.test.js +365 -44
  916. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  917. package/dist/src/utils/memoryImportProcessor.js +19 -25
  918. package/dist/src/utils/memoryImportProcessor.js.map +1 -1
  919. package/dist/src/utils/memoryImportProcessor.test.js +24 -155
  920. package/dist/src/utils/memoryImportProcessor.test.js.map +1 -1
  921. package/dist/src/utils/messageInspectors.d.ts +1 -1
  922. package/dist/src/utils/nextSpeakerChecker.d.ts +3 -3
  923. package/dist/src/utils/nextSpeakerChecker.js +10 -4
  924. package/dist/src/utils/nextSpeakerChecker.js.map +1 -1
  925. package/dist/src/utils/nextSpeakerChecker.test.js +85 -66
  926. package/dist/src/utils/nextSpeakerChecker.test.js.map +1 -1
  927. package/dist/src/utils/package.d.ts +12 -0
  928. package/dist/src/utils/package.js +15 -0
  929. package/dist/src/utils/package.js.map +1 -0
  930. package/dist/src/utils/partUtils.d.ts +22 -1
  931. package/dist/src/utils/partUtils.js +68 -0
  932. package/dist/src/utils/partUtils.js.map +1 -1
  933. package/dist/src/utils/partUtils.test.js +112 -1
  934. package/dist/src/utils/partUtils.test.js.map +1 -1
  935. package/dist/src/utils/pathCorrector.d.ts +25 -0
  936. package/dist/src/utils/pathCorrector.js +33 -0
  937. package/dist/src/utils/pathCorrector.js.map +1 -0
  938. package/dist/src/utils/pathCorrector.test.d.ts +6 -0
  939. package/dist/src/utils/pathCorrector.test.js +83 -0
  940. package/dist/src/utils/pathCorrector.test.js.map +1 -0
  941. package/dist/src/utils/pathReader.d.ts +17 -0
  942. package/dist/src/utils/pathReader.js +92 -0
  943. package/dist/src/utils/pathReader.js.map +1 -0
  944. package/dist/src/utils/pathReader.test.d.ts +6 -0
  945. package/dist/src/utils/pathReader.test.js +406 -0
  946. package/dist/src/utils/pathReader.test.js.map +1 -0
  947. package/dist/src/utils/paths.d.ts +1 -18
  948. package/dist/src/utils/paths.js +133 -57
  949. package/dist/src/utils/paths.js.map +1 -1
  950. package/dist/src/utils/paths.test.js +200 -68
  951. package/dist/src/utils/paths.test.js.map +1 -1
  952. package/dist/src/utils/promptIdContext.d.ts +7 -0
  953. package/dist/src/utils/promptIdContext.js +8 -0
  954. package/dist/src/utils/promptIdContext.js.map +1 -0
  955. package/dist/src/utils/quotaErrorDetection.d.ts +1 -3
  956. package/dist/src/utils/quotaErrorDetection.js +0 -46
  957. package/dist/src/utils/quotaErrorDetection.js.map +1 -1
  958. package/dist/src/utils/retry.d.ts +5 -10
  959. package/dist/src/utils/retry.js +114 -197
  960. package/dist/src/utils/retry.js.map +1 -1
  961. package/dist/src/utils/retry.test.js +196 -130
  962. package/dist/src/utils/retry.test.js.map +1 -1
  963. package/dist/src/utils/safeJsonStringify.d.ts +4 -4
  964. package/dist/src/utils/safeJsonStringify.js +31 -7
  965. package/dist/src/utils/safeJsonStringify.js.map +1 -1
  966. package/dist/src/utils/schemaValidator.js +15 -1
  967. package/dist/src/utils/schemaValidator.js.map +1 -1
  968. package/dist/src/utils/schemaValidator.test.d.ts +6 -0
  969. package/dist/src/utils/schemaValidator.test.js +113 -0
  970. package/dist/src/utils/schemaValidator.test.js.map +1 -0
  971. package/dist/src/utils/session.js +1 -1
  972. package/dist/src/utils/session.js.map +1 -1
  973. package/dist/src/utils/shell-utils.d.ts +21 -3
  974. package/dist/src/utils/shell-utils.js +427 -159
  975. package/dist/src/utils/shell-utils.js.map +1 -1
  976. package/dist/src/utils/shell-utils.test.js +250 -59
  977. package/dist/src/utils/shell-utils.test.js.map +1 -1
  978. package/dist/src/utils/stdio.d.ts +32 -0
  979. package/dist/src/utils/stdio.js +85 -0
  980. package/dist/src/utils/stdio.js.map +1 -0
  981. package/dist/src/utils/stdio.test.d.ts +6 -0
  982. package/dist/src/utils/stdio.test.js +47 -0
  983. package/dist/src/utils/stdio.test.js.map +1 -0
  984. package/dist/src/utils/summarizer.d.ts +6 -4
  985. package/dist/src/utils/summarizer.js +8 -9
  986. package/dist/src/utils/summarizer.js.map +1 -1
  987. package/dist/src/utils/summarizer.test.js +32 -12
  988. package/dist/src/utils/summarizer.test.js.map +1 -1
  989. package/dist/src/utils/systemEncoding.js +7 -6
  990. package/dist/src/utils/systemEncoding.js.map +1 -1
  991. package/dist/src/utils/systemEncoding.test.js +4 -3
  992. package/dist/src/utils/systemEncoding.test.js.map +1 -1
  993. package/dist/src/utils/terminal.d.ts +14 -0
  994. package/dist/src/utils/terminal.js +38 -0
  995. package/dist/src/utils/terminal.js.map +1 -0
  996. package/dist/src/utils/terminalSerializer.d.ts +25 -0
  997. package/dist/src/utils/terminalSerializer.js +432 -0
  998. package/dist/src/utils/terminalSerializer.js.map +1 -0
  999. package/dist/src/utils/terminalSerializer.test.d.ts +6 -0
  1000. package/dist/src/utils/terminalSerializer.test.js +176 -0
  1001. package/dist/src/utils/terminalSerializer.test.js.map +1 -0
  1002. package/dist/src/utils/textUtils.d.ts +5 -0
  1003. package/dist/src/utils/textUtils.js +14 -0
  1004. package/dist/src/utils/textUtils.js.map +1 -1
  1005. package/dist/src/utils/textUtils.test.d.ts +6 -0
  1006. package/dist/src/utils/textUtils.test.js +59 -0
  1007. package/dist/src/utils/textUtils.test.js.map +1 -0
  1008. package/dist/src/utils/thoughtUtils.d.ts +21 -0
  1009. package/dist/src/utils/thoughtUtils.js +39 -0
  1010. package/dist/src/utils/thoughtUtils.js.map +1 -0
  1011. package/dist/src/utils/thoughtUtils.test.d.ts +6 -0
  1012. package/dist/src/utils/thoughtUtils.test.js +78 -0
  1013. package/dist/src/utils/thoughtUtils.test.js.map +1 -0
  1014. package/dist/src/utils/tool-utils.d.ts +19 -0
  1015. package/dist/src/utils/tool-utils.js +67 -0
  1016. package/dist/src/utils/tool-utils.js.map +1 -0
  1017. package/dist/src/utils/tool-utils.test.d.ts +6 -0
  1018. package/dist/src/utils/tool-utils.test.js +69 -0
  1019. package/dist/src/utils/tool-utils.test.js.map +1 -0
  1020. package/dist/src/utils/userAccountManager.d.ts +20 -0
  1021. package/dist/src/utils/userAccountManager.js +115 -0
  1022. package/dist/src/utils/userAccountManager.js.map +1 -0
  1023. package/dist/src/utils/userAccountManager.test.d.ts +6 -0
  1024. package/dist/src/utils/{user_account.test.js → userAccountManager.test.js} +41 -36
  1025. package/dist/src/utils/userAccountManager.test.js.map +1 -0
  1026. package/dist/src/utils/workspaceContext.d.ts +4 -3
  1027. package/dist/src/utils/workspaceContext.js +23 -17
  1028. package/dist/src/utils/workspaceContext.js.map +1 -1
  1029. package/dist/src/utils/workspaceContext.test.js +45 -19
  1030. package/dist/src/utils/workspaceContext.test.js.map +1 -1
  1031. package/dist/tsconfig.tsbuildinfo +1 -1
  1032. package/package.json +24 -10
  1033. package/dist/src/core/modelCheck.d.ts +0 -14
  1034. package/dist/src/core/modelCheck.js +0 -62
  1035. package/dist/src/core/modelCheck.js.map +0 -1
  1036. package/dist/src/test-utils/tools.d.ts +0 -44
  1037. package/dist/src/test-utils/tools.js.map +0 -1
  1038. package/dist/src/utils/flashFallback.integration.test.js +0 -118
  1039. package/dist/src/utils/flashFallback.integration.test.js.map +0 -1
  1040. package/dist/src/utils/user_account.d.ts +0 -9
  1041. package/dist/src/utils/user_account.js +0 -109
  1042. package/dist/src/utils/user_account.js.map +0 -1
  1043. package/dist/src/utils/user_account.test.js.map +0 -1
  1044. package/dist/src/utils/user_id.d.ts +0 -11
  1045. package/dist/src/utils/user_id.js +0 -49
  1046. package/dist/src/utils/user_id.js.map +0 -1
  1047. package/dist/src/utils/user_id.test.js +0 -21
  1048. package/dist/src/utils/user_id.test.js.map +0 -1
  1049. /package/dist/src/{utils/flashFallback.integration.test.d.ts → agents/codebase-investigator.test.d.ts} +0 -0
  1050. /package/dist/src/{utils/user_account.test.d.ts → agents/executor.test.d.ts} +0 -0
  1051. /package/dist/src/{utils/user_id.test.d.ts → agents/invocation.test.d.ts} +0 -0
@@ -0,0 +1,1362 @@
1
+ /**
2
+ * @license
3
+ * Copyright 2025 Google LLC
4
+ * SPDX-License-Identifier: Apache-2.0
5
+ */
6
+ import { describe, it, expect, vi, beforeEach, afterEach, } from 'vitest';
7
+ import { debugLogger } from '../utils/debugLogger.js';
8
+ import { AgentExecutor } from './executor.js';
9
+ import { makeFakeConfig } from '../test-utils/config.js';
10
+ import { ToolRegistry } from '../tools/tool-registry.js';
11
+ import { LSTool } from '../tools/ls.js';
12
+ import { LS_TOOL_NAME, READ_FILE_TOOL_NAME } from '../tools/tool-names.js';
13
+ import { GeminiChat, StreamEventType, } from '../core/geminiChat.js';
14
+ import {} from '@google/genai';
15
+ import { MockTool } from '../test-utils/mock-tool.js';
16
+ import { getDirectoryContextString } from '../utils/environmentContext.js';
17
+ import { z } from 'zod';
18
+ import { promptIdContext } from '../utils/promptIdContext.js';
19
+ import { logAgentStart, logAgentFinish, logRecoveryAttempt, } from '../telemetry/loggers.js';
20
+ import { AgentStartEvent, AgentFinishEvent, RecoveryAttemptEvent, } from '../telemetry/types.js';
21
+ import { AgentTerminateMode } from './types.js';
22
+ import { CompressionStatus } from '../core/turn.js';
23
+ import { ChatCompressionService } from '../services/chatCompressionService.js';
24
+ import { getModelConfigAlias } from './registry.js';
25
+ const { mockSendMessageStream, mockExecuteToolCall, mockSetSystemInstruction, mockCompress, mockSetTools, } = vi.hoisted(() => ({
26
+ mockSendMessageStream: vi.fn(),
27
+ mockExecuteToolCall: vi.fn(),
28
+ mockSetSystemInstruction: vi.fn(),
29
+ mockCompress: vi.fn(),
30
+ mockSetTools: vi.fn(),
31
+ }));
32
+ let mockChatHistory = [];
33
+ const mockSetHistory = vi.fn((newHistory) => {
34
+ mockChatHistory = newHistory;
35
+ });
36
+ vi.mock('../services/chatCompressionService.js', () => ({
37
+ ChatCompressionService: vi.fn().mockImplementation(() => ({
38
+ compress: mockCompress,
39
+ })),
40
+ }));
41
+ vi.mock('../core/geminiChat.js', async (importOriginal) => {
42
+ const actual = await importOriginal();
43
+ return {
44
+ ...actual,
45
+ GeminiChat: vi.fn().mockImplementation(() => ({
46
+ sendMessageStream: mockSendMessageStream,
47
+ getHistory: vi.fn((_curated) => [...mockChatHistory]),
48
+ setHistory: mockSetHistory,
49
+ setSystemInstruction: mockSetSystemInstruction,
50
+ setTools: mockSetTools,
51
+ })),
52
+ };
53
+ });
54
+ vi.mock('../core/nonInteractiveToolExecutor.js', () => ({
55
+ executeToolCall: mockExecuteToolCall,
56
+ }));
57
+ vi.mock('../utils/environmentContext.js');
58
+ vi.mock('../telemetry/loggers.js', () => ({
59
+ logAgentStart: vi.fn(),
60
+ logAgentFinish: vi.fn(),
61
+ logRecoveryAttempt: vi.fn(),
62
+ }));
63
+ vi.mock('../utils/promptIdContext.js', async (importOriginal) => {
64
+ const actual = await importOriginal();
65
+ return {
66
+ ...actual,
67
+ promptIdContext: {
68
+ ...actual.promptIdContext,
69
+ getStore: vi.fn(),
70
+ run: vi.fn((_id, fn) => fn()),
71
+ },
72
+ };
73
+ });
74
+ const MockedGeminiChat = vi.mocked(GeminiChat);
75
+ const mockedGetDirectoryContextString = vi.mocked(getDirectoryContextString);
76
+ const mockedPromptIdContext = vi.mocked(promptIdContext);
77
+ const mockedLogAgentStart = vi.mocked(logAgentStart);
78
+ const mockedLogAgentFinish = vi.mocked(logAgentFinish);
79
+ const mockedLogRecoveryAttempt = vi.mocked(logRecoveryAttempt);
80
+ // Constants for testing
81
+ const TASK_COMPLETE_TOOL_NAME = 'complete_task';
82
+ const MOCK_TOOL_NOT_ALLOWED = new MockTool({ name: 'write_file_interactive' });
83
+ /**
84
+ * Helper to create a mock API response chunk.
85
+ * Uses conditional spread to handle readonly functionCalls property safely.
86
+ */
87
+ const createMockResponseChunk = (parts, functionCalls) => ({
88
+ candidates: [{ index: 0, content: { role: 'model', parts } }],
89
+ ...(functionCalls && functionCalls.length > 0 ? { functionCalls } : {}),
90
+ });
91
+ /**
92
+ * Helper to mock a single turn of model response in the stream.
93
+ */
94
+ const mockModelResponse = (functionCalls, thought, text) => {
95
+ const parts = [];
96
+ if (thought) {
97
+ parts.push({
98
+ text: `**${thought}** This is the reasoning part.`,
99
+ thought: true,
100
+ });
101
+ }
102
+ if (text)
103
+ parts.push({ text });
104
+ const responseChunk = createMockResponseChunk(parts, functionCalls);
105
+ mockSendMessageStream.mockImplementationOnce(async () => (async function* () {
106
+ yield {
107
+ type: StreamEventType.CHUNK,
108
+ value: responseChunk,
109
+ };
110
+ })());
111
+ };
112
+ /**
113
+ * Helper to extract the message parameters sent to sendMessageStream.
114
+ * Provides type safety for inspecting mock calls.
115
+ */
116
+ const getMockMessageParams = (callIndex) => {
117
+ const call = mockSendMessageStream.mock.calls[callIndex];
118
+ expect(call).toBeDefined();
119
+ return {
120
+ modelConfigKey: call[0],
121
+ message: call[1],
122
+ };
123
+ };
124
+ let mockConfig;
125
+ let parentToolRegistry;
126
+ /**
127
+ * Type-safe helper to create agent definitions for tests.
128
+ */
129
+ const createTestDefinition = (tools = [LS_TOOL_NAME], runConfigOverrides = {}, outputConfigMode = 'default', schema = z.string()) => {
130
+ let outputConfig;
131
+ if (outputConfigMode === 'default') {
132
+ outputConfig = {
133
+ outputName: 'finalResult',
134
+ description: 'The final result.',
135
+ schema,
136
+ };
137
+ }
138
+ return {
139
+ name: 'TestAgent',
140
+ description: 'An agent for testing.',
141
+ inputConfig: {
142
+ inputs: { goal: { type: 'string', required: true, description: 'goal' } },
143
+ },
144
+ modelConfig: { model: 'gemini-test-model', temp: 0, top_p: 1 },
145
+ runConfig: { max_time_minutes: 5, max_turns: 5, ...runConfigOverrides },
146
+ promptConfig: { systemPrompt: 'Achieve the goal: ${goal}.' },
147
+ toolConfig: { tools },
148
+ outputConfig,
149
+ };
150
+ };
151
+ describe('AgentExecutor', () => {
152
+ let activities;
153
+ let onActivity;
154
+ let abortController;
155
+ let signal;
156
+ beforeEach(async () => {
157
+ vi.resetAllMocks();
158
+ mockCompress.mockClear();
159
+ mockSetHistory.mockClear();
160
+ mockSendMessageStream.mockReset();
161
+ mockSetSystemInstruction.mockReset();
162
+ mockSetTools.mockReset();
163
+ mockExecuteToolCall.mockReset();
164
+ mockedLogAgentStart.mockReset();
165
+ mockedLogAgentFinish.mockReset();
166
+ mockedPromptIdContext.getStore.mockReset();
167
+ mockedPromptIdContext.run.mockImplementation((_id, fn) => fn());
168
+ ChatCompressionService.mockImplementation(() => ({
169
+ compress: mockCompress,
170
+ }));
171
+ mockCompress.mockResolvedValue({
172
+ newHistory: null,
173
+ info: { compressionStatus: CompressionStatus.NOOP },
174
+ });
175
+ MockedGeminiChat.mockImplementation(() => ({
176
+ sendMessageStream: mockSendMessageStream,
177
+ setSystemInstruction: mockSetSystemInstruction,
178
+ setTools: mockSetTools,
179
+ getHistory: vi.fn((_curated) => [...mockChatHistory]),
180
+ getLastPromptTokenCount: vi.fn(() => 100),
181
+ setHistory: mockSetHistory,
182
+ }));
183
+ vi.useFakeTimers();
184
+ mockConfig = makeFakeConfig();
185
+ parentToolRegistry = new ToolRegistry(mockConfig);
186
+ parentToolRegistry.registerTool(new LSTool(mockConfig));
187
+ parentToolRegistry.registerTool(new MockTool({ name: READ_FILE_TOOL_NAME }));
188
+ parentToolRegistry.registerTool(MOCK_TOOL_NOT_ALLOWED);
189
+ vi.spyOn(mockConfig, 'getToolRegistry').mockResolvedValue(parentToolRegistry);
190
+ mockedGetDirectoryContextString.mockResolvedValue('Mocked Environment Context');
191
+ activities = [];
192
+ onActivity = (activity) => activities.push(activity);
193
+ abortController = new AbortController();
194
+ signal = abortController.signal;
195
+ });
196
+ afterEach(() => {
197
+ vi.useRealTimers();
198
+ });
199
+ describe('create (Initialization and Validation)', () => {
200
+ it('should create successfully with allowed tools', async () => {
201
+ const definition = createTestDefinition([LS_TOOL_NAME]);
202
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
203
+ expect(executor).toBeInstanceOf(AgentExecutor);
204
+ });
205
+ it('SECURITY: should throw if a tool is not on the non-interactive allowlist', async () => {
206
+ const definition = createTestDefinition([MOCK_TOOL_NOT_ALLOWED.name]);
207
+ await expect(AgentExecutor.create(definition, mockConfig, onActivity)).rejects.toThrow(/not on the allow-list for non-interactive execution/);
208
+ });
209
+ it('should create an isolated ToolRegistry for the agent', async () => {
210
+ const definition = createTestDefinition([
211
+ LS_TOOL_NAME,
212
+ READ_FILE_TOOL_NAME,
213
+ ]);
214
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
215
+ const agentRegistry = executor['toolRegistry'];
216
+ expect(agentRegistry).not.toBe(parentToolRegistry);
217
+ expect(agentRegistry.getAllToolNames()).toEqual(expect.arrayContaining([LS_TOOL_NAME, READ_FILE_TOOL_NAME]));
218
+ expect(agentRegistry.getAllToolNames()).toHaveLength(2);
219
+ expect(agentRegistry.getTool(MOCK_TOOL_NOT_ALLOWED.name)).toBeUndefined();
220
+ });
221
+ it('should use parentPromptId from context to create agentId', async () => {
222
+ const parentId = 'parent-id';
223
+ mockedPromptIdContext.getStore.mockReturnValue(parentId);
224
+ const definition = createTestDefinition();
225
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
226
+ expect(executor['agentId']).toMatch(new RegExp(`^${parentId}-${definition.name}-`));
227
+ });
228
+ it('should correctly apply templates to initialMessages', async () => {
229
+ const definition = createTestDefinition();
230
+ // Override promptConfig to use initialMessages instead of systemPrompt
231
+ definition.promptConfig = {
232
+ initialMessages: [
233
+ { role: 'user', parts: [{ text: 'Goal: ${goal}' }] },
234
+ { role: 'model', parts: [{ text: 'OK, starting on ${goal}.' }] },
235
+ ],
236
+ };
237
+ const inputs = { goal: 'TestGoal' };
238
+ // Mock a response to prevent the loop from running forever
239
+ mockModelResponse([
240
+ {
241
+ name: TASK_COMPLETE_TOOL_NAME,
242
+ args: { finalResult: 'done' },
243
+ id: 'call1',
244
+ },
245
+ ]);
246
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
247
+ await executor.run(inputs, signal);
248
+ const chatConstructorArgs = MockedGeminiChat.mock.calls[0];
249
+ const startHistory = chatConstructorArgs[3]; // history is the 4th arg
250
+ expect(startHistory).toBeDefined();
251
+ expect(startHistory).toHaveLength(2);
252
+ // Perform checks on defined objects to satisfy TS
253
+ const firstPart = startHistory?.[0]?.parts?.[0];
254
+ expect(firstPart?.text).toBe('Goal: TestGoal');
255
+ const secondPart = startHistory?.[1]?.parts?.[0];
256
+ expect(secondPart?.text).toBe('OK, starting on TestGoal.');
257
+ });
258
+ });
259
+ describe('run (Execution Loop and Logic)', () => {
260
+ it('should log AgentFinish with error if run throws', async () => {
261
+ const definition = createTestDefinition();
262
+ // Make the definition invalid to cause an error during run
263
+ definition.inputConfig.inputs = {
264
+ goal: { type: 'string', required: true, description: 'goal' },
265
+ };
266
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
267
+ // Run without inputs to trigger validation error
268
+ await expect(executor.run({}, signal)).rejects.toThrow(/Missing required input parameters/);
269
+ expect(mockedLogAgentStart).toHaveBeenCalledTimes(1);
270
+ expect(mockedLogAgentFinish).toHaveBeenCalledTimes(1);
271
+ expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.objectContaining({
272
+ terminate_reason: AgentTerminateMode.ERROR,
273
+ }));
274
+ });
275
+ it('should execute successfully when model calls complete_task with output (Happy Path with Output)', async () => {
276
+ const definition = createTestDefinition();
277
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
278
+ const inputs = { goal: 'Find files' };
279
+ // Turn 1: Model calls ls
280
+ mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id: 'call1' }], 'T1: Listing');
281
+ mockExecuteToolCall.mockResolvedValueOnce({
282
+ status: 'success',
283
+ request: {
284
+ callId: 'call1',
285
+ name: LS_TOOL_NAME,
286
+ args: { path: '.' },
287
+ isClientInitiated: false,
288
+ prompt_id: 'test-prompt',
289
+ },
290
+ tool: {},
291
+ invocation: {},
292
+ response: {
293
+ callId: 'call1',
294
+ resultDisplay: 'file1.txt',
295
+ responseParts: [
296
+ {
297
+ functionResponse: {
298
+ name: LS_TOOL_NAME,
299
+ response: { result: 'file1.txt' },
300
+ id: 'call1',
301
+ },
302
+ },
303
+ ],
304
+ error: undefined,
305
+ errorType: undefined,
306
+ contentLength: undefined,
307
+ },
308
+ });
309
+ // Turn 2: Model calls complete_task with required output
310
+ mockModelResponse([
311
+ {
312
+ name: TASK_COMPLETE_TOOL_NAME,
313
+ args: { finalResult: 'Found file1.txt' },
314
+ id: 'call2',
315
+ },
316
+ ], 'T2: Done');
317
+ const output = await executor.run(inputs, signal);
318
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
319
+ const systemInstruction = MockedGeminiChat.mock.calls[0][1];
320
+ expect(systemInstruction).toContain(`MUST call the \`${TASK_COMPLETE_TOOL_NAME}\` tool`);
321
+ expect(systemInstruction).toContain('Mocked Environment Context');
322
+ expect(systemInstruction).toContain('You are running in a non-interactive mode');
323
+ expect(systemInstruction).toContain('Always use absolute paths');
324
+ const { modelConfigKey } = getMockMessageParams(0);
325
+ expect(modelConfigKey.model).toBe(getModelConfigAlias(definition));
326
+ const call = mockSetTools.mock.calls[0];
327
+ const sentTools = call[0][0].functionDeclarations;
328
+ expect(sentTools).toBeDefined();
329
+ expect(sentTools).toEqual(expect.arrayContaining([
330
+ expect.objectContaining({ name: LS_TOOL_NAME }),
331
+ expect.objectContaining({ name: TASK_COMPLETE_TOOL_NAME }),
332
+ ]));
333
+ const completeToolDef = sentTools.find((t) => t.name === TASK_COMPLETE_TOOL_NAME);
334
+ expect(completeToolDef?.parameters?.required).toContain('finalResult');
335
+ expect(output.result).toBe('Found file1.txt');
336
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
337
+ // Telemetry checks
338
+ expect(mockedLogAgentStart).toHaveBeenCalledTimes(1);
339
+ expect(mockedLogAgentStart).toHaveBeenCalledWith(mockConfig, expect.any(AgentStartEvent));
340
+ expect(mockedLogAgentFinish).toHaveBeenCalledTimes(1);
341
+ expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.any(AgentFinishEvent));
342
+ const finishEvent = mockedLogAgentFinish.mock.calls[0][1];
343
+ expect(finishEvent.terminate_reason).toBe(AgentTerminateMode.GOAL);
344
+ // Context checks
345
+ expect(mockedPromptIdContext.run).toHaveBeenCalledTimes(2); // Two turns
346
+ const agentId = executor['agentId'];
347
+ expect(mockedPromptIdContext.run).toHaveBeenNthCalledWith(1, `${agentId}#0`, expect.any(Function));
348
+ expect(mockedPromptIdContext.run).toHaveBeenNthCalledWith(2, `${agentId}#1`, expect.any(Function));
349
+ expect(activities).toEqual(expect.arrayContaining([
350
+ expect.objectContaining({
351
+ type: 'THOUGHT_CHUNK',
352
+ data: { text: 'T1: Listing' },
353
+ }),
354
+ expect.objectContaining({
355
+ type: 'TOOL_CALL_END',
356
+ data: { name: LS_TOOL_NAME, output: 'file1.txt' },
357
+ }),
358
+ expect.objectContaining({
359
+ type: 'TOOL_CALL_START',
360
+ data: {
361
+ name: TASK_COMPLETE_TOOL_NAME,
362
+ args: { finalResult: 'Found file1.txt' },
363
+ },
364
+ }),
365
+ expect.objectContaining({
366
+ type: 'TOOL_CALL_END',
367
+ data: {
368
+ name: TASK_COMPLETE_TOOL_NAME,
369
+ output: expect.stringContaining('Output submitted'),
370
+ },
371
+ }),
372
+ ]));
373
+ });
374
+ it('should execute successfully when model calls complete_task without output (Happy Path No Output)', async () => {
375
+ const definition = createTestDefinition([LS_TOOL_NAME], {}, 'none');
376
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
377
+ mockModelResponse([
378
+ { name: LS_TOOL_NAME, args: { path: '.' }, id: 'call1' },
379
+ ]);
380
+ mockExecuteToolCall.mockResolvedValueOnce({
381
+ status: 'success',
382
+ request: {
383
+ callId: 'call1',
384
+ name: LS_TOOL_NAME,
385
+ args: { path: '.' },
386
+ isClientInitiated: false,
387
+ prompt_id: 'test-prompt',
388
+ },
389
+ tool: {},
390
+ invocation: {},
391
+ response: {
392
+ callId: 'call1',
393
+ resultDisplay: 'ok',
394
+ responseParts: [
395
+ {
396
+ functionResponse: {
397
+ name: LS_TOOL_NAME,
398
+ response: {},
399
+ id: 'call1',
400
+ },
401
+ },
402
+ ],
403
+ error: undefined,
404
+ errorType: undefined,
405
+ contentLength: undefined,
406
+ },
407
+ });
408
+ mockModelResponse([{ name: TASK_COMPLETE_TOOL_NAME, args: {}, id: 'call2' }], 'Task finished.');
409
+ const output = await executor.run({ goal: 'Do work' }, signal);
410
+ const { modelConfigKey } = getMockMessageParams(0);
411
+ expect(modelConfigKey.model).toBe(getModelConfigAlias(definition));
412
+ const call = mockSetTools.mock.calls[0];
413
+ const sentTools = call[0][0].functionDeclarations;
414
+ expect(sentTools).toBeDefined();
415
+ const completeToolDef = sentTools.find((t) => t.name === TASK_COMPLETE_TOOL_NAME);
416
+ expect(completeToolDef?.parameters?.required).toEqual([]);
417
+ expect(completeToolDef?.description).toContain('signal that you have completed');
418
+ expect(output.result).toBe('Task completed successfully.');
419
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
420
+ });
421
+ it('should error immediately if the model stops tools without calling complete_task (Protocol Violation)', async () => {
422
+ const definition = createTestDefinition();
423
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
424
+ mockModelResponse([
425
+ { name: LS_TOOL_NAME, args: { path: '.' }, id: 'call1' },
426
+ ]);
427
+ mockExecuteToolCall.mockResolvedValueOnce({
428
+ status: 'success',
429
+ request: {
430
+ callId: 'call1',
431
+ name: LS_TOOL_NAME,
432
+ args: { path: '.' },
433
+ isClientInitiated: false,
434
+ prompt_id: 'test-prompt',
435
+ },
436
+ tool: {},
437
+ invocation: {},
438
+ response: {
439
+ callId: 'call1',
440
+ resultDisplay: 'ok',
441
+ responseParts: [
442
+ {
443
+ functionResponse: {
444
+ name: LS_TOOL_NAME,
445
+ response: {},
446
+ id: 'call1',
447
+ },
448
+ },
449
+ ],
450
+ error: undefined,
451
+ errorType: undefined,
452
+ contentLength: undefined,
453
+ },
454
+ });
455
+ // Turn 2 (protocol violation)
456
+ mockModelResponse([], 'I think I am done.');
457
+ // Turn 3 (recovery turn - also fails)
458
+ mockModelResponse([], 'I still give up.');
459
+ const output = await executor.run({ goal: 'Strict test' }, signal);
460
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
461
+ const expectedError = `Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'.`;
462
+ expect(output.terminate_reason).toBe(AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL);
463
+ expect(output.result).toBe(expectedError);
464
+ // Telemetry check for error
465
+ expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.objectContaining({
466
+ terminate_reason: AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL,
467
+ }));
468
+ expect(activities).toContainEqual(expect.objectContaining({
469
+ type: 'ERROR',
470
+ data: expect.objectContaining({
471
+ context: 'protocol_violation',
472
+ error: expectedError,
473
+ }),
474
+ }));
475
+ });
476
+ it('should report an error if complete_task is called with missing required arguments', async () => {
477
+ const definition = createTestDefinition();
478
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
479
+ // Turn 1: Missing arg
480
+ mockModelResponse([
481
+ {
482
+ name: TASK_COMPLETE_TOOL_NAME,
483
+ args: { wrongArg: 'oops' },
484
+ id: 'call1',
485
+ },
486
+ ]);
487
+ // Turn 2: Corrected
488
+ mockModelResponse([
489
+ {
490
+ name: TASK_COMPLETE_TOOL_NAME,
491
+ args: { finalResult: 'Corrected result' },
492
+ id: 'call2',
493
+ },
494
+ ]);
495
+ const output = await executor.run({ goal: 'Error test' }, signal);
496
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
497
+ const expectedError = "Missing required argument 'finalResult' for completion.";
498
+ expect(activities).toContainEqual(expect.objectContaining({
499
+ type: 'ERROR',
500
+ data: {
501
+ context: 'tool_call',
502
+ name: TASK_COMPLETE_TOOL_NAME,
503
+ error: expectedError,
504
+ },
505
+ }));
506
+ const turn2Params = getMockMessageParams(1);
507
+ const turn2Parts = turn2Params.message;
508
+ expect(turn2Parts).toBeDefined();
509
+ expect(turn2Parts).toHaveLength(1);
510
+ expect(turn2Parts[0]).toEqual(expect.objectContaining({
511
+ functionResponse: expect.objectContaining({
512
+ name: TASK_COMPLETE_TOOL_NAME,
513
+ response: { error: expectedError },
514
+ id: 'call1',
515
+ }),
516
+ }));
517
+ expect(output.result).toBe('Corrected result');
518
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
519
+ });
520
+ it('should handle multiple calls to complete_task in the same turn (accept first, block rest)', async () => {
521
+ const definition = createTestDefinition([], {}, 'none');
522
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
523
+ // Turn 1: Duplicate calls
524
+ mockModelResponse([
525
+ { name: TASK_COMPLETE_TOOL_NAME, args: {}, id: 'call1' },
526
+ { name: TASK_COMPLETE_TOOL_NAME, args: {}, id: 'call2' },
527
+ ]);
528
+ const output = await executor.run({ goal: 'Dup test' }, signal);
529
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(1);
530
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
531
+ const completions = activities.filter((a) => a.type === 'TOOL_CALL_END' &&
532
+ a.data['name'] === TASK_COMPLETE_TOOL_NAME);
533
+ const errors = activities.filter((a) => a.type === 'ERROR' && a.data['name'] === TASK_COMPLETE_TOOL_NAME);
534
+ expect(completions).toHaveLength(1);
535
+ expect(errors).toHaveLength(1);
536
+ expect(errors[0].data['error']).toContain('Task already marked complete in this turn');
537
+ });
538
+ it('should execute parallel tool calls and then complete', async () => {
539
+ const definition = createTestDefinition([LS_TOOL_NAME]);
540
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
541
+ const call1 = {
542
+ name: LS_TOOL_NAME,
543
+ args: { path: '/a' },
544
+ id: 'c1',
545
+ };
546
+ const call2 = {
547
+ name: LS_TOOL_NAME,
548
+ args: { path: '/b' },
549
+ id: 'c2',
550
+ };
551
+ // Turn 1: Parallel calls
552
+ mockModelResponse([call1, call2]);
553
+ // Concurrency mock
554
+ let callsStarted = 0;
555
+ let resolveCalls;
556
+ const bothStarted = new Promise((r) => {
557
+ resolveCalls = r;
558
+ });
559
+ mockExecuteToolCall.mockImplementation(async (_ctx, reqInfo) => {
560
+ callsStarted++;
561
+ if (callsStarted === 2)
562
+ resolveCalls();
563
+ await vi.advanceTimersByTimeAsync(100);
564
+ return {
565
+ status: 'success',
566
+ request: reqInfo,
567
+ tool: {},
568
+ invocation: {},
569
+ response: {
570
+ callId: reqInfo.callId,
571
+ resultDisplay: 'ok',
572
+ responseParts: [
573
+ {
574
+ functionResponse: {
575
+ name: reqInfo.name,
576
+ response: {},
577
+ id: reqInfo.callId,
578
+ },
579
+ },
580
+ ],
581
+ error: undefined,
582
+ errorType: undefined,
583
+ contentLength: undefined,
584
+ },
585
+ };
586
+ });
587
+ // Turn 2: Completion
588
+ mockModelResponse([
589
+ {
590
+ name: TASK_COMPLETE_TOOL_NAME,
591
+ args: { finalResult: 'done' },
592
+ id: 'c3',
593
+ },
594
+ ]);
595
+ const runPromise = executor.run({ goal: 'Parallel' }, signal);
596
+ await vi.advanceTimersByTimeAsync(1);
597
+ await bothStarted;
598
+ await vi.advanceTimersByTimeAsync(150);
599
+ await vi.advanceTimersByTimeAsync(1);
600
+ const output = await runPromise;
601
+ expect(mockExecuteToolCall).toHaveBeenCalledTimes(2);
602
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
603
+ // Safe access to message parts
604
+ const turn2Params = getMockMessageParams(1);
605
+ const parts = turn2Params.message;
606
+ expect(parts).toBeDefined();
607
+ expect(parts).toHaveLength(2);
608
+ expect(parts).toEqual(expect.arrayContaining([
609
+ expect.objectContaining({
610
+ functionResponse: expect.objectContaining({ id: 'c1' }),
611
+ }),
612
+ expect.objectContaining({
613
+ functionResponse: expect.objectContaining({ id: 'c2' }),
614
+ }),
615
+ ]));
616
+ });
617
+ it('SECURITY: should block unauthorized tools and provide explicit failure to model', async () => {
618
+ const definition = createTestDefinition([LS_TOOL_NAME]);
619
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
620
+ // Turn 1: Model tries to use a tool not in its config
621
+ const badCallId = 'bad_call_1';
622
+ mockModelResponse([
623
+ {
624
+ name: READ_FILE_TOOL_NAME,
625
+ args: { path: 'secret.txt' },
626
+ id: badCallId,
627
+ },
628
+ ]);
629
+ // Turn 2: Model gives up and completes
630
+ mockModelResponse([
631
+ {
632
+ name: TASK_COMPLETE_TOOL_NAME,
633
+ args: { finalResult: 'Could not read file.' },
634
+ id: 'c2',
635
+ },
636
+ ]);
637
+ const consoleWarnSpy = vi
638
+ .spyOn(debugLogger, 'warn')
639
+ .mockImplementation(() => { });
640
+ await executor.run({ goal: 'Sec test' }, signal);
641
+ // Verify external executor was not called (Security held)
642
+ expect(mockExecuteToolCall).not.toHaveBeenCalled();
643
+ // 2. Verify console warning
644
+ expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining(`[AgentExecutor] Blocked call:`));
645
+ consoleWarnSpy.mockRestore();
646
+ // Verify specific error was sent back to model
647
+ const turn2Params = getMockMessageParams(1);
648
+ const parts = turn2Params.message;
649
+ expect(parts).toBeDefined();
650
+ expect(parts[0]).toEqual(expect.objectContaining({
651
+ functionResponse: expect.objectContaining({
652
+ id: badCallId,
653
+ name: READ_FILE_TOOL_NAME,
654
+ response: {
655
+ error: expect.stringContaining('Unauthorized tool call'),
656
+ },
657
+ }),
658
+ }));
659
+ // Verify Activity Stream reported the error
660
+ expect(activities).toContainEqual(expect.objectContaining({
661
+ type: 'ERROR',
662
+ data: expect.objectContaining({
663
+ context: 'tool_call_unauthorized',
664
+ name: READ_FILE_TOOL_NAME,
665
+ }),
666
+ }));
667
+ });
668
+ });
669
+ describe('Edge Cases and Error Handling', () => {
670
+ it('should report an error if complete_task output fails schema validation', async () => {
671
+ const definition = createTestDefinition([], {}, 'default', z.string().min(10));
672
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
673
+ // Turn 1: Invalid arg (too short)
674
+ mockModelResponse([
675
+ {
676
+ name: TASK_COMPLETE_TOOL_NAME,
677
+ args: { finalResult: 'short' },
678
+ id: 'call1',
679
+ },
680
+ ]);
681
+ // Turn 2: Corrected
682
+ mockModelResponse([
683
+ {
684
+ name: TASK_COMPLETE_TOOL_NAME,
685
+ args: { finalResult: 'This is a much longer and valid result' },
686
+ id: 'call2',
687
+ },
688
+ ]);
689
+ const output = await executor.run({ goal: 'Validation test' }, signal);
690
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
691
+ const expectedError = 'Output validation failed: {"formErrors":["String must contain at least 10 character(s)"],"fieldErrors":{}}';
692
+ // Check that the error was reported in the activity stream
693
+ expect(activities).toContainEqual(expect.objectContaining({
694
+ type: 'ERROR',
695
+ data: {
696
+ context: 'tool_call',
697
+ name: TASK_COMPLETE_TOOL_NAME,
698
+ error: expect.stringContaining('Output validation failed'),
699
+ },
700
+ }));
701
+ // Check that the error was sent back to the model for the next turn
702
+ const turn2Params = getMockMessageParams(1);
703
+ const turn2Parts = turn2Params.message;
704
+ expect(turn2Parts).toEqual([
705
+ expect.objectContaining({
706
+ functionResponse: expect.objectContaining({
707
+ name: TASK_COMPLETE_TOOL_NAME,
708
+ response: { error: expectedError },
709
+ id: 'call1',
710
+ }),
711
+ }),
712
+ ]);
713
+ // Check that the agent eventually succeeded
714
+ expect(output.result).toContain('This is a much longer and valid result');
715
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
716
+ });
717
+ it('should throw and log if GeminiChat creation fails', async () => {
718
+ const definition = createTestDefinition();
719
+ const initError = new Error('Chat creation failed');
720
+ MockedGeminiChat.mockImplementationOnce(() => {
721
+ throw initError;
722
+ });
723
+ // We expect the error to be thrown during the run, not creation
724
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
725
+ await expect(executor.run({ goal: 'test' }, signal)).rejects.toThrow(`Failed to create chat object: ${initError}`);
726
+ // Ensure the error was reported via the activity callback
727
+ expect(activities).toContainEqual(expect.objectContaining({
728
+ type: 'ERROR',
729
+ data: expect.objectContaining({
730
+ error: `Error: Failed to create chat object: ${initError}`,
731
+ }),
732
+ }));
733
+ // Ensure the agent run was logged as a failure
734
+ expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.objectContaining({
735
+ terminate_reason: AgentTerminateMode.ERROR,
736
+ }));
737
+ });
738
+ it('should handle a failed tool call and feed the error to the model', async () => {
739
+ const definition = createTestDefinition([LS_TOOL_NAME]);
740
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
741
+ const toolErrorMessage = 'Tool failed spectacularly';
742
+ // Turn 1: Model calls a tool that will fail
743
+ mockModelResponse([
744
+ { name: LS_TOOL_NAME, args: { path: '/fake' }, id: 'call1' },
745
+ ]);
746
+ mockExecuteToolCall.mockResolvedValueOnce({
747
+ status: 'error',
748
+ request: {
749
+ callId: 'call1',
750
+ name: LS_TOOL_NAME,
751
+ args: { path: '/fake' },
752
+ isClientInitiated: false,
753
+ prompt_id: 'test-prompt',
754
+ },
755
+ tool: {},
756
+ invocation: {},
757
+ response: {
758
+ callId: 'call1',
759
+ resultDisplay: '',
760
+ responseParts: [
761
+ {
762
+ functionResponse: {
763
+ name: LS_TOOL_NAME,
764
+ response: { error: toolErrorMessage },
765
+ id: 'call1',
766
+ },
767
+ },
768
+ ],
769
+ error: {
770
+ type: 'ToolError',
771
+ message: toolErrorMessage,
772
+ },
773
+ errorType: 'ToolError',
774
+ contentLength: 0,
775
+ },
776
+ });
777
+ // Turn 2: Model sees the error and completes
778
+ mockModelResponse([
779
+ {
780
+ name: TASK_COMPLETE_TOOL_NAME,
781
+ args: { finalResult: 'Aborted due to tool failure.' },
782
+ id: 'call2',
783
+ },
784
+ ]);
785
+ const output = await executor.run({ goal: 'Tool failure test' }, signal);
786
+ expect(mockExecuteToolCall).toHaveBeenCalledTimes(1);
787
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
788
+ // Verify the error was reported in the activity stream
789
+ expect(activities).toContainEqual(expect.objectContaining({
790
+ type: 'ERROR',
791
+ data: {
792
+ context: 'tool_call',
793
+ name: LS_TOOL_NAME,
794
+ error: toolErrorMessage,
795
+ },
796
+ }));
797
+ // Verify the error was sent back to the model
798
+ const turn2Params = getMockMessageParams(1);
799
+ const parts = turn2Params.message;
800
+ expect(parts).toEqual([
801
+ expect.objectContaining({
802
+ functionResponse: expect.objectContaining({
803
+ name: LS_TOOL_NAME,
804
+ id: 'call1',
805
+ response: {
806
+ error: toolErrorMessage,
807
+ },
808
+ }),
809
+ }),
810
+ ]);
811
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
812
+ expect(output.result).toBe('Aborted due to tool failure.');
813
+ });
814
+ });
815
+ describe('run (Termination Conditions)', () => {
816
+ const mockWorkResponse = (id) => {
817
+ mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
818
+ mockExecuteToolCall.mockResolvedValueOnce({
819
+ status: 'success',
820
+ request: {
821
+ callId: id,
822
+ name: LS_TOOL_NAME,
823
+ args: { path: '.' },
824
+ isClientInitiated: false,
825
+ prompt_id: 'test-prompt',
826
+ },
827
+ tool: {},
828
+ invocation: {},
829
+ response: {
830
+ callId: id,
831
+ resultDisplay: 'ok',
832
+ responseParts: [
833
+ { functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
834
+ ],
835
+ error: undefined,
836
+ errorType: undefined,
837
+ contentLength: undefined,
838
+ },
839
+ });
840
+ };
841
+ it('should terminate when max_turns is reached', async () => {
842
+ const MAX = 2;
843
+ const definition = createTestDefinition([LS_TOOL_NAME], {
844
+ max_turns: MAX,
845
+ });
846
+ const executor = await AgentExecutor.create(definition, mockConfig);
847
+ mockWorkResponse('t1');
848
+ mockWorkResponse('t2');
849
+ // Recovery turn
850
+ mockModelResponse([], 'I give up');
851
+ const output = await executor.run({ goal: 'Turns test' }, signal);
852
+ expect(output.terminate_reason).toBe(AgentTerminateMode.MAX_TURNS);
853
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX + 1);
854
+ });
855
+ it('should terminate with TIMEOUT if a model call takes too long', async () => {
856
+ const definition = createTestDefinition([LS_TOOL_NAME], {
857
+ max_time_minutes: 0.5, // 30 seconds
858
+ });
859
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
860
+ // Mock a model call that is interruptible by an abort signal.
861
+ mockSendMessageStream.mockImplementationOnce(async (_key, _message, _promptId, signal) =>
862
+ // eslint-disable-next-line require-yield
863
+ (async function* () {
864
+ await new Promise((resolve) => {
865
+ // This promise resolves when aborted, ending the generator.
866
+ signal?.addEventListener('abort', () => {
867
+ resolve();
868
+ });
869
+ });
870
+ })());
871
+ // Recovery turn
872
+ mockModelResponse([], 'I give up');
873
+ const runPromise = executor.run({ goal: 'Timeout test' }, signal);
874
+ // Advance time past the timeout to trigger the abort.
875
+ await vi.advanceTimersByTimeAsync(31 * 1000);
876
+ const output = await runPromise;
877
+ expect(output.terminate_reason).toBe(AgentTerminateMode.TIMEOUT);
878
+ expect(output.result).toContain('Agent timed out after 0.5 minutes.');
879
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
880
+ // Verify activity stream reported the timeout
881
+ expect(activities).toContainEqual(expect.objectContaining({
882
+ type: 'ERROR',
883
+ data: expect.objectContaining({
884
+ context: 'timeout',
885
+ error: 'Agent timed out after 0.5 minutes.',
886
+ }),
887
+ }));
888
+ // Verify telemetry
889
+ expect(mockedLogAgentFinish).toHaveBeenCalledWith(mockConfig, expect.objectContaining({
890
+ terminate_reason: AgentTerminateMode.TIMEOUT,
891
+ }));
892
+ });
893
+ it('should terminate with TIMEOUT if a tool call takes too long', async () => {
894
+ const definition = createTestDefinition([LS_TOOL_NAME], {
895
+ max_time_minutes: 1,
896
+ });
897
+ const executor = await AgentExecutor.create(definition, mockConfig);
898
+ mockModelResponse([
899
+ { name: LS_TOOL_NAME, args: { path: '.' }, id: 't1' },
900
+ ]);
901
+ // Long running tool
902
+ mockExecuteToolCall.mockImplementationOnce(async (_ctx, reqInfo) => {
903
+ await vi.advanceTimersByTimeAsync(61 * 1000);
904
+ return {
905
+ status: 'success',
906
+ request: reqInfo,
907
+ tool: {},
908
+ invocation: {},
909
+ response: {
910
+ callId: 't1',
911
+ resultDisplay: 'ok',
912
+ responseParts: [],
913
+ error: undefined,
914
+ errorType: undefined,
915
+ contentLength: undefined,
916
+ },
917
+ };
918
+ });
919
+ // Recovery turn
920
+ mockModelResponse([], 'I give up');
921
+ const output = await executor.run({ goal: 'Timeout test' }, signal);
922
+ expect(output.terminate_reason).toBe(AgentTerminateMode.TIMEOUT);
923
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
924
+ });
925
+ it('should terminate when AbortSignal is triggered', async () => {
926
+ const definition = createTestDefinition();
927
+ const executor = await AgentExecutor.create(definition, mockConfig);
928
+ mockSendMessageStream.mockImplementationOnce(async () => (async function* () {
929
+ yield {
930
+ type: StreamEventType.CHUNK,
931
+ value: createMockResponseChunk([
932
+ { text: 'Thinking...', thought: true },
933
+ ]),
934
+ };
935
+ abortController.abort();
936
+ })());
937
+ const output = await executor.run({ goal: 'Abort test' }, signal);
938
+ expect(output.terminate_reason).toBe(AgentTerminateMode.ABORTED);
939
+ });
940
+ });
941
+ describe('run (Recovery Turns)', () => {
942
+ const mockWorkResponse = (id) => {
943
+ mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
944
+ mockExecuteToolCall.mockResolvedValueOnce({
945
+ status: 'success',
946
+ request: {
947
+ callId: id,
948
+ name: LS_TOOL_NAME,
949
+ args: { path: '.' },
950
+ isClientInitiated: false,
951
+ prompt_id: 'test-prompt',
952
+ },
953
+ tool: {},
954
+ invocation: {},
955
+ response: {
956
+ callId: id,
957
+ resultDisplay: 'ok',
958
+ responseParts: [
959
+ { functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
960
+ ],
961
+ error: undefined,
962
+ errorType: undefined,
963
+ contentLength: undefined,
964
+ },
965
+ });
966
+ };
967
+ it('should recover successfully if complete_task is called during the grace turn after MAX_TURNS', async () => {
968
+ const MAX = 1;
969
+ const definition = createTestDefinition([LS_TOOL_NAME], {
970
+ max_turns: MAX,
971
+ });
972
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
973
+ // Turn 1 (hits max_turns)
974
+ mockWorkResponse('t1');
975
+ // Recovery Turn (succeeds)
976
+ mockModelResponse([
977
+ {
978
+ name: TASK_COMPLETE_TOOL_NAME,
979
+ args: { finalResult: 'Recovered!' },
980
+ id: 't2',
981
+ },
982
+ ], 'Recovering from max turns');
983
+ const output = await executor.run({ goal: 'Turns recovery' }, signal);
984
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
985
+ expect(output.result).toBe('Recovered!');
986
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX + 1); // 1 regular + 1 recovery
987
+ expect(activities).toContainEqual(expect.objectContaining({
988
+ type: 'THOUGHT_CHUNK',
989
+ data: {
990
+ text: 'Execution limit reached (MAX_TURNS). Attempting one final recovery turn with a grace period.',
991
+ },
992
+ }));
993
+ expect(activities).toContainEqual(expect.objectContaining({
994
+ type: 'THOUGHT_CHUNK',
995
+ data: { text: 'Graceful recovery succeeded.' },
996
+ }));
997
+ });
998
+ it('should fail if complete_task is NOT called during the grace turn after MAX_TURNS', async () => {
999
+ const MAX = 1;
1000
+ const definition = createTestDefinition([LS_TOOL_NAME], {
1001
+ max_turns: MAX,
1002
+ });
1003
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1004
+ // Turn 1 (hits max_turns)
1005
+ mockWorkResponse('t1');
1006
+ // Recovery Turn (fails by calling no tools)
1007
+ mockModelResponse([], 'I give up again.');
1008
+ const output = await executor.run({ goal: 'Turns recovery fail' }, signal);
1009
+ expect(output.terminate_reason).toBe(AgentTerminateMode.MAX_TURNS);
1010
+ expect(output.result).toContain('Agent reached max turns limit');
1011
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(MAX + 1);
1012
+ expect(activities).toContainEqual(expect.objectContaining({
1013
+ type: 'ERROR',
1014
+ data: expect.objectContaining({
1015
+ context: 'recovery_turn',
1016
+ error: 'Graceful recovery attempt failed. Reason: stop',
1017
+ }),
1018
+ }));
1019
+ });
1020
+ it('should recover successfully from a protocol violation (no complete_task)', async () => {
1021
+ const definition = createTestDefinition();
1022
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1023
+ // Turn 1: Normal work
1024
+ mockWorkResponse('t1');
1025
+ // Turn 2: Protocol violation (no tool calls)
1026
+ mockModelResponse([], 'I think I am done, but I forgot the right tool.');
1027
+ // Turn 3: Recovery turn (succeeds)
1028
+ mockModelResponse([
1029
+ {
1030
+ name: TASK_COMPLETE_TOOL_NAME,
1031
+ args: { finalResult: 'Recovered from violation!' },
1032
+ id: 't3',
1033
+ },
1034
+ ], 'My mistake, here is the completion.');
1035
+ const output = await executor.run({ goal: 'Violation recovery' }, signal);
1036
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
1037
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
1038
+ expect(output.result).toBe('Recovered from violation!');
1039
+ expect(activities).toContainEqual(expect.objectContaining({
1040
+ type: 'THOUGHT_CHUNK',
1041
+ data: {
1042
+ text: 'Execution limit reached (ERROR_NO_COMPLETE_TASK_CALL). Attempting one final recovery turn with a grace period.',
1043
+ },
1044
+ }));
1045
+ });
1046
+ it('should fail recovery from a protocol violation if it violates again', async () => {
1047
+ const definition = createTestDefinition();
1048
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1049
+ // Turn 1: Normal work
1050
+ mockWorkResponse('t1');
1051
+ // Turn 2: Protocol violation (no tool calls)
1052
+ mockModelResponse([], 'I think I am done, but I forgot the right tool.');
1053
+ // Turn 3: Recovery turn (fails again)
1054
+ mockModelResponse([], 'I still dont know what to do.');
1055
+ const output = await executor.run({ goal: 'Violation recovery fail' }, signal);
1056
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
1057
+ expect(output.terminate_reason).toBe(AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL);
1058
+ expect(output.result).toContain(`Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'`);
1059
+ expect(activities).toContainEqual(expect.objectContaining({
1060
+ type: 'ERROR',
1061
+ data: expect.objectContaining({
1062
+ context: 'recovery_turn',
1063
+ error: 'Graceful recovery attempt failed. Reason: stop',
1064
+ }),
1065
+ }));
1066
+ });
1067
+ it('should recover successfully from a TIMEOUT', async () => {
1068
+ const definition = createTestDefinition([LS_TOOL_NAME], {
1069
+ max_time_minutes: 0.5, // 30 seconds
1070
+ });
1071
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1072
+ // Mock a model call that gets interrupted by the timeout.
1073
+ mockSendMessageStream.mockImplementationOnce(async (_key, _message, _promptId, signal) =>
1074
+ // eslint-disable-next-line require-yield
1075
+ (async function* () {
1076
+ // This promise never resolves, it waits for abort.
1077
+ await new Promise((resolve) => {
1078
+ signal?.addEventListener('abort', () => resolve());
1079
+ });
1080
+ })());
1081
+ // Recovery turn (succeeds)
1082
+ mockModelResponse([
1083
+ {
1084
+ name: TASK_COMPLETE_TOOL_NAME,
1085
+ args: { finalResult: 'Recovered from timeout!' },
1086
+ id: 't2',
1087
+ },
1088
+ ], 'Apologies for the delay, finishing up.');
1089
+ const runPromise = executor.run({ goal: 'Timeout recovery' }, signal);
1090
+ // Advance time past the timeout to trigger the abort and recovery.
1091
+ await vi.advanceTimersByTimeAsync(31 * 1000);
1092
+ const output = await runPromise;
1093
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2); // 1 failed + 1 recovery
1094
+ expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
1095
+ expect(output.result).toBe('Recovered from timeout!');
1096
+ expect(activities).toContainEqual(expect.objectContaining({
1097
+ type: 'THOUGHT_CHUNK',
1098
+ data: {
1099
+ text: 'Execution limit reached (TIMEOUT). Attempting one final recovery turn with a grace period.',
1100
+ },
1101
+ }));
1102
+ });
1103
+ it('should fail recovery from a TIMEOUT if the grace period also times out', async () => {
1104
+ const definition = createTestDefinition([LS_TOOL_NAME], {
1105
+ max_time_minutes: 0.5, // 30 seconds
1106
+ });
1107
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1108
+ mockSendMessageStream.mockImplementationOnce(async (_key, _message, _promptId, signal) =>
1109
+ // eslint-disable-next-line require-yield
1110
+ (async function* () {
1111
+ await new Promise((resolve) => signal?.addEventListener('abort', () => resolve()));
1112
+ })());
1113
+ // Mock the recovery call to also be long-running
1114
+ mockSendMessageStream.mockImplementationOnce(async (_key, _message, _promptId, signal) =>
1115
+ // eslint-disable-next-line require-yield
1116
+ (async function* () {
1117
+ await new Promise((resolve) => signal?.addEventListener('abort', () => resolve()));
1118
+ })());
1119
+ const runPromise = executor.run({ goal: 'Timeout recovery fail' }, signal);
1120
+ // 1. Trigger the main timeout
1121
+ await vi.advanceTimersByTimeAsync(31 * 1000);
1122
+ // 2. Let microtasks run (start recovery turn)
1123
+ await vi.advanceTimersByTimeAsync(1);
1124
+ // 3. Trigger the grace period timeout (60s)
1125
+ await vi.advanceTimersByTimeAsync(61 * 1000);
1126
+ const output = await runPromise;
1127
+ expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
1128
+ expect(output.terminate_reason).toBe(AgentTerminateMode.TIMEOUT);
1129
+ expect(output.result).toContain('Agent timed out after 0.5 minutes.');
1130
+ expect(activities).toContainEqual(expect.objectContaining({
1131
+ type: 'ERROR',
1132
+ data: expect.objectContaining({
1133
+ context: 'recovery_turn',
1134
+ error: 'Graceful recovery attempt failed. Reason: stop',
1135
+ }),
1136
+ }));
1137
+ });
1138
+ });
1139
+ describe('Telemetry and Logging', () => {
1140
+ const mockWorkResponse = (id) => {
1141
+ mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
1142
+ mockExecuteToolCall.mockResolvedValueOnce({
1143
+ status: 'success',
1144
+ request: {
1145
+ callId: id,
1146
+ name: LS_TOOL_NAME,
1147
+ args: { path: '.' },
1148
+ isClientInitiated: false,
1149
+ prompt_id: 'test-prompt',
1150
+ },
1151
+ tool: {},
1152
+ invocation: {},
1153
+ response: {
1154
+ callId: id,
1155
+ resultDisplay: 'ok',
1156
+ responseParts: [
1157
+ { functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
1158
+ ],
1159
+ error: undefined,
1160
+ errorType: undefined,
1161
+ contentLength: undefined,
1162
+ },
1163
+ });
1164
+ };
1165
+ beforeEach(() => {
1166
+ mockedLogRecoveryAttempt.mockClear();
1167
+ });
1168
+ it('should log a RecoveryAttemptEvent when a recoverable error occurs and recovery fails', async () => {
1169
+ const MAX = 1;
1170
+ const definition = createTestDefinition([LS_TOOL_NAME], {
1171
+ max_turns: MAX,
1172
+ });
1173
+ const executor = await AgentExecutor.create(definition, mockConfig);
1174
+ // Turn 1 (hits max_turns)
1175
+ mockWorkResponse('t1');
1176
+ // Recovery Turn (fails by calling no tools)
1177
+ mockModelResponse([], 'I give up again.');
1178
+ await executor.run({ goal: 'Turns recovery fail' }, signal);
1179
+ expect(mockedLogRecoveryAttempt).toHaveBeenCalledTimes(1);
1180
+ const recoveryEvent = mockedLogRecoveryAttempt.mock.calls[0][1];
1181
+ expect(recoveryEvent).toBeInstanceOf(RecoveryAttemptEvent);
1182
+ expect(recoveryEvent.agent_name).toBe(definition.name);
1183
+ expect(recoveryEvent.reason).toBe(AgentTerminateMode.MAX_TURNS);
1184
+ expect(recoveryEvent.success).toBe(false);
1185
+ expect(recoveryEvent.turn_count).toBe(1);
1186
+ expect(recoveryEvent.duration_ms).toBeGreaterThanOrEqual(0);
1187
+ });
1188
+ it('should log a successful RecoveryAttemptEvent when recovery succeeds', async () => {
1189
+ const MAX = 1;
1190
+ const definition = createTestDefinition([LS_TOOL_NAME], {
1191
+ max_turns: MAX,
1192
+ });
1193
+ const executor = await AgentExecutor.create(definition, mockConfig);
1194
+ // Turn 1 (hits max_turns)
1195
+ mockWorkResponse('t1');
1196
+ // Recovery Turn (succeeds)
1197
+ mockModelResponse([
1198
+ {
1199
+ name: TASK_COMPLETE_TOOL_NAME,
1200
+ args: { finalResult: 'Recovered!' },
1201
+ id: 't2',
1202
+ },
1203
+ ], 'Recovering from max turns');
1204
+ await executor.run({ goal: 'Turns recovery success' }, signal);
1205
+ expect(mockedLogRecoveryAttempt).toHaveBeenCalledTimes(1);
1206
+ const recoveryEvent = mockedLogRecoveryAttempt.mock.calls[0][1];
1207
+ expect(recoveryEvent).toBeInstanceOf(RecoveryAttemptEvent);
1208
+ expect(recoveryEvent.success).toBe(true);
1209
+ expect(recoveryEvent.reason).toBe(AgentTerminateMode.MAX_TURNS);
1210
+ });
1211
+ });
1212
+ describe('Chat Compression', () => {
1213
+ const mockWorkResponse = (id) => {
1214
+ mockModelResponse([{ name: LS_TOOL_NAME, args: { path: '.' }, id }]);
1215
+ mockExecuteToolCall.mockResolvedValueOnce({
1216
+ status: 'success',
1217
+ request: {
1218
+ callId: id,
1219
+ name: LS_TOOL_NAME,
1220
+ args: { path: '.' },
1221
+ isClientInitiated: false,
1222
+ prompt_id: 'test-prompt',
1223
+ },
1224
+ tool: {},
1225
+ invocation: {},
1226
+ response: {
1227
+ callId: id,
1228
+ resultDisplay: 'ok',
1229
+ responseParts: [
1230
+ { functionResponse: { name: LS_TOOL_NAME, response: {}, id } },
1231
+ ],
1232
+ error: undefined,
1233
+ errorType: undefined,
1234
+ contentLength: undefined,
1235
+ },
1236
+ });
1237
+ };
1238
+ it('should attempt to compress chat history on each turn', async () => {
1239
+ const definition = createTestDefinition();
1240
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1241
+ // Mock compression to do nothing
1242
+ mockCompress.mockResolvedValue({
1243
+ newHistory: null,
1244
+ info: { compressionStatus: CompressionStatus.NOOP },
1245
+ });
1246
+ // Turn 1
1247
+ mockWorkResponse('t1');
1248
+ // Turn 2: Complete
1249
+ mockModelResponse([
1250
+ {
1251
+ name: TASK_COMPLETE_TOOL_NAME,
1252
+ args: { finalResult: 'Done' },
1253
+ id: 'call2',
1254
+ },
1255
+ ], 'T2');
1256
+ await executor.run({ goal: 'Compress test' }, signal);
1257
+ expect(mockCompress).toHaveBeenCalledTimes(2);
1258
+ });
1259
+ it('should update chat history when compression is successful', async () => {
1260
+ const definition = createTestDefinition();
1261
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1262
+ const compressedHistory = [
1263
+ { role: 'user', parts: [{ text: 'compressed' }] },
1264
+ ];
1265
+ mockCompress.mockResolvedValue({
1266
+ newHistory: compressedHistory,
1267
+ info: { compressionStatus: CompressionStatus.COMPRESSED },
1268
+ });
1269
+ // Turn 1: Complete
1270
+ mockModelResponse([
1271
+ {
1272
+ name: TASK_COMPLETE_TOOL_NAME,
1273
+ args: { finalResult: 'Done' },
1274
+ id: 'call1',
1275
+ },
1276
+ ], 'T1');
1277
+ await executor.run({ goal: 'Compress success' }, signal);
1278
+ expect(mockCompress).toHaveBeenCalledTimes(1);
1279
+ expect(mockSetHistory).toHaveBeenCalledTimes(1);
1280
+ expect(mockSetHistory).toHaveBeenCalledWith(compressedHistory);
1281
+ });
1282
+ it('should pass hasFailedCompressionAttempt=true to compression after a failure', async () => {
1283
+ const definition = createTestDefinition();
1284
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1285
+ // First call fails
1286
+ mockCompress.mockResolvedValueOnce({
1287
+ newHistory: null,
1288
+ info: {
1289
+ compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
1290
+ },
1291
+ });
1292
+ // Second call is neutral
1293
+ mockCompress.mockResolvedValueOnce({
1294
+ newHistory: null,
1295
+ info: { compressionStatus: CompressionStatus.NOOP },
1296
+ });
1297
+ // Turn 1
1298
+ mockWorkResponse('t1');
1299
+ // Turn 2: Complete
1300
+ mockModelResponse([
1301
+ {
1302
+ name: TASK_COMPLETE_TOOL_NAME,
1303
+ args: { finalResult: 'Done' },
1304
+ id: 't2',
1305
+ },
1306
+ ], 'T2');
1307
+ await executor.run({ goal: 'Compress fail' }, signal);
1308
+ expect(mockCompress).toHaveBeenCalledTimes(2);
1309
+ // First call, hasFailedCompressionAttempt is false
1310
+ expect(mockCompress.mock.calls[0][5]).toBe(false);
1311
+ // Second call, hasFailedCompressionAttempt is true
1312
+ expect(mockCompress.mock.calls[1][5]).toBe(true);
1313
+ });
1314
+ it('should reset hasFailedCompressionAttempt flag after a successful compression', async () => {
1315
+ const definition = createTestDefinition();
1316
+ const executor = await AgentExecutor.create(definition, mockConfig, onActivity);
1317
+ const compressedHistory = [
1318
+ { role: 'user', parts: [{ text: 'compressed' }] },
1319
+ ];
1320
+ // Turn 1: Fails
1321
+ mockCompress.mockResolvedValueOnce({
1322
+ newHistory: null,
1323
+ info: {
1324
+ compressionStatus: CompressionStatus.COMPRESSION_FAILED_INFLATED_TOKEN_COUNT,
1325
+ },
1326
+ });
1327
+ // Turn 2: Succeeds
1328
+ mockCompress.mockResolvedValueOnce({
1329
+ newHistory: compressedHistory,
1330
+ info: { compressionStatus: CompressionStatus.COMPRESSED },
1331
+ });
1332
+ // Turn 3: Neutral
1333
+ mockCompress.mockResolvedValueOnce({
1334
+ newHistory: null,
1335
+ info: { compressionStatus: CompressionStatus.NOOP },
1336
+ });
1337
+ // Turn 1
1338
+ mockWorkResponse('t1');
1339
+ // Turn 2
1340
+ mockWorkResponse('t2');
1341
+ // Turn 3: Complete
1342
+ mockModelResponse([
1343
+ {
1344
+ name: TASK_COMPLETE_TOOL_NAME,
1345
+ args: { finalResult: 'Done' },
1346
+ id: 't3',
1347
+ },
1348
+ ], 'T3');
1349
+ await executor.run({ goal: 'Compress reset' }, signal);
1350
+ expect(mockCompress).toHaveBeenCalledTimes(3);
1351
+ // Call 1: hasFailed... is false
1352
+ expect(mockCompress.mock.calls[0][5]).toBe(false);
1353
+ // Call 2: hasFailed... is true
1354
+ expect(mockCompress.mock.calls[1][5]).toBe(true);
1355
+ // Call 3: hasFailed... is false again
1356
+ expect(mockCompress.mock.calls[2][5]).toBe(false);
1357
+ expect(mockSetHistory).toHaveBeenCalledTimes(1);
1358
+ expect(mockSetHistory).toHaveBeenCalledWith(compressedHistory);
1359
+ });
1360
+ });
1361
+ });
1362
+ //# sourceMappingURL=executor.test.js.map