Skip to content

Conversation

@jackwotherspoon
Copy link
Collaborator

@jackwotherspoon jackwotherspoon commented Dec 7, 2025

Summary

Optimizes session summary generation by moving it from exit-time (blocking) to startup-time (non-blocking), eliminating the potential max of a 5 second delay when closing the CLI.

Previously, when a user exited the CLI, the application would block while making an API call to generate a summary for the current session. This caused a noticeable delay before the terminal returned to the user. Now, summary generation happens in the background on the next startup, making exit instant.

Also added a check that only generates a summary if more than 1 user messages exist in the session. This way non-interactive mode sessions are not summarized as well as single message sessions where the initial prompt most likely captures the overall intent of the user, saving model calls.

Details

Move summary generation from exit to startup

  • Removed the blocking await generateAndSaveSummary(config) call from the cleanup handler in AppContainer.tsx
  • Added a fire-and-forget generateSummary(config).catch(...) call in the startup useEffect
  • Summary generation now runs in the background without blocking the UI or delaying startup

Add summary generation to --list-sessions

  • When running gemini --list-sessions, the CLI now checks if the most recent session needs a summary and generates one if so
  • This ensures the session list shows an up-to-date summary for the previous session
  • Uses a blocking call here since the user is explicitly viewing sessions and expects accurate data

Use filename-based sorting instead of mtime

  • Changed from sorting sessions by file modification time (mtime) to sorting by filename
  • Session filenames contain creation timestamps (e.g., session-2024-01-15T10-30-abc123.json)
  • This correctly identifies the most recently created session rather than the most recently modified
  • Fixes edge case where resuming an old session would incorrectly mark it as "most recent" due to updated mtime

Skip single message sessions (1+ user message threshold)

  • Only generate summaries for sessions with more than 1 user message
  • Short sessions (like single non-interactive prompts) don't benefit from summaries - the first message already serves as a good description
  • Reduces unnecessary API calls and helps users avoid hitting rate limits

Code cleanup

  • Removed redundant dirExists variable in getPreviousSession
  • Removed generateAndSaveFromCurrentSession function (dead code after refactor)
  • Simplified session finding logic to only check the most recent session file
  • Switched from sync fs to async fs/promises for non-blocking I/O

Files Changed

File Changes
packages/core/src/services/sessionSummaryUtils.ts Refactored getPreviousSession to use filename sorting and 5-message threshold; simplified generateSummary for fire-and-forget usage
packages/core/src/services/sessionSummaryUtils.test.ts Updated tests for new behavior including message threshold and filename-based sorting
packages/cli/src/ui/AppContainer.tsx Removed blocking exit call; added fire-and-forget startup call
packages/cli/src/utils/sessions.ts Added generateSummary call before listing sessions
packages/cli/src/utils/sessions.test.ts Added mock for generateSummary

Testing

  • All existing tests updated and passing
  • New test cases added for:
    • Filename-based session ordering
    • Sessions with 0 or 1 message returning null

Related Issues

Related to #8476

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

@jackwotherspoon jackwotherspoon requested a review from a team as a code owner December 7, 2025 21:38
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @jackwotherspoon, 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 refactors the session summary generation mechanism within the CLI. The primary goal is to enhance user experience by making application exit instantaneous, achieved by deferring summary creation to a background process during the subsequent startup. Additionally, it ensures that session summaries are accurate and readily available when users explicitly request to view their session history, while also optimizing resource usage by intelligently deciding which sessions warrant a summary.

Highlights

  • Performance Optimization: Session summary generation has been moved from a blocking exit-time operation to a non-blocking startup-time background task, eliminating a ~5 second delay when closing the CLI.
  • Improved Session Listing: When listing sessions (--list-sessions), the CLI now proactively checks and generates a summary for the most recent session if needed, ensuring accurate and up-to-date information.
  • Enhanced Session Identification: Session sorting now relies on timestamps embedded in filenames rather than file modification times (mtime), correctly identifying the most recently created session and preventing issues with resumed old sessions.
  • Resource Efficiency: Summaries are now only generated for sessions with 5 or more user messages, reducing unnecessary API calls and helping users avoid rate limits for short, less meaningful interactions.
  • Code Modernization: Various code cleanup tasks were performed, including removing dead code, simplifying logic, and migrating synchronous file system operations to asynchronous fs/promises for better performance.
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
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 is a great refactoring that significantly improves the user experience by moving the blocking session summary generation to a background task on startup. The changes are well-structured, and the logic for identifying sessions that need a summary is sound, including the filename-based sorting and the message count threshold. The addition of summary generation to --list-sessions is also a thoughtful touch to ensure data is up-to-date. I have one suggestion to improve the robustness of the file handling logic to make it more resilient to potential race conditions.

@github-actions
Copy link

github-actions bot commented Dec 7, 2025

Size Change: +2.97 kB (+0.01%)

Total Size: 21.6 MB

Filename Size Change
./bundle/gemini.js 21.5 MB +2.97 kB (+0.01%)
ℹ️ View Unchanged
Filename Size
./bundle/sandbox-macos-permissive-closed.sb 1.03 kB
./bundle/sandbox-macos-permissive-open.sb 890 B
./bundle/sandbox-macos-permissive-proxied.sb 1.31 kB
./bundle/sandbox-macos-restrictive-closed.sb 3.29 kB
./bundle/sandbox-macos-restrictive-open.sb 3.36 kB
./bundle/sandbox-macos-restrictive-proxied.sb 3.56 kB

compressed-size-action

@jacob314
Copy link
Collaborator

jacob314 commented Dec 8, 2025

This looks like a solid refactor that will improve the user experience by making the CLI exit immediately. I have a few suggestions to improve maintainability and performance.

Review Summary

  • Refactor: Moving the summary generation to startup (fire-and-forget) and list-sessions (blocking) is a great UX improvement.
  • Logic: The filename-based sorting and the 5-message threshold seem correct and well-implemented.
  • Performance: There's a small opportunity to optimize file I/O in getPreviousSession.
  • Maintainability: The threshold constant (5) should be a named constant.

Detailed Comments

  1. Magic Number:
    In packages/core/src/services/sessionSummaryUtils.ts, the value 5 is used as a threshold for generating summaries.

    if (userMessageCount < 5) {

    Please extract this to a named constant (e.g., MIN_MESSAGES_FOR_SUMMARY) at the top of the file or in a constants file. This makes the intent clear and easier to change later.

  2. Redundant I/O:
    In getPreviousSession, you read and parse the session file to check the message count and existing summary. If generateSummary proceeds, it calls generateAndSaveSummary, which reads and parses the same file again.
    Suggestion: You could modify getPreviousSession (or return a helper object) to pass the parsed conversation to generateSummary, avoiding the second read. generateAndSaveSummary would still need its final re-read (to handle race conditions), but we can save one read operation.

  3. Behavior of getPreviousSession:
    The current logic checks only the most recent session.

    const mostRecentFile = sessionFiles[0];
    // ...
    if (userMessageCount < 5) { return null; }

    If the user has a "skipped" session (e.g., 2 messages) as their most recent one, and the one before that was a long unsummarized session (e.g., from a crash), the older one will never be summarized.
    Question: Is this the intended behavior? The PR description says "Simplified session finding logic to only check the most recent session file," which implies yes, but I want to confirm we are okay leaving potentially unsummarized older sessions. (This is likely acceptable for a "previous session" feature).

  4. Tests:
    The tests in packages/core/src/services/sessionSummaryUtils.test.ts are comprehensive. Good job mocking fs/promises.

  5. Imports:
    You are using import fs from 'node:fs/promises' in the implementation and import * as fs from 'node:fs/promises' in the test. This is acceptable, but consider checking if import fs works in the test as well for consistency, unless vi.mock specifically requires the namespace import in your setup.

@jackwotherspoon
Copy link
Collaborator Author

jackwotherspoon commented Dec 8, 2025

If the user has a "skipped" session (e.g., 2 messages) as their most recent one, and the one before that was a long unsummarized session (e.g., from a crash), the older one will never be summarized.
Question: Is this the intended behavior? The PR description says "Simplified session finding logic to only check the most recent session file," which implies yes, but I want to confirm we are okay leaving potentially unsummarized older sessions. (This is likely acceptable for a "previous session" feature).

Yes this is intended. Used to use mimetypes to look at most recently "edited" session but this was pointless as old sessions should already be summarized. If I resumed an old session, i don't want the next startup to look for a summary on that file. So I removed the pain of searching mimetypes to rely on file names which are by date and time.

Also didn't want Gemini CLI to repeatedly go back and summarize old sessions. Users could have a large amount of sessions pre-dating this summarization feature and always going back and summarizing 1 potentially really old session is strange behavior.

Just looking at previous session makes this behavior more clear and faster by only looking at most recent created session and will start from the feature being rolled out.

@gemini-cli gemini-cli bot added size/l A large sized PR review/involved PRs that may take a lot of work to review labels Dec 9, 2025
@jacob314
Copy link
Collaborator

jacob314 commented Dec 9, 2025

In packages/cli/src/ui/AppContainer.tsx, the useEffect calling generateSummary will run twice in development/debug mode due to React.StrictMode. Consider using a useRef to ensure it only runs once per mount to avoid redundant checks/calls.

const summaryGeneratedRef = useRef(false);
useEffect(() => {
  if (summaryGeneratedRef.current) return;
  summaryGeneratedRef.current = true;
  // ... generateSummary logic
}, [config]);

Copy link
Collaborator

@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

@jackwotherspoon
Copy link
Collaborator Author

In packages/cli/src/ui/AppContainer.tsx, the useEffect calling generateSummary will run twice in development/debug mode due to React.StrictMode. Consider using a useRef to ensure it only runs once per mount to avoid redundant checks/calls.

const summaryGeneratedRef = useRef(false);
useEffect(() => {
  if (summaryGeneratedRef.current) return;
  summaryGeneratedRef.current = true;
  // ... generateSummary logic
}, [config]);

Done 👍

@jackwotherspoon jackwotherspoon added this pull request to the merge queue Dec 10, 2025
Merged via the queue into main with commit ee6556c Dec 10, 2025
20 checks passed
@jackwotherspoon jackwotherspoon deleted the optimize-session-summary branch December 10, 2025 03:36
@jackwotherspoon
Copy link
Collaborator Author

/patch preview

@github-actions
Copy link

Patch workflow(s) dispatched successfully!

📋 Details:

  • Channels: preview
  • Commit: ee6556cbd2f00e83718a27695083c588afa1fb0a
  • Workflows Created: 1

🔗 Track Progress:

@github-actions
Copy link

🚀 Patch PR Created!

📋 Patch Details:

📝 Next Steps:

  1. Review and approve the hotfix PR: #14908
  2. Once merged, the patch release will automatically trigger
  3. You'll receive updates here when the release completes

🔗 Track Progress:

@github-actions
Copy link

🚀 Patch Release Started!

📋 Release Details:

  • Environment: prod
  • Channel: preview → publishing to npm tag preview
  • Version: v0.21.0-preview.1
  • Hotfix PR: Merged ✅
  • Release Branch: release/v0.21.0-preview.1-pr-14691

⏳ Status: The patch release is now running. You'll receive another update when it completes.

🔗 Track Progress:

@github-actions
Copy link

Patch Release Complete!

📦 Release Details:

🎉 Status: Your patch has been successfully released and published to npm!

📝 What's Available:

🔗 Links:

thacio added a commit to thacio/auditaria that referenced this pull request Dec 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review/involved PRs that may take a lot of work to review size/l A large sized PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants