fix(core): flush transcript for pure tool-call responses to ensure BeforeTool hooks see complete state#20418
Conversation
…esponses Extends the fix in google-gemini#17996: when the model emits a functionCall with no response text and no thoughts, recordMessage was not called, leaving BeforeTool hooks with no gemini entry in the transcript at dispatch time. - Add hasThoughts flag (from google-gemini#17996) to track thought-only responses - Add hasToolCall to flush condition so pure tool calls also trigger a transcript write before tool execution - Add regression test verifying gemini entry is written on pure tool call Fixes the edge case noted in PR google-gemini#17996 discussion.
Summary of ChangesHello @krishdef7, 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 Highlights
Changelog
Activity
Using Gemini Code AssistThe 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
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 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
|
There was a problem hiding this comment.
Code Review
This pull request correctly addresses an edge case where the transcript was not being flushed for pure tool-call responses, ensuring BeforeTool hooks have access to the complete conversation state. The added unit test effectively validates this fix. Regarding the new feature to prevent the expansion of @ commands on pasted input, this appears to be a non-standard UX pattern improvement introduced in a single component. According to repository guidelines (Rule: Maintain consistency with existing UI behavior across components. Defer non-standard UX pattern improvements to be addressed holistically rather than in a single component.), such improvements should be addressed holistically rather than in a single component, so this feature should be deferred for a broader discussion and consistent implementation across the application.
|
Closing in favor of #20419 — this branch accidentally included unrelated paste detection changes. The new PR is a clean 1-commit, 2-file diff. |
Summary
Extends #17996 to cover a remaining edge case: when the model emits a
functionCallwith no response text and no thoughts,recordMessagewas never called, leaving BeforeTool hooks with nogeminientry in the transcript at dispatch time.Details
PR #17996 introduced the
hasThoughtsflag to flush the transcript when thoughts precede a tool call. However, the flush condition wasresponseText || hasThoughts— so a pure tool call (no text, no thoughts) still skippedrecordMessage.Before this PR, transcript state at BeforeTool hook dispatch:
{ "messages": [ { "type": "user", "content": "analyze test.py" } ] }After this PR, transcript state at BeforeTool hook dispatch:
{ "messages": [ { "type": "user", "content": "analyze test.py" }, { "type": "gemini", "content": "" } ] }Changes:
hasThoughtsflag tracking (same pattern as Save transcript to file before function call is performed #17996, needed since that PR isn't merged yet)responseText || hasThoughts || hasToolCallprocessStreamResponse— no new dependencies, no architectural changesWhy
processStreamResponseand notToolExecutor:An earlier approach considered flushing at the tool dispatch point in
CoreToolScheduler. That would require threadingchatRecordingServicethroughCoreToolScheduler → ToolExecutor, coupling recording logic into the scheduler. The correct separation of concerns keeps all recording inGeminiChat.processStreamResponse, where it already lives.Related Issues
Related to #17996, #17922
How to Validate
gemini-type entryUnit test added:
should flush transcript before tool dispatch for pure tool call with no text or thoughtsingeminiChat.test.ts— mocks a purefunctionCallstream and asserts agemini-type message is written to disk before stream completion.Pre-Merge Checklist
npm run build)