Skip to content

feat(core): implement stale output elision for history pruning#21998

Open
kunal-10-cloud wants to merge 5 commits intogoogle-gemini:mainfrom
kunal-10-cloud:feat/stale-output-elision
Open

feat(core): implement stale output elision for history pruning#21998
kunal-10-cloud wants to merge 5 commits intogoogle-gemini:mainfrom
kunal-10-cloud:feat/stale-output-elision

Conversation

@kunal-10-cloud
Copy link
Copy Markdown
Contributor

@kunal-10-cloud kunal-10-cloud commented Mar 11, 2026

Summary

Adds stale output elision to the history pipeline. When the agent reads a file and later modifies it, the original read output in history is automatically replaced with a compact marker, saving context window tokens and preventing the model from reasoning over outdated content.

Details

Uses a two-pass scan over chat history — one pass to identify write operations, a second to find read outputs that are now stale. Elision is immutable, idempotent, skips error responses, and only applies when the replacement is smaller than the original. Telemetry is included, mirroring the existing tool output masking pattern.

Related Issues

Closes #21891

How to Validate

  1. Read a file, then edit it in the same session.
  2. Ask the model about the file — it should describe the edited version, not the original.
  3. Run unit tests: npm test -w @google/gemini-cli-core -- src/services/staleOutputElisionService.test.ts — all 14 should pass.

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

@kunal-10-cloud kunal-10-cloud requested a review from a team as a code owner March 11, 2026 07:55
@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 a significant enhancement to the chat history management by implementing stale output elision. This mechanism intelligently prunes the conversation history, specifically targeting tool outputs that become irrelevant after subsequent file modifications. By replacing these outdated entries with concise markers, the system efficiently manages the context window, ensuring the model operates with the most current information and reducing token usage.

Highlights

  • Stale Output Elision: Implemented a new service, StaleOutputElisionService, to automatically identify and replace outdated tool read outputs in the chat history with a compact marker. This occurs when a file is read and then subsequently modified within the same session.
  • Context Window Optimization: The primary goal of this feature is to save context window tokens by removing verbose, irrelevant information, thereby allowing the model to focus on current and accurate data.
  • Algorithm Details: The elision process involves a two-pass scan: first, identifying all write operations and their target file paths; second, scanning for read outputs that correspond to files later modified by a write operation. Elision is applied only if the original output exceeds a minimum token threshold, is not an error response, and has not been previously elided.
  • Telemetry Integration: Added new telemetry events and logging to track the number of elided outputs and the total tokens saved by this feature, providing insights into its effectiveness.
Changelog
  • packages/core/src/core/client.ts
    • Imported StaleOutputElisionService.
    • Added a private instance of StaleOutputElisionService.
    • Initialized StaleOutputElisionService in the constructor.
    • Invoked tryElideStaleOutputs before tryMaskToolOutputs in the history processing pipeline.
    • Implemented tryElideStaleOutputs method to orchestrate the elision process.
  • packages/core/src/services/staleOutputElisionService.test.ts
    • Added a new test file for StaleOutputElisionService.
    • Included comprehensive unit tests covering basic elision, no-op conditions, token thresholding, error response skipping, idempotency, immutability, multiple elisions, marker content, and path normalization.
  • packages/core/src/services/staleOutputElisionService.ts
    • Added a new service file defining StaleOutputElisionService.
    • Defined constants STALE_OUTPUT_ELISION_TAG and MIN_TOKENS_TO_ELIDE.
    • Defined sets for READ_TOOL_NAMES and WRITE_TOOL_NAMES.
    • Implemented the core elide method with a two-pass algorithm to identify and replace stale read outputs.
    • Included helper methods for extracting read/write paths, normalizing paths, checking for already-elided or error responses, and formatting elision markers.
  • packages/core/src/telemetry/clearcut-logger/clearcut-logger.ts
    • Imported StaleOutputElisionEvent.
    • Added STALE_OUTPUT_ELISION to the EventNames enum.
    • Implemented logStaleOutputElisionEvent to log elision metrics.
  • packages/core/src/telemetry/clearcut-logger/event-metadata-key.ts
    • Added new EventMetadataKey enums: GEMINI_CLI_STALE_OUTPUT_ELISION_COUNT and GEMINI_CLI_STALE_OUTPUT_ELISION_TOKENS_SAVED.
  • packages/core/src/telemetry/loggers.ts
    • Imported StaleOutputElisionEvent.
    • Added logStaleOutputElision function to facilitate logging of elision events.
  • packages/core/src/telemetry/types.ts
    • Defined the StaleOutputElisionEvent class, including its properties and methods for OpenTelemetry attributes and log body.
    • Added StaleOutputElisionEvent to the TelemetryEvent union type.
Activity
  • The author has updated relevant documentation and README (if needed).
  • The author has added/updated tests for this feature.
  • The author has validated the changes on MacOS using npm run.
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.

@gemini-cli gemini-cli bot added priority/p2 Important but can be addressed in a future release. area/agent Issues related to Core Agent, Tools, Memory, Sub-Agents, Hooks, Agent Quality labels Mar 11, 2026
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 stale output elision service to prune chat history, optimizing context window usage by replacing original read output with a compact marker when a file is read and modified. While the service is well-integrated into the GeminiClient with thorough unit tests and telemetry, a security vulnerability was identified where the file path included in the elision marker is not sanitized, potentially leading to prompt injection if a malicious path is provided. Additionally, a high-severity issue related to path normalization was found, which could cause elision to fail when symbolic links are used. Both issues align with existing repository rules regarding prompt injection prevention and consistent path resolution/symlink handling.

@kunal-10-cloud kunal-10-cloud force-pushed the feat/stale-output-elision branch 2 times, most recently from 2d5b2d8 to e1212d7 Compare March 11, 2026 15:25
@kunal-10-cloud
Copy link
Copy Markdown
Contributor Author

kunal-10-cloud commented Mar 11, 2026

Hi @SandyTao520, @abhipatel12, @jerop, @sehoon38, @gsquared94, @cynthialong0-0, @jacob314 please review this pr once and let me know if any changes are required

@gemini-cli gemini-cli bot added the 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. label Mar 11, 2026
Introduces StaleOutputElisionService, which retroactively collapses
stale tool read outputs from the chat history when the agent later
modifies the same file. This saves context window tokens and prevents
the model from being confused by outdated file content.

- New StaleOutputElisionService with a two-pass O(n) algorithm:
  - Pass 1: builds a write-log from functionCall parts in model turns
  - Pass 2: identifies read outputs whose files were later written
  - Apply phase: immutable-update of stale parts with elision marker
- Supports read_file, read_many_files (read side) and edit, write_file
  (write side)
- Elision marker format: <stale_output_elided>[Content elided – file
  '...' was subsequently modified by <tool>]</stale_output_elided>
- Guards: skips error responses, already-elided parts, outputs below
  MIN_TOKENS_TO_ELIDE (100 tokens)
- Integrated in GeminiClient.processTurn() before tryMaskToolOutputs

- New StaleOutputElisionEvent (BaseTelemetryEvent) in types.ts
- New EventMetadataKey constants (IDs 172–173) in event-metadata-key.ts
- STALE_OUTPUT_ELISION added to EventNames enum in clearcut-logger.ts
- logStaleOutputElisionEvent() added to ClearcutLogger
- logStaleOutputElision() function added to loggers.ts

- 14 unit tests covering: basic elision (read_file/edit/write_file),
  read_many_files, no-op cases (wrong path, reversed order, no writes,
  empty history), token threshold guard, error skip, idempotency,
  immutability, multiple pairs, marker content

Fixes #<session-continuity-epic-sub-issue-4>
@kunal-10-cloud kunal-10-cloud force-pushed the feat/stale-output-elision branch from 7d52d90 to 64c3c75 Compare March 15, 2026 17:14
@kunal-10-cloud
Copy link
Copy Markdown
Contributor Author

@gsquared94, conflicts on this branch are resolved now. Can you please review this PR as well whenever you are available, since it has been open for quite a while

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 🔒 maintainer only ⛔ Do not contribute. Internal roadmap item. priority/p2 Important but can be addressed in a future release.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Stale Output Elision (History Pruning)

1 participant