fix(core): flush transcript for pure tool-call responses to ensure BeforeTool hooks see complete state#20419
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 refines the chat transcript recording mechanism to ensure that 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 addresses an important edge case where the session transcript was not updated for model responses containing only a tool call, without any accompanying text or thoughts. This could lead to BeforeTool hooks operating on stale state.
The fix correctly extends the condition for recording a model message to include hasToolCall, ensuring that a gemini entry is always added to the transcript when the model produces any output, including a pure tool call. The addition of the hasThoughts flag, while duplicated from another pending PR, is necessary here for completeness.
The new unit test effectively validates this fix by simulating a pure tool call stream and asserting that the transcript is written to disk with the new gemini message. The changes are well-contained and the logic is sound. I have no further comments.
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)