refactor(cli): migrate core tools to native ToolDisplay property and fix UI rendering#25186
refactor(cli): migrate core tools to native ToolDisplay property and fix UI rendering#25186
Conversation
…tadata overwrite This addresses PR feedback by: - Creating a `renderDisplayDiff` utility to render `DisplayDiff` objects. - Creating a `displayContentToString` utility to safely extract text from any `DisplayContent`. - Updating non-interactive CLI to use `displayContentToString` to avoid data loss on non-text output. - Updating `useAgentStream` to use `displayContentToString` to avoid stale UI state for non-text output. - Shallow merging the `display` object in `useAgentStream` rather than replacing it, preventing loss of display metadata.
|
Hi @mbleigh, 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! |
Summary of ChangesHello, 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 refines the UI rendering logic for tool outputs by introducing a more robust Highlights
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request implements a new ToolDisplay protocol to standardize how tool execution results are presented across the CLI. It updates core tools like Edit, Grep, and Shell to provide structured display metadata and modifies UI components, including DenseToolMessage and ToolInfo, to render this information. Feedback suggests flattening multiline summaries in the dense view to maintain layout consistency and adjusting the merge logic in populateToolDisplay to ensure that tool-provided metadata correctly overrides default values.
| const summaryText = display.resultSummary ? ( | ||
| <Text color={theme.text.accent} wrap="truncate-end"> | ||
| → {display.resultSummary} | ||
| </Text> | ||
| ) : status === CoreToolCallStatus.Error ? ( | ||
| <Text color={theme.status.error} wrap="truncate-end"> | ||
| → {typeof resultDisplay === 'string' ? resultDisplay : 'Failed'} | ||
| </Text> | ||
| ) : undefined; |
There was a problem hiding this comment.
The summary text for both successful results and errors should be flattened (newlines replaced with spaces) to maintain the single-line compact layout expected in the dense view. This ensures layout consistency by preventing variable item heights within the list, which is preferred over dynamic calculations.
| const summaryText = display.resultSummary ? ( | |
| <Text color={theme.text.accent} wrap="truncate-end"> | |
| → {display.resultSummary} | |
| </Text> | |
| ) : status === CoreToolCallStatus.Error ? ( | |
| <Text color={theme.status.error} wrap="truncate-end"> | |
| → {typeof resultDisplay === 'string' ? resultDisplay : 'Failed'} | |
| </Text> | |
| ) : undefined; | |
| const summaryText = display.resultSummary ? ( | |
| <Text color={theme.text.accent} wrap="truncate-end"> | |
| → {display.resultSummary.replace(/\n/g, ' ')} | |
| </Text> | |
| ) : status === CoreToolCallStatus.Error ? ( | |
| <Text color={theme.status.error} wrap="truncate-end"> | |
| → {typeof resultDisplay === 'string' ? resultDisplay.replace(/\n/g, ' ').trim() : 'Failed'} | |
| </Text> | |
| ) : undefined; |
References
- To ensure layout consistency in a list, it is preferable to make all items have a fixed height rather than dynamically calculating variable item heights.
There was a problem hiding this comment.
This makes sense, let's do it.
This change completes the transition of the interactive agent session (`useAgentStream`) to a declarative-first tool rendering system. Key changes: - Reverted experimental `ToolDisplay` logic from legacy UI components (`DenseToolMessage`, etc.) to establish a clean baseline. - Introduced `HistoryItemToolDisplayGroup` and `ToolGroupDisplay` component in CLI. - Added `display` property to `ToolCallRequestInfo` to carry declarative UI info natively. - Populated tool request display information at the source (`Turn.ts` and `Scheduler.ts`) using dynamic descriptions from tool invocations. - Updated `useAgentStream` to emit the new history item type, providing a standalone rendering path for interactive sessions. - Ensured tool descriptions are updated when arguments are modified during confirmation.
Key enhancements: - Updated `UpdateTopicTool` to provide declarative 'notice' display info, using dynamic descriptions for high-fidelity output. - Refined `ToolGroupDisplay` to 'hoist' notice-format tools to the top of the group. - Implemented conditional boxing in `ToolGroupDisplay`: borders are now suppressed in compact mode, matching the standard CLI view. - Added support for `resultSummary` rendering at the bottom of text results in boxed mode. - Improved `useAgentStream` to wait for turn completion before pushing tools to history, ensuring all notices for a turn are correctly grouped and hoisted together. - Fixed margin and border logic to handle seamless transitions between notices and tool boxes.
9ca5d74 to
9e03476
Compare
|
Size Change: +13.7 kB (+0.04%) Total Size: 34 MB
ℹ️ View Unchanged
|
|
@gemini-cli Please help me understand this pull request by deeply reviewing the code, the linked work item, and it's parent and children. I'm curious how this change factors into the overall effort, what other alternatives were considered, etc. |
Deep Review: PR #25186 - Refactor CLI Tool RenderingThis pull request represents a significant architectural shift in how Gemini CLI handles tool execution feedback and UI rendering. Below is a deep dive into the changes, their rationale, and how they factor into the broader project roadmap. 1. Architectural Shift: "Display-Native Tools"Historically, Gemini CLI relied on a central adapter layer (primarily PR #25186 migrates the system to a "Display-Native" model:
2. UI & Rendering PredictabilityThe introduction of
3. Key Bug Fix:
|
|
This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding. |
- Revert unnecessary comment in ToolGroupDisplay.tsx. - Use "Shell" as the display name for the Shell tool and add TODO for ANSI support. - Restore visibility of matched lines in Grep and RipGrep tool displays by including them in display metadata. - Confirmed existing newline flattening in DenseToolMessage.tsx.
|
This pull request is being closed as it has been open for 14 days without a 'help wanted' designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding. |
Pull request was closed
|
✅ 75 tests passed successfully on gemini-3-flash-preview. 🧠 Model Steering GuidanceThis PR modifies files that affect the model's behavior (prompts, tools, or instructions).
This is an automated guidance message triggered by steering logic signatures. |

Summary
This PR migrates the core CLI tools and rendering pipeline to emit and consume a native
ToolDisplayobject, deprecating the legacyreturnDisplayadapter. By shifting control of the display schema directly to the tools themselves, the UI can now render tool responses more predictably across both compact (DenseToolMessage) and full-width (ToolMessage) views.Fixes #25046
Details
1. Core Tool Migrations
The following core tools have been updated to populate and emit their own
ToolDisplayobjects (includingname,description,resultSummary, andresult), bypassing the legacy translation layer:editgrep/ripGreplsshellread-filewrite-file2. Event Pipeline & Type Updates
ToolCallResponseInfo,event-translator, andtool-executorto process the newToolDisplayproperty.populateToolDisplay(tool-display-utils.ts) where legacy JSON payloads were indiscriminately overwriting explicitly definedresult: nullvalues from tools likeripGrep.3. UI & Rendering Fixes
useAgentStreamnow seamlessly bridges the newdisplayproperty intoIndividualToolCallDisplay.ToolGroupMessagenow checkstool.originalRequestNameinstead of justtool.nameto determine if a tool supports the compact view. This allows subagent-aliased tools (likeSearchText) to correctly render as compactDenseToolMessagecomponents.ToolMessageandToolSharedwhere tool summaries were duplicated in both the header line and the result box. If a tool explicitly setsdisplay.resulttonull, the summary is rendered in the box, and automatically hidden from the header.Related Issues
Fixes #25046
How to Validate
ls,read_file,grep_search).DenseToolMessage.SearchTextin subagents) successfully trigger the compact view.result: null(likegrep_search) cleanly render their summary in the main box when forced into a non-compact view, without duplicating the summary in the header.Pre-Merge Checklist