From 4b2701195a5e8e594217c7862e4d245446f417af Mon Sep 17 00:00:00 2001 From: gemini-cli-robot Date: Tue, 13 Jan 2026 22:04:14 -0800 Subject: [PATCH] fix(patch): cherry-pick eda47f5 to release/v0.24.0-preview.2-pr-16557 [CONFLICTS] (#16577) Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com> Co-authored-by: Sandy Tao --- packages/core/src/core/coreToolScheduler.ts | 29 ++++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/packages/core/src/core/coreToolScheduler.ts b/packages/core/src/core/coreToolScheduler.ts index 20afc07b2c..f53ab8530b 100644 --- a/packages/core/src/core/coreToolScheduler.ts +++ b/packages/core/src/core/coreToolScheduler.ts @@ -923,21 +923,36 @@ export class CoreToolScheduler { this._cancelAllQueuedCalls(); } + // If we are already finalizing, another concurrent call to + // checkAndNotifyCompletion will just return. The ongoing finalized loop + // will pick up any new tools added to completedToolCallsForBatch. + if (this.isFinalizingToolCalls) { + return; + } + // If there's nothing to report and we weren't cancelled, we can stop. // But if we were cancelled, we must proceed to potentially start the next queued request. if (this.completedToolCallsForBatch.length === 0 && !signal.aborted) { return; } - if (this.onAllToolCallsComplete) { - this.isFinalizingToolCalls = true; - // Use the batch array, not the (now empty) active array. - await this.onAllToolCallsComplete(this.completedToolCallsForBatch); - this.completedToolCallsForBatch = []; // Clear after reporting. + this.isFinalizingToolCalls = true; + try { + // We use a while loop here to ensure that if new tools are added to the + // batch (e.g., via cancellation) while we are awaiting + // onAllToolCallsComplete, they are also reported before we finish. + while (this.completedToolCallsForBatch.length > 0) { + const batchToReport = [...this.completedToolCallsForBatch]; + this.completedToolCallsForBatch = []; + if (this.onAllToolCallsComplete) { + await this.onAllToolCallsComplete(batchToReport); + } + } + } finally { this.isFinalizingToolCalls = false; + this.isCancelling = false; + this.notifyToolCallsUpdate(); } - this.isCancelling = false; - this.notifyToolCallsUpdate(); // After completion of the entire batch, process the next item in the main request queue. if (this.requestQueue.length > 0) {