Skip to content

fix(core): strip thoughts from scrubbed history turns and resolve thought leakage#27971

Open
amelidev wants to merge 15 commits into
google-gemini:mainfrom
amelidev:b_470967254
Open

fix(core): strip thoughts from scrubbed history turns and resolve thought leakage#27971
amelidev wants to merge 15 commits into
google-gemini:mainfrom
amelidev:b_470967254

Conversation

@amelidev

Copy link
Copy Markdown
Contributor

Summary

This PR resolves a Thought Leakage issue where the Gemini model's internal monologues/reasoning thoughts leak into plain-text history turns, confusing the model in subsequent turns and causing it to emulate scratchpad thoughts or enter infinite loop monologues.

Details

  • Surgical Thought Stripping: Updated scrubContents inside packages/core/src/utils/historyHardening.ts to actively filter out any parts where part.thought is truthy, before map-scrubbing the remaining fields. This ensures nested executions (e.g. subagents) do not leak raw thoughts as plain conversational text.
  • Alternation Preservation: Updated scrubHistory to run coalesce on the scrubbed turns. This safely discards any turns made empty by thought stripping while maintaining the Gemini API's strict role-alternation invariant.
  • Robust Thought Detection: Unified the thought checks in stripThoughts to check for truthy p.thought properties rather than strictly p.thought === true, matching how thoughts are represented.
  • Comprehensive Unit Testing: Created a new robust unit test suite (thought leakage in getHistoryTurns) in packages/core/src/core/geminiChat.test.ts to reproduce and confirm the fix.

Related Issues

Resolves the issue documented in issue.md.

How to Validate

Run the targeted and whole history hardening test suites using Vitest:

npx vitest run packages/core/src/core/geminiChat.test.ts -t "thought leakage in getHistoryTurns"
npx vitest run packages/core/src/utils/historyHardening.test.ts

All tests pass perfectly in under 15 seconds.

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:
    • Linux (npm run)

@amelidev amelidev requested review from a team as code owners June 16, 2026 23:14
@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 addresses a critical issue where the Gemini model's internal reasoning thoughts were leaking into the plain-text conversation history. By introducing a preprocessing step to strip these thoughts and subsequently coalescing the remaining turns, the changes ensure that the model history remains clean and compliant with API requirements, preventing the model from confusing its own scratchpad with user-facing dialogue.

Highlights

  • Thought Leakage Prevention: Implemented a surgical stripping mechanism in scrubContents to filter out internal model thoughts, preventing them from leaking into conversational history.
  • History Hardening Improvements: Updated hardenHistory and scrubHistory to coalesce turns after thought removal, ensuring strict role-alternation invariants are maintained.
  • Robust Thought Detection: Unified logic to identify thought parts by checking for truthy thought properties, improving reliability across different model outputs.
  • Testing: Added comprehensive unit tests in geminiChat.test.ts and historyHardening.test.ts to reproduce and verify the fix for thought leakage.
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.

@github-actions github-actions Bot added the size/m A medium sized PR label Jun 16, 2026
@github-actions

github-actions Bot commented Jun 16, 2026

Copy link
Copy Markdown

📊 PR Size: size/L

  • Lines changed: 319
  • Additions: +304
  • Deletions: -15
  • Files changed: 3

@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 changes to filter out internal model thoughts from the chat history during history hardening and scrubbing, preventing thought leakage. It adds a stripThoughts helper function in historyHardening.ts and updates scrubContents to exclude thought parts, accompanied by comprehensive unit tests. The reviewer noted an inconsistency in how thoughts are detected between stripThoughts (strict boolean check) and scrubContents (truthy check), suggesting a unified truthy check to ensure robust thought detection.

Comment thread packages/core/src/utils/historyHardening.ts Outdated
amelidev and others added 2 commits June 16, 2026 17:22
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@luisfelipe-alt

Copy link
Copy Markdown
Contributor

/gemini review

@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 removes peer dependency flags from package-lock.json and implements logic to strip internal model thoughts from the conversation history in packages/core. This includes adding a stripThoughts step in hardenHistory, filtering out thought parts in scrubContents, and adding corresponding unit tests. The review feedback suggests adding defensive checks to ensure that parts are valid objects before using the 'in' operator to prevent runtime TypeErrors, and using the nullish coalescing operator (??) instead of logical OR (||) when providing default values for optional properties.

Comment thread packages/core/src/utils/historyHardening.ts Outdated
Comment thread packages/core/src/utils/historyHardening.ts Outdated
amelidev and others added 2 commits June 16, 2026 17:28
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@amelidev

Copy link
Copy Markdown
Contributor Author

/gemini review

@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 removes "peer": true from several dependencies in package-lock.json and implements a mechanism to strip internal model thoughts (where part.thought === true) from conversational history in packages/core. This includes adding a stripThoughts pass in hardenHistory and filtering out thought parts in scrubContents, along with corresponding unit tests. The feedback suggests extracting the inline thought check into a reusable type guard isThoughtPart with a local interface and a detailed comment, in accordance with repository guidelines for using undocumented SDK properties, and using this helper consistently across the codebase.

Comment thread packages/core/src/utils/historyHardening.ts
Comment thread packages/core/src/utils/historyHardening.ts Outdated
@amelidev

Copy link
Copy Markdown
Contributor Author

/gemini review

@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 removes peer dependency flags from several packages in package-lock.json and implements a mechanism to strip internal model thoughts (where part.thought === true) from chat history in packages/core. Specifically, a new stripThoughts helper has been introduced in historyHardening.ts to filter out thought parts and discard any resulting empty turns during history hardening and scrubbing. Corresponding unit tests have been added to verify this behavior and prevent thought leakage. There are no review comments to address, and I have no additional feedback to provide.

@amelidev

Copy link
Copy Markdown
Contributor Author

/gemini review

@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 removes the "peer": true flag from various dependencies in package-lock.json and introduces a mechanism to strip internal thought parts (where part.thought === true) from chat history. Specifically, it adds a stripThoughts function in historyHardening.ts that filters out thought parts and removes empty turns, integrating it into hardenHistory and scrubContents. Additionally, new unit tests are added in geminiChat.test.ts and historyHardening.test.ts to verify this behavior. There are no review comments, and I have no feedback to provide.

Comment thread packages/core/src/utils/historyHardening.ts Outdated
Comment thread packages/core/src/utils/historyHardening.ts Outdated
Comment thread packages/core/src/core/geminiChat.test.ts
@gemini-cli

gemini-cli Bot commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Hi there! Thank you for your interest in contributing to Gemini CLI.

To ensure we maintain high code quality and focus on our prioritized roadmap, we only guarantee review and consideration of pull requests for issues that are explicitly labeled as 'help wanted'.

This PR will be closed in 7 days if it remains without that designation. We encourage you to find and contribute to existing 'help wanted' issues in our backlog! Thank you for your understanding.

…and type safety

- Cast synthetic model thought parts in geminiChat.test.ts using as unknown as Part for strict type safety and consistency.

- Extract isInternalThought helper function with no type casting or ESLint suppression required.

- Optimize stripThoughts using .some() to avoid unnecessary allocations on thought-free turns.

- Remove redundant trailing filter in stripThoughts.

- Consolidate multi-pass loop in scrubHistory into a single, high-performance pass that scrubs and coalesces adjacent turns immutably.

- Ensure strict immutability in coalesce and scrubHistory by completely replacing the turn object instead of mutating in place.
@rmedranollamas

Copy link
Copy Markdown
Contributor

Closing this pull request as it does not have an associated tracked issue linked, and there has been no progress since the nudge.

@amelidev

Copy link
Copy Markdown
Contributor Author

Hello @rmedranollamas
This is a work in progress, It is linked to the buganizer issue b_470967254 I was about to put the last commit to fix @galz10 comments.
Could you please re-open it ?

@amelidev

Copy link
Copy Markdown
Contributor Author

Thank you very much!

@galdawave galdawave reopened this Jun 24, 2026
@rmedranollamas

rmedranollamas commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

Reopening this PR .

@luisfelipe-alt

Copy link
Copy Markdown
Contributor

/gemini review

@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 changes to strip internal thought parts from the conversation history and handle empty turns in packages/core. It updates hardenHistory, scrubHistory, and scrubContents to filter out parts where thought is true, and includes corresponding unit tests. The reviewer pointed out that isInternalThought strictly checks for part.thought === true instead of truthiness, which could lead to thought leakage if the API returns truthy values other than true.

Comment thread packages/core/src/utils/historyHardening.ts
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
@luisfelipe-alt

Copy link
Copy Markdown
Contributor

/gemini review

@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 removes peer dependency flags from package-lock.json and introduces history hardening logic to strip internal thought parts from conversation history. The core changes add a stripThoughts helper and update history scrubbing and coalescing functions, supported by new unit tests. The review feedback highlights a potential issue in scrubContents where stripping all thought parts from a Content object could result in an empty parts array, potentially triggering a 400 Bad Request from the Gemini API, and suggests filtering out empty content objects.

Comment thread packages/core/src/utils/historyHardening.ts Outdated
@github-actions github-actions Bot added the size/l A large sized PR label Jun 25, 2026
@amelidev

Copy link
Copy Markdown
Contributor Author

/gemini review

@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 removes peer dependency flags from several packages in package-lock.json and implements logic in packages/core to strip internal thought parts from chat history and contents. Specifically, a new stripThoughts pass is integrated into hardenHistory, and both scrubHistory and scrubContents are updated to filter out thought parts and remove empty turns. Unit tests have been added to verify these changes. The reviewer's feedback correctly identifies a TypeScript compilation issue in historyHardening.ts where part.thought is accessed on the Part type without casting it to ThoughtPart.

Comment thread packages/core/src/utils/historyHardening.ts Outdated
@amelidev

Copy link
Copy Markdown
Contributor Author

/gemini review

@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 implements the filtering of internal thought parts from chat history and contents to prevent thought leakage and ensure compatibility with strict APIs. It introduces a stripThoughts helper in historyHardening.ts to remove thought parts before coalescing, updates scrubHistory and scrubContents to exclude thought parts and clean up empty turns, and adds comprehensive unit tests to validate these changes. As there are no review comments, I have no feedback to provide.

@DavidAPierce DavidAPierce 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.

LGTM.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/l A large sized PR size/m A medium sized PR status/need-issue Pull requests that need to have an associated issue. status/pr-nudge-sent

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants