Splitting this out of #203 / #219 as suggested.
GeminiPart.init(from:) checks container.contains(.text) first (GeminiLanguageModel.swift:894) and that branch never reads thoughtSignature, so a signature arriving on a text part is dropped. respond also keeps only the functionCall parts of a turn (:311), so a signature on a sibling text part would have nowhere to go even once decoded.
This is deliberately separate from #203: there, a missing signature on a functionCall is a hard 400 INVALID_ARGUMENT. Here the docs say a response with no functionCall may carry a signature on its last part, and that returning it is recommended for quality while omitting it is not an error. So this is lost output quality on thinking models rather than a failure.
Carrying it needs somewhere to keep it on the response side. Transcript.ToolCall now has providerMetadata for exactly this kind of opaque state; Transcript.Response has no equivalent, and adding one is a public API decision rather than an adapter change — which is why I haven't proposed a patch here.
Happy to implement whichever shape you'd prefer.
Splitting this out of #203 / #219 as suggested.
GeminiPart.init(from:)checkscontainer.contains(.text)first (GeminiLanguageModel.swift:894) and that branch never readsthoughtSignature, so a signature arriving on a text part is dropped.respondalso keeps only thefunctionCallparts of a turn (:311), so a signature on a sibling text part would have nowhere to go even once decoded.This is deliberately separate from #203: there, a missing signature on a
functionCallis a hard400 INVALID_ARGUMENT. Here the docs say a response with nofunctionCallmay carry a signature on its last part, and that returning it is recommended for quality while omitting it is not an error. So this is lost output quality on thinking models rather than a failure.Carrying it needs somewhere to keep it on the response side.
Transcript.ToolCallnow hasproviderMetadatafor exactly this kind of opaque state;Transcript.Responsehas no equivalent, and adding one is a public API decision rather than an adapter change — which is why I haven't proposed a patch here.Happy to implement whichever shape you'd prefer.