@google/gemini-cli-core 0.37.0-preview.1 → 0.38.0-preview.0

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 (449) hide show
  1. package/README.md +58 -50
  2. package/dist/docs/changelogs/index.md +25 -0
  3. package/dist/docs/changelogs/latest.md +353 -362
  4. package/dist/docs/changelogs/preview.md +399 -366
  5. package/dist/docs/cli/plan-mode.md +1 -0
  6. package/dist/docs/cli/sandbox.md +52 -0
  7. package/dist/docs/cli/settings.md +49 -46
  8. package/dist/docs/core/remote-agents.md +14 -18
  9. package/dist/docs/core/subagents.md +63 -27
  10. package/dist/docs/get-started/authentication.md +2 -2
  11. package/dist/docs/get-started/installation.md +7 -0
  12. package/dist/docs/hooks/index.md +6 -6
  13. package/dist/docs/reference/configuration.md +43 -13
  14. package/dist/docs/reference/keyboard-shortcuts.md +14 -9
  15. package/dist/docs/reference/tools.md +4 -4
  16. package/dist/docs/release-confidence.md +0 -6
  17. package/dist/docs/releases.md +4 -0
  18. package/dist/docs/tools/mcp-server.md +3 -3
  19. package/dist/docs/tools/web-fetch.md +3 -0
  20. package/dist/src/agent/agent-session.test.js +14 -6
  21. package/dist/src/agent/agent-session.test.js.map +1 -1
  22. package/dist/src/agent/event-translator.js +2 -1
  23. package/dist/src/agent/event-translator.js.map +1 -1
  24. package/dist/src/agent/event-translator.test.js +1 -0
  25. package/dist/src/agent/event-translator.test.js.map +1 -1
  26. package/dist/src/agent/legacy-agent-session.d.ts +47 -4
  27. package/dist/src/agent/legacy-agent-session.js +38 -15
  28. package/dist/src/agent/legacy-agent-session.js.map +1 -1
  29. package/dist/src/agent/legacy-agent-session.test.js +60 -73
  30. package/dist/src/agent/legacy-agent-session.test.js.map +1 -1
  31. package/dist/src/agent/mock.js +7 -1
  32. package/dist/src/agent/mock.js.map +1 -1
  33. package/dist/src/agent/mock.test.js +1 -1
  34. package/dist/src/agent/mock.test.js.map +1 -1
  35. package/dist/src/agent/types.d.ts +34 -1
  36. package/dist/src/agents/agent-scheduler.js +6 -1
  37. package/dist/src/agents/agent-scheduler.js.map +1 -1
  38. package/dist/src/agents/agent-scheduler.test.js +38 -0
  39. package/dist/src/agents/agent-scheduler.test.js.map +1 -1
  40. package/dist/src/agents/auth-provider/api-key-provider.test.js +18 -2
  41. package/dist/src/agents/auth-provider/api-key-provider.test.js.map +1 -1
  42. package/dist/src/agents/auth-provider/value-resolver.test.js +30 -0
  43. package/dist/src/agents/auth-provider/value-resolver.test.js.map +1 -1
  44. package/dist/src/agents/browser/analyzeScreenshot.js +36 -6
  45. package/dist/src/agents/browser/analyzeScreenshot.js.map +1 -1
  46. package/dist/src/agents/browser/analyzeScreenshot.test.js +35 -3
  47. package/dist/src/agents/browser/analyzeScreenshot.test.js.map +1 -1
  48. package/dist/src/agents/browser/browserAgentFactory.d.ts +8 -0
  49. package/dist/src/agents/browser/browserAgentFactory.js +174 -118
  50. package/dist/src/agents/browser/browserAgentFactory.js.map +1 -1
  51. package/dist/src/agents/browser/browserAgentFactory.test.js +70 -1
  52. package/dist/src/agents/browser/browserAgentFactory.test.js.map +1 -1
  53. package/dist/src/agents/browser/browserAgentInvocation.js +29 -2
  54. package/dist/src/agents/browser/browserAgentInvocation.js.map +1 -1
  55. package/dist/src/agents/browser/browserAgentInvocation.test.js +51 -5
  56. package/dist/src/agents/browser/browserAgentInvocation.test.js.map +1 -1
  57. package/dist/src/agents/browser/browserManager.d.ts +38 -0
  58. package/dist/src/agents/browser/browserManager.js +117 -6
  59. package/dist/src/agents/browser/browserManager.js.map +1 -1
  60. package/dist/src/agents/browser/browserManager.test.js +156 -2
  61. package/dist/src/agents/browser/browserManager.test.js.map +1 -1
  62. package/dist/src/agents/browser/modelAvailability.d.ts +5 -0
  63. package/dist/src/agents/browser/modelAvailability.js +12 -0
  64. package/dist/src/agents/browser/modelAvailability.js.map +1 -1
  65. package/dist/src/agents/local-executor.d.ts +5 -0
  66. package/dist/src/agents/local-executor.js +98 -181
  67. package/dist/src/agents/local-executor.js.map +1 -1
  68. package/dist/src/agents/local-executor.test.js +386 -101
  69. package/dist/src/agents/local-executor.test.js.map +1 -1
  70. package/dist/src/agents/memory-manager-agent.js +1 -0
  71. package/dist/src/agents/memory-manager-agent.js.map +1 -1
  72. package/dist/src/agents/memory-manager-agent.test.js +6 -0
  73. package/dist/src/agents/memory-manager-agent.test.js.map +1 -1
  74. package/dist/src/agents/registry.js +3 -10
  75. package/dist/src/agents/registry.js.map +1 -1
  76. package/dist/src/agents/skill-extraction-agent.d.ts +24 -0
  77. package/dist/src/agents/skill-extraction-agent.js +269 -0
  78. package/dist/src/agents/skill-extraction-agent.js.map +1 -0
  79. package/dist/src/agents/types.d.ts +11 -0
  80. package/dist/src/code_assist/admin/admin_controls.js +1 -1
  81. package/dist/src/code_assist/admin/admin_controls.js.map +1 -1
  82. package/dist/src/code_assist/experiments/flagNames.d.ts +1 -0
  83. package/dist/src/code_assist/experiments/flagNames.js +1 -0
  84. package/dist/src/code_assist/experiments/flagNames.js.map +1 -1
  85. package/dist/src/code_assist/server.js +1 -1
  86. package/dist/src/code_assist/server.js.map +1 -1
  87. package/dist/src/commands/memory.js +1 -1
  88. package/dist/src/commands/memory.js.map +1 -1
  89. package/dist/src/config/config.d.ts +34 -31
  90. package/dist/src/config/config.js +101 -38
  91. package/dist/src/config/config.js.map +1 -1
  92. package/dist/src/config/config.test.js +102 -15
  93. package/dist/src/config/config.test.js.map +1 -1
  94. package/dist/src/config/extensions/integrity.js +1 -1
  95. package/dist/src/config/extensions/integrity.js.map +1 -1
  96. package/dist/src/config/projectRegistry.js +5 -3
  97. package/dist/src/config/projectRegistry.js.map +1 -1
  98. package/dist/src/config/scoped-config.d.ts +30 -0
  99. package/dist/src/config/scoped-config.js +69 -0
  100. package/dist/src/config/scoped-config.js.map +1 -0
  101. package/dist/src/config/scoped-config.test.d.ts +6 -0
  102. package/dist/src/config/scoped-config.test.js +161 -0
  103. package/dist/src/config/scoped-config.test.js.map +1 -0
  104. package/dist/src/config/storage.d.ts +2 -0
  105. package/dist/src/config/storage.js +7 -2
  106. package/dist/src/config/storage.js.map +1 -1
  107. package/dist/src/config/storage.test.js +7 -7
  108. package/dist/src/config/storage.test.js.map +1 -1
  109. package/dist/src/confirmation-bus/types.d.ts +2 -2
  110. package/dist/src/context/agentHistoryProvider.d.ts +1 -1
  111. package/dist/src/context/agentHistoryProvider.js +1 -5
  112. package/dist/src/context/agentHistoryProvider.js.map +1 -1
  113. package/dist/src/context/agentHistoryProvider.test.js +2 -39
  114. package/dist/src/context/agentHistoryProvider.test.js.map +1 -1
  115. package/dist/src/context/contextCompressionService.d.ts +30 -0
  116. package/dist/src/context/contextCompressionService.js +405 -0
  117. package/dist/src/context/contextCompressionService.js.map +1 -0
  118. package/dist/src/context/contextCompressionService.test.d.ts +1 -0
  119. package/dist/src/context/contextCompressionService.test.js +253 -0
  120. package/dist/src/context/contextCompressionService.test.js.map +1 -0
  121. package/dist/src/context/{contextManager.d.ts → memoryContextManager.d.ts} +1 -1
  122. package/dist/src/context/{contextManager.js → memoryContextManager.js} +2 -2
  123. package/dist/src/context/memoryContextManager.js.map +1 -0
  124. package/dist/src/context/{contextManager.test.js → memoryContextManager.test.js} +22 -28
  125. package/dist/src/context/memoryContextManager.test.js.map +1 -0
  126. package/dist/src/context/profiles.d.ts +7 -0
  127. package/dist/src/context/profiles.js +21 -0
  128. package/dist/src/context/profiles.js.map +1 -0
  129. package/dist/src/context/toolDistillationService.test.js +3 -0
  130. package/dist/src/context/toolDistillationService.test.js.map +1 -1
  131. package/dist/src/context/types.d.ts +36 -0
  132. package/dist/src/context/types.js.map +1 -0
  133. package/dist/src/core/baseLlmClient.js +1 -1
  134. package/dist/src/core/baseLlmClient.js.map +1 -1
  135. package/dist/src/core/baseLlmClient.test.js +1 -0
  136. package/dist/src/core/baseLlmClient.test.js.map +1 -1
  137. package/dist/src/core/client.js +1 -1
  138. package/dist/src/core/client.js.map +1 -1
  139. package/dist/src/core/client.test.js +7 -6
  140. package/dist/src/core/client.test.js.map +1 -1
  141. package/dist/src/core/geminiChat.js +8 -0
  142. package/dist/src/core/geminiChat.js.map +1 -1
  143. package/dist/src/core/geminiChat.test.js +1 -0
  144. package/dist/src/core/geminiChat.test.js.map +1 -1
  145. package/dist/src/core/geminiChat_network_retry.test.js +1 -0
  146. package/dist/src/core/geminiChat_network_retry.test.js.map +1 -1
  147. package/dist/src/core/logger.js +4 -4
  148. package/dist/src/core/logger.js.map +1 -1
  149. package/dist/src/core/logger.test.js +1 -1
  150. package/dist/src/core/logger.test.js.map +1 -1
  151. package/dist/src/core/loggingContentGenerator.js +1 -1
  152. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  153. package/dist/src/generated/git-commit.d.ts +2 -2
  154. package/dist/src/generated/git-commit.js +2 -2
  155. package/dist/src/hooks/hookEventHandler.js +8 -0
  156. package/dist/src/hooks/hookEventHandler.js.map +1 -1
  157. package/dist/src/hooks/hookRunner.js +9 -5
  158. package/dist/src/hooks/hookRunner.js.map +1 -1
  159. package/dist/src/hooks/hookRunner.test.js +20 -3
  160. package/dist/src/hooks/hookRunner.test.js.map +1 -1
  161. package/dist/src/hooks/hookSystem.d.ts +2 -0
  162. package/dist/src/hooks/hookSystem.js +1 -0
  163. package/dist/src/hooks/hookSystem.js.map +1 -1
  164. package/dist/src/hooks/hookTranslator.js +20 -13
  165. package/dist/src/hooks/hookTranslator.js.map +1 -1
  166. package/dist/src/hooks/hookTranslator.test.js +36 -0
  167. package/dist/src/hooks/hookTranslator.test.js.map +1 -1
  168. package/dist/src/hooks/types.d.ts +2 -0
  169. package/dist/src/ide/ide-client.js +3 -3
  170. package/dist/src/ide/ide-client.js.map +1 -1
  171. package/dist/src/ide/ide-connection-utils.js +1 -1
  172. package/dist/src/ide/ide-connection-utils.js.map +1 -1
  173. package/dist/src/ide/ide-installer.js +3 -3
  174. package/dist/src/ide/ide-installer.js.map +1 -1
  175. package/dist/src/ide/process-utils.js +3 -3
  176. package/dist/src/ide/process-utils.js.map +1 -1
  177. package/dist/src/index.d.ts +4 -1
  178. package/dist/src/index.js +5 -1
  179. package/dist/src/index.js.map +1 -1
  180. package/dist/src/output/json-formatter.js +2 -1
  181. package/dist/src/output/json-formatter.js.map +1 -1
  182. package/dist/src/policy/config.test.js +21 -20
  183. package/dist/src/policy/config.test.js.map +1 -1
  184. package/dist/src/policy/policies/memory-manager.toml +11 -1
  185. package/dist/src/policy/policies/plan.toml +4 -3
  186. package/dist/src/policy/policies/read-only.toml +6 -0
  187. package/dist/src/policy/policies/sandbox-default.toml +2 -3
  188. package/dist/src/policy/policy-engine.js +23 -0
  189. package/dist/src/policy/policy-engine.js.map +1 -1
  190. package/dist/src/policy/policy-engine.test.js +129 -1
  191. package/dist/src/policy/policy-engine.test.js.map +1 -1
  192. package/dist/src/policy/sandboxPolicyManager.d.ts +26 -1
  193. package/dist/src/policy/sandboxPolicyManager.js +41 -12
  194. package/dist/src/policy/sandboxPolicyManager.js.map +1 -1
  195. package/dist/src/policy/sandboxPolicyManager.test.d.ts +6 -0
  196. package/dist/src/policy/sandboxPolicyManager.test.js +61 -0
  197. package/dist/src/policy/sandboxPolicyManager.test.js.map +1 -0
  198. package/dist/src/policy/workspace-policy.test.js +18 -15
  199. package/dist/src/policy/workspace-policy.test.js.map +1 -1
  200. package/dist/src/prompts/snippets.js +6 -3
  201. package/dist/src/prompts/snippets.js.map +1 -1
  202. package/dist/src/prompts/snippets.legacy.js +6 -2
  203. package/dist/src/prompts/snippets.legacy.js.map +1 -1
  204. package/dist/src/prompts/utils.test.js +7 -5
  205. package/dist/src/prompts/utils.test.js.map +1 -1
  206. package/dist/src/safety/built-in.js +1 -1
  207. package/dist/src/safety/built-in.js.map +1 -1
  208. package/dist/src/sandbox/linux/LinuxSandboxManager.d.ts +4 -4
  209. package/dist/src/sandbox/linux/LinuxSandboxManager.js +47 -191
  210. package/dist/src/sandbox/linux/LinuxSandboxManager.js.map +1 -1
  211. package/dist/src/sandbox/linux/LinuxSandboxManager.test.js +33 -395
  212. package/dist/src/sandbox/linux/LinuxSandboxManager.test.js.map +1 -1
  213. package/dist/src/sandbox/linux/bwrapArgsBuilder.d.ts +24 -0
  214. package/dist/src/sandbox/linux/bwrapArgsBuilder.js +200 -0
  215. package/dist/src/sandbox/linux/bwrapArgsBuilder.js.map +1 -0
  216. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.d.ts +6 -0
  217. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js +247 -0
  218. package/dist/src/sandbox/linux/bwrapArgsBuilder.test.js.map +1 -0
  219. package/dist/src/sandbox/macos/MacOsSandboxManager.d.ts +3 -0
  220. package/dist/src/sandbox/macos/MacOsSandboxManager.js +12 -5
  221. package/dist/src/sandbox/macos/MacOsSandboxManager.js.map +1 -1
  222. package/dist/src/sandbox/macos/MacOsSandboxManager.test.js +20 -0
  223. package/dist/src/sandbox/macos/MacOsSandboxManager.test.js.map +1 -1
  224. package/dist/src/sandbox/macos/baseProfile.d.ts +1 -1
  225. package/dist/src/sandbox/macos/baseProfile.js +28 -4
  226. package/dist/src/sandbox/macos/baseProfile.js.map +1 -1
  227. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js +1 -1
  228. package/dist/src/sandbox/macos/seatbeltArgsBuilder.js.map +1 -1
  229. package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.js +2 -1
  230. package/dist/src/sandbox/macos/seatbeltArgsBuilder.test.js.map +1 -1
  231. package/dist/src/sandbox/utils/fsUtils.js +8 -6
  232. package/dist/src/sandbox/utils/fsUtils.js.map +1 -1
  233. package/dist/src/sandbox/utils/fsUtils.test.d.ts +6 -0
  234. package/dist/src/sandbox/utils/fsUtils.test.js +43 -0
  235. package/dist/src/sandbox/utils/fsUtils.test.js.map +1 -0
  236. package/dist/src/sandbox/utils/proactivePermissions.d.ts +19 -0
  237. package/dist/src/sandbox/utils/proactivePermissions.js +163 -0
  238. package/dist/src/sandbox/utils/proactivePermissions.js.map +1 -0
  239. package/dist/src/sandbox/utils/proactivePermissions.test.d.ts +6 -0
  240. package/dist/src/sandbox/utils/proactivePermissions.test.js +145 -0
  241. package/dist/src/sandbox/utils/proactivePermissions.test.js.map +1 -0
  242. package/dist/src/sandbox/utils/sandboxDenialUtils.d.ts +16 -1
  243. package/dist/src/sandbox/utils/sandboxDenialUtils.js +98 -24
  244. package/dist/src/sandbox/utils/sandboxDenialUtils.js.map +1 -1
  245. package/dist/src/sandbox/utils/sandboxDenialUtils.test.js +152 -1
  246. package/dist/src/sandbox/utils/sandboxDenialUtils.test.js.map +1 -1
  247. package/dist/src/sandbox/utils/sandboxReadWriteUtils.js +4 -0
  248. package/dist/src/sandbox/utils/sandboxReadWriteUtils.js.map +1 -1
  249. package/dist/src/sandbox/windows/GeminiSandbox.cs +90 -42
  250. package/dist/src/sandbox/windows/WindowsSandboxManager.d.ts +4 -0
  251. package/dist/src/sandbox/windows/WindowsSandboxManager.js +65 -60
  252. package/dist/src/sandbox/windows/WindowsSandboxManager.js.map +1 -1
  253. package/dist/src/sandbox/windows/WindowsSandboxManager.test.js +99 -54
  254. package/dist/src/sandbox/windows/WindowsSandboxManager.test.js.map +1 -1
  255. package/dist/src/sandbox/windows/windowsSandboxDenialUtils.d.ts +2 -1
  256. package/dist/src/sandbox/windows/windowsSandboxDenialUtils.js +19 -18
  257. package/dist/src/sandbox/windows/windowsSandboxDenialUtils.js.map +1 -1
  258. package/dist/src/scheduler/scheduler.js +1 -1
  259. package/dist/src/scheduler/scheduler.js.map +1 -1
  260. package/dist/src/scheduler/scheduler_hooks.test.js +1 -1
  261. package/dist/src/scheduler/scheduler_hooks.test.js.map +1 -1
  262. package/dist/src/scheduler/tool-executor.js +1 -1
  263. package/dist/src/scheduler/tool-executor.js.map +1 -1
  264. package/dist/src/scheduler/tool-executor.test.js +1 -1
  265. package/dist/src/scheduler/tool-executor.test.js.map +1 -1
  266. package/dist/src/services/executionLifecycleService.d.ts +1 -0
  267. package/dist/src/services/executionLifecycleService.js +3 -0
  268. package/dist/src/services/executionLifecycleService.js.map +1 -1
  269. package/dist/src/services/gitService.js +1 -1
  270. package/dist/src/services/gitService.js.map +1 -1
  271. package/dist/src/services/memoryService.d.ts +65 -0
  272. package/dist/src/services/memoryService.js +511 -0
  273. package/dist/src/services/memoryService.js.map +1 -0
  274. package/dist/src/services/memoryService.test.d.ts +6 -0
  275. package/dist/src/services/memoryService.test.js +563 -0
  276. package/dist/src/services/memoryService.test.js.map +1 -0
  277. package/dist/src/services/sandboxManager.d.ts +17 -0
  278. package/dist/src/services/sandboxManager.integration.test.js +18 -11
  279. package/dist/src/services/sandboxManager.integration.test.js.map +1 -1
  280. package/dist/src/services/sandboxManager.js +20 -0
  281. package/dist/src/services/sandboxManager.js.map +1 -1
  282. package/dist/src/services/sandboxManager.test.js +84 -56
  283. package/dist/src/services/sandboxManager.test.js.map +1 -1
  284. package/dist/src/services/sandboxManagerFactory.js +2 -5
  285. package/dist/src/services/sandboxManagerFactory.js.map +1 -1
  286. package/dist/src/services/sandboxedFileSystemService.js +14 -3
  287. package/dist/src/services/sandboxedFileSystemService.js.map +1 -1
  288. package/dist/src/services/sandboxedFileSystemService.test.js +29 -14
  289. package/dist/src/services/sandboxedFileSystemService.test.js.map +1 -1
  290. package/dist/src/services/shellExecutionService.d.ts +16 -1
  291. package/dist/src/services/shellExecutionService.js +70 -10
  292. package/dist/src/services/shellExecutionService.js.map +1 -1
  293. package/dist/src/services/shellExecutionService.test.js +65 -4
  294. package/dist/src/services/shellExecutionService.test.js.map +1 -1
  295. package/dist/src/services/worktreeService.test.js +7 -7
  296. package/dist/src/services/worktreeService.test.js.map +1 -1
  297. package/dist/src/skills/skillLoader.d.ts +8 -0
  298. package/dist/src/skills/skillLoader.js +1 -1
  299. package/dist/src/skills/skillLoader.js.map +1 -1
  300. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +29 -1
  301. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +101 -0
  302. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  303. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +167 -0
  304. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  305. package/dist/src/telemetry/clearcut-logger/event-metadata-key.d.ts +9 -1
  306. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js +20 -1
  307. package/dist/src/telemetry/clearcut-logger/event-metadata-key.js.map +1 -1
  308. package/dist/src/telemetry/loggers.d.ts +22 -0
  309. package/dist/src/telemetry/loggers.js +40 -1
  310. package/dist/src/telemetry/loggers.js.map +1 -1
  311. package/dist/src/telemetry/metrics.d.ts +108 -0
  312. package/dist/src/telemetry/metrics.js +177 -0
  313. package/dist/src/telemetry/metrics.js.map +1 -1
  314. package/dist/src/telemetry/metrics.test.js +254 -0
  315. package/dist/src/telemetry/metrics.test.js.map +1 -1
  316. package/dist/src/tools/complete-task.d.ts +29 -0
  317. package/dist/src/tools/complete-task.js +123 -0
  318. package/dist/src/tools/complete-task.js.map +1 -0
  319. package/dist/src/tools/complete-task.test.d.ts +6 -0
  320. package/dist/src/tools/complete-task.test.js +114 -0
  321. package/dist/src/tools/complete-task.test.js.map +1 -0
  322. package/dist/src/tools/definitions/base-declarations.d.ts +2 -0
  323. package/dist/src/tools/definitions/base-declarations.js +3 -0
  324. package/dist/src/tools/definitions/base-declarations.js.map +1 -1
  325. package/dist/src/tools/definitions/coreTools.d.ts +1 -1
  326. package/dist/src/tools/definitions/coreTools.js +1 -1
  327. package/dist/src/tools/definitions/coreTools.js.map +1 -1
  328. package/dist/src/tools/definitions/dynamic-declaration-helpers.js +4 -0
  329. package/dist/src/tools/definitions/dynamic-declaration-helpers.js.map +1 -1
  330. package/dist/src/tools/definitions/model-family-sets/default-legacy.js +3 -3
  331. package/dist/src/tools/definitions/model-family-sets/default-legacy.js.map +1 -1
  332. package/dist/src/tools/definitions/model-family-sets/gemini-3.js +3 -3
  333. package/dist/src/tools/definitions/model-family-sets/gemini-3.js.map +1 -1
  334. package/dist/src/tools/grep.test.js +2 -2
  335. package/dist/src/tools/grep.test.js.map +1 -1
  336. package/dist/src/tools/jit-context.js +3 -3
  337. package/dist/src/tools/jit-context.js.map +1 -1
  338. package/dist/src/tools/jit-context.test.js +15 -13
  339. package/dist/src/tools/jit-context.test.js.map +1 -1
  340. package/dist/src/tools/mcp-client.js +1 -1
  341. package/dist/src/tools/mcp-client.js.map +1 -1
  342. package/dist/src/tools/mcp-tool.test.js +1 -1
  343. package/dist/src/tools/mcp-tool.test.js.map +1 -1
  344. package/dist/src/tools/ripGrep.test.js +1 -1
  345. package/dist/src/tools/ripGrep.test.js.map +1 -1
  346. package/dist/src/tools/shell.d.ts +7 -4
  347. package/dist/src/tools/shell.js +255 -37
  348. package/dist/src/tools/shell.js.map +1 -1
  349. package/dist/src/tools/shell.test.js +182 -8
  350. package/dist/src/tools/shell.test.js.map +1 -1
  351. package/dist/src/tools/shellBackgroundTools.d.ts +38 -0
  352. package/dist/src/tools/shellBackgroundTools.integration.test.d.ts +6 -0
  353. package/dist/src/tools/shellBackgroundTools.integration.test.js +86 -0
  354. package/dist/src/tools/shellBackgroundTools.integration.test.js.map +1 -0
  355. package/dist/src/tools/shellBackgroundTools.js +186 -0
  356. package/dist/src/tools/shellBackgroundTools.js.map +1 -0
  357. package/dist/src/tools/shellBackgroundTools.test.d.ts +6 -0
  358. package/dist/src/tools/shellBackgroundTools.test.js +230 -0
  359. package/dist/src/tools/shellBackgroundTools.test.js.map +1 -0
  360. package/dist/src/tools/shell_proactive.test.d.ts +6 -0
  361. package/dist/src/tools/shell_proactive.test.js +122 -0
  362. package/dist/src/tools/shell_proactive.test.js.map +1 -0
  363. package/dist/src/tools/tool-names.d.ts +3 -3
  364. package/dist/src/tools/tool-names.js +3 -2
  365. package/dist/src/tools/tool-names.js.map +1 -1
  366. package/dist/src/tools/tools.js +1 -1
  367. package/dist/src/tools/tools.js.map +1 -1
  368. package/dist/src/tools/web-fetch.js +8 -8
  369. package/dist/src/tools/web-fetch.js.map +1 -1
  370. package/dist/src/tools/web-fetch.test.js +5 -5
  371. package/dist/src/tools/web-fetch.test.js.map +1 -1
  372. package/dist/src/tools/xcode-mcp-fix-transport.js +1 -1
  373. package/dist/src/tools/xcode-mcp-fix-transport.js.map +1 -1
  374. package/dist/src/utils/bfsFileSearch.js +3 -6
  375. package/dist/src/utils/bfsFileSearch.js.map +1 -1
  376. package/dist/src/utils/checkpointUtils.js +11 -8
  377. package/dist/src/utils/checkpointUtils.js.map +1 -1
  378. package/dist/src/utils/compatibility.js +0 -7
  379. package/dist/src/utils/compatibility.js.map +1 -1
  380. package/dist/src/utils/compatibility.test.js +0 -9
  381. package/dist/src/utils/compatibility.test.js.map +1 -1
  382. package/dist/src/utils/editor.js +3 -0
  383. package/dist/src/utils/editor.js.map +1 -1
  384. package/dist/src/utils/errorParsing.js +2 -2
  385. package/dist/src/utils/errorParsing.js.map +1 -1
  386. package/dist/src/utils/events.d.ts +12 -0
  387. package/dist/src/utils/events.js +7 -0
  388. package/dist/src/utils/events.js.map +1 -1
  389. package/dist/src/utils/fetch.d.ts +1 -0
  390. package/dist/src/utils/fetch.js +22 -6
  391. package/dist/src/utils/fetch.js.map +1 -1
  392. package/dist/src/utils/fetch.test.js +26 -1
  393. package/dist/src/utils/fetch.test.js.map +1 -1
  394. package/dist/src/utils/fileUtils.js +1 -1
  395. package/dist/src/utils/fileUtils.js.map +1 -1
  396. package/dist/src/utils/filesearch/crawler.js +1 -1
  397. package/dist/src/utils/filesearch/crawler.js.map +1 -1
  398. package/dist/src/utils/filesearch/fileSearch.test.js +7 -2
  399. package/dist/src/utils/filesearch/fileSearch.test.js.map +1 -1
  400. package/dist/src/utils/getPty.js +2 -2
  401. package/dist/src/utils/getPty.js.map +1 -1
  402. package/dist/src/utils/gitIgnoreParser.js +2 -2
  403. package/dist/src/utils/gitIgnoreParser.js.map +1 -1
  404. package/dist/src/utils/gitUtils.js +2 -2
  405. package/dist/src/utils/gitUtils.js.map +1 -1
  406. package/dist/src/utils/googleErrors.js +5 -5
  407. package/dist/src/utils/googleErrors.js.map +1 -1
  408. package/dist/src/utils/ignoreFileParser.js +1 -1
  409. package/dist/src/utils/ignoreFileParser.js.map +1 -1
  410. package/dist/src/utils/memoryDiscovery.js +3 -7
  411. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  412. package/dist/src/utils/paths.d.ts +8 -0
  413. package/dist/src/utils/paths.js +37 -6
  414. package/dist/src/utils/paths.js.map +1 -1
  415. package/dist/src/utils/paths.test.js +61 -3
  416. package/dist/src/utils/paths.test.js.map +1 -1
  417. package/dist/src/utils/process-utils.js +2 -2
  418. package/dist/src/utils/process-utils.js.map +1 -1
  419. package/dist/src/utils/retry.js +7 -0
  420. package/dist/src/utils/retry.js.map +1 -1
  421. package/dist/src/utils/retry.test.js +41 -0
  422. package/dist/src/utils/retry.test.js.map +1 -1
  423. package/dist/src/utils/secure-browser-launcher.js +1 -1
  424. package/dist/src/utils/secure-browser-launcher.js.map +1 -1
  425. package/dist/src/utils/shell-utils.d.ts +9 -0
  426. package/dist/src/utils/shell-utils.integration.test.js +1 -1
  427. package/dist/src/utils/shell-utils.integration.test.js.map +1 -1
  428. package/dist/src/utils/shell-utils.js +43 -4
  429. package/dist/src/utils/shell-utils.js.map +1 -1
  430. package/dist/src/utils/shell-utils.test.js +13 -1
  431. package/dist/src/utils/shell-utils.test.js.map +1 -1
  432. package/dist/src/utils/systemEncoding.js +1 -1
  433. package/dist/src/utils/systemEncoding.js.map +1 -1
  434. package/dist/src/utils/terminalSerializer.d.ts +1 -0
  435. package/dist/src/utils/terminalSerializer.js +31 -8
  436. package/dist/src/utils/terminalSerializer.js.map +1 -1
  437. package/dist/src/utils/terminalSerializer.test.js +3 -2
  438. package/dist/src/utils/terminalSerializer.test.js.map +1 -1
  439. package/dist/src/utils/workspaceContext.js +2 -2
  440. package/dist/src/utils/workspaceContext.js.map +1 -1
  441. package/dist/tsconfig.tsbuildinfo +1 -1
  442. package/package.json +1 -1
  443. package/dist/google-gemini-cli-core-0.37.0-preview.0.tgz +0 -0
  444. package/dist/src/context/contextManager.js.map +0 -1
  445. package/dist/src/context/contextManager.test.js.map +0 -1
  446. package/dist/src/services/types.d.ts +0 -14
  447. package/dist/src/services/types.js.map +0 -1
  448. /package/dist/src/context/{contextManager.test.d.ts → memoryContextManager.test.d.ts} +0 -0
  449. /package/dist/src/{services → context}/types.js +0 -0
@@ -35,7 +35,7 @@ import { PromptRegistry } from '../prompts/prompt-registry.js';
35
35
  import { ResourceRegistry } from '../resources/resource-registry.js';
36
36
  import { DiscoveredMCPTool } from '../tools/mcp-tool.js';
37
37
  import { LSTool } from '../tools/ls.js';
38
- import { LS_TOOL_NAME, READ_FILE_TOOL_NAME } from '../tools/tool-names.js';
38
+ import { COMPLETE_TASK_TOOL_NAME, LS_TOOL_NAME, READ_FILE_TOOL_NAME, } from '../tools/tool-names.js';
39
39
  import { GeminiChat, StreamEventType, } from '../core/geminiChat.js';
40
40
  import {} from '@google/genai';
41
41
  import { MockTool } from '../test-utils/mock-tool.js';
@@ -113,6 +113,17 @@ vi.mock('../utils/promptIdContext.js', async (importOriginal) => {
113
113
  },
114
114
  };
115
115
  });
116
+ vi.mock('../config/scoped-config.js', async (importOriginal) => {
117
+ const actual = await importOriginal();
118
+ return {
119
+ ...actual,
120
+ runWithScopedWorkspaceContext: vi.fn(actual.runWithScopedWorkspaceContext),
121
+ createScopedWorkspaceContext: vi.fn(actual.createScopedWorkspaceContext),
122
+ };
123
+ });
124
+ import { runWithScopedWorkspaceContext, createScopedWorkspaceContext, } from '../config/scoped-config.js';
125
+ const mockedRunWithScopedWorkspaceContext = vi.mocked(runWithScopedWorkspaceContext);
126
+ const mockedCreateScopedWorkspaceContext = vi.mocked(createScopedWorkspaceContext);
116
127
  const MockedGeminiChat = vi.mocked(GeminiChat);
117
128
  const mockedGetDirectoryContextString = vi.mocked(getDirectoryContextString);
118
129
  const mockedPromptIdContext = vi.mocked(promptIdContext);
@@ -120,8 +131,31 @@ const mockedLogAgentStart = vi.mocked(logAgentStart);
120
131
  const mockedLogAgentFinish = vi.mocked(logAgentFinish);
121
132
  const mockedLogRecoveryAttempt = vi.mocked(logRecoveryAttempt);
122
133
  // Constants for testing
123
- const TASK_COMPLETE_TOOL_NAME = 'complete_task';
124
134
  const MOCK_TOOL_NOT_ALLOWED = new MockTool({ name: 'write_file_interactive' });
135
+ /**
136
+ * Helper to mock a successful completion result from the scheduler.
137
+ */
138
+ const mockCompletionResult = (callId, submittedOutput, toolName = COMPLETE_TASK_TOOL_NAME) => {
139
+ mockScheduleAgentTools.mockResolvedValueOnce([
140
+ {
141
+ status: 'success',
142
+ request: {
143
+ callId,
144
+ name: toolName,
145
+ args: {},
146
+ prompt_id: 'test-prompt',
147
+ },
148
+ response: {
149
+ resultDisplay: 'Task completed.',
150
+ responseParts: [],
151
+ data: {
152
+ taskCompleted: true,
153
+ submittedOutput,
154
+ },
155
+ },
156
+ },
157
+ ]);
158
+ };
125
159
  /**
126
160
  * Helper to create a mock API response chunk.
127
161
  * Uses conditional spread to handle readonly functionCalls property safely.
@@ -212,11 +246,50 @@ describe('LocalAgentExecutor', () => {
212
246
  vi.resetAllMocks();
213
247
  mockCompress.mockClear();
214
248
  mockSetHistory.mockClear();
215
- mockSendMessageStream.mockReset();
249
+ mockSendMessageStream.mockReset().mockResolvedValue({
250
+ async *[Symbol.asyncIterator]() {
251
+ yield {
252
+ type: StreamEventType.CHUNK,
253
+ value: { candidates: [] },
254
+ };
255
+ },
256
+ });
216
257
  mockSetSystemInstruction.mockReset();
217
- mockScheduleAgentTools.mockReset();
258
+ mockScheduleAgentTools
259
+ .mockReset()
260
+ .mockImplementation(async (_config, requests) =>
261
+ // Default mock behavior for scheduleAgentTools
262
+ requests.map((req) => {
263
+ if (req.name === COMPLETE_TASK_TOOL_NAME) {
264
+ return {
265
+ status: 'success',
266
+ request: req,
267
+ response: {
268
+ resultDisplay: 'Task completed.',
269
+ responseParts: [],
270
+ data: {
271
+ taskCompleted: true,
272
+ submittedOutput: req.args['finalResult'] ||
273
+ req.args['result'] ||
274
+ JSON.stringify(req.args),
275
+ },
276
+ },
277
+ };
278
+ }
279
+ return {
280
+ status: 'success',
281
+ request: req,
282
+ response: {
283
+ resultDisplay: 'Mock tool executed',
284
+ responseParts: [],
285
+ data: {},
286
+ },
287
+ };
288
+ }));
218
289
  mockedLogAgentStart.mockReset();
219
290
  mockedLogAgentFinish.mockReset();
291
+ mockedRunWithScopedWorkspaceContext.mockClear();
292
+ mockedCreateScopedWorkspaceContext.mockClear();
220
293
  mockedPromptIdContext.getStore.mockReset();
221
294
  mockedPromptIdContext.run.mockImplementation((_id, fn) => fn());
222
295
  ChatCompressionService.mockImplementation(() => ({
@@ -281,7 +354,7 @@ describe('LocalAgentExecutor', () => {
281
354
  const executor = await LocalAgentExecutor.create(definition, extendedContext, onActivity);
282
355
  mockModelResponse([
283
356
  {
284
- name: TASK_COMPLETE_TOOL_NAME,
357
+ name: COMPLETE_TASK_TOOL_NAME,
285
358
  args: { finalResult: 'done' },
286
359
  id: 'call1',
287
360
  },
@@ -336,7 +409,7 @@ describe('LocalAgentExecutor', () => {
336
409
  const executor = await LocalAgentExecutor.create(definition, context);
337
410
  mockModelResponse([
338
411
  {
339
- name: TASK_COMPLETE_TOOL_NAME,
412
+ name: COMPLETE_TASK_TOOL_NAME,
340
413
  args: { finalResult: 'done' },
341
414
  id: 'call1',
342
415
  },
@@ -374,7 +447,7 @@ describe('LocalAgentExecutor', () => {
374
447
  const executor = await LocalAgentExecutor.create(definition, context);
375
448
  mockModelResponse([
376
449
  {
377
- name: TASK_COMPLETE_TOOL_NAME,
450
+ name: COMPLETE_TASK_TOOL_NAME,
378
451
  args: { finalResult: 'done' },
379
452
  id: 'call1',
380
453
  },
@@ -403,8 +476,12 @@ describe('LocalAgentExecutor', () => {
403
476
  const executor = await LocalAgentExecutor.create(definition, mockConfig, onActivity);
404
477
  const agentRegistry = executor['toolRegistry'];
405
478
  expect(agentRegistry).not.toBe(parentToolRegistry);
406
- expect(agentRegistry.getAllToolNames()).toEqual(expect.arrayContaining([LS_TOOL_NAME, READ_FILE_TOOL_NAME]));
407
- expect(agentRegistry.getAllToolNames()).toHaveLength(2);
479
+ expect(agentRegistry.getAllToolNames()).toEqual(expect.arrayContaining([
480
+ LS_TOOL_NAME,
481
+ READ_FILE_TOOL_NAME,
482
+ COMPLETE_TASK_TOOL_NAME,
483
+ ]));
484
+ expect(agentRegistry.getAllToolNames()).toHaveLength(3);
408
485
  expect(agentRegistry.getTool(MOCK_TOOL_NOT_ALLOWED.name)).toBeUndefined();
409
486
  });
410
487
  it('should use parentPromptId from context to create agentId', async () => {
@@ -430,7 +507,7 @@ describe('LocalAgentExecutor', () => {
430
507
  // Mock a response to prevent the loop from running forever
431
508
  mockModelResponse([
432
509
  {
433
- name: TASK_COMPLETE_TOOL_NAME,
510
+ name: COMPLETE_TASK_TOOL_NAME,
434
511
  args: { finalResult: 'done' },
435
512
  id: 'call1',
436
513
  },
@@ -536,6 +613,39 @@ describe('LocalAgentExecutor', () => {
536
613
  expect(toolNames).toContain(LS_TOOL_NAME);
537
614
  });
538
615
  });
616
+ describe('run (Workspace Scoping)', () => {
617
+ it('should use runWithScopedWorkspaceContext when workspaceDirectories is set', async () => {
618
+ const definition = createTestDefinition();
619
+ definition.workspaceDirectories = ['/tmp/extra-dir'];
620
+ const executor = await LocalAgentExecutor.create(definition, mockConfig, onActivity);
621
+ // Mock a simple complete_task response so run() terminates
622
+ mockModelResponse([
623
+ {
624
+ name: COMPLETE_TASK_TOOL_NAME,
625
+ args: { finalResult: 'done' },
626
+ id: 'c1',
627
+ },
628
+ ]);
629
+ await executor.run({ goal: 'test' }, signal);
630
+ expect(mockedCreateScopedWorkspaceContext).toHaveBeenCalledOnce();
631
+ expect(mockedRunWithScopedWorkspaceContext).toHaveBeenCalledOnce();
632
+ });
633
+ it('should not use runWithScopedWorkspaceContext when workspaceDirectories is not set', async () => {
634
+ const definition = createTestDefinition();
635
+ const executor = await LocalAgentExecutor.create(definition, mockConfig, onActivity);
636
+ // Mock a simple complete_task response so run() terminates
637
+ mockModelResponse([
638
+ {
639
+ name: COMPLETE_TASK_TOOL_NAME,
640
+ args: { finalResult: 'done' },
641
+ id: 'c1',
642
+ },
643
+ ]);
644
+ await executor.run({ goal: 'test' }, signal);
645
+ expect(mockedCreateScopedWorkspaceContext).not.toHaveBeenCalled();
646
+ expect(mockedRunWithScopedWorkspaceContext).not.toHaveBeenCalled();
647
+ });
648
+ });
539
649
  describe('run (Execution Loop and Logic)', () => {
540
650
  it('should log AgentFinish with error if run throws', async () => {
541
651
  const definition = createTestDefinition();
@@ -595,15 +705,43 @@ describe('LocalAgentExecutor', () => {
595
705
  // Turn 2: Model calls complete_task with required output
596
706
  mockModelResponse([
597
707
  {
598
- name: TASK_COMPLETE_TOOL_NAME,
708
+ name: COMPLETE_TASK_TOOL_NAME,
599
709
  args: { finalResult: 'Found file1.txt' },
600
710
  id: 'call2',
601
711
  },
602
712
  ], 'T2: Done');
713
+ mockScheduleAgentTools.mockResolvedValueOnce([
714
+ {
715
+ status: 'success',
716
+ request: {
717
+ callId: 'call2',
718
+ name: COMPLETE_TASK_TOOL_NAME,
719
+ args: { finalResult: 'Found file1.txt' },
720
+ prompt_id: 'p1',
721
+ },
722
+ response: {
723
+ resultDisplay: 'Output submitted and task completed.',
724
+ responseParts: [
725
+ {
726
+ functionResponse: {
727
+ name: COMPLETE_TASK_TOOL_NAME,
728
+ id: 'call2',
729
+ response: { result: 'Output submitted and task completed.' },
730
+ },
731
+ },
732
+ ],
733
+ data: {
734
+ taskCompleted: true,
735
+ submittedOutput: 'Found file1.txt',
736
+ },
737
+ },
738
+ },
739
+ ]);
603
740
  const output = await executor.run(inputs, signal);
604
741
  expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
742
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(2);
605
743
  const systemInstruction = MockedGeminiChat.mock.calls[0][1];
606
- expect(systemInstruction).toContain(`MUST call the \`${TASK_COMPLETE_TOOL_NAME}\` tool`);
744
+ expect(systemInstruction).toContain(`MUST call the \`${COMPLETE_TASK_TOOL_NAME}\` tool`);
607
745
  expect(systemInstruction).toContain('Mocked Environment Context');
608
746
  expect(systemInstruction).toContain('You are running in a non-interactive mode');
609
747
  expect(systemInstruction).toContain('Always use absolute paths');
@@ -616,10 +754,11 @@ describe('LocalAgentExecutor', () => {
616
754
  expect(sentTools).toBeDefined();
617
755
  expect(sentTools).toEqual(expect.arrayContaining([
618
756
  expect.objectContaining({ name: LS_TOOL_NAME }),
619
- expect.objectContaining({ name: TASK_COMPLETE_TOOL_NAME }),
757
+ expect.objectContaining({ name: COMPLETE_TASK_TOOL_NAME }),
620
758
  ]));
621
- const completeToolDef = sentTools.find((t) => t.name === TASK_COMPLETE_TOOL_NAME);
622
- expect(completeToolDef?.parameters?.required).toContain('finalResult');
759
+ const completeToolDef = sentTools.find((t) => t.name === COMPLETE_TASK_TOOL_NAME);
760
+ const completeSchema = completeToolDef?.parametersJsonSchema;
761
+ expect(completeSchema?.['required']).toContain('finalResult');
623
762
  expect(output.result).toBe('Found file1.txt');
624
763
  expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
625
764
  // Telemetry checks
@@ -632,8 +771,8 @@ describe('LocalAgentExecutor', () => {
632
771
  // Context checks
633
772
  expect(mockedPromptIdContext.run).toHaveBeenCalledTimes(2); // Two turns
634
773
  // Recording checks
635
- expect(mockRecordCompletedToolCalls).toHaveBeenCalledTimes(1);
636
- expect(mockRecordCompletedToolCalls).toHaveBeenCalledWith(expect.any(String), // model
774
+ expect(mockRecordCompletedToolCalls).toHaveBeenCalledTimes(2);
775
+ expect(mockRecordCompletedToolCalls).toHaveBeenNthCalledWith(1, expect.any(String), // model
637
776
  expect.arrayContaining([
638
777
  expect.objectContaining({
639
778
  status: 'success',
@@ -660,14 +799,14 @@ describe('LocalAgentExecutor', () => {
660
799
  expect.objectContaining({
661
800
  type: 'TOOL_CALL_START',
662
801
  data: expect.objectContaining({
663
- name: TASK_COMPLETE_TOOL_NAME,
802
+ name: COMPLETE_TASK_TOOL_NAME,
664
803
  args: { finalResult: 'Found file1.txt' },
665
804
  }),
666
805
  }),
667
806
  expect.objectContaining({
668
807
  type: 'TOOL_CALL_END',
669
808
  data: expect.objectContaining({
670
- name: TASK_COMPLETE_TOOL_NAME,
809
+ name: COMPLETE_TASK_TOOL_NAME,
671
810
  output: expect.stringContaining('Output submitted'),
672
811
  }),
673
812
  }),
@@ -711,11 +850,12 @@ describe('LocalAgentExecutor', () => {
711
850
  ]);
712
851
  mockModelResponse([
713
852
  {
714
- name: TASK_COMPLETE_TOOL_NAME,
853
+ name: COMPLETE_TASK_TOOL_NAME,
715
854
  args: { result: 'All work done' },
716
855
  id: 'call2',
717
856
  },
718
857
  ], 'Task finished.');
858
+ mockCompletionResult('call2', 'All work done');
719
859
  const output = await executor.run({ goal: 'Do work' }, signal);
720
860
  const { modelConfigKey } = getMockMessageParams(0);
721
861
  expect(modelConfigKey.model).toBe(getModelConfigAlias(definition));
@@ -723,11 +863,13 @@ describe('LocalAgentExecutor', () => {
723
863
  const passedToolsArg = chatConstructorArgs[2];
724
864
  const sentTools = passedToolsArg[0].functionDeclarations;
725
865
  expect(sentTools).toBeDefined();
726
- const completeToolDef = sentTools.find((t) => t.name === TASK_COMPLETE_TOOL_NAME);
727
- expect(completeToolDef?.parameters?.required).toEqual(['result']);
866
+ const completeToolDef = sentTools.find((t) => t.name === COMPLETE_TASK_TOOL_NAME);
867
+ const schema = completeToolDef?.parametersJsonSchema;
868
+ expect(schema?.['required']).toContain('result');
728
869
  expect(completeToolDef?.description).toContain('submit your final findings');
729
870
  expect(output.result).toBe('All work done');
730
871
  expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
872
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(2);
731
873
  });
732
874
  it('should error immediately if the model stops tools without calling complete_task (Protocol Violation)', async () => {
733
875
  const definition = createTestDefinition();
@@ -771,7 +913,7 @@ describe('LocalAgentExecutor', () => {
771
913
  mockModelResponse([], 'I still give up.');
772
914
  const output = await executor.run({ goal: 'Strict test' }, signal);
773
915
  expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
774
- const expectedError = `Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'.`;
916
+ const expectedError = `Agent stopped calling tools but did not call '${COMPLETE_TASK_TOOL_NAME}'.`;
775
917
  expect(output.terminate_reason).toBe(AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL);
776
918
  expect(output.result).toBe(expectedError);
777
919
  // Telemetry check for error
@@ -793,27 +935,59 @@ describe('LocalAgentExecutor', () => {
793
935
  // Turn 1: Missing arg
794
936
  mockModelResponse([
795
937
  {
796
- name: TASK_COMPLETE_TOOL_NAME,
938
+ name: COMPLETE_TASK_TOOL_NAME,
797
939
  args: { wrongArg: 'oops' },
798
940
  id: 'call1',
799
941
  },
800
942
  ]);
943
+ // Mock failure in scheduler for Turn 1
944
+ mockScheduleAgentTools.mockResolvedValueOnce([
945
+ {
946
+ status: 'error',
947
+ request: {
948
+ callId: 'call1',
949
+ name: COMPLETE_TASK_TOOL_NAME,
950
+ args: { wrongArg: 'oops' },
951
+ prompt_id: 'p1',
952
+ },
953
+ response: {
954
+ resultDisplay: 'Error',
955
+ responseParts: [
956
+ {
957
+ functionResponse: {
958
+ name: COMPLETE_TASK_TOOL_NAME,
959
+ id: 'call1',
960
+ response: {
961
+ error: "Missing required argument 'finalResult' for completion.",
962
+ },
963
+ },
964
+ },
965
+ ],
966
+ error: {
967
+ message: "Missing required argument 'finalResult' for completion.",
968
+ type: 'INVALID_TOOL_PARAMS',
969
+ },
970
+ },
971
+ },
972
+ ]);
801
973
  // Turn 2: Corrected
802
974
  mockModelResponse([
803
975
  {
804
- name: TASK_COMPLETE_TOOL_NAME,
976
+ name: COMPLETE_TASK_TOOL_NAME,
805
977
  args: { finalResult: 'Corrected result' },
806
978
  id: 'call2',
807
979
  },
808
980
  ]);
981
+ mockCompletionResult('call2', 'Corrected result');
809
982
  const output = await executor.run({ goal: 'Error test' }, signal);
810
983
  expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
984
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(2);
811
985
  const expectedError = "Missing required argument 'finalResult' for completion.";
812
986
  expect(activities).toContainEqual(expect.objectContaining({
813
987
  type: 'ERROR',
814
988
  data: expect.objectContaining({
815
989
  context: 'tool_call',
816
- name: TASK_COMPLETE_TOOL_NAME,
990
+ name: COMPLETE_TASK_TOOL_NAME,
817
991
  error: expectedError,
818
992
  errorType: SubagentActivityErrorType.GENERIC,
819
993
  }),
@@ -824,7 +998,7 @@ describe('LocalAgentExecutor', () => {
824
998
  expect(turn2Parts).toHaveLength(1);
825
999
  expect(turn2Parts[0]).toEqual(expect.objectContaining({
826
1000
  functionResponse: expect.objectContaining({
827
- name: TASK_COMPLETE_TOOL_NAME,
1001
+ name: COMPLETE_TASK_TOOL_NAME,
828
1002
  response: { error: expectedError },
829
1003
  id: 'call1',
830
1004
  }),
@@ -832,31 +1006,61 @@ describe('LocalAgentExecutor', () => {
832
1006
  expect(output.result).toBe('Corrected result');
833
1007
  expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
834
1008
  });
835
- it('should handle multiple calls to complete_task in the same turn (accept first, block rest)', async () => {
1009
+ it('should handle multiple calls to complete_task in the same turn', async () => {
836
1010
  const definition = createTestDefinition([], {}, 'none');
837
1011
  const executor = await LocalAgentExecutor.create(definition, mockConfig, onActivity);
838
1012
  // Turn 1: Duplicate calls
839
1013
  mockModelResponse([
840
1014
  {
841
- name: TASK_COMPLETE_TOOL_NAME,
842
- args: { result: 'done' },
1015
+ name: COMPLETE_TASK_TOOL_NAME,
1016
+ args: { result: 'first' },
843
1017
  id: 'call1',
844
1018
  },
845
1019
  {
846
- name: TASK_COMPLETE_TOOL_NAME,
847
- args: { result: 'ignored' },
1020
+ name: COMPLETE_TASK_TOOL_NAME,
1021
+ args: { result: 'second' },
848
1022
  id: 'call2',
849
1023
  },
850
1024
  ]);
1025
+ mockScheduleAgentTools.mockResolvedValueOnce([
1026
+ {
1027
+ status: 'success',
1028
+ request: {
1029
+ callId: 'call1',
1030
+ name: COMPLETE_TASK_TOOL_NAME,
1031
+ args: { result: 'first' },
1032
+ prompt_id: 'p1',
1033
+ },
1034
+ response: {
1035
+ resultDisplay: 'ok',
1036
+ responseParts: [],
1037
+ data: { taskCompleted: true, submittedOutput: 'first' },
1038
+ },
1039
+ },
1040
+ {
1041
+ status: 'success',
1042
+ request: {
1043
+ callId: 'call2',
1044
+ name: COMPLETE_TASK_TOOL_NAME,
1045
+ args: { result: 'second' },
1046
+ prompt_id: 'p1',
1047
+ },
1048
+ response: {
1049
+ resultDisplay: 'ok',
1050
+ responseParts: [],
1051
+ data: { taskCompleted: true, submittedOutput: 'second' },
1052
+ },
1053
+ },
1054
+ ]);
851
1055
  const output = await executor.run({ goal: 'Dup test' }, signal);
852
1056
  expect(mockSendMessageStream).toHaveBeenCalledTimes(1);
1057
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(1);
853
1058
  expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
1059
+ // In current impl, the first successful complete_task in the batch is respected.
1060
+ expect(output.result).toBe('first');
854
1061
  const completions = activities.filter((a) => a.type === 'TOOL_CALL_END' &&
855
- a.data['name'] === TASK_COMPLETE_TOOL_NAME);
856
- const errors = activities.filter((a) => a.type === 'ERROR' && a.data['name'] === TASK_COMPLETE_TOOL_NAME);
857
- expect(completions).toHaveLength(1);
858
- expect(errors).toHaveLength(1);
859
- expect(errors[0].data['error']).toContain('Task already marked complete in this turn');
1062
+ a.data['name'] === COMPLETE_TASK_TOOL_NAME);
1063
+ expect(completions).toHaveLength(2);
860
1064
  });
861
1065
  it('should execute parallel tool calls and then complete', async () => {
862
1066
  const definition = createTestDefinition([LS_TOOL_NAME]);
@@ -881,39 +1085,57 @@ describe('LocalAgentExecutor', () => {
881
1085
  });
882
1086
  mockScheduleAgentTools.mockImplementation(async (_ctx, requests) => {
883
1087
  const results = await Promise.all(requests.map(async (reqInfo) => {
884
- callsStarted++;
885
- if (callsStarted === 2)
886
- resolveCalls();
887
- await vi.advanceTimersByTimeAsync(100);
888
- return {
889
- status: CoreToolCallStatus.Success,
890
- request: reqInfo,
891
- tool: {},
892
- invocation: {},
893
- response: {
894
- callId: reqInfo.callId,
895
- resultDisplay: 'ok',
896
- responseParts: [
897
- {
898
- functionResponse: {
899
- name: reqInfo.name,
900
- response: {},
901
- id: reqInfo.callId,
1088
+ if (reqInfo.name === LS_TOOL_NAME) {
1089
+ callsStarted++;
1090
+ if (callsStarted === 2)
1091
+ resolveCalls();
1092
+ await vi.advanceTimersByTimeAsync(100);
1093
+ return {
1094
+ status: CoreToolCallStatus.Success,
1095
+ request: reqInfo,
1096
+ tool: {},
1097
+ invocation: {},
1098
+ response: {
1099
+ callId: reqInfo.callId,
1100
+ resultDisplay: 'ok',
1101
+ responseParts: [
1102
+ {
1103
+ functionResponse: {
1104
+ name: reqInfo.name,
1105
+ response: {},
1106
+ id: reqInfo.callId,
1107
+ },
902
1108
  },
1109
+ ],
1110
+ error: undefined,
1111
+ errorType: undefined,
1112
+ contentLength: 0,
1113
+ },
1114
+ };
1115
+ }
1116
+ else if (reqInfo.name === COMPLETE_TASK_TOOL_NAME) {
1117
+ return {
1118
+ status: CoreToolCallStatus.Success,
1119
+ request: reqInfo,
1120
+ response: {
1121
+ callId: reqInfo.callId,
1122
+ resultDisplay: 'Task completed.',
1123
+ responseParts: [],
1124
+ data: {
1125
+ taskCompleted: true,
1126
+ submittedOutput: reqInfo.args['finalResult'],
903
1127
  },
904
- ],
905
- error: undefined,
906
- errorType: undefined,
907
- contentLength: 0,
908
- },
909
- };
1128
+ },
1129
+ };
1130
+ }
1131
+ throw new Error(`Unexpected tool: ${reqInfo.name}`);
910
1132
  }));
911
1133
  return results;
912
1134
  });
913
1135
  // Turn 2: Completion
914
1136
  mockModelResponse([
915
1137
  {
916
- name: TASK_COMPLETE_TOOL_NAME,
1138
+ name: COMPLETE_TASK_TOOL_NAME,
917
1139
  args: { finalResult: 'done' },
918
1140
  id: 'c3',
919
1141
  },
@@ -924,7 +1146,7 @@ describe('LocalAgentExecutor', () => {
924
1146
  await vi.advanceTimersByTimeAsync(150);
925
1147
  await vi.advanceTimersByTimeAsync(1);
926
1148
  const output = await runPromise;
927
- expect(mockScheduleAgentTools).toHaveBeenCalledTimes(1);
1149
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(2);
928
1150
  expect(output.terminate_reason).toBe(AgentTerminateMode.GOAL);
929
1151
  // Safe access to message parts
930
1152
  const turn2Params = getMockMessageParams(1);
@@ -955,7 +1177,7 @@ describe('LocalAgentExecutor', () => {
955
1177
  // Turn 2: Model gives up and completes
956
1178
  mockModelResponse([
957
1179
  {
958
- name: TASK_COMPLETE_TOOL_NAME,
1180
+ name: COMPLETE_TASK_TOOL_NAME,
959
1181
  args: { finalResult: 'Could not read file.' },
960
1182
  id: 'c2',
961
1183
  },
@@ -963,9 +1185,28 @@ describe('LocalAgentExecutor', () => {
963
1185
  const consoleWarnSpy = vi
964
1186
  .spyOn(debugLogger, 'warn')
965
1187
  .mockImplementation(() => { });
1188
+ mockScheduleAgentTools.mockResolvedValueOnce([
1189
+ {
1190
+ status: 'success',
1191
+ request: {
1192
+ callId: 'c2',
1193
+ name: COMPLETE_TASK_TOOL_NAME,
1194
+ args: { finalResult: 'Could not read file.' },
1195
+ prompt_id: 'p2',
1196
+ },
1197
+ response: {
1198
+ resultDisplay: 'Output submitted and task completed.',
1199
+ responseParts: [],
1200
+ data: {
1201
+ taskCompleted: true,
1202
+ submittedOutput: 'Could not read file.',
1203
+ },
1204
+ },
1205
+ },
1206
+ ]);
966
1207
  await executor.run({ goal: 'Sec test' }, signal);
967
- // Verify external executor was not called (Security held)
968
- expect(mockScheduleAgentTools).not.toHaveBeenCalled();
1208
+ // Verify external executor was called exactly once (for complete_task)
1209
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(1);
969
1210
  // 2. Verify console warning
970
1211
  expect(consoleWarnSpy).toHaveBeenCalledWith(expect.stringContaining(`[LocalAgentExecutor] Blocked call:`));
971
1212
  consoleWarnSpy.mockRestore();
@@ -1000,28 +1241,53 @@ describe('LocalAgentExecutor', () => {
1000
1241
  // Turn 1: Invalid arg (too short)
1001
1242
  mockModelResponse([
1002
1243
  {
1003
- name: TASK_COMPLETE_TOOL_NAME,
1244
+ name: COMPLETE_TASK_TOOL_NAME,
1004
1245
  args: { finalResult: 'short' },
1005
1246
  id: 'call1',
1006
1247
  },
1007
1248
  ]);
1249
+ const expectedError = 'Output validation failed: {"formErrors":["String must contain at least 10 character(s)"],"fieldErrors":{}}';
1250
+ mockScheduleAgentTools.mockResolvedValueOnce([
1251
+ {
1252
+ status: 'error',
1253
+ request: {
1254
+ callId: 'call1',
1255
+ name: COMPLETE_TASK_TOOL_NAME,
1256
+ args: { finalResult: 'short' },
1257
+ prompt_id: 'p1',
1258
+ },
1259
+ response: {
1260
+ resultDisplay: expectedError,
1261
+ responseParts: [
1262
+ {
1263
+ functionResponse: {
1264
+ name: COMPLETE_TASK_TOOL_NAME,
1265
+ id: 'call1',
1266
+ response: { error: expectedError },
1267
+ },
1268
+ },
1269
+ ],
1270
+ data: { taskCompleted: false },
1271
+ error: new Error(expectedError),
1272
+ },
1273
+ },
1274
+ ]);
1008
1275
  // Turn 2: Corrected
1009
1276
  mockModelResponse([
1010
1277
  {
1011
- name: TASK_COMPLETE_TOOL_NAME,
1278
+ name: COMPLETE_TASK_TOOL_NAME,
1012
1279
  args: { finalResult: 'This is a much longer and valid result' },
1013
1280
  id: 'call2',
1014
1281
  },
1015
1282
  ]);
1016
1283
  const output = await executor.run({ goal: 'Validation test' }, signal);
1017
1284
  expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
1018
- const expectedError = 'Output validation failed: {"formErrors":["String must contain at least 10 character(s)"],"fieldErrors":{}}';
1019
1285
  // Check that the error was reported in the activity stream
1020
1286
  expect(activities).toContainEqual(expect.objectContaining({
1021
1287
  type: 'ERROR',
1022
1288
  data: expect.objectContaining({
1023
1289
  context: 'tool_call',
1024
- name: TASK_COMPLETE_TOOL_NAME,
1290
+ name: COMPLETE_TASK_TOOL_NAME,
1025
1291
  error: expect.stringContaining('Output validation failed'),
1026
1292
  errorType: SubagentActivityErrorType.GENERIC,
1027
1293
  }),
@@ -1032,7 +1298,7 @@ describe('LocalAgentExecutor', () => {
1032
1298
  expect(turn2Parts).toEqual([
1033
1299
  expect.objectContaining({
1034
1300
  functionResponse: expect.objectContaining({
1035
- name: TASK_COMPLETE_TOOL_NAME,
1301
+ name: COMPLETE_TASK_TOOL_NAME,
1036
1302
  response: { error: expectedError },
1037
1303
  id: 'call1',
1038
1304
  }),
@@ -1105,13 +1371,32 @@ describe('LocalAgentExecutor', () => {
1105
1371
  // Turn 2: Model sees the error and completes
1106
1372
  mockModelResponse([
1107
1373
  {
1108
- name: TASK_COMPLETE_TOOL_NAME,
1374
+ name: COMPLETE_TASK_TOOL_NAME,
1109
1375
  args: { finalResult: 'Aborted due to tool failure.' },
1110
1376
  id: 'call2',
1111
1377
  },
1112
1378
  ]);
1379
+ mockScheduleAgentTools.mockResolvedValueOnce([
1380
+ {
1381
+ status: 'success',
1382
+ request: {
1383
+ callId: 'call2',
1384
+ name: COMPLETE_TASK_TOOL_NAME,
1385
+ args: { finalResult: 'Aborted due to tool failure.' },
1386
+ prompt_id: 'p2',
1387
+ },
1388
+ response: {
1389
+ resultDisplay: 'Task completed.',
1390
+ responseParts: [],
1391
+ data: {
1392
+ taskCompleted: true,
1393
+ submittedOutput: 'Aborted due to tool failure.',
1394
+ },
1395
+ },
1396
+ },
1397
+ ]);
1113
1398
  const output = await executor.run({ goal: 'Tool failure test' }, signal);
1114
- expect(mockScheduleAgentTools).toHaveBeenCalledTimes(1);
1399
+ expect(mockScheduleAgentTools).toHaveBeenCalledTimes(2);
1115
1400
  expect(mockSendMessageStream).toHaveBeenCalledTimes(2);
1116
1401
  // Verify the error was reported in the activity stream
1117
1402
  expect(activities).toContainEqual(expect.objectContaining({
@@ -1183,7 +1468,7 @@ describe('LocalAgentExecutor', () => {
1183
1468
  // Turn 2: Model sees the rejection + consolidated instructions and completes
1184
1469
  mockModelResponse([
1185
1470
  {
1186
- name: TASK_COMPLETE_TOOL_NAME,
1471
+ name: COMPLETE_TASK_TOOL_NAME,
1187
1472
  args: { finalResult: 'User rejected access to /secret.' },
1188
1473
  id: 'call2',
1189
1474
  },
@@ -1283,7 +1568,7 @@ describe('LocalAgentExecutor', () => {
1283
1568
  const executor = await LocalAgentExecutor.create(definition, mockConfig, onActivity);
1284
1569
  mockModelResponse([
1285
1570
  {
1286
- name: TASK_COMPLETE_TOOL_NAME,
1571
+ name: COMPLETE_TASK_TOOL_NAME,
1287
1572
  args: { finalResult: 'done' },
1288
1573
  id: 'call1',
1289
1574
  },
@@ -1307,7 +1592,7 @@ describe('LocalAgentExecutor', () => {
1307
1592
  const executor = await LocalAgentExecutor.create(definition, mockConfig, onActivity);
1308
1593
  mockModelResponse([
1309
1594
  {
1310
- name: TASK_COMPLETE_TOOL_NAME,
1595
+ name: COMPLETE_TASK_TOOL_NAME,
1311
1596
  args: { finalResult: 'done' },
1312
1597
  id: 'call1',
1313
1598
  },
@@ -1487,7 +1772,7 @@ describe('LocalAgentExecutor', () => {
1487
1772
  // Recovery Turn (succeeds)
1488
1773
  mockModelResponse([
1489
1774
  {
1490
- name: TASK_COMPLETE_TOOL_NAME,
1775
+ name: COMPLETE_TASK_TOOL_NAME,
1491
1776
  args: { finalResult: 'Recovered!' },
1492
1777
  id: 't2',
1493
1778
  },
@@ -1542,7 +1827,7 @@ describe('LocalAgentExecutor', () => {
1542
1827
  // Turn 3: Recovery turn (succeeds)
1543
1828
  mockModelResponse([
1544
1829
  {
1545
- name: TASK_COMPLETE_TOOL_NAME,
1830
+ name: COMPLETE_TASK_TOOL_NAME,
1546
1831
  args: { finalResult: 'Recovered from violation!' },
1547
1832
  id: 't3',
1548
1833
  },
@@ -1570,7 +1855,7 @@ describe('LocalAgentExecutor', () => {
1570
1855
  const output = await executor.run({ goal: 'Violation recovery fail' }, signal);
1571
1856
  expect(mockSendMessageStream).toHaveBeenCalledTimes(3);
1572
1857
  expect(output.terminate_reason).toBe(AgentTerminateMode.ERROR_NO_COMPLETE_TASK_CALL);
1573
- expect(output.result).toContain(`Agent stopped calling tools but did not call '${TASK_COMPLETE_TOOL_NAME}'`);
1858
+ expect(output.result).toContain(`Agent stopped calling tools but did not call '${COMPLETE_TASK_TOOL_NAME}'`);
1574
1859
  expect(activities).toContainEqual(expect.objectContaining({
1575
1860
  type: 'ERROR',
1576
1861
  data: expect.objectContaining({
@@ -1599,7 +1884,7 @@ describe('LocalAgentExecutor', () => {
1599
1884
  // Recovery turn (succeeds)
1600
1885
  mockModelResponse([
1601
1886
  {
1602
- name: TASK_COMPLETE_TOOL_NAME,
1887
+ name: COMPLETE_TASK_TOOL_NAME,
1603
1888
  args: { finalResult: 'Recovered from timeout!' },
1604
1889
  id: 't2',
1605
1890
  },
@@ -1721,7 +2006,7 @@ describe('LocalAgentExecutor', () => {
1721
2006
  // Recovery Turn (succeeds)
1722
2007
  mockModelResponse([
1723
2008
  {
1724
- name: TASK_COMPLETE_TOOL_NAME,
2009
+ name: COMPLETE_TASK_TOOL_NAME,
1725
2010
  args: { finalResult: 'Recovered!' },
1726
2011
  id: 't2',
1727
2012
  },
@@ -1759,7 +2044,7 @@ describe('LocalAgentExecutor', () => {
1759
2044
  // Turn 2: Model calls complete_task
1760
2045
  mockModelResponse([
1761
2046
  {
1762
- name: TASK_COMPLETE_TOOL_NAME,
2047
+ name: COMPLETE_TASK_TOOL_NAME,
1763
2048
  args: { finalResult: 'Done' },
1764
2049
  id: 'call2',
1765
2050
  },
@@ -1811,7 +2096,7 @@ describe('LocalAgentExecutor', () => {
1811
2096
  const executor = await LocalAgentExecutor.create(definition, configWithHints);
1812
2097
  mockModelResponse([
1813
2098
  {
1814
- name: TASK_COMPLETE_TOOL_NAME,
2099
+ name: COMPLETE_TASK_TOOL_NAME,
1815
2100
  args: { finalResult: 'Done' },
1816
2101
  id: 'call1',
1817
2102
  },
@@ -1841,7 +2126,7 @@ describe('LocalAgentExecutor', () => {
1841
2126
  // Turn 2: Model calls complete_task
1842
2127
  mockModelResponse([
1843
2128
  {
1844
- name: TASK_COMPLETE_TOOL_NAME,
2129
+ name: COMPLETE_TASK_TOOL_NAME,
1845
2130
  args: { finalResult: 'Done' },
1846
2131
  id: 'call2',
1847
2132
  },
@@ -1909,7 +2194,7 @@ describe('LocalAgentExecutor', () => {
1909
2194
  mockScheduleAgentTools.mockReturnValueOnce(toolCallPromise);
1910
2195
  mockModelResponse([
1911
2196
  {
1912
- name: TASK_COMPLETE_TOOL_NAME,
2197
+ name: COMPLETE_TASK_TOOL_NAME,
1913
2198
  args: { finalResult: 'Done' },
1914
2199
  id: 'call2',
1915
2200
  },
@@ -1964,7 +2249,7 @@ describe('LocalAgentExecutor', () => {
1964
2249
  mockScheduleAgentTools.mockReturnValueOnce(toolCallPromise);
1965
2250
  mockModelResponse([
1966
2251
  {
1967
- name: TASK_COMPLETE_TOOL_NAME,
2252
+ name: COMPLETE_TASK_TOOL_NAME,
1968
2253
  args: { finalResult: 'Done' },
1969
2254
  id: 'call2',
1970
2255
  },
@@ -2018,7 +2303,7 @@ describe('LocalAgentExecutor', () => {
2018
2303
  expect(configWithHints.injectionService.getInjections('background_completion')).toEqual(['bg output']);
2019
2304
  mockModelResponse([
2020
2305
  {
2021
- name: TASK_COMPLETE_TOOL_NAME,
2306
+ name: COMPLETE_TASK_TOOL_NAME,
2022
2307
  args: { finalResult: 'Done' },
2023
2308
  id: 'call1',
2024
2309
  },
@@ -2074,7 +2359,7 @@ describe('LocalAgentExecutor', () => {
2074
2359
  // Turn 2: Complete
2075
2360
  mockModelResponse([
2076
2361
  {
2077
- name: TASK_COMPLETE_TOOL_NAME,
2362
+ name: COMPLETE_TASK_TOOL_NAME,
2078
2363
  args: { finalResult: 'Done' },
2079
2364
  id: 'call2',
2080
2365
  },
@@ -2095,7 +2380,7 @@ describe('LocalAgentExecutor', () => {
2095
2380
  // Turn 1: Complete
2096
2381
  mockModelResponse([
2097
2382
  {
2098
- name: TASK_COMPLETE_TOOL_NAME,
2383
+ name: COMPLETE_TASK_TOOL_NAME,
2099
2384
  args: { finalResult: 'Done' },
2100
2385
  id: 'call1',
2101
2386
  },
@@ -2125,7 +2410,7 @@ describe('LocalAgentExecutor', () => {
2125
2410
  // Turn 2: Complete
2126
2411
  mockModelResponse([
2127
2412
  {
2128
- name: TASK_COMPLETE_TOOL_NAME,
2413
+ name: COMPLETE_TASK_TOOL_NAME,
2129
2414
  args: { finalResult: 'Done' },
2130
2415
  id: 't2',
2131
2416
  },
@@ -2167,7 +2452,7 @@ describe('LocalAgentExecutor', () => {
2167
2452
  // Turn 3: Complete
2168
2453
  mockModelResponse([
2169
2454
  {
2170
- name: TASK_COMPLETE_TOOL_NAME,
2455
+ name: COMPLETE_TASK_TOOL_NAME,
2171
2456
  args: { finalResult: 'Done' },
2172
2457
  id: 't3',
2173
2458
  },
@@ -2283,7 +2568,7 @@ describe('LocalAgentExecutor', () => {
2283
2568
  ]);
2284
2569
  mockModelResponse([
2285
2570
  {
2286
- name: TASK_COMPLETE_TOOL_NAME,
2571
+ name: COMPLETE_TASK_TOOL_NAME,
2287
2572
  args: { finalResult: 'done' },
2288
2573
  id: 'c1',
2289
2574
  },
@@ -2342,7 +2627,7 @@ describe('LocalAgentExecutor', () => {
2342
2627
  };
2343
2628
  mockModelResponse([
2344
2629
  {
2345
- name: TASK_COMPLETE_TOOL_NAME,
2630
+ name: COMPLETE_TASK_TOOL_NAME,
2346
2631
  args: { finalResult: 'ok' },
2347
2632
  id: 'c1',
2348
2633
  },
@@ -2353,7 +2638,7 @@ describe('LocalAgentExecutor', () => {
2353
2638
  const names = declarations.map((d) => d.name);
2354
2639
  expect(names.filter((n) => n === LS_TOOL_NAME)).toHaveLength(1);
2355
2640
  expect(names.filter((n) => n === 'fill')).toHaveLength(1);
2356
- expect(names.filter((n) => n === TASK_COMPLETE_TOOL_NAME)).toHaveLength(1);
2641
+ expect(names.filter((n) => n === COMPLETE_TASK_TOOL_NAME)).toHaveLength(1);
2357
2642
  // Total = ls + fill + complete_task
2358
2643
  expect(declarations).toHaveLength(3);
2359
2644
  });
@@ -2401,7 +2686,7 @@ describe('LocalAgentExecutor', () => {
2401
2686
  // Turn 2: Model completes
2402
2687
  mockModelResponse([
2403
2688
  {
2404
- name: TASK_COMPLETE_TOOL_NAME,
2689
+ name: COMPLETE_TASK_TOOL_NAME,
2405
2690
  args: { finalResult: 'done' },
2406
2691
  id: 'call-done',
2407
2692
  },
@@ -2420,7 +2705,7 @@ describe('LocalAgentExecutor', () => {
2420
2705
  const definition = createInstanceToolDefinition([new MockTool({ name: 'take_snapshot' })], 'none');
2421
2706
  mockModelResponse([
2422
2707
  {
2423
- name: TASK_COMPLETE_TOOL_NAME,
2708
+ name: COMPLETE_TASK_TOOL_NAME,
2424
2709
  args: { result: 'done' },
2425
2710
  id: 'c1',
2426
2711
  },
@@ -2429,7 +2714,7 @@ describe('LocalAgentExecutor', () => {
2429
2714
  await executor.run({ goal: 'Test' }, signal);
2430
2715
  const declarations = getSentFunctionDeclarations();
2431
2716
  const names = declarations.map((d) => d.name);
2432
- expect(names).toContain(TASK_COMPLETE_TOOL_NAME);
2717
+ expect(names).toContain(COMPLETE_TASK_TOOL_NAME);
2433
2718
  expect(names).toContain('take_snapshot');
2434
2719
  expect(declarations).toHaveLength(2);
2435
2720
  });
@@ -2455,7 +2740,7 @@ describe('LocalAgentExecutor', () => {
2455
2740
  const definition = createInstanceToolDefinition(instanceTools);
2456
2741
  mockModelResponse([
2457
2742
  {
2458
- name: TASK_COMPLETE_TOOL_NAME,
2743
+ name: COMPLETE_TASK_TOOL_NAME,
2459
2744
  args: { finalResult: 'done' },
2460
2745
  id: 'c1',
2461
2746
  },
@@ -2483,7 +2768,7 @@ describe('LocalAgentExecutor', () => {
2483
2768
  vi.spyOn(mockConfig, 'getSystemInstructionMemory').mockReturnValue(mockMemory);
2484
2769
  mockModelResponse([
2485
2770
  {
2486
- name: TASK_COMPLETE_TOOL_NAME,
2771
+ name: COMPLETE_TASK_TOOL_NAME,
2487
2772
  args: { finalResult: 'done' },
2488
2773
  id: 'call1',
2489
2774
  },
@@ -2502,7 +2787,7 @@ describe('LocalAgentExecutor', () => {
2502
2787
  vi.spyOn(mockConfig, 'isJitContextEnabled').mockReturnValue(false);
2503
2788
  mockModelResponse([
2504
2789
  {
2505
- name: TASK_COMPLETE_TOOL_NAME,
2790
+ name: COMPLETE_TASK_TOOL_NAME,
2506
2791
  args: { finalResult: 'done' },
2507
2792
  id: 'call1',
2508
2793
  },
@@ -2523,7 +2808,7 @@ describe('LocalAgentExecutor', () => {
2523
2808
  vi.spyOn(mockConfig, 'isJitContextEnabled').mockReturnValue(true);
2524
2809
  mockModelResponse([
2525
2810
  {
2526
- name: TASK_COMPLETE_TOOL_NAME,
2811
+ name: COMPLETE_TASK_TOOL_NAME,
2527
2812
  args: { finalResult: 'done' },
2528
2813
  id: 'call1',
2529
2814
  },