Skip to content

refactor(cli,core): foundational layout, identity management, and type safety#23286

Merged
jwhelangoog merged 2 commits intomainfrom
dense-output-build-prep
Mar 24, 2026
Merged

refactor(cli,core): foundational layout, identity management, and type safety#23286
jwhelangoog merged 2 commits intomainfrom
dense-output-build-prep

Conversation

@jwhelangoog
Copy link
Contributor

@jwhelangoog jwhelangoog commented Mar 20, 2026

This commit establishes the structural foundation and required infrastructure to support the upcoming compact tool output changes. It includes identity management improvements, layout fixes, and type-safety enhancements that stand independently.

  1. Identity & History Management:
  • useHistoryManager: Ensure strictly increasing IDs for history items, even with identical timestamps.
  • acpClient: Introduced callIdCounter to prevent callId collisions during rapid execution.
  • MainContent: Implemented negative ID logic for pending items to ensure stable React keys and prevent collisions.
  • historyUtils: New file containing extracted history logic (isToolExecuting, getAllToolCalls) hoisted from AppContainer.
  1. UI Infrastructure & Layout:
  • test-utils/render: Modernized renderWithProviders and removed legacy props.
  • AskUserDialog: Fixed layout, scroll visibility, and alignment issues.
  • toolLayoutUtils: Increased TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT for better spacing.
  • ShellToolMessage/ToolGroupMessage: Updated line-count expectations and snapshots to align with layout changes.
  1. IDE & Diffing Improvements:
  • ToolActionsContext: Refactored IdeClient initialization to fix a race condition and potential memory leak.
  • edit/diffOptions: Improved accuracy of diff stat derivation, ensuring "full content" stats are available for the model.
  • coreToolScheduler: Automatically derive diff stats from patches if missing.
  • state-manager: Ensure diffStat preservation for rejected tool calls.
  1. Type Safety & Constants:
  • types/tools: Added foundational types like DiffStat, FileDiff, and StructuredToolResult.
  • Type Guards: Added guards for isFileDiff, isTodoList, isAnsiOutput, and hasSummary.
  • CodeColorizer: Added function overloads to gracefully handle null language detection.
  • tool-names: Introduced DISPLAY_NAME constants for consistent tool labeling.

This commit passes all workspace tests and builds successfully. Feature-specific logic for compact output is excluded.

Summary

Details

Related Issues

Related to #20974
Related to #16190

How to Validate

Pre-Merge Checklist

  • Updated relevant documentation and README (if needed)
  • Added/updated tests (if needed)
  • 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

@jwhelangoog jwhelangoog requested review from a team as code owners March 20, 2026 19:14
@gemini-cli
Copy link
Contributor

gemini-cli bot commented Mar 20, 2026

Hi @jwhelangoog, 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
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 establishes a robust structural foundation for upcoming compact tool output changes. It significantly enhances identity management across various components, refines UI layouts for improved user experience, and strengthens type safety throughout the codebase. These changes are designed to provide a more stable, predictable, and maintainable platform for future development, particularly in how tool outputs and user interactions are handled.

Highlights

  • Identity & History Management: Ensured strictly increasing IDs for history items, even with identical timestamps, introduced a callIdCounter to prevent callId collisions, and implemented negative ID logic for pending items to ensure stable React keys. Extracted history logic into a new historyUtils.ts file.
  • UI Infrastructure & Layout: Modernized renderWithProviders in test utilities, fixed layout, scroll visibility, and alignment issues in AskUserDialog, and increased TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT for better spacing. Updated line-count expectations and snapshots for ShellToolMessage and ToolGroupMessage.
  • IDE & Diffing Improvements: Refactored IdeClient initialization in ToolActionsContext to fix a race condition and potential memory leak. Improved accuracy of diff stat derivation, ensuring "full content" stats are available for the model, and automatically derive diff stats from patches if missing. Ensured diffStat preservation for rejected tool calls.
  • Type Safety & Constants: Added foundational types like DiffStat, FileDiff, and StructuredToolResult. Introduced type guards for isFileDiff, isTodoList, isAnsiOutput, and hasSummary. Added function overloads to CodeColorizer to gracefully handle null language detection, and introduced DISPLAY_NAME constants for consistent tool labeling.
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

github-actions bot commented Mar 20, 2026

Size Change: +4.09 kB (+0.02%)

Total Size: 26.2 MB

Filename Size Change
./bundle/chunk-6GCDS7KQ.js 0 B -1.95 MB (removed) 🏆
./bundle/chunk-7SZLRARL.js 0 B -14.5 MB (removed) 🏆
./bundle/chunk-DNIRWBWA.js 0 B -3.64 MB (removed) 🏆
./bundle/core-NT6PDYMG.js 0 B -42.9 kB (removed) 🏆
./bundle/devtoolsService-NGSLBP5W.js 0 B -27.7 kB (removed) 🏆
./bundle/interactiveCli-QKRLD63B.js 0 B -1.62 MB (removed) 🏆
./bundle/oauth2-provider-EBPZITIB.js 0 B -9.16 kB (removed) 🏆
./bundle/chunk-2HSM4KGN.js 3.64 MB +3.64 MB (new file) 🆕
./bundle/chunk-7CGXLV7I.js 1.95 MB +1.95 MB (new file) 🆕
./bundle/chunk-TAVU3XKE.js 14.5 MB +14.5 MB (new file) 🆕
./bundle/core-BDKWE6UE.js 43.3 kB +43.3 kB (new file) 🆕
./bundle/devtoolsService-AFQB6LAL.js 27.7 kB +27.7 kB (new file) 🆕
./bundle/interactiveCli-R5O7ZIZ6.js 1.62 MB +1.62 MB (new file) 🆕
./bundle/oauth2-provider-H4L5TSQF.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 521 kB +176 B (+0.03%)
./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-FUUTEVVM.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-VGDJNR3K.js 922 B +922 B (new file) 🆕

compressed-size-action

Copy link
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 foundational layout, identity management, and type safety improvements to the Gemini CLI project. The changes include ensuring strictly increasing IDs for history items, preventing callId collisions, modernizing test rendering, fixing UI layout issues, refactoring IDE client initialization, improving diff stat derivation, adding foundational types, and introducing display name constants for tools. The review focuses on ensuring the correct implementation of the callId counter and the accuracy of the scroll arrows in the AskUserDialog component.

Note: Security Review did not run due to the size of the PR.

@gemini-cli gemini-cli bot added the priority/p1 Important and should be addressed in the near term. label Mar 20, 2026
}
terminalWidth={mainAreaWidth}
item={{ ...item, id: 0 }}
item={{ ...item, id: -(i + 1) }}
Copy link
Contributor

Choose a reason for hiding this comment

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

why are you making these ids negative? seems odd.

Copy link
Contributor Author

@jwhelangoog jwhelangoog Mar 20, 2026

Choose a reason for hiding this comment

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

This now assigns a sequential negative id to transient pending history items until they eventually are transitioned into a permanent (positive) history id. Previously pending items were based on an id of zero; potential for dup key errors.

@jwhelangoog jwhelangoog force-pushed the dense-output-build-prep branch 7 times, most recently from 820c873 to 7ad2090 Compare March 20, 2026 23:33
Copy link
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.

Approved whether these comments are addressed

@jacob314
Copy link
Contributor

Code Review for PR #23286 (Frontend & Core Focus)

Review generated via /review-frontend and reviewed by Jacob.

This PR establishes an excellent structural foundation for the upcoming compact tool output changes. It cleanly extracts history management logic (historyUtils.ts), modernizes test rendering (renderWithProviders), fixes UI layout and keyboard interaction issues (AskUserDialog, toolLayoutUtils), and introduces important state stability improvements (e.g. useHistoryManager strictly increasing IDs, and speculative DiffStat calculation for canceled Edit tool calls).

However, I've identified a few architectural and logical issues that should be addressed to ensure consistency and prevent subtle bugs in the future.

Critical Findings

  1. Type Duplication (packages/cli/src/ui/types.ts):

    • Issue: The PR introduces DiffStat and FileDiff interfaces to packages/cli/src/ui/types.ts. However, these exact types are already defined and exported from packages/core/src/tools/tools.ts. Redefining them in the CLI package violates DRY and risks future type mismatches.
    • Recommendation: Remove the duplicate definitions from packages/cli/src/ui/types.ts and import them directly from @google/gemini-cli-core.
  2. Type Guard Robustness and Placement (packages/cli/src/ui/types.ts):

    • Issue: The new type guards (isListResult, isGrepResult) rely on checking for the presence of optional array properties (e.g., 'files' in res || 'include' in res for isListResult). If a tool successfully executes but returns an empty result (e.g., ReadManyFiles skipped all files, returning only { summary: "Read 0 files", skipped: [...] } without an include or files array), it will fail isListResult. Furthermore, since these types represent the output of tools that live in packages/core, they must be defined in core so the tools can actually return them in a future PR without creating a circular dependency.
    • Recommendation: Define these result interfaces (GrepResult, ListDirectoryResult, etc.) and their type guards in packages/core/src/tools/tools.ts, just like you did with StructuredToolResult. Also, consider strictly requiring the arrays to be present (even if empty []) or using a discriminated union property (e.g., kind: 'ListResult') to make these results unambiguously identifiable.

Improvements

  1. IdeClient State Initialization (packages/cli/src/ui/contexts/ToolActionsContext.tsx):

    • Observation: Moving ideClient into useState(() => new IdeClient(...)) fixes the exhaustive-deps warning and ensures a stable reference.
    • Issue: In React Strict Mode (common in dev), the useState initializer runs twice, creating a second IdeClient instance that is immediately discarded and never disposed. While it likely won't leak sockets (since connect() isn't called on the discarded instance), it's worth noting. More importantly, if config.ide.ideIntegrationEnabled or ideRpcSocketPath change at runtime, the IdeClient will not be recreated because the useState initializer only runs on mount.
    • Recommendation: If the ToolActionsProvider remounts when settings change, this is fine. If it is meant to react dynamically to settings changes, consider returning to a standard useEffect for creation and cleanup, and properly manage the dependencies.
  2. TOGGLE_ALL State Mismatch (packages/cli/src/ui/components/AskUserDialog.tsx):

    • Issue: When the user selects "All of the above" in a multi-select prompt, choiceQuestionReducer correctly toggles all predefined indices in selectedIndices. However, it completely ignores the isCustomOptionSelected state (the "Other" text input). If the user had "Other" checked, and then toggles "All of the above" off, the custom option remains checked.
    • Recommendation: Consider whether TOGGLE_ALL should also clear the custom option state to keep the behavior cohesive, or explicitly document that "All" strictly refers to predefined options.

Nitpicks

  1. callIdCounter in acpClient.ts: Using a module-level let callIdCounter = 0; is fine for the standard CLI lifecycle, but just be aware that it will persist and increment across multiple independent runAcpClient sessions within the same Node process (e.g., during tests). This isn't a bug, just a side effect of module-level state.

@jwhelangoog
Copy link
Contributor Author

Providing the following updates to address feedback from /review-frontend and Jacob


Critical Findings

Type Duplication (packages/cli/src/ui/types.ts):

@jwhelangoog: removed duplicate definitions from types.ts

Type Guard Robustness and Placement (packages/cli/src/ui/types.ts):

@jwhelangoog: moved improved guards to tools.ts

Improvements

IdeClient State Initialization (packages/cli/src/ui/contexts/ToolActionsContext.tsx):

@jwhelangoog: changes to this file have been reverted.

TOGGLE_ALL State Mismatch (packages/cli/src/ui/components/AskUserDialog.tsx):

@jwhelangoog: outside PR scope

@jwhelangoog jwhelangoog force-pushed the dense-output-build-prep branch 3 times, most recently from 9ca0cb4 to 6c6e51e Compare March 21, 2026 07:35
Copy link
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

@jwhelangoog
Copy link
Contributor Author

@anj-s please review for google-gemini/gemini-cli-prompt-approvers approval. TIA!

DEFAULT_DIFF_OPTIONS,
);

// Determine the full content as originally proposed by the AI to ensure accurate diff stats.
Copy link
Contributor

Choose a reason for hiding this comment

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

right bellow this we call getDiffStat. Why is htat not sufficient? Worry we are adding duplicate logic here and elsewhere in this pr tracking diffs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Added to alleviate the case when user's modify AI suggested changes. Will create an issue for further cleanup / refactor.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
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

@jwhelangoog jwhelangoog force-pushed the dense-output-build-prep branch 2 times, most recently from d999ece to 5e65786 Compare March 23, 2026 23:19
@github-actions
Copy link

github-actions bot commented Mar 23, 2026

🧠 Model Steering Guidance

This PR modifies files that affect the model's behavior (prompts, tools, or instructions).

  • ⚠️ Consider adding Evals: No behavioral evaluations (evals/*.eval.ts) were added or updated in this PR. Consider adding a test case to verify the new behavior and prevent regressions.
  • 🚀 Maintainer Reminder: Please ensure that these changes do not regress results on benchmark evals before merging.

This is an automated guidance message triggered by steering logic signatures.

@jwhelangoog jwhelangoog force-pushed the dense-output-build-prep branch from 5e65786 to 8507b97 Compare March 23, 2026 23:26
…e safety

This commit establishes the structural foundation and required infrastructure to support the upcoming compact tool output changes. It includes identity management improvements, layout fixes, and type-safety enhancements that stand independently.

1. Identity & History Management:
- useHistoryManager: Ensure strictly increasing IDs for history items, even with identical timestamps.
- acpClient: Introduced callIdCounter to prevent callId collisions during rapid execution.
- MainContent: Implemented negative ID logic for pending items to ensure stable React keys and prevent collisions.
- historyUtils: New file containing extracted history logic (isToolExecuting, getAllToolCalls) hoisted from AppContainer.

2. UI Infrastructure & Layout:
- test-utils/render: Modernized renderWithProviders and removed legacy props.
- AskUserDialog: Fixed layout, scroll visibility, and alignment issues.
- toolLayoutUtils: Increased TOOL_RESULT_STANDARD_RESERVED_LINE_COUNT for better spacing.
- ShellToolMessage/ToolGroupMessage: Updated line-count expectations and snapshots to align with layout changes.

3. IDE & Diffing Improvements:
- ToolActionsContext: Refactored IdeClient initialization to fix a race condition and potential memory leak.
- edit/diffOptions: Improved accuracy of diff stat derivation, ensuring "full content" stats are available for the model.
- coreToolScheduler: Automatically derive diff stats from patches if missing.
- state-manager: Ensure diffStat preservation for rejected tool calls.

4. Type Safety & Constants:
- types/tools: Added foundational types like DiffStat, FileDiff, and StructuredToolResult.
- Type Guards: Added guards for isFileDiff, isTodoList, isAnsiOutput, and hasSummary.
- CodeColorizer: Added function overloads to gracefully handle null language detection.
- tool-names: Introduced DISPLAY_NAME constants for consistent tool labeling.

5. Changes from Review Feedback
- consolidated tool-related interfaces and type guards within tools.js
@jwhelangoog jwhelangoog force-pushed the dense-output-build-prep branch from 8507b97 to 87cc88b Compare March 24, 2026 01:23
@jwhelangoog jwhelangoog added this pull request to the merge queue Mar 24, 2026
Merged via the queue into main with commit 89ca788 Mar 24, 2026
28 checks passed
@jwhelangoog jwhelangoog deleted the dense-output-build-prep branch March 24, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

priority/p1 Important and should be addressed in the near term.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants