feat(cli): introduce visualize tool for rich data display#18778
feat(cli): introduce visualize tool for rich data display#18778
Conversation
- Implement `visualize` tool in core to support tables, charts, and diffs. - Add `RichDataDisplay` UI component using Ink for rendering visualizations. - Integrate visualization support into `ToolResultDisplay`. - Update system prompts to encourage the use of the `visualize` tool for structured data. - Add `info` semantic color to themes. - Fix shell parser initialization in tests.
Summary of ChangesHello @bdmorgan, 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 significantly enhances the CLI's ability to display complex data by introducing a dedicated visualization tool. This new feature allows for the structured presentation of information through tables, various chart types, and code diffs, moving beyond plain text outputs. The changes include core tool implementation, a new UI component for rendering these visualizations, and updates to the system's guidance to encourage its use, ultimately providing a richer and more intuitive user experience for data analysis and review within the command-line interface. Highlights
Changelog
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. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a visualize tool for richer data display in the CLI, a great enhancement for usability. The implementation is comprehensive, covering tables, various charts, and diffs, along with the necessary UI components and tests.
I've identified two high-severity issues related to the rendering logic that could lead to UI bugs. One concerns the pie chart's proportional bar calculation, which can cause it to exceed its container width, and has been addressed with a suggestion for a more robust distribution method. The other is a hardcoded height for diff rendering, which can result in improper truncation. My detailed comments provide suggestions for fixing these.
| {normalized.map((item, i) => { | ||
| const percent = total > 0 ? item.value / total : 0; | ||
| const barWidth = Math.max( | ||
| 1, | ||
| Math.floor(percent * availableWidth), | ||
| ); | ||
| return ( | ||
| <Text key={i} color={colors[i % colors.length]}> | ||
| {'█'.repeat(barWidth)} | ||
| </Text> | ||
| ); | ||
| })} |
There was a problem hiding this comment.
The current logic for calculating barWidth for the pie chart's proportional bar can lead to the total width exceeding availableWidth. When percent * availableWidth is less than 1, Math.floor makes it 0, and Math.max(1, 0) sets barWidth to 1. If there are many small-percentage items, the sum of these minimum-width bars can overflow the container, causing wrapping and breaking the visualization.
A more robust approach is to calculate all widths proportionally and distribute any remainder from flooring to ensure the total width exactly matches availableWidth.
{(() => {
if (total <= 0) {
return null;
}
const preciseWidths = normalized.map(
(item) => (item.value / total) * availableWidth,
);
const flooredWidths = preciseWidths.map((w) => Math.floor(w));
let remainder =
availableWidth - flooredWidths.reduce((sum, w) => sum + w, 0);
const fractionalParts = preciseWidths.map((w, i) => ({
index: i,
fraction: w - flooredWidths[i],
}));
fractionalParts.sort((a, b) => b.fraction - a.fraction);
for (let i = 0; i < remainder; i++) {
const indexToIncrement =
fractionalParts[i % fractionalParts.length].index;
flooredWidths[indexToIncrement]++;
}
return normalized.map((_item, i) => {
const barWidth = flooredWidths[i];
if (barWidth <= 0) {
return null;
}
return (
<Text key={i} color={colors[i % colors.length]}>
{'█'.repeat(barWidth)}
</Text>
);
});
})()}
References
- When distributing surplus space proportionally (e.g., in a table layout), avoid simple rounding with
Math.floor()for each column's share as it can lead to unused space. Instead, use a more precise method like the Largest Remainder Method to ensure all available space is utilized.
| content = ( | ||
| <RichDataDisplay | ||
| data={truncatedResultDisplay as RichVisualization} | ||
| availableWidth={childWidth} | ||
| /> | ||
| ); |
There was a problem hiding this comment.
The RichDataDisplay component isn't receiving the availableTerminalHeight, causing it to use a hardcoded height for diff rendering. This can lead to improper truncation.
To fix this, you should pass availableHeight to the RichDataDisplay component.
You will also need to update RichDataDisplay.tsx to accept and use this prop:
- Add
availableTerminalHeight?: number;toRichDataDisplayProps. - Destructure
availableTerminalHeightfrom the component's props. - Pass
availableTerminalHeightto theDiffRenderer, for example:availableTerminalHeight={availableTerminalHeight ?? 20}.
| content = ( | |
| <RichDataDisplay | |
| data={truncatedResultDisplay as RichVisualization} | |
| availableWidth={childWidth} | |
| /> | |
| ); | |
| content = ( | |
| <RichDataDisplay | |
| data={truncatedResultDisplay as RichVisualization} | |
| availableWidth={childWidth} | |
| availableTerminalHeight={availableHeight} | |
| /> | |
| ); |
|
Hi there! Thank you for your contribution to Gemini CLI. We really appreciate the time and effort you've put into this pull request. To keep our backlog manageable and ensure we're focusing on current priorities, we are closing pull requests that haven't seen maintainer activity for 30 days. Currently, the team is prioritizing work associated with 🔒 maintainer only or help wanted issues. If you believe this change is still critical, please feel free to comment with updated details. Otherwise, we encourage contributors to focus on open issues labeled as help wanted. Thank you for your understanding! |
Description
This PR introduces a new
visualizetool that allows the model to present structured data such as tables, charts (bar, pie, line), and diffs in a more readable and visual format within the CLI.Key Changes
visualizetool andRichVisualizationtype.RichDataDisplaycomponent using Ink to render various visualization types.RichDataDisplayintoToolResultDisplayfor seamless rendering of tool outputs.infosemantic color to themes.