@google/gemini-cli-core 0.12.0-nightly.20251023.c4c0c0d1 → 0.12.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 (258) hide show
  1. package/README.md +7 -5
  2. package/dist/index.d.ts +3 -0
  3. package/dist/index.js +2 -0
  4. package/dist/index.js.map +1 -1
  5. package/dist/src/agents/subagent-tool-wrapper.test.js +2 -4
  6. package/dist/src/agents/subagent-tool-wrapper.test.js.map +1 -1
  7. package/dist/src/code_assist/oauth2.d.ts +2 -2
  8. package/dist/src/code_assist/oauth2.js +53 -41
  9. package/dist/src/code_assist/oauth2.js.map +1 -1
  10. package/dist/src/code_assist/oauth2.test.js +65 -33
  11. package/dist/src/code_assist/oauth2.test.js.map +1 -1
  12. package/dist/src/code_assist/server.d.ts +3 -3
  13. package/dist/src/code_assist/server.js.map +1 -1
  14. package/dist/src/code_assist/setup.d.ts +2 -2
  15. package/dist/src/code_assist/setup.js.map +1 -1
  16. package/dist/src/config/config.d.ts +12 -3
  17. package/dist/src/config/config.js +35 -9
  18. package/dist/src/config/config.js.map +1 -1
  19. package/dist/src/config/config.test.js +58 -21
  20. package/dist/src/config/config.test.js.map +1 -1
  21. package/dist/src/config/storage.d.ts +1 -0
  22. package/dist/src/config/storage.js +3 -0
  23. package/dist/src/config/storage.js.map +1 -1
  24. package/dist/src/core/client.d.ts +1 -11
  25. package/dist/src/core/client.js +17 -165
  26. package/dist/src/core/client.js.map +1 -1
  27. package/dist/src/core/client.test.js +70 -405
  28. package/dist/src/core/client.test.js.map +1 -1
  29. package/dist/src/core/contentGenerator.js +39 -28
  30. package/dist/src/core/contentGenerator.js.map +1 -1
  31. package/dist/src/core/contentGenerator.test.js +28 -0
  32. package/dist/src/core/contentGenerator.test.js.map +1 -1
  33. package/dist/src/core/coreToolScheduler.d.ts +7 -7
  34. package/dist/src/core/coreToolScheduler.js +312 -183
  35. package/dist/src/core/coreToolScheduler.js.map +1 -1
  36. package/dist/src/core/coreToolScheduler.test.js +239 -9
  37. package/dist/src/core/coreToolScheduler.test.js.map +1 -1
  38. package/dist/src/core/fakeContentGenerator.d.ts +33 -0
  39. package/dist/src/core/fakeContentGenerator.js +58 -0
  40. package/dist/src/core/fakeContentGenerator.js.map +1 -0
  41. package/dist/src/core/fakeContentGenerator.test.d.ts +6 -0
  42. package/dist/src/core/fakeContentGenerator.test.js +127 -0
  43. package/dist/src/core/fakeContentGenerator.test.js.map +1 -0
  44. package/dist/src/core/loggingContentGenerator.d.ts +1 -0
  45. package/dist/src/core/loggingContentGenerator.js +113 -33
  46. package/dist/src/core/loggingContentGenerator.js.map +1 -1
  47. package/dist/src/core/nonInteractiveToolExecutor.js +5 -4
  48. package/dist/src/core/nonInteractiveToolExecutor.js.map +1 -1
  49. package/dist/src/core/prompts.test.js +30 -108
  50. package/dist/src/core/prompts.test.js.map +1 -1
  51. package/dist/src/core/recordingContentGenerator.d.ts +18 -0
  52. package/dist/src/core/recordingContentGenerator.js +77 -0
  53. package/dist/src/core/recordingContentGenerator.js.map +1 -0
  54. package/dist/src/core/recordingContentGenerator.test.d.ts +6 -0
  55. package/dist/src/core/recordingContentGenerator.test.js +101 -0
  56. package/dist/src/core/recordingContentGenerator.test.js.map +1 -0
  57. package/dist/src/fallback/handler.js +2 -0
  58. package/dist/src/fallback/handler.js.map +1 -1
  59. package/dist/src/generated/git-commit.d.ts +2 -2
  60. package/dist/src/generated/git-commit.js +2 -2
  61. package/dist/src/generated/git-commit.js.map +1 -1
  62. package/dist/src/index.d.ts +3 -0
  63. package/dist/src/index.js +3 -0
  64. package/dist/src/index.js.map +1 -1
  65. package/dist/src/mcp/google-auth-provider.d.ts +2 -0
  66. package/dist/src/mcp/google-auth-provider.js +19 -2
  67. package/dist/src/mcp/google-auth-provider.js.map +1 -1
  68. package/dist/src/mcp/google-auth-provider.test.js +42 -9
  69. package/dist/src/mcp/google-auth-provider.test.js.map +1 -1
  70. package/dist/src/mcp/oauth-provider.js +2 -2
  71. package/dist/src/mcp/oauth-provider.js.map +1 -1
  72. package/dist/src/mcp/oauth-provider.test.js +130 -0
  73. package/dist/src/mcp/oauth-provider.test.js.map +1 -1
  74. package/dist/src/mcp/oauth-token-storage.js +5 -4
  75. package/dist/src/mcp/oauth-token-storage.js.map +1 -1
  76. package/dist/src/mcp/oauth-token-storage.test.js +17 -11
  77. package/dist/src/mcp/oauth-token-storage.test.js.map +1 -1
  78. package/dist/src/mcp/oauth-utils.d.ts +7 -0
  79. package/dist/src/mcp/oauth-utils.js +19 -0
  80. package/dist/src/mcp/oauth-utils.js.map +1 -1
  81. package/dist/src/mcp/oauth-utils.test.js +32 -0
  82. package/dist/src/mcp/oauth-utils.test.js.map +1 -1
  83. package/dist/src/mcp/sa-impersonation-provider.d.ts +0 -6
  84. package/dist/src/mcp/sa-impersonation-provider.js +6 -23
  85. package/dist/src/mcp/sa-impersonation-provider.js.map +1 -1
  86. package/dist/src/mcp/token-storage/base-token-storage.test.js +75 -84
  87. package/dist/src/mcp/token-storage/base-token-storage.test.js.map +1 -1
  88. package/dist/src/mcp/token-storage/keychain-token-storage.d.ts +6 -2
  89. package/dist/src/mcp/token-storage/keychain-token-storage.js +62 -6
  90. package/dist/src/mcp/token-storage/keychain-token-storage.js.map +1 -1
  91. package/dist/src/mcp/token-storage/keychain-token-storage.test.js +54 -3
  92. package/dist/src/mcp/token-storage/keychain-token-storage.test.js.map +1 -1
  93. package/dist/src/mcp/token-storage/types.d.ts +6 -0
  94. package/dist/src/mcp/token-storage/types.js.map +1 -1
  95. package/dist/src/policy/policy-engine.js +4 -0
  96. package/dist/src/policy/policy-engine.js.map +1 -1
  97. package/dist/src/services/chatCompressionService.d.ts +32 -0
  98. package/dist/src/services/chatCompressionService.js +164 -0
  99. package/dist/src/services/chatCompressionService.js.map +1 -0
  100. package/dist/src/services/chatCompressionService.test.d.ts +6 -0
  101. package/dist/src/services/chatCompressionService.test.js +211 -0
  102. package/dist/src/services/chatCompressionService.test.js.map +1 -0
  103. package/dist/src/services/fileDiscoveryService.d.ts +0 -8
  104. package/dist/src/services/fileDiscoveryService.js +5 -33
  105. package/dist/src/services/fileDiscoveryService.js.map +1 -1
  106. package/dist/src/services/fileDiscoveryService.test.js +11 -11
  107. package/dist/src/services/fileDiscoveryService.test.js.map +1 -1
  108. package/dist/src/services/loopDetectionService.js +19 -9
  109. package/dist/src/services/loopDetectionService.js.map +1 -1
  110. package/dist/src/services/loopDetectionService.test.js +40 -11
  111. package/dist/src/services/loopDetectionService.test.js.map +1 -1
  112. package/dist/src/telemetry/clearcut-logger/clearcut-logger.d.ts +1 -0
  113. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js +40 -33
  114. package/dist/src/telemetry/clearcut-logger/clearcut-logger.js.map +1 -1
  115. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js +1 -1
  116. package/dist/src/telemetry/clearcut-logger/clearcut-logger.test.js.map +1 -1
  117. package/dist/src/telemetry/index.d.ts +1 -0
  118. package/dist/src/telemetry/index.js +1 -0
  119. package/dist/src/telemetry/index.js.map +1 -1
  120. package/dist/src/telemetry/loggers.js +10 -17
  121. package/dist/src/telemetry/loggers.js.map +1 -1
  122. package/dist/src/telemetry/loggers.test.js +173 -30
  123. package/dist/src/telemetry/loggers.test.js.map +1 -1
  124. package/dist/src/telemetry/metrics.d.ts +1 -1
  125. package/dist/src/telemetry/metrics.js +1 -1
  126. package/dist/src/telemetry/metrics.js.map +1 -1
  127. package/dist/src/telemetry/metrics.test.js +2 -2
  128. package/dist/src/telemetry/metrics.test.js.map +1 -1
  129. package/dist/src/telemetry/semantic.d.ts +82 -0
  130. package/dist/src/telemetry/semantic.js +269 -0
  131. package/dist/src/telemetry/semantic.js.map +1 -0
  132. package/dist/src/telemetry/semantic.test.d.ts +6 -0
  133. package/dist/src/telemetry/semantic.test.js +387 -0
  134. package/dist/src/telemetry/semantic.test.js.map +1 -0
  135. package/dist/src/telemetry/trace.d.ts +46 -0
  136. package/dist/src/telemetry/trace.js +121 -0
  137. package/dist/src/telemetry/trace.js.map +1 -0
  138. package/dist/src/telemetry/types.d.ts +37 -18
  139. package/dist/src/telemetry/types.js +107 -36
  140. package/dist/src/telemetry/types.js.map +1 -1
  141. package/dist/src/telemetry/uiTelemetry.js +6 -6
  142. package/dist/src/telemetry/uiTelemetry.js.map +1 -1
  143. package/dist/src/telemetry/uiTelemetry.test.js +88 -66
  144. package/dist/src/telemetry/uiTelemetry.test.js.map +1 -1
  145. package/dist/src/tools/edit.d.ts +3 -2
  146. package/dist/src/tools/edit.js +15 -11
  147. package/dist/src/tools/edit.js.map +1 -1
  148. package/dist/src/tools/edit.test.js +19 -0
  149. package/dist/src/tools/edit.test.js.map +1 -1
  150. package/dist/src/tools/glob.js +4 -2
  151. package/dist/src/tools/glob.js.map +1 -1
  152. package/dist/src/tools/glob.test.js +203 -199
  153. package/dist/src/tools/glob.test.js.map +1 -1
  154. package/dist/src/tools/grep.js +2 -2
  155. package/dist/src/tools/grep.js.map +1 -1
  156. package/dist/src/tools/ls.js +2 -1
  157. package/dist/src/tools/ls.js.map +1 -1
  158. package/dist/src/tools/ls.test.js +0 -7
  159. package/dist/src/tools/ls.test.js.map +1 -1
  160. package/dist/src/tools/mcp-client-manager.js +2 -1
  161. package/dist/src/tools/mcp-client-manager.js.map +1 -1
  162. package/dist/src/tools/mcp-client.d.ts +4 -1
  163. package/dist/src/tools/mcp-client.js +71 -92
  164. package/dist/src/tools/mcp-client.js.map +1 -1
  165. package/dist/src/tools/mcp-client.test.js +16 -6
  166. package/dist/src/tools/mcp-client.test.js.map +1 -1
  167. package/dist/src/tools/mcp-tool.d.ts +3 -2
  168. package/dist/src/tools/mcp-tool.js +12 -10
  169. package/dist/src/tools/mcp-tool.js.map +1 -1
  170. package/dist/src/tools/memoryTool.d.ts +5 -3
  171. package/dist/src/tools/memoryTool.js +9 -7
  172. package/dist/src/tools/memoryTool.js.map +1 -1
  173. package/dist/src/tools/read-file.js +7 -3
  174. package/dist/src/tools/read-file.js.map +1 -1
  175. package/dist/src/tools/read-file.test.js +25 -2
  176. package/dist/src/tools/read-file.test.js.map +1 -1
  177. package/dist/src/tools/shell.d.ts +6 -4
  178. package/dist/src/tools/shell.js +18 -12
  179. package/dist/src/tools/shell.js.map +1 -1
  180. package/dist/src/tools/shell.test.js +7 -0
  181. package/dist/src/tools/shell.test.js.map +1 -1
  182. package/dist/src/tools/smart-edit.d.ts +2 -1
  183. package/dist/src/tools/smart-edit.js +10 -9
  184. package/dist/src/tools/smart-edit.js.map +1 -1
  185. package/dist/src/tools/tool-registry.d.ts +5 -1
  186. package/dist/src/tools/tool-registry.js +10 -3
  187. package/dist/src/tools/tool-registry.js.map +1 -1
  188. package/dist/src/tools/tools.d.ts +6 -0
  189. package/dist/src/tools/tools.js +29 -17
  190. package/dist/src/tools/tools.js.map +1 -1
  191. package/dist/src/tools/web-fetch.js +1 -12
  192. package/dist/src/tools/web-fetch.js.map +1 -1
  193. package/dist/src/tools/web-fetch.test.js +2 -2
  194. package/dist/src/tools/web-fetch.test.js.map +1 -1
  195. package/dist/src/tools/write-file.d.ts +2 -1
  196. package/dist/src/tools/write-file.js +6 -6
  197. package/dist/src/tools/write-file.js.map +1 -1
  198. package/dist/src/tools/write-todos.d.ts +2 -1
  199. package/dist/src/tools/write-todos.js +5 -2
  200. package/dist/src/tools/write-todos.js.map +1 -1
  201. package/dist/src/utils/environmentContext.d.ts +2 -1
  202. package/dist/src/utils/environmentContext.js +18 -0
  203. package/dist/src/utils/environmentContext.js.map +1 -1
  204. package/dist/src/utils/errorParsing.d.ts +1 -1
  205. package/dist/src/utils/errorParsing.js +5 -33
  206. package/dist/src/utils/errorParsing.js.map +1 -1
  207. package/dist/src/utils/errorParsing.test.js +0 -88
  208. package/dist/src/utils/errorParsing.test.js.map +1 -1
  209. package/dist/src/utils/errors.d.ts +3 -0
  210. package/dist/src/utils/errors.js +6 -0
  211. package/dist/src/utils/errors.js.map +1 -1
  212. package/dist/src/utils/events.d.ts +19 -1
  213. package/dist/src/utils/events.js +9 -0
  214. package/dist/src/utils/events.js.map +1 -1
  215. package/dist/src/utils/extensionLoader.d.ts +38 -0
  216. package/dist/src/utils/extensionLoader.js +20 -0
  217. package/dist/src/utils/extensionLoader.js.map +1 -0
  218. package/dist/src/utils/flashFallback.test.js +26 -45
  219. package/dist/src/utils/flashFallback.test.js.map +1 -1
  220. package/dist/src/utils/getFolderStructure.js +7 -16
  221. package/dist/src/utils/getFolderStructure.js.map +1 -1
  222. package/dist/src/utils/googleErrors.d.ts +104 -0
  223. package/dist/src/utils/googleErrors.js +152 -0
  224. package/dist/src/utils/googleErrors.js.map +1 -0
  225. package/dist/src/utils/googleErrors.test.d.ts +6 -0
  226. package/dist/src/utils/googleErrors.test.js +301 -0
  227. package/dist/src/utils/googleErrors.test.js.map +1 -0
  228. package/dist/src/utils/googleQuotaErrors.d.ts +35 -0
  229. package/dist/src/utils/googleQuotaErrors.js +131 -0
  230. package/dist/src/utils/googleQuotaErrors.js.map +1 -0
  231. package/dist/src/utils/googleQuotaErrors.test.d.ts +6 -0
  232. package/dist/src/utils/googleQuotaErrors.test.js +281 -0
  233. package/dist/src/utils/googleQuotaErrors.test.js.map +1 -0
  234. package/dist/src/utils/ignorePatterns.test.js +26 -30
  235. package/dist/src/utils/ignorePatterns.test.js.map +1 -1
  236. package/dist/src/utils/memoryDiscovery.d.ts +2 -2
  237. package/dist/src/utils/memoryDiscovery.js +3 -2
  238. package/dist/src/utils/memoryDiscovery.js.map +1 -1
  239. package/dist/src/utils/memoryDiscovery.test.js +19 -35
  240. package/dist/src/utils/memoryDiscovery.test.js.map +1 -1
  241. package/dist/src/utils/paths.js +126 -26
  242. package/dist/src/utils/paths.js.map +1 -1
  243. package/dist/src/utils/paths.test.js +200 -68
  244. package/dist/src/utils/paths.test.js.map +1 -1
  245. package/dist/src/utils/quotaErrorDetection.d.ts +0 -2
  246. package/dist/src/utils/quotaErrorDetection.js +0 -46
  247. package/dist/src/utils/quotaErrorDetection.js.map +1 -1
  248. package/dist/src/utils/retry.js +41 -145
  249. package/dist/src/utils/retry.js.map +1 -1
  250. package/dist/src/utils/retry.test.js +31 -110
  251. package/dist/src/utils/retry.test.js.map +1 -1
  252. package/dist/src/utils/shell-utils.test.js +70 -0
  253. package/dist/src/utils/shell-utils.test.js.map +1 -1
  254. package/dist/src/utils/workspaceContext.js +1 -1
  255. package/dist/src/utils/workspaceContext.js.map +1 -1
  256. package/dist/tsconfig.tsbuildinfo +1 -1
  257. package/package.json +2 -2
  258. package/dist/google-gemini-cli-core-0.12.0-nightly.20251022.0542de95.tgz +0 -0
@@ -3,7 +3,7 @@
3
3
  * Copyright 2025 Google LLC
4
4
  * SPDX-License-Identifier: Apache-2.0
5
5
  */
6
- import { ToolConfirmationOutcome, ApprovalMode, logToolCall, ToolErrorType, ToolCallEvent, logToolOutputTruncated, ToolOutputTruncatedEvent, } from '../index.js';
6
+ import { ToolConfirmationOutcome, ApprovalMode, logToolCall, ToolErrorType, ToolCallEvent, logToolOutputTruncated, ToolOutputTruncatedEvent, runInDevTraceSpan, } from '../index.js';
7
7
  import { READ_FILE_TOOL_NAME, SHELL_TOOL_NAME } from '../tools/tool-names.js';
8
8
  import { getResponseTextFromParts } from '../utils/generateContentResponseUtilities.js';
9
9
  import { isModifiableDeclarativeTool, modifyWithEditor, } from '../tools/modifiable-tool.js';
@@ -145,6 +145,9 @@ ${truncatedContent}`,
145
145
  }
146
146
  }
147
147
  export class CoreToolScheduler {
148
+ // Static WeakMap to track which MessageBus instances already have a handler subscribed
149
+ // This prevents duplicate subscriptions when multiple CoreToolScheduler instances are created
150
+ static subscribedMessageBuses = new WeakMap();
148
151
  toolCalls = [];
149
152
  outputUpdateHandler;
150
153
  onAllToolCallsComplete;
@@ -154,7 +157,10 @@ export class CoreToolScheduler {
154
157
  onEditorClose;
155
158
  isFinalizingToolCalls = false;
156
159
  isScheduling = false;
160
+ isCancelling = false;
157
161
  requestQueue = [];
162
+ toolCallQueue = [];
163
+ completedToolCallsForBatch = [];
158
164
  constructor(options) {
159
165
  this.config = options.config;
160
166
  this.outputUpdateHandler = options.outputUpdateHandler;
@@ -163,12 +169,31 @@ export class CoreToolScheduler {
163
169
  this.getPreferredEditor = options.getPreferredEditor;
164
170
  this.onEditorClose = options.onEditorClose;
165
171
  // Subscribe to message bus for ASK_USER policy decisions
172
+ // Use a static WeakMap to ensure we only subscribe ONCE per MessageBus instance
173
+ // This prevents memory leaks when multiple CoreToolScheduler instances are created
174
+ // (e.g., on every React render, or for each non-interactive tool call)
166
175
  if (this.config.getEnableMessageBusIntegration()) {
167
176
  const messageBus = this.config.getMessageBus();
168
- messageBus.subscribe(MessageBusType.TOOL_CONFIRMATION_REQUEST, this.handleToolConfirmationRequest.bind(this));
177
+ // Check if we've already subscribed a handler to this message bus
178
+ if (!CoreToolScheduler.subscribedMessageBuses.has(messageBus)) {
179
+ // Create a shared handler that will be used for this message bus
180
+ const sharedHandler = (request) => {
181
+ // When ASK_USER policy decision is made, respond with requiresUserConfirmation=true
182
+ // to tell tools to use their legacy confirmation flow
183
+ messageBus.publish({
184
+ type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
185
+ correlationId: request.correlationId,
186
+ confirmed: false,
187
+ requiresUserConfirmation: true,
188
+ });
189
+ };
190
+ messageBus.subscribe(MessageBusType.TOOL_CONFIRMATION_REQUEST, sharedHandler);
191
+ // Store the handler in the WeakMap so we don't subscribe again
192
+ CoreToolScheduler.subscribedMessageBuses.set(messageBus, sharedHandler);
193
+ }
169
194
  }
170
195
  }
171
- setStatusInternal(targetCallId, newStatus, auxiliaryData) {
196
+ setStatusInternal(targetCallId, newStatus, signal, auxiliaryData) {
172
197
  this.toolCalls = this.toolCalls.map((currentCall) => {
173
198
  if (currentCall.request.callId !== targetCallId ||
174
199
  currentCall.status === 'success' ||
@@ -298,7 +323,6 @@ export class CoreToolScheduler {
298
323
  }
299
324
  });
300
325
  this.notifyToolCallsUpdate();
301
- this.checkAndNotifyCompletion();
302
326
  }
303
327
  setArgsInternal(targetCallId, args) {
304
328
  this.toolCalls = this.toolCalls.map((call) => {
@@ -368,40 +392,66 @@ export class CoreToolScheduler {
368
392
  }
369
393
  }
370
394
  schedule(request, signal) {
371
- if (this.isRunning() || this.isScheduling) {
372
- return new Promise((resolve, reject) => {
373
- const abortHandler = () => {
374
- // Find and remove the request from the queue
375
- const index = this.requestQueue.findIndex((item) => item.request === request);
376
- if (index > -1) {
377
- this.requestQueue.splice(index, 1);
378
- reject(new Error('Tool call cancelled while in queue.'));
379
- }
380
- };
381
- signal.addEventListener('abort', abortHandler, { once: true });
382
- this.requestQueue.push({
383
- request,
384
- signal,
385
- resolve: () => {
386
- signal.removeEventListener('abort', abortHandler);
387
- resolve();
388
- },
389
- reject: (reason) => {
390
- signal.removeEventListener('abort', abortHandler);
391
- reject(reason);
392
- },
395
+ return runInDevTraceSpan({ name: 'schedule' }, async ({ metadata: spanMetadata }) => {
396
+ spanMetadata.input = request;
397
+ if (this.isRunning() || this.isScheduling) {
398
+ return new Promise((resolve, reject) => {
399
+ const abortHandler = () => {
400
+ // Find and remove the request from the queue
401
+ const index = this.requestQueue.findIndex((item) => item.request === request);
402
+ if (index > -1) {
403
+ this.requestQueue.splice(index, 1);
404
+ reject(new Error('Tool call cancelled while in queue.'));
405
+ }
406
+ };
407
+ signal.addEventListener('abort', abortHandler, { once: true });
408
+ this.requestQueue.push({
409
+ request,
410
+ signal,
411
+ resolve: () => {
412
+ signal.removeEventListener('abort', abortHandler);
413
+ resolve();
414
+ },
415
+ reject: (reason) => {
416
+ signal.removeEventListener('abort', abortHandler);
417
+ reject(reason);
418
+ },
419
+ });
393
420
  });
394
- });
421
+ }
422
+ return this._schedule(request, signal);
423
+ });
424
+ }
425
+ cancelAll(signal) {
426
+ if (this.isCancelling) {
427
+ return;
428
+ }
429
+ this.isCancelling = true;
430
+ // Cancel the currently active tool call, if there is one.
431
+ if (this.toolCalls.length > 0) {
432
+ const activeCall = this.toolCalls[0];
433
+ // Only cancel if it's in a cancellable state.
434
+ if (activeCall.status === 'awaiting_approval' ||
435
+ activeCall.status === 'executing' ||
436
+ activeCall.status === 'scheduled' ||
437
+ activeCall.status === 'validating') {
438
+ this.setStatusInternal(activeCall.request.callId, 'cancelled', signal, 'User cancelled the operation.');
439
+ }
395
440
  }
396
- return this._schedule(request, signal);
441
+ // Clear the queue and mark all queued items as cancelled for completion reporting.
442
+ this._cancelAllQueuedCalls();
443
+ // Finalize the batch immediately.
444
+ void this.checkAndNotifyCompletion(signal);
397
445
  }
398
446
  async _schedule(request, signal) {
399
447
  this.isScheduling = true;
448
+ this.isCancelling = false;
400
449
  try {
401
450
  if (this.isRunning()) {
402
451
  throw new Error('Cannot schedule new tool calls while other tool calls are actively running (executing or awaiting approval).');
403
452
  }
404
453
  const requestsToProcess = Array.isArray(request) ? request : [request];
454
+ this.completedToolCallsForBatch = [];
405
455
  const newToolCalls = requestsToProcess.map((reqInfo) => {
406
456
  const toolInstance = this.config
407
457
  .getToolRegistry()
@@ -434,28 +484,55 @@ export class CoreToolScheduler {
434
484
  startTime: Date.now(),
435
485
  };
436
486
  });
437
- this.toolCalls = this.toolCalls.concat(newToolCalls);
438
- this.notifyToolCallsUpdate();
439
- for (const toolCall of newToolCalls) {
440
- if (toolCall.status !== 'validating') {
441
- continue;
487
+ this.toolCallQueue.push(...newToolCalls);
488
+ await this._processNextInQueue(signal);
489
+ }
490
+ finally {
491
+ this.isScheduling = false;
492
+ }
493
+ }
494
+ async _processNextInQueue(signal) {
495
+ // If there's already a tool being processed, or the queue is empty, stop.
496
+ if (this.toolCalls.length > 0 || this.toolCallQueue.length === 0) {
497
+ return;
498
+ }
499
+ // If cancellation happened between steps, handle it.
500
+ if (signal.aborted) {
501
+ this._cancelAllQueuedCalls();
502
+ // Finalize the batch.
503
+ await this.checkAndNotifyCompletion(signal);
504
+ return;
505
+ }
506
+ const toolCall = this.toolCallQueue.shift();
507
+ // This is now the single active tool call.
508
+ this.toolCalls = [toolCall];
509
+ this.notifyToolCallsUpdate();
510
+ // Handle tools that were already errored during creation.
511
+ if (toolCall.status === 'error') {
512
+ // An error during validation means this "active" tool is already complete.
513
+ // We need to check for batch completion to either finish or process the next in queue.
514
+ await this.checkAndNotifyCompletion(signal);
515
+ return;
516
+ }
517
+ // This logic is moved from the old `for` loop in `_schedule`.
518
+ if (toolCall.status === 'validating') {
519
+ const { request: reqInfo, invocation } = toolCall;
520
+ try {
521
+ if (signal.aborted) {
522
+ this.setStatusInternal(reqInfo.callId, 'cancelled', signal, 'Tool call cancelled by user.');
523
+ // The completion check will handle the cascade.
524
+ await this.checkAndNotifyCompletion(signal);
525
+ return;
442
526
  }
443
- const validatingCall = toolCall;
444
- const { request: reqInfo, invocation } = validatingCall;
445
- try {
446
- if (signal.aborted) {
447
- this.setStatusInternal(reqInfo.callId, 'cancelled', 'Tool call cancelled by user.');
448
- continue;
449
- }
450
- const confirmationDetails = await invocation.shouldConfirmExecute(signal);
451
- if (!confirmationDetails) {
452
- this.setToolCallOutcome(reqInfo.callId, ToolConfirmationOutcome.ProceedAlways);
453
- this.setStatusInternal(reqInfo.callId, 'scheduled');
454
- continue;
455
- }
456
- if (this.isAutoApproved(validatingCall)) {
527
+ const confirmationDetails = await invocation.shouldConfirmExecute(signal);
528
+ if (!confirmationDetails) {
529
+ this.setToolCallOutcome(reqInfo.callId, ToolConfirmationOutcome.ProceedAlways);
530
+ this.setStatusInternal(reqInfo.callId, 'scheduled', signal);
531
+ }
532
+ else {
533
+ if (this.isAutoApproved(toolCall)) {
457
534
  this.setToolCallOutcome(reqInfo.callId, ToolConfirmationOutcome.ProceedAlways);
458
- this.setStatusInternal(reqInfo.callId, 'scheduled');
535
+ this.setStatusInternal(reqInfo.callId, 'scheduled', signal);
459
536
  }
460
537
  else {
461
538
  // Allow IDE to resolve confirmation
@@ -475,35 +552,33 @@ export class CoreToolScheduler {
475
552
  ...confirmationDetails,
476
553
  onConfirm: (outcome, payload) => this.handleConfirmationResponse(reqInfo.callId, originalOnConfirm, outcome, signal, payload),
477
554
  };
478
- this.setStatusInternal(reqInfo.callId, 'awaiting_approval', wrappedConfirmationDetails);
555
+ this.setStatusInternal(reqInfo.callId, 'awaiting_approval', signal, wrappedConfirmationDetails);
479
556
  }
480
557
  }
481
- catch (error) {
482
- if (signal.aborted) {
483
- this.setStatusInternal(reqInfo.callId, 'cancelled', 'Tool call cancelled by user.');
484
- continue;
485
- }
486
- this.setStatusInternal(reqInfo.callId, 'error', createErrorResponse(reqInfo, error instanceof Error ? error : new Error(String(error)), ToolErrorType.UNHANDLED_EXCEPTION));
558
+ }
559
+ catch (error) {
560
+ if (signal.aborted) {
561
+ this.setStatusInternal(reqInfo.callId, 'cancelled', signal, 'Tool call cancelled by user.');
562
+ await this.checkAndNotifyCompletion(signal);
563
+ }
564
+ else {
565
+ this.setStatusInternal(reqInfo.callId, 'error', signal, createErrorResponse(reqInfo, error instanceof Error ? error : new Error(String(error)), ToolErrorType.UNHANDLED_EXCEPTION));
566
+ await this.checkAndNotifyCompletion(signal);
487
567
  }
488
568
  }
489
- await this.attemptExecutionOfScheduledCalls(signal);
490
- void this.checkAndNotifyCompletion();
491
- }
492
- finally {
493
- this.isScheduling = false;
494
569
  }
570
+ await this.attemptExecutionOfScheduledCalls(signal);
495
571
  }
496
572
  async handleConfirmationResponse(callId, originalOnConfirm, outcome, signal, payload) {
497
573
  const toolCall = this.toolCalls.find((c) => c.request.callId === callId && c.status === 'awaiting_approval');
498
574
  if (toolCall && toolCall.status === 'awaiting_approval') {
499
575
  await originalOnConfirm(outcome);
500
576
  }
501
- if (outcome === ToolConfirmationOutcome.ProceedAlways) {
502
- await this.autoApproveCompatiblePendingTools(signal, callId);
503
- }
504
577
  this.setToolCallOutcome(callId, outcome);
505
578
  if (outcome === ToolConfirmationOutcome.Cancel || signal.aborted) {
506
- this.setStatusInternal(callId, 'cancelled', 'User did not allow tool call');
579
+ // Instead of just cancelling one tool, trigger the full cancel cascade.
580
+ this.cancelAll(signal);
581
+ return; // `cancelAll` calls `checkAndNotifyCompletion`, so we can exit here.
507
582
  }
508
583
  else if (outcome === ToolConfirmationOutcome.ModifyWithEditor) {
509
584
  const waitingToolCall = toolCall;
@@ -513,13 +588,13 @@ export class CoreToolScheduler {
513
588
  if (!editorType) {
514
589
  return;
515
590
  }
516
- this.setStatusInternal(callId, 'awaiting_approval', {
591
+ this.setStatusInternal(callId, 'awaiting_approval', signal, {
517
592
  ...waitingToolCall.confirmationDetails,
518
593
  isModifying: true,
519
594
  });
520
595
  const { updatedParams, updatedDiff } = await modifyWithEditor(waitingToolCall.request.args, modifyContext, editorType, signal, this.onEditorClose);
521
596
  this.setArgsInternal(callId, updatedParams);
522
- this.setStatusInternal(callId, 'awaiting_approval', {
597
+ this.setStatusInternal(callId, 'awaiting_approval', signal, {
523
598
  ...waitingToolCall.confirmationDetails,
524
599
  fileDiff: updatedDiff,
525
600
  isModifying: false,
@@ -531,7 +606,7 @@ export class CoreToolScheduler {
531
606
  if (payload?.newContent && toolCall) {
532
607
  await this._applyInlineModify(toolCall, payload, signal);
533
608
  }
534
- this.setStatusInternal(callId, 'scheduled');
609
+ this.setStatusInternal(callId, 'scheduled', signal);
535
610
  }
536
611
  await this.attemptExecutionOfScheduledCalls(signal);
537
612
  }
@@ -551,7 +626,7 @@ export class CoreToolScheduler {
551
626
  const updatedParams = modifyContext.createUpdatedParams(currentContent, payload.newContent, toolCall.request.args);
552
627
  const updatedDiff = Diff.createPatch(modifyContext.getFilePath(toolCall.request.args), currentContent, payload.newContent, 'Current', 'Proposed');
553
628
  this.setArgsInternal(toolCall.request.callId, updatedParams);
554
- this.setStatusInternal(toolCall.request.callId, 'awaiting_approval', {
629
+ this.setStatusInternal(toolCall.request.callId, 'awaiting_approval', signal, {
555
630
  ...toolCall.confirmationDetails,
556
631
  fileDiff: updatedDiff,
557
632
  });
@@ -569,7 +644,7 @@ export class CoreToolScheduler {
569
644
  const scheduledCall = toolCall;
570
645
  const { callId, name: toolName } = scheduledCall.request;
571
646
  const invocation = scheduledCall.invocation;
572
- this.setStatusInternal(callId, 'executing');
647
+ this.setStatusInternal(callId, 'executing', signal);
573
648
  const liveOutputCallback = scheduledCall.tool.canUpdateOutput && this.outputUpdateHandler
574
649
  ? (outputChunk) => {
575
650
  if (this.outputUpdateHandler) {
@@ -582,103 +657,142 @@ export class CoreToolScheduler {
582
657
  }
583
658
  : undefined;
584
659
  const shellExecutionConfig = this.config.getShellExecutionConfig();
585
- // TODO: Refactor to remove special casing for ShellToolInvocation.
586
- // Introduce a generic callbacks object for the execute method to handle
587
- // things like `onPid` and `onLiveOutput`. This will make the scheduler
588
- // agnostic to the invocation type.
589
- let promise;
590
- if (invocation instanceof ShellToolInvocation) {
591
- const setPidCallback = (pid) => {
592
- this.toolCalls = this.toolCalls.map((tc) => tc.request.callId === callId && tc.status === 'executing'
593
- ? { ...tc, pid }
594
- : tc);
595
- this.notifyToolCallsUpdate();
660
+ await runInDevTraceSpan({
661
+ name: toolCall.tool.name,
662
+ attributes: { type: 'tool-call' },
663
+ }, async ({ metadata: spanMetadata }) => {
664
+ spanMetadata.input = {
665
+ request: toolCall.request,
596
666
  };
597
- promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig, setPidCallback);
598
- }
599
- else {
600
- promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig);
601
- }
602
- try {
603
- const toolResult = await promise;
604
- if (signal.aborted) {
605
- this.setStatusInternal(callId, 'cancelled', 'User cancelled tool execution.');
606
- continue;
607
- }
608
- if (toolResult.error === undefined) {
609
- let content = toolResult.llmContent;
610
- let outputFile = undefined;
611
- const contentLength = typeof content === 'string' ? content.length : undefined;
612
- if (typeof content === 'string' &&
613
- toolName === SHELL_TOOL_NAME &&
614
- this.config.getEnableToolOutputTruncation() &&
615
- this.config.getTruncateToolOutputThreshold() > 0 &&
616
- this.config.getTruncateToolOutputLines() > 0) {
617
- const originalContentLength = content.length;
618
- const threshold = this.config.getTruncateToolOutputThreshold();
619
- const lines = this.config.getTruncateToolOutputLines();
620
- const truncatedResult = await truncateAndSaveToFile(content, callId, this.config.storage.getProjectTempDir(), threshold, lines);
621
- content = truncatedResult.content;
622
- outputFile = truncatedResult.outputFile;
623
- if (outputFile) {
624
- logToolOutputTruncated(this.config, new ToolOutputTruncatedEvent(scheduledCall.request.prompt_id, {
625
- toolName,
626
- originalContentLength,
627
- truncatedContentLength: content.length,
628
- threshold,
629
- lines,
630
- }));
631
- }
632
- }
633
- const response = convertToFunctionResponse(toolName, callId, content);
634
- const successResponse = {
635
- callId,
636
- responseParts: response,
637
- resultDisplay: toolResult.returnDisplay,
638
- error: undefined,
639
- errorType: undefined,
640
- outputFile,
641
- contentLength,
667
+ // TODO: Refactor to remove special casing for ShellToolInvocation.
668
+ // Introduce a generic callbacks object for the execute method to handle
669
+ // things like `onPid` and `onLiveOutput`. This will make the scheduler
670
+ // agnostic to the invocation type.
671
+ let promise;
672
+ if (invocation instanceof ShellToolInvocation) {
673
+ const setPidCallback = (pid) => {
674
+ this.toolCalls = this.toolCalls.map((tc) => tc.request.callId === callId && tc.status === 'executing'
675
+ ? { ...tc, pid }
676
+ : tc);
677
+ this.notifyToolCallsUpdate();
642
678
  };
643
- this.setStatusInternal(callId, 'success', successResponse);
679
+ promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig, setPidCallback);
644
680
  }
645
681
  else {
646
- // It is a failure
647
- const error = new Error(toolResult.error.message);
648
- const errorResponse = createErrorResponse(scheduledCall.request, error, toolResult.error.type);
649
- this.setStatusInternal(callId, 'error', errorResponse);
682
+ promise = invocation.execute(signal, liveOutputCallback, shellExecutionConfig);
650
683
  }
651
- }
652
- catch (executionError) {
653
- if (signal.aborted) {
654
- this.setStatusInternal(callId, 'cancelled', 'User cancelled tool execution.');
684
+ try {
685
+ const toolResult = await promise;
686
+ spanMetadata.output = toolResult;
687
+ if (signal.aborted) {
688
+ this.setStatusInternal(callId, 'cancelled', signal, 'User cancelled tool execution.');
689
+ }
690
+ else if (toolResult.error === undefined) {
691
+ let content = toolResult.llmContent;
692
+ let outputFile = undefined;
693
+ const contentLength = typeof content === 'string' ? content.length : undefined;
694
+ if (typeof content === 'string' &&
695
+ toolName === SHELL_TOOL_NAME &&
696
+ this.config.getEnableToolOutputTruncation() &&
697
+ this.config.getTruncateToolOutputThreshold() > 0 &&
698
+ this.config.getTruncateToolOutputLines() > 0) {
699
+ const originalContentLength = content.length;
700
+ const threshold = this.config.getTruncateToolOutputThreshold();
701
+ const lines = this.config.getTruncateToolOutputLines();
702
+ const truncatedResult = await truncateAndSaveToFile(content, callId, this.config.storage.getProjectTempDir(), threshold, lines);
703
+ content = truncatedResult.content;
704
+ outputFile = truncatedResult.outputFile;
705
+ if (outputFile) {
706
+ logToolOutputTruncated(this.config, new ToolOutputTruncatedEvent(scheduledCall.request.prompt_id, {
707
+ toolName,
708
+ originalContentLength,
709
+ truncatedContentLength: content.length,
710
+ threshold,
711
+ lines,
712
+ }));
713
+ }
714
+ }
715
+ const response = convertToFunctionResponse(toolName, callId, content);
716
+ const successResponse = {
717
+ callId,
718
+ responseParts: response,
719
+ resultDisplay: toolResult.returnDisplay,
720
+ error: undefined,
721
+ errorType: undefined,
722
+ outputFile,
723
+ contentLength,
724
+ };
725
+ this.setStatusInternal(callId, 'success', signal, successResponse);
726
+ }
727
+ else {
728
+ // It is a failure
729
+ const error = new Error(toolResult.error.message);
730
+ const errorResponse = createErrorResponse(scheduledCall.request, error, toolResult.error.type);
731
+ this.setStatusInternal(callId, 'error', signal, errorResponse);
732
+ }
655
733
  }
656
- else {
657
- this.setStatusInternal(callId, 'error', createErrorResponse(scheduledCall.request, executionError instanceof Error
658
- ? executionError
659
- : new Error(String(executionError)), ToolErrorType.UNHANDLED_EXCEPTION));
734
+ catch (executionError) {
735
+ spanMetadata.error = executionError;
736
+ if (signal.aborted) {
737
+ this.setStatusInternal(callId, 'cancelled', signal, 'User cancelled tool execution.');
738
+ }
739
+ else {
740
+ this.setStatusInternal(callId, 'error', signal, createErrorResponse(scheduledCall.request, executionError instanceof Error
741
+ ? executionError
742
+ : new Error(String(executionError)), ToolErrorType.UNHANDLED_EXCEPTION));
743
+ }
660
744
  }
661
- }
745
+ await this.checkAndNotifyCompletion(signal);
746
+ });
662
747
  }
663
748
  }
664
749
  }
665
- async checkAndNotifyCompletion() {
666
- const allCallsAreTerminal = this.toolCalls.every((call) => call.status === 'success' ||
667
- call.status === 'error' ||
668
- call.status === 'cancelled');
669
- if (this.toolCalls.length > 0 && allCallsAreTerminal) {
670
- const completedCalls = [...this.toolCalls];
750
+ async checkAndNotifyCompletion(signal) {
751
+ // This method is now only concerned with the single active tool call.
752
+ if (this.toolCalls.length === 0) {
753
+ // It's possible to be called when a batch is cancelled before any tool has started.
754
+ if (signal.aborted && this.toolCallQueue.length > 0) {
755
+ this._cancelAllQueuedCalls();
756
+ }
757
+ }
758
+ else {
759
+ const activeCall = this.toolCalls[0];
760
+ const isTerminal = activeCall.status === 'success' ||
761
+ activeCall.status === 'error' ||
762
+ activeCall.status === 'cancelled';
763
+ // If the active tool is not in a terminal state (e.g., it's 'executing' or 'awaiting_approval'),
764
+ // then the scheduler is still busy or paused. We should not proceed.
765
+ if (!isTerminal) {
766
+ return;
767
+ }
768
+ // The active tool is finished. Move it to the completed batch.
769
+ const completedCall = activeCall;
770
+ this.completedToolCallsForBatch.push(completedCall);
771
+ logToolCall(this.config, new ToolCallEvent(completedCall));
772
+ // Clear the active tool slot. This is crucial for the sequential processing.
671
773
  this.toolCalls = [];
672
- for (const call of completedCalls) {
673
- logToolCall(this.config, new ToolCallEvent(call));
774
+ }
775
+ // Now, check if the entire batch is complete.
776
+ // The batch is complete if the queue is empty or the operation was cancelled.
777
+ if (this.toolCallQueue.length === 0 || signal.aborted) {
778
+ if (signal.aborted) {
779
+ this._cancelAllQueuedCalls();
780
+ }
781
+ // If there's nothing to report and we weren't cancelled, we can stop.
782
+ // But if we were cancelled, we must proceed to potentially start the next queued request.
783
+ if (this.completedToolCallsForBatch.length === 0 && !signal.aborted) {
784
+ return;
674
785
  }
675
786
  if (this.onAllToolCallsComplete) {
676
787
  this.isFinalizingToolCalls = true;
677
- await this.onAllToolCallsComplete(completedCalls);
788
+ // Use the batch array, not the (now empty) active array.
789
+ await this.onAllToolCallsComplete(this.completedToolCallsForBatch);
790
+ this.completedToolCallsForBatch = []; // Clear after reporting.
678
791
  this.isFinalizingToolCalls = false;
679
792
  }
793
+ this.isCancelling = false;
680
794
  this.notifyToolCallsUpdate();
681
- // After completion, process the next item in the queue.
795
+ // After completion of the entire batch, process the next item in the main request queue.
682
796
  if (this.requestQueue.length > 0) {
683
797
  const next = this.requestQueue.shift();
684
798
  this._schedule(next.request, next.signal)
@@ -686,10 +800,58 @@ export class CoreToolScheduler {
686
800
  .catch(next.reject);
687
801
  }
688
802
  }
803
+ else {
804
+ // The batch is not yet complete, so continue processing the current batch sequence.
805
+ await this._processNextInQueue(signal);
806
+ }
807
+ }
808
+ _cancelAllQueuedCalls() {
809
+ while (this.toolCallQueue.length > 0) {
810
+ const queuedCall = this.toolCallQueue.shift();
811
+ // Don't cancel tools that already errored during validation.
812
+ if (queuedCall.status === 'error') {
813
+ this.completedToolCallsForBatch.push(queuedCall);
814
+ continue;
815
+ }
816
+ const durationMs = 'startTime' in queuedCall && queuedCall.startTime
817
+ ? Date.now() - queuedCall.startTime
818
+ : undefined;
819
+ const errorMessage = '[Operation Cancelled] User cancelled the operation.';
820
+ this.completedToolCallsForBatch.push({
821
+ request: queuedCall.request,
822
+ tool: queuedCall.tool,
823
+ invocation: queuedCall.invocation,
824
+ status: 'cancelled',
825
+ response: {
826
+ callId: queuedCall.request.callId,
827
+ responseParts: [
828
+ {
829
+ functionResponse: {
830
+ id: queuedCall.request.callId,
831
+ name: queuedCall.request.name,
832
+ response: {
833
+ error: errorMessage,
834
+ },
835
+ },
836
+ },
837
+ ],
838
+ resultDisplay: undefined,
839
+ error: undefined,
840
+ errorType: undefined,
841
+ contentLength: errorMessage.length,
842
+ },
843
+ durationMs,
844
+ outcome: ToolConfirmationOutcome.Cancel,
845
+ });
846
+ }
689
847
  }
690
848
  notifyToolCallsUpdate() {
691
849
  if (this.onToolCallsUpdate) {
692
- this.onToolCallsUpdate([...this.toolCalls]);
850
+ this.onToolCallsUpdate([
851
+ ...this.completedToolCallsForBatch,
852
+ ...this.toolCalls,
853
+ ...this.toolCallQueue,
854
+ ]);
693
855
  }
694
856
  }
695
857
  setToolCallOutcome(callId, outcome) {
@@ -702,23 +864,6 @@ export class CoreToolScheduler {
702
864
  };
703
865
  });
704
866
  }
705
- /**
706
- * Handle tool confirmation requests from the message bus when policy decision is ASK_USER.
707
- * This publishes a response with requiresUserConfirmation=true to signal the tool
708
- * that it should fall back to its legacy confirmation UI.
709
- */
710
- handleToolConfirmationRequest(request) {
711
- // When ASK_USER policy decision is made, the message bus emits the request here.
712
- // We respond with requiresUserConfirmation=true to tell the tool to use its
713
- // legacy confirmation flow (which will show diffs, URLs, etc in the UI).
714
- const messageBus = this.config.getMessageBus();
715
- messageBus.publish({
716
- type: MessageBusType.TOOL_CONFIRMATION_RESPONSE,
717
- correlationId: request.correlationId,
718
- confirmed: false, // Not auto-approved
719
- requiresUserConfirmation: true, // Use legacy UI confirmation
720
- });
721
- }
722
867
  isAutoApproved(toolCall) {
723
868
  if (this.config.getApprovalMode() === ApprovalMode.YOLO) {
724
869
  return true;
@@ -731,21 +876,5 @@ export class CoreToolScheduler {
731
876
  }
732
877
  return doesToolInvocationMatch(tool, invocation, allowedTools);
733
878
  }
734
- async autoApproveCompatiblePendingTools(signal, triggeringCallId) {
735
- const pendingTools = this.toolCalls.filter((call) => call.status === 'awaiting_approval' &&
736
- call.request.callId !== triggeringCallId);
737
- for (const pendingTool of pendingTools) {
738
- try {
739
- const stillNeedsConfirmation = await pendingTool.invocation.shouldConfirmExecute(signal);
740
- if (!stillNeedsConfirmation) {
741
- this.setToolCallOutcome(pendingTool.request.callId, ToolConfirmationOutcome.ProceedAlways);
742
- this.setStatusInternal(pendingTool.request.callId, 'scheduled');
743
- }
744
- }
745
- catch (error) {
746
- console.error(`Error checking confirmation for tool ${pendingTool.request.callId}:`, error);
747
- }
748
- }
749
- }
750
879
  }
751
880
  //# sourceMappingURL=coreToolScheduler.js.map