Skip to content

feat(core): improve subagent result display#20378

Merged
joshualitt merged 2 commits intomainfrom
jl/subagent-return-ux
Mar 9, 2026
Merged

feat(core): improve subagent result display#20378
joshualitt merged 2 commits intomainfrom
jl/subagent-return-ux

Conversation

@joshualitt
Copy link
Copy Markdown
Contributor

Fixes #18289

@gemini-code-assist
Copy link
Copy Markdown
Contributor

Summary of Changes

Hello @joshualitt, 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 user experience for viewing subagent and tool execution results within the CLI. By implementing intelligent truncation that prioritizes the start of subagent outputs and automatically converting JSON results into a more readable Markdown format, the changes aim to make complex outputs more digestible and easier to understand at a glance.

Highlights

  • Improved Subagent Result Display: Subagent results in the CLI now truncate from the top, showing the beginning of the output, and are limited to a configurable maximum number of lines (15 lines by default).
  • Automatic JSON to Markdown Conversion: Tool results, including those from browser, local, and remote agents, are now automatically formatted into readable Markdown if their output is valid JSON, significantly enhancing readability.
  • Configurable Overflow Direction: The ToolResultDisplay component now supports an overflowDirection prop, allowing content to be truncated from either the 'top' (default, showing the end of the content) or 'bottom' (showing the beginning of the content).
  • New Markdown Utility Functions: Introduced jsonToMarkdown and safeJsonToMarkdown utility functions to convert JSON-like strings into a structured Markdown format, including table rendering for arrays of similar objects.
Changelog
  • packages/cli/src/ui/components/messages/ToolMessage.tsx
    • Imported Kind and SUBAGENT_MAX_LINES.
    • Added kind prop to ToolMessageProps.
    • Conditionally passed maxLines and overflowDirection to ToolResultDisplay for subagent (Kind.Think) messages.
  • packages/cli/src/ui/components/messages/ToolResultDisplay.tsx
    • Added overflowDirection prop to ToolResultDisplayProps.
    • Modified truncation logic to respect the overflowDirection when limiting characters and lines.
    • Updated useMemo dependencies to include overflowDirection.
    • Passed overflowDirection to MaxSizedBox.
  • packages/cli/src/ui/components/messages/ToolResultDisplayOverflow.test.tsx
    • Refactored tests to focus on ToolResultDisplay component.
    • Added new tests to verify overflowDirection functionality for both 'bottom' and 'top' truncation with string and ANSI content.
    • Mocked useUIState and useAlternateBuffer.
  • packages/cli/src/ui/constants.ts
    • Added SUBAGENT_MAX_LINES constant with a value of 15.
  • packages/cli/src/ui/hooks/toolMapping.ts
    • Mapped the call.tool?.kind property to the IndividualToolCallDisplay object.
  • packages/cli/src/ui/types.ts
    • Imported Kind type from @google/gemini-cli-core.
    • Added an optional kind property to the IndividualToolCallDisplay interface.
  • packages/core/src/agents/browser/browserAgentInvocation.ts
    • Imported safeJsonToMarkdown.
    • Applied safeJsonToMarkdown to the browser agent's output.result for display.
  • packages/core/src/agents/local-invocation.ts
    • Imported safeJsonToMarkdown.
    • Applied safeJsonToMarkdown to the local subagent's output.result for display.
  • packages/core/src/agents/remote-invocation.ts
    • Imported safeJsonToMarkdown.
    • Applied safeJsonToMarkdown to the remote agent's outputText for returnDisplay.
  • packages/core/src/utils/markdownUtils.test.ts
    • Added a new test file for markdownUtils.
    • Included comprehensive unit tests for jsonToMarkdown and safeJsonToMarkdown covering primitives, arrays, objects, nested structures, and table rendering.
  • packages/core/src/utils/markdownUtils.ts
    • Added a new utility file for Markdown conversion.
    • Implemented jsonToMarkdown to convert JSON-compatible data into a structured Markdown format, including special handling for arrays of similar objects to render as tables.
    • Implemented safeJsonToMarkdown to safely parse a string as JSON and convert it to Markdown, falling back to the original string if parsing fails.
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.

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

  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.

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 introduces a significant improvement to the display of subagent results by truncating long outputs from the top, showing the beginning of the content instead of the end. This is achieved by adding an overflowDirection property that controls the truncation behavior. Additionally, a new safeJsonToMarkdown utility has been added to format JSON outputs from agents into a more readable markdown format, which is a great enhancement for usability. The changes are well-tested. I have one suggestion to reduce code duplication in the truncation logic.

@gemini-cli gemini-cli bot added area/core Issues related to User Interface, OS Support, Core Functionality area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. labels Feb 26, 2026
@joshualitt joshualitt force-pushed the jl/subagent-return-ux branch from a58f54b to 23ce7f3 Compare February 26, 2026 01:50
@github-actions
Copy link
Copy Markdown

github-actions bot commented Feb 26, 2026

Size Change: +4.9 kB (+0.02%)

Total Size: 26 MB

Filename Size Change
./bundle/gemini.js 25.6 MB +4.9 kB (+0.02%)
ℹ️ View Unchanged
Filename Size
./bundle/node_modules/@google/gemini-cli-devtools/dist/client/main.js 221 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/_client-assets.js 227 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/index.js 11.5 kB
./bundle/node_modules/@google/gemini-cli-devtools/dist/src/types.js 132 B
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB
./bundle/sandbox-macos-strict-open.sb 4.82 kB
./bundle/sandbox-macos-strict-proxied.sb 5.02 kB

compressed-size-action

@joshualitt joshualitt force-pushed the jl/subagent-return-ux branch from 23ce7f3 to 2f056d0 Compare February 26, 2026 18:07
@joshualitt joshualitt marked this pull request as ready for review February 26, 2026 18:26
@joshualitt joshualitt requested review from a team as code owners February 26, 2026 18:26
@joshualitt joshualitt force-pushed the jl/subagent-return-ux branch 4 times, most recently from cf72b6d to 7ae739c Compare February 26, 2026 22:23
@jacob314 jacob314 self-requested a review February 26, 2026 23:52
@jacob314
Copy link
Copy Markdown
Contributor

This review was generated using /review-frontend running with 3.1 pro-preview.

I've reviewed the PR and found a couple of areas where the code could better align with our strict development rules:

1. Unnecessary Mocking in ToolResultDisplayOverflow.test.tsx

The PR introduces vi.mock() for useUIState and useAlternateBuffer at the top of the file. Our development rules prefer avoiding global mocks when possible, especially since renderWithProviders already supports injecting these values.
You can remove the vi.mock() blocks and pass the configuration natively during the render call:

const { lastFrame, waitUntilReady, unmount } = renderWithProviders(
  <ToolResultDisplay ... />,
  {
    uiState: { renderMarkdown: true },
    useAlternateBuffer: false,
  }
);

2. Unsafe Type Assertions in markdownUtils.ts

In isArrayOfSimilarObjects, there are as object assertions along with disabled lint rules (eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion). Our rules strictly forbid any and unknown without immediate narrowing, and disabling lint rules for type assertions should be avoided if there is a type-safe alternative.

This can be cleanly resolved without assertions by defining a type guard. When Array.prototype.every is used with a type guard, TypeScript automatically narrows the array:

function isRecord(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

function isArrayOfSimilarObjects(
  data: unknown[],
): data is Array<Record<string, unknown>> {
  if (data.length === 0) return false;
  
  if (!data.every(isRecord)) return false;
  
  // `data` is now strictly typed as `Array<Record<string, unknown>>`
  const firstKeys = Object.keys(data[0]).sort().join(',');
  return data.every(item => Object.keys(item).sort().join(',') === firstKeys);
}

Great work on the feature overall, the JSON to Markdown conversion and managing overflowDirection for subagents will be a solid improvement!

@joshualitt joshualitt force-pushed the jl/subagent-return-ux branch 2 times, most recently from e89137b to 7b6c4dc Compare March 2, 2026 23:09
@joshualitt joshualitt requested a review from jacob314 March 2, 2026 23:41
@joshualitt
Copy link
Copy Markdown
Contributor Author

@jacob314 ptal, all feedback should be addressed. Thanks!

}
}

function isRecord(value: unknown): value is Record<string, unknown> {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

We have 2 other isRecord() implementations across the codebase. Can we de-dupe in a central place?

@joshualitt joshualitt force-pushed the jl/subagent-return-ux branch 4 times, most recently from 3e00a98 to 71504d5 Compare March 9, 2026 18:49
@joshualitt joshualitt force-pushed the jl/subagent-return-ux branch from 71504d5 to ceff622 Compare March 9, 2026 19:01
@joshualitt joshualitt added this pull request to the merge queue Mar 9, 2026
Merged via the queue into main with commit a17691f Mar 9, 2026
27 checks passed
@joshualitt joshualitt deleted the jl/subagent-return-ux branch March 9, 2026 20:18
kunal-10-cloud pushed a commit to kunal-10-cloud/gemini-cli that referenced this pull request Mar 12, 2026
liamhelmer pushed a commit to badal-io/gemini-cli that referenced this pull request Mar 12, 2026
yashodipmore pushed a commit to yashodipmore/geemi-cli that referenced this pull request Mar 21, 2026
SUNDRAM07 pushed a commit to SUNDRAM07/gemini-cli that referenced this pull request Mar 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality area/core Issues related to User Interface, OS Support, Core Functionality 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[UX] Clean Subagent return UI

4 participants