Skip to content

fix: ACP: separate conversational text from execute tool command title#23179

Merged
sripasg merged 1 commit intomainfrom
sripas_fix_1572
Mar 24, 2026
Merged

fix: ACP: separate conversational text from execute tool command title#23179
sripasg merged 1 commit intomainfrom
sripas_fix_1572

Conversation

@sripasg
Copy link
Copy Markdown
Contributor

@sripasg sripasg commented Mar 20, 2026

Summary

  • Refactor the ACP tool execution to strictly separate the executable commands from tool explanations.
  • Ensure large MCP tool payloads are handled properly by intelligently truncating them
  • Update formatting logic to eliminate code duplication across shell and MCP invocation routines.
  • Add corresponding tests

Details

  • Extract explanation separately into independent agent_thought_chunk updates - and the main tool execution titles is caught by the IDE UIs cleanly (as shown in the screenshots)
  • Eliminate code duplication in ShellToolInvocation by implementing a private method - getContextualDetails to accurately map the context parameters.
  • Introduce a truncation rule in DiscoveredMCPToolInvocation that truncates long JSON parameter payloads (heuristic -- exceeding 500 characters), summarizing them with just the initial root keys instead of cluttering terminal output.
  • Refactor the unit tests in mcp-tool.test.ts to strictly adhere to tool schema constraints (providing the correct {command: '...'} properties)
  • Update acpClient.test.ts to precisely assert against the new split sessionUpdate json.

Related Issues

Fixes maintainers-gemini-cli#1572

How to Validate

Ensure that commands and explanations are separated out as shown in the screenshot below (after fix) with similar prompts that require approval from user for running a command.

image

Pre-Merge Checklist

  • [NA] Updated relevant documentation and README (if needed)
  • [✅] Added/updated tests (if needed)
  • [NA] Noted breaking changes (if any)
  • [✅] Validated on required platforms/methods:
    • [✅] MacOS
      • [✅] npm run
      • npx
      • Docker
      • Podman
      • Seatbelt
    • Windows
      • npm run
      • npx
      • Docker
    • Linux
      • npm run
      • npx
      • Docker

@sripasg sripasg requested review from a team as code owners March 20, 2026 00:16
@gemini-cli
Copy link
Copy Markdown
Contributor

gemini-cli bot commented Mar 20, 2026

Hi @sripasg, thank you so much for your contribution to Gemini CLI! We really appreciate the time and effort you've put into this.

We're making some updates to our contribution process to improve how we track and review changes. Please take a moment to review our recent discussion post: Improving Our Contribution Process & Introducing New Guidelines.

Key Update: Starting January 26, 2026, the Gemini CLI project will require all pull requests to be associated with an existing issue. Any pull requests not linked to an issue by that date will be automatically closed.

Thank you for your understanding and for being a part of our community!

@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 refactors the ACP tool execution pipeline to achieve a strict separation between raw executable commands and the agent's conversational explanations. By introducing dedicated methods for display titles and explanations, the change ensures that integrated development environments (IDEs) present only the clean, syntax-highlightable command in interactive tool call blocks, while routing any supplementary conversational context as separate preceding thought chunks. This significantly enhances the clarity and user experience when interacting with agent-suggested commands.

Highlights

  • New Tool Invocation Methods: Introduced getDisplayTitle() and getExplanation() to the ToolInvocation interface, allowing tools to explicitly separate their raw command from conversational metadata.
  • ACP Client Refactoring: Modified acpClient.ts to utilize getDisplayTitle() for the interactive tool call block's title and to emit any getExplanation() content as a distinct agent_thought_chunk before the tool block.
  • Shell Tool Enhancement: Overrode ShellToolInvocation to ensure getDisplayTitle() returns only the raw shell command, moving contextual details like current working directory and background status into getExplanation().
  • MCP Tool Integration: Applied the same logical separation within DiscoveredMCPToolInvocation for dynamically mapped JetBrains/MCP commands, ensuring consistent formatting and including comprehensive unit tests.
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 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 counter productive. 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 Mar 20, 2026

Size Change: +1.41 kB (+0.01%)

Total Size: 26.1 MB

Filename Size Change
./bundle/chunk-5WHECDMU.js 0 B -1.95 MB (removed) 🏆
./bundle/chunk-PCHLEJA6.js 0 B -3.64 MB (removed) 🏆
./bundle/chunk-PSA3BUJH.js 0 B -14.5 MB (removed) 🏆
./bundle/core-26SMDAAO.js 0 B -42.4 kB (removed) 🏆
./bundle/devtoolsService-TPWBJEIV.js 0 B -27.7 kB (removed) 🏆
./bundle/interactiveCli-ZH3KIV4V.js 0 B -1.61 MB (removed) 🏆
./bundle/oauth2-provider-XBFZH2JB.js 0 B -9.16 kB (removed) 🏆
./bundle/chunk-5Q4KPBEJ.js 1.95 MB +1.95 MB (new file) 🆕
./bundle/chunk-A3H5FHMA.js 14.5 MB +14.5 MB (new file) 🆕
./bundle/chunk-A7LBA4ST.js 3.64 MB +3.64 MB (new file) 🆕
./bundle/core-KZLPCWWO.js 42.4 kB +42.4 kB (new file) 🆕
./bundle/devtoolsService-SCLTOAT7.js 27.7 kB +27.7 kB (new file) 🆕
./bundle/interactiveCli-MSU2UIWO.js 1.61 MB +1.61 MB (new file) 🆕
./bundle/oauth2-provider-64NMS3SB.js 9.16 kB +9.16 kB (new file) 🆕
ℹ️ View Unchanged
Filename Size Change
./bundle/chunk-34MYV7JD.js 2.45 kB 0 B
./bundle/chunk-5AUYMPVF.js 858 B 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/devtools-36NN55EP.js 696 kB 0 B
./bundle/dist-T73EYRDX.js 356 B 0 B
./bundle/gemini.js 519 kB +461 B (+0.09%)
./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-DL6LDUAP.js 0 B -922 B (removed) 🏆
./bundle/multipart-parser-KPBZEGQU.js 11.7 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB 0 B
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 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/tree-sitter-7U6MW5PS.js 274 kB 0 B
./bundle/tree-sitter-bash-34ZGLXVX.js 1.84 MB 0 B
./bundle/memoryDiscovery-OAYTXEXH.js 922 B +922 B (new file) 🆕

compressed-size-action

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 is a good refactoring that separates the raw command from its contextual explanation for tool invocations, which will improve the UI experience in IDEs. The introduction of getDisplayTitle() and getExplanation() methods is well-implemented across the shell and mcp-tool invocations. My review identifies a critical issue in a new test that incorrectly validates the implementation, and a high-severity issue regarding code duplication that should be addressed to improve maintainability.

@gemini-cli gemini-cli bot added the status/need-issue Pull requests that need to have an associated issue. label Mar 20, 2026
@jacob314
Copy link
Copy Markdown
Contributor

This review is provided by the Gemini CLI /review-frontend command.

The pull request successfully implements the separation between the raw executable command (display title) and the contextual explanations for ACP tools. This is a solid architectural improvement that keeps IDE UIs clean.

However, I've identified a few issues with the implementation, which align with the review feedback previously left by gemini-code-assist:

1. High-Severity Code Duplication in acpClient.ts

The explanation is correctly extracted and sent as an agent_thought_chunk. However, this entire block of code is duplicated inside the if (confirmationDetails) block and the else block:

const explanation = typeof invocation.getExplanation === 'function' ? invocation.getExplanation() : '';
if (explanation) {
  await this.sendUpdate({
    sessionUpdate: 'agent_thought_chunk',
    content: { type: 'text', text: explanation },
  });
}

Recommendation: Refactor acpClient.ts to compute both the title and explanation immediately after const invocation = tool.build(args);. This eliminates the duplicate logic and consolidates the fallback pattern (invocation.getDisplayTitle?.() ?? invocation.getDescription()).

2. Failing/Flawed Unit Test in acpClient.test.ts

The test should split getDisplayTitle and getExplanation for title and content in permission request was added, but this test expected the explanation text to magically appear inside the content array payload of requestPermission. As written, the implementation correctly sends the explanation via a separate sendUpdate before requesting permission, causing this test to fail.
Recommendation: Update the assertion to verify that mockConnection.sessionUpdate is correctly called with sessionUpdate: 'agent_thought_chunk'.

3. Schema Validation Failures in mcp-tool.test.ts

The three tests added for DiscoveredMCPTool failed because they tried to instantiate the mock tool with an invalid payload ({ command: 'ls -la' }). The mock tool's input schema explicitly requires { param: { type: 'string' } }. Furthermore, when testing the fallback display title, the test asserted against tool.serverToolName, whereas the code correctly returns tool.displayName (which combines both the server and tool name).
Recommendation: Update the test suite to use valid schema payloads (e.g., creating a separate commandTool mock with the command property required) and update the fallback assertion to tool.displayName.

Prompting Retrospective

Expected Original Prompt:

"Update the ACP tool execution pipeline to strictly separate raw executable commands from the agent's contextual explanations. Add getDisplayTitle and getExplanation to the ToolInvocation interface. Use getDisplayTitle for the title of the tool call, and send the explanation as a separate agent_thought_chunk before the tool call block in acpClient.ts. Do this for ShellToolInvocation and DiscoveredMCPToolInvocation. Add tests to verify this behavior."

Suggested Improvement:
To yield cleaner, passing code, the user could have added:

"Compute the title and explanation at the top of the execution block in acpClient.ts to avoid duplicating the sendUpdate logic across the confirmation if/else branches. When writing tests, ensure that assertions on the acpClient.ts behavior correctly verify sendUpdate is called with the thought chunk rather than looking for it in the tool payload. Finally, when mocking DiscoveredMCPTool for tests, ensure your test inputs satisfy the mock tool's JSON schema constraints."

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Thank you, @jacob314, for this incredibly thorough and insightful review! Your detailed analysis has pinpointed several critical areas for improvement, and I appreciate you taking the time to provide such clear and actionable feedback. I've reviewed your comments and agree with your assessment on all points.

Here's a breakdown of the issues and the path forward:

1. High-Severity Code Duplication in acpClient.ts

You are absolutely correct. The duplication of the explanation logic is a significant maintainability concern. Your recommendation to refactor acpClient.ts to compute both title and explanation immediately after const invocation = tool.build(args); is a solid approach to eliminate this redundancy and consolidate the logic. This will improve code clarity and reduce potential for future errors.

2. Failing/Flawed Unit Test in acpClient.test.ts

Thank you for catching the flaw in the should split getDisplayTitle and getExplanation for title and content in permission request test. You're right that the current implementation correctly sends the explanation as an agent_thought_chunk via sendUpdate before the permission request, making the original assertion incorrect. The test needs to be updated to verify the mockConnection.sessionUpdate call for the agent_thought_chunk as you suggested.

3. Schema Validation Failures in mcp-tool.test.ts

Your observations regarding the DiscoveredMCPTool tests are spot on. The mock tool instantiation with an invalid payload ({ command: 'ls -la' }) and the incorrect assertion against tool.serverToolName instead of tool.displayName are indeed issues. The tests should be updated to use valid schema payloads (e.g., by creating a commandTool mock with the command property) and to assert against tool.displayName for the fallback display title.

@sripasg, please take a look at these points. Addressing them will significantly improve the correctness, maintainability, and test coverage of this pull request. Let me know if you have any questions as you work through these changes.

@sripasg
Copy link
Copy Markdown
Contributor Author

sripasg commented Mar 20, 2026

@jacob314 - addressed all feedback .. thank you !

@jacob314
Copy link
Copy Markdown
Contributor

PR Review

Thanks for this PR! The separation of the conversational explanation from the core command title is a great improvement for the IDE UI, and the implementation handles backward compatibility well.

I have a couple of minor suggestions to improve code maintainability and cleanliness:

  1. Magic Number in mcp-tool.ts:
    In packages/core/src/tools/mcp-tool.ts, the string length check (if (stringified.length > 500)) uses 500 as a magic number. Consider extracting this into a named constant (e.g., const MAX_EXPLANATION_LENGTH = 500;) to make the heuristic clearer and easier to adjust in the future.

  2. Array Initialization in acpClient.ts:
    Around line 1050 in packages/cli/src/acp/acpClient.ts, the code currently does:

    const updateContent: acp.ToolCallContent[] = [];
    if (content) {
      updateContent.push(content);
    }

    This could be simplified back to the way it was handled previously:

    const updateContent = content ? [content] : [];

Overall, the logic is solid and the tests cover the new behavior effectively. Great work!

@sripasg
Copy link
Copy Markdown
Contributor Author

sripasg commented Mar 21, 2026

feedback applied.

@sripasg sripasg self-assigned this Mar 21, 2026
Copy link
Copy Markdown
Contributor

@jacob314 jacob314 left a comment

Choose a reason for hiding this comment

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

lgtm

@sripasg sripasg enabled auto-merge March 24, 2026 00:27
@sripasg sripasg disabled auto-merge March 24, 2026 00:39
@sripasg sripasg added this pull request to the merge queue Mar 24, 2026
Merged via the queue into main with commit 84caf00 Mar 24, 2026
27 checks passed
@sripasg sripasg deleted the sripas_fix_1572 branch March 24, 2026 00:55
warrenzhu25 pushed a commit to warrenzhu25/gemini-cli that referenced this pull request Apr 9, 2026
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.

3 participants