Skip to content

feat(cli): auto-compress chat history on context window overflow#28488

Open
kunalrawat425 wants to merge 1 commit into
google-gemini:mainfrom
kunalrawat425:kunalrawat425/feat-auto-compress-on-overflow
Open

feat(cli): auto-compress chat history on context window overflow#28488
kunalrawat425 wants to merge 1 commit into
google-gemini:mainfrom
kunalrawat425:kunalrawat425/feat-auto-compress-on-overflow

Conversation

@kunalrawat425

Copy link
Copy Markdown

Add a new model.autoCompressOnOverflow setting that automatically compresses chat history when the context window is about to overflow, instead of stopping with a warning.

  • Cancel the current submit
  • Show a clear info message that auto-compression is starting
  • Await geminiClient.tryCompressChat() in the background
  • Display the compression result when done
  • Prompt the user to re-send their message

Add a new `model.autoCompressOnOverflow` boolean setting (default: false)
that, when enabled, automatically runs context compression when a prompt
is about to exceed the context window limit — instead of stopping with a
warning and requiring the user to manually run /compress.

When the context-window-will-overflow event fires and the setting is on:
- Cancel the current submit (existing behavior)
- Show a clear info message that auto-compression is starting
- Await geminiClient.tryCompressChat() in the background
- Display the compression result (token savings) when done
- Prompt the user to re-send their message

When the setting is off the existing warning-only behavior is unchanged.

The new setting appears in the settings dialog under the Model category
and does not require a restart.
@kunalrawat425
kunalrawat425 requested a review from a team as a code owner July 22, 2026 15:57
@github-actions github-actions Bot added the size/m A medium sized PR label Jul 22, 2026
@github-actions

Copy link
Copy Markdown

📊 PR Size: size/M

  • Lines changed: 66
  • Additions: +65
  • Deletions: -1
  • Files changed: 3

@gemini-code-assist

Copy link
Copy Markdown
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 introduces an automated mechanism to handle context window overflows in the CLI. By adding a configurable option, the system can now proactively compress chat history instead of simply halting with an error. This improves the continuity of long-running chat sessions by managing token usage more gracefully.

Highlights

  • New Configuration Setting: Added a new 'autoCompressOnOverflow' setting to the model configuration, allowing users to enable automatic chat history compression when context limits are reached.
  • Automated Compression Logic: Integrated background compression logic in the Gemini stream hook that triggers when the context window is near capacity, providing real-time feedback to the user.
  • User Experience Improvements: Implemented a non-blocking flow that notifies the user when compression starts and prompts them to re-send their message once the process completes successfully.
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 the 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 counterproductive. 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.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

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 an autoCompressOnOverflow configuration setting to automatically compress chat history when the context window is close to overflowing. Feedback highlights a critical race condition and usability issue where the background compression task cannot be cancelled and allows user input in the meantime; using an AbortController and setting isResponding is recommended to handle this safely. Additionally, the setting's description should be updated to accurately reflect that users must manually re-send their prompt after compression, rather than it being retried automatically.

Comment on lines +1349 to +1393
if (
isMoreThan25PercentUsed &&
settings.merged.model.autoCompressOnOverflow
) {
addItem({
type: 'info',
text: `Context window limit reached (${remainingTokenCount.toLocaleString()} tokens left). Auto-compressing history — your prompt will be ready to re-send after compression completes.`,
});

void (async () => {
try {
const promptId = `auto-compress-overflow-${Date.now()}`;
const compressed = await geminiClient.tryCompressChat(
promptId,
true,
);
if (compressed) {
addItem({
type: MessageType.COMPRESSION,
compression: {
isPending: false,
originalTokenCount: compressed.originalTokenCount,
newTokenCount: compressed.newTokenCount,
compressionStatus: compressed.compressionStatus,
},
} as HistoryItemCompression);
addItem({
type: 'info',
text: 'Auto-compression complete. Please re-send your prompt.',
});
} else {
addItem({
type: 'info',
text: 'Auto-compression failed. Use `/compress` manually or reduce your message size.',
});
}
} catch {
addItem({
type: 'info',
text: 'Auto-compression encountered an error. Use `/compress` manually.',
});
}
})();
return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Race Condition & Un-cancellable Background Task in Auto-Compression

There is a significant race condition and usability issue with the current background auto-compression implementation:

  1. Un-cancellable Task: When auto-compression starts, isResponding is not set to true. Because of this, streamingState remains Idle, and cancelOngoingRequest (triggered by Escape or Ctrl+C) will return early and do nothing. The user cannot cancel the background compression.
  2. Race Condition: Since the input remains active, the user can type and submit a new prompt while the background compression is still running. When the compression finishes, it will call addItem and inject messages ("Auto-compression complete...") right in the middle of the new streaming prompt's UI/history.

Solution

To resolve this, we should:

  1. Set isResponding to true during compression to disable input and indicate that the system is busy.
  2. Create a new AbortController for the compression task and assign it to abortControllerRef.current so that user cancellation (Escape/Ctrl+C) can abort the compression.
  3. Pass the abort signal to tryCompressChat and check signal.aborted before updating the UI state.
      if (
        isMoreThan25PercentUsed &&
        settings.merged.model.autoCompressOnOverflow
      ) {
        setIsResponding(true);
        const compressController = new AbortController();
        abortControllerRef.current = compressController;

        addItem({
          type: 'info',
          text: 'Context window limit reached (' + remainingTokenCount.toLocaleString() + ' tokens left). Auto-compressing history — your prompt will be ready to re-send after compression completes.',
        });

        void (async () => {
          try {
            const promptId = 'auto-compress-overflow-' + Date.now();
            const compressed = await geminiClient.tryCompressChat(
              promptId,
              true,
              compressController.signal,
            );
            if (compressController.signal.aborted) {
              return;
            }
            if (compressed) {
              addItem({
                type: MessageType.COMPRESSION,
                compression: {
                  isPending: false,
                  originalTokenCount: compressed.originalTokenCount,
                  newTokenCount: compressed.newTokenCount,
                  compressionStatus: compressed.compressionStatus,
                },
              } as HistoryItemCompression);
              addItem({
                type: 'info',
                text: 'Auto-compression complete. Please re-send your prompt.',
              });
            } else {
              addItem({
                type: 'info',
                text: 'Auto-compression failed. Use `/compress` manually or reduce your message size.',
              });
            }
          } catch {
            if (compressController.signal.aborted) {
              return;
            }
            addItem({
              type: 'info',
              text: 'Auto-compression encountered an error. Use `/compress` manually.',
            });
          } finally {
            if (!compressController.signal.aborted) {
              setIsResponding(false);
            }
          }
        })();
        return;
      }
References
  1. Asynchronous operations that can be cancelled by the user should accept and propagate an AbortSignal to ensure cancellability and prevent dangling processes or network requests.

Comment on lines +1128 to +1129
description:
'When the context window is about to overflow, automatically compress the chat history and retry the prompt instead of stopping with an error.',

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

high

Discrepancy in Setting Description

The setting description states that it will "automatically compress the chat history and retry the prompt", but the actual implementation in useGeminiStream.ts cancels the current submit and prompts the user to manually re-send their prompt ("Auto-compression complete. Please re-send your prompt.").

Updating the description to accurately reflect the manual re-send behavior prevents user confusion. Please also update the corresponding descriptions in schemas/settings.schema.json to match this change.

Suggested change
description:
'When the context window is about to overflow, automatically compress the chat history and retry the prompt instead of stopping with an error.',
description:
'When the context window is about to overflow, automatically compress the chat history and prompt to re-send instead of stopping with an error.',

@gemini-cli gemini-cli Bot added the status/need-issue Pull requests that need to have an associated issue. label Jul 22, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m A medium sized PR status/need-issue Pull requests that need to have an associated issue.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant