Skip to content

fix(patch): cherry-pick 02995ba to release/v0.41.1-pr-26568 to patch version v0.41.1 and create version 0.41.2#26589

Merged
kschaab merged 1 commit intorelease/v0.41.1-pr-26568from
hotfix/v0.41.1/0.41.2/stable/cherry-pick-02995ba/pr-26568
May 6, 2026
Merged

fix(patch): cherry-pick 02995ba to release/v0.41.1-pr-26568 to patch version v0.41.1 and create version 0.41.2#26589
kschaab merged 1 commit intorelease/v0.41.1-pr-26568from
hotfix/v0.41.1/0.41.2/stable/cherry-pick-02995ba/pr-26568

Conversation

@gemini-cli-robot
Copy link
Copy Markdown
Collaborator

This PR automatically cherry-picks commit 02995ba to patch version v0.41.1 in the stable release to create version 0.41.2.

@gemini-cli-robot gemini-cli-robot requested a review from a team as a code owner May 6, 2026 16:37
@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request implements a significant refactor of the tool execution synchronization logic within the Task class. By moving away from a single-promise resolution model to an event-driven approach, the system now more reliably manages concurrent tool calls and state transitions. These changes ensure that the task execution loop correctly waits for all pending tools to complete while properly handling user approvals and cancellations, ultimately improving the robustness of the agent's tool orchestration.

Highlights

  • Refactored Tool Completion Logic: Replaced the promise-based toolCompletionPromise mechanism with a more robust EventEmitter (toolUpdateEmitter) to handle tool state updates and synchronization.
  • Improved Race Condition Handling: Introduced isAwaitingApprovalOnly and updated waitForPendingTools to correctly handle scenarios where multiple tool confirmations occur concurrently, preventing task hangs.
  • Enhanced Test Coverage: Added comprehensive test cases for race conditions, multi-turn tool resolution, and subagent progress events to ensure stability.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 6, 2026

Size Change: -4 B (0%)

Total Size: 33.9 MB

Filename Size Change
./bundle/chunk-35VDEPM3.js 0 B -3.8 kB (removed) 🏆
./bundle/chunk-GOGEWMVR.js 0 B -2.73 MB (removed) 🏆
./bundle/chunk-I4UWG4KK.js 0 B -14.7 MB (removed) 🏆
./bundle/chunk-J2SCDLQB.js 0 B -49.2 kB (removed) 🏆
./bundle/chunk-LLUYQNAO.js 0 B -3.43 kB (removed) 🏆
./bundle/chunk-XQRHSNOS.js 0 B -674 kB (removed) 🏆
./bundle/core-QZQMKCAL.js 0 B -48.1 kB (removed) 🏆
./bundle/devtoolsService-FEEAP3WR.js 0 B -28 kB (removed) 🏆
./bundle/gemini-CVPPWPLU.js 0 B -575 kB (removed) 🏆
./bundle/interactiveCli-R5M6MHOU.js 0 B -1.31 MB (removed) 🏆
./bundle/liteRtServerManager-6I7DYFQL.js 0 B -2.08 kB (removed) 🏆
./bundle/oauth2-provider-OEGATLOL.js 0 B -9.16 kB (removed) 🏆
./bundle/chunk-6VKNJAAF.js 3.43 kB +3.43 kB (new file) 🆕
./bundle/chunk-7GPZNKFP.js 3.8 kB +3.8 kB (new file) 🆕
./bundle/chunk-IB6S67FM.js 14.7 MB +14.7 MB (new file) 🆕
./bundle/chunk-KR5EJNFN.js 674 kB +674 kB (new file) 🆕
./bundle/chunk-MYSRI4IG.js 2.73 MB +2.73 MB (new file) 🆕
./bundle/chunk-RPFUPDQF.js 49.2 kB +49.2 kB (new file) 🆕
./bundle/core-AKVKWRS3.js 48.1 kB +48.1 kB (new file) 🆕
./bundle/devtoolsService-5QUVMRO5.js 28 kB +28 kB (new file) 🆕
./bundle/gemini-4X3X4CSY.js 575 kB +575 kB (new file) 🆕
./bundle/interactiveCli-SM5R2QMU.js 1.31 MB +1.31 MB (new file) 🆕
./bundle/liteRtServerManager-2D7AN6C4.js 2.08 kB +2.08 kB (new file) 🆕
./bundle/oauth2-provider-47JXH756.js 9.16 kB +9.16 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./bundle/bundled/third_party/index.js 8 MB 0 B
./bundle/chunk-34MYV7JD.js 2.45 kB 0 B
./bundle/chunk-5AUYMPVF.js 858 B 0 B
./bundle/chunk-5PS3AYFU.js 1.18 kB 0 B
./bundle/chunk-664ZODQF.js 124 kB 0 B
./bundle/chunk-DAHVX5MI.js 206 kB 0 B
./bundle/chunk-IUUIT4SU.js 56.5 kB 0 B
./bundle/chunk-RJTRUG2J.js 39.8 kB 0 B
./bundle/chunk-XRLFHCHC.js 1.97 MB 0 B
./bundle/cleanup-5MTS5IPW.js 0 B -932 B (removed) 🏆
./bundle/devtools-36NN55EP.js 696 kB 0 B
./bundle/dist-T73EYRDX.js 356 B 0 B
./bundle/events-XB7DADIJ.js 418 B 0 B
./bundle/examples/hooks/scripts/on-start.js 188 B 0 B
./bundle/examples/mcp-server/example.js 1.43 kB 0 B
./bundle/gemini.js 4.97 kB 0 B
./bundle/getMachineId-bsd-TXG52NKR.js 1.55 kB 0 B
./bundle/getMachineId-darwin-7OE4DDZ6.js 1.55 kB 0 B
./bundle/getMachineId-linux-SHIFKOOX.js 1.34 kB 0 B
./bundle/getMachineId-unsupported-5U5DOEYY.js 1.06 kB 0 B
./bundle/getMachineId-win-6KLLGOI4.js 1.72 kB 0 B
./bundle/memoryDiscovery-FN3IAPBT.js 980 B 0 B
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 222 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 229 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 13.4 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B 0 B
./bundle/sandbox-macos-permissive-open.sb 890 B 0 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB 0 B
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB 0 B
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB 0 B
./bundle/sandbox-macos-strict-open.sb 4.82 kB 0 B
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB 0 B
./bundle/src-QVCVGIUX.js 47 kB 0 B
./bundle/start-FISSTD4K.js 0 B -622 B (removed) 🏆
./bundle/tree-sitter-7U6MW5PS.js 274 kB 0 B
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB 0 B
./bundle/cleanup-7AGYOD7S.js 932 B +932 B (new file) 🆕
./bundle/start-OMPSXZT6.js 622 B +622 B (new file) 🆕

compressed-size-action

@gemini-cli gemini-cli Bot added the status/need-issue Pull requests that need to have an associated issue. label May 6, 2026
Copy link
Copy Markdown
Contributor

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the Task class in packages/a2a-server to use an EventEmitter for managing tool execution states, replacing the previous promise-based synchronization. This change improves the handling of complex tool lifecycles and race conditions. New test suites were introduced to verify these improvements, including scenarios for concurrent tool scheduling and cancellation. Review feedback highlighted a race condition in waitForPendingTools where concurrent waiters might fail to catch a cancellation error if it is cleared prematurely, and recommended resetting the cancellation state when new tool calls are registered to ensure the task can proceed with subsequent work.

I am having trouble creating individual review comments. Click here to see my feedback.

packages/a2a-server/src/agent/task.ts (213-230)

high

There is a race condition in waitForPendingTools when multiple concurrent callers are waiting. If cancelPendingTools is called, this.cancellationError is set and an update event is emitted. All concurrent waiters will wake up and exit the loop. However, the first waiter to reach line 216 or 228 will clear this.cancellationError by setting it to undefined. Subsequent waiters will then see undefined and resolve successfully instead of throwing the cancellation error.

To fix this, avoid clearing the error within waitForPendingTools. Instead, you should clear it when new work is initiated (e.g., in _registerToolCall). Additionally, per repository rules, this asynchronous operation should ideally accept and propagate an AbortSignal to ensure consistent cancellation handling.

    while (this.pendingToolCalls.size > 0 && !this.isAwaitingApprovalOnly()) {
      if (this.cancellationError) {
        throw this.cancellationError;
      }
      logger.info(
        '[Task] Waiting for ' + this.pendingToolCalls.size + ' pending tool(s)...',
      );
      await new Promise((resolve) =>
        this.toolUpdateEmitter.once('update', resolve),
      );
    }
    if (this.cancellationError) {
      throw this.cancellationError;
    }
References
  1. Asynchronous operations that can be cancelled by the user should accept and propagate an AbortSignal to ensure cancellability and prevent dangling processes or network requests.
  2. When managing the state of asynchronous operations, rely on an explicit state variable rather than checking for the existence of a promise object.

packages/a2a-server/src/agent/task.ts (179-181)

high

When new tool calls are registered, any previous cancellation error should be cleared to allow the task to proceed with new work. This also ensures that waitForPendingTools doesn't immediately throw an old error from a previous turn. This ensures explicit state management for the asynchronous operation's lifecycle.

  private _registerToolCall(toolCallId: string, status: string): void {
    this.cancellationError = undefined;
    this.pendingToolCalls.set(toolCallId, status);
    this.toolUpdateEmitter.emit('update');
  }
References
  1. When managing the state of asynchronous operations, rely on an explicit state variable rather than checking for the existence of a promise object.

@kschaab kschaab enabled auto-merge (squash) May 6, 2026 17:05
@kschaab kschaab merged commit 0da6569 into release/v0.41.1-pr-26568 May 6, 2026
28 checks passed
@kschaab kschaab deleted the hotfix/v0.41.1/0.41.2/stable/cherry-pick-02995ba/pr-26568 branch May 6, 2026 17:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status/need-issue Pull requests that need to have an associated issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants