Skip to content

fix(prompt): preserve Google assistant text alongside tool calls#1940

Open
zxuhan wants to merge 1 commit intoJetBrains:developfrom
zxuhan:fix/google-preserve-assistant-text-with-tool-calls
Open

fix(prompt): preserve Google assistant text alongside tool calls#1940
zxuhan wants to merge 1 commit intoJetBrains:developfrom
zxuhan:fix/google-preserve-assistant-text-with-tool-calls

Conversation

@zxuhan
Copy link
Copy Markdown
Contributor

@zxuhan zxuhan commented May 1, 2026

Summary

Fixes #1152.

GoogleLLMClient was filtering out Message.Assistant whenever the same response contained any Tool.Call, silently discarding model-generated text the user had already paid for. The encoder also wrote that assistant text and the tool call as two separate "model" turns, which is not how Gemini emitted them.

This change:

  • Removes the responses.filter { ... } in processGoogleCandidate that dropped assistant text when tool calls were present.
  • Adds a pendingTextParts buffer in createGoogleRequest so assistant text is sent in the same GoogleContent as the following Tool.Call(s).
  • Tightens the turn-boundary logic so that Tool.Result closes any pending model turn and a following Assistant closes any pending user (results) turn. This keeps user/model alternation correct across tool round-trips.

Existing tests around parallel tool calls and thought signatures continue to pass; the helper rename from flushCalls to flushModel does not change observable behavior for those cases.

Test plan

  • ./gradlew :prompt:prompt-executor:prompt-executor-clients:prompt-executor-google-client:jvmTest (43 tests, 0 failures)
  • New tests:
    • processGoogleCandidate keeps Assistant text alongside Tool Call
    • processGoogleCandidate keeps Reasoning, Assistant text, and Tool Call together
    • createGoogleRequest merges Assistant text with following Tool Call into single model content
    • createGoogleRequest preserves model-user-model order across tool round-trip
    • createGoogleRequest carries thought signature from Reasoning between Assistant text and Tool Call

GoogleLLMClient was filtering out Message.Assistant whenever any
Tool.Call was present in the same response, silently dropping model
output. The encoder also wrote assistant text and the tool call as
two separate "model" turns, which Gemini does not expect when they
came from a single response.

Keep all decoded responses, and merge buffered assistant text into the
same GoogleContent as the following Tool.Calls. Close the model turn
explicitly when a Tool.Result starts a user turn so the resulting
contents alternate user/model correctly.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

GoogleLLMClient should probably not silence assistant messages that come alongside tool calls

1 participant