fix(google-genai): Map messages to the gen_ai conventions - #24352
Conversation
Google's `Content` was reported verbatim, so `gen_ai.input.messages` carried
`{role, parts: [{text}]}` instead of `{role, parts: [{type, content}]}`. The
product's normalizer drops parts it cannot type, so none of the input messages
rendered, and `role: "model"` is not a `gen_ai` role.
Every part kind is now translated (text, thought, function call, function
response, inline data, file data), `model` becomes `assistant`, and bare parts
in one array stay one turn so a multimodal message is not split.
A `config.systemInstruction` passed as a `Content` object also never reached
`gen_ai.system_instructions`: it was routed through `extractSystemInstructions`,
which only reads `.content`. It is now read straight off the config.
Also sets `gen_ai.output.messages`, which this integration never wrote. Relay's
migration of the deprecated `gen_ai.response.text` is lossy for tool calls, so a
turn that only called a tool rendered an empty Output.
Fixes #24327
size-limit report 📦
|
|
bugbot run |
JPeer264
left a comment
There was a problem hiding this comment.
implementation looks fine IMO. Would wait for @RulaKhaled for a better judgement though
RulaKhaled
left a comment
There was a problem hiding this comment.
lgtm! This used to be a requirement of otel conventions which we no longer follow
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Want reviews to match your repository better? Bugbot Learning can learn team-specific rules from PR activity. A team admin can enable Learning in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 4745a84. Configure here.
| } | ||
|
|
||
| // Part kinds we don't know yet render as JSON rather than disappearing. | ||
| return { type: 'object', content: part }; |
There was a problem hiding this comment.
Thought signatures recorded as object parts
Medium Severity
partToMessagePart never handles thoughtSignature, so a part that only carries that field hits the unknown-part fallback and stores the raw base64 blob on gen_ai.input.messages and gen_ai.output.messages. Thinking models attach these signatures on later turns, which inflates span payloads the same way inlineData.data would.
Reviewed by Cursor Bugbot for commit 4745a84. Configure here.


Google GenAI reported its own
Contentshape, so no input message rendered, fixed by mapping parts and roles to the conventions.I added tests covering each part kind, an object
systemInstruction, and a tool call's output messages.closes #24327