fix: handle google model reasoning correctly (#82)

Kujtim Hoxha created

Change summary

providers/google/google.go                                                                           | 198 
providers/google/provider_options.go                                                                 |   1 
providers/openrouter/language_model_hooks.go                                                         | 133 
providertests/google_test.go                                                                         |   1 
providertests/openrouter_test.go                                                                     |   1 
providertests/testdata/TestGoogleCommon/gemini-2.5-flash/multi_tool.yaml                             |  14 
providertests/testdata/TestGoogleCommon/gemini-2.5-flash/multi_tool_streaming.yaml                   |   8 
providertests/testdata/TestGoogleCommon/gemini-2.5-flash/simple.yaml                                 |  10 
providertests/testdata/TestGoogleCommon/gemini-2.5-flash/simple_streaming.yaml                       |   6 
providertests/testdata/TestGoogleCommon/gemini-2.5-flash/tool.yaml                                   |  15 
providertests/testdata/TestGoogleCommon/gemini-2.5-flash/tool_streaming.yaml                         |   2 
providertests/testdata/TestGoogleCommon/gemini-2.5-pro/multi_tool.yaml                               |  18 
providertests/testdata/TestGoogleCommon/gemini-2.5-pro/multi_tool_streaming.yaml                     |   2 
providertests/testdata/TestGoogleCommon/gemini-2.5-pro/simple.yaml                                   |  14 
providertests/testdata/TestGoogleCommon/gemini-2.5-pro/simple_streaming.yaml                         |   2 
providertests/testdata/TestGoogleCommon/gemini-2.5-pro/tool.yaml                                     |  15 
providertests/testdata/TestGoogleCommon/gemini-2.5-pro/tool_streaming.yaml                           |   2 
providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/multi_tool.yaml                         |  87 
providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/multi_tool_streaming.yaml               |  27 
providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/simple.yaml                             |  33 
providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/simple_streaming.yaml                   |  27 
providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/tool.yaml                               |  77 
providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/tool_streaming.yaml                     |  27 
providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/simple.yaml                         |   4 
providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/simple_streaming.yaml               |  38 
providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/tool.yaml                           |  12 
providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/tool_streaming.yaml                 |  87 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/multi_tool.yaml                      |  18 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/multi_tool_streaming.yaml            |   2 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/simple.yaml                          |  14 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/simple_streaming.yaml                |   6 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/tool.yaml                            |  19 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/tool_streaming.yaml                  |   2 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/multi_tool.yaml                        |  22 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/multi_tool_streaming.yaml              |   2 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/simple.yaml                            |  20 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/simple_streaming.yaml                  |   2 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/tool.yaml                              |  21 
providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/tool_streaming.yaml                    |   2 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/complex_object.yaml               |  10 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/complex_object_streaming.yaml     |   2 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/simple_object.yaml                |  12 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/simple_object_streaming.yaml      |   6 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/complex_object.yaml                 |  14 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/complex_object_streaming.yaml       |   2 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/simple_object.yaml                  |  10 
providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/simple_object_streaming.yaml        |   6 
providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/complex_object.yaml           |  33 
providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/complex_object_streaming.yaml |  27 
providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/simple_object.yaml            |  63 
providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/simple_object_streaming.yaml  |  27 
providertests/testdata/TestGoogleThinking/gemini-2.5-flash/thinking-streaming.yaml                   |   2 
providertests/testdata/TestGoogleThinking/gemini-2.5-flash/thinking.yaml                             |  13 
providertests/testdata/TestGoogleThinking/gemini-2.5-pro/thinking-streaming.yaml                     |   2 
providertests/testdata/TestGoogleThinking/gemini-2.5-pro/thinking.yaml                               |  17 
providertests/testdata/TestGoogleThinking/gemini-3-pro-preview/thinking-streaming.yaml               |  27 
providertests/testdata/TestGoogleThinking/gemini-3-pro-preview/thinking.yaml                         |  81 
providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/multi_tool.yaml                     |  26 
providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/multi_tool_streaming.yaml           |  26 
providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/simple.yaml                         |  26 
providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/simple_streaming.yaml               |  32 
providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/tool.yaml                           |  26 
providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/tool_streaming.yaml                 |  26 
providertests/testdata/TestOpenRouterThinking/gemini-3-pro-preview/thinking-streaming.yaml           |  26 
providertests/testdata/TestOpenRouterThinking/gemini-3-pro-preview/thinking.yaml                     |  26 
65 files changed, 1,264 insertions(+), 295 deletions(-)

Detailed changes

providers/google/google.go ๐Ÿ”—

@@ -387,19 +387,37 @@ func toGooglePrompt(prompt fantasy.Prompt) (*genai.Content, []*genai.Content, []
 			}
 		case fantasy.MessageRoleAssistant:
 			var parts []*genai.Part
-			// INFO: (kujtim) this is kind of a hacky way to include thinking for google
-			// weirdly thinking needs to be included in a function call
-			var signature []byte
+			var currentReasoningMetadata *ReasoningMetadata
 			for _, part := range msg.Content {
 				switch part.GetType() {
+				case fantasy.ContentTypeReasoning:
+					reasoning, ok := fantasy.AsMessagePart[fantasy.ReasoningPart](part)
+					if !ok {
+						continue
+					}
+
+					metadata, ok := reasoning.ProviderOptions[Name]
+					if !ok {
+						continue
+					}
+					reasoningMetadata, ok := metadata.(*ReasoningMetadata)
+					if !ok {
+						continue
+					}
+					currentReasoningMetadata = reasoningMetadata
 				case fantasy.ContentTypeText:
 					text, ok := fantasy.AsMessagePart[fantasy.TextPart](part)
 					if !ok || text.Text == "" {
 						continue
 					}
-					parts = append(parts, &genai.Part{
+					geminiPart := &genai.Part{
 						Text: text.Text,
-					})
+					}
+					if currentReasoningMetadata != nil {
+						geminiPart.ThoughtSignature = []byte(currentReasoningMetadata.Signature)
+						currentReasoningMetadata = nil
+					}
+					parts = append(parts, geminiPart)
 				case fantasy.ContentTypeToolCall:
 					toolCall, ok := fantasy.AsMessagePart[fantasy.ToolCallPart](part)
 					if !ok {
@@ -411,33 +429,18 @@ func toGooglePrompt(prompt fantasy.Prompt) (*genai.Content, []*genai.Content, []
 					if err != nil {
 						continue
 					}
-					parts = append(parts, &genai.Part{
+					geminiPart := &genai.Part{
 						FunctionCall: &genai.FunctionCall{
 							ID:   toolCall.ToolCallID,
 							Name: toolCall.ToolName,
 							Args: result,
 						},
-						ThoughtSignature: signature,
-					})
-					// reset
-					signature = nil
-				case fantasy.ContentTypeReasoning:
-					reasoning, ok := fantasy.AsMessagePart[fantasy.ReasoningPart](part)
-					if !ok {
-						continue
-					}
-					metadata, ok := reasoning.ProviderOptions[Name]
-					if !ok {
-						continue
-					}
-					reasoningMetadata, ok := metadata.(*ReasoningMetadata)
-					if !ok {
-						continue
 					}
-					if !ok || reasoningMetadata.Signature == "" {
-						continue
+					if currentReasoningMetadata != nil {
+						geminiPart.ThoughtSignature = []byte(currentReasoningMetadata.Signature)
+						currentReasoningMetadata = nil
 					}
-					signature = []byte(reasoningMetadata.Signature)
+					parts = append(parts, geminiPart)
 				}
 			}
 			if len(parts) > 0 {
@@ -635,7 +638,18 @@ func (g *languageModel) Stream(ctx context.Context, call fantasy.Call) (fantasy.
 									return
 								}
 							} else {
-								// Regular text part
+								// Start new text block if not already active
+								if !isActiveText {
+									isActiveText = true
+									currentTextBlockID = fmt.Sprintf("%d", blockCounter)
+									blockCounter++
+									if !yield(fantasy.StreamPart{
+										Type: fantasy.StreamPartTypeTextStart,
+										ID:   currentTextBlockID,
+									}) {
+										return
+									}
+								}
 								// End any active reasoning block before starting text
 								if isActiveReasoning {
 									isActiveReasoning = false
@@ -651,16 +665,23 @@ func (g *languageModel) Stream(ctx context.Context, call fantasy.Call) (fantasy.
 									}) {
 										return
 									}
-								}
+								} else if part.ThoughtSignature != nil {
+									metadata := &ReasoningMetadata{
+										Signature: string(part.ThoughtSignature),
+									}
 
-								// Start new text block if not already active
-								if !isActiveText {
-									isActiveText = true
-									currentTextBlockID = fmt.Sprintf("%d", blockCounter)
-									blockCounter++
 									if !yield(fantasy.StreamPart{
-										Type: fantasy.StreamPartTypeTextStart,
-										ID:   currentTextBlockID,
+										Type: fantasy.StreamPartTypeReasoningStart,
+										ID:   currentReasoningBlockID,
+									}) {
+										return
+									}
+									if !yield(fantasy.StreamPart{
+										Type: fantasy.StreamPartTypeReasoningEnd,
+										ID:   currentReasoningBlockID,
+										ProviderMetadata: fantasy.ProviderMetadata{
+											Name: metadata,
+										},
 									}) {
 										return
 									}
@@ -687,11 +708,13 @@ func (g *languageModel) Stream(ctx context.Context, call fantasy.Call) (fantasy.
 								return
 							}
 						}
+						toolCallID := cmp.Or(part.FunctionCall.ID, g.providerOptions.toolCallIDFunc())
+						// End any active reasoning block before starting text
 						if isActiveReasoning {
 							isActiveReasoning = false
-
 							metadata := &ReasoningMetadata{
 								Signature: string(part.ThoughtSignature),
+								ToolID:    toolCallID,
 							}
 							if !yield(fantasy.StreamPart{
 								Type: fantasy.StreamPartTypeReasoningEnd,
@@ -702,10 +725,28 @@ func (g *languageModel) Stream(ctx context.Context, call fantasy.Call) (fantasy.
 							}) {
 								return
 							}
-						}
-
-						toolCallID := cmp.Or(part.FunctionCall.ID, g.providerOptions.toolCallIDFunc())
+						} else if part.ThoughtSignature != nil {
+							metadata := &ReasoningMetadata{
+								Signature: string(part.ThoughtSignature),
+								ToolID:    toolCallID,
+							}
 
+							if !yield(fantasy.StreamPart{
+								Type: fantasy.StreamPartTypeReasoningStart,
+								ID:   currentReasoningBlockID,
+							}) {
+								return
+							}
+							if !yield(fantasy.StreamPart{
+								Type: fantasy.StreamPartTypeReasoningEnd,
+								ID:   currentReasoningBlockID,
+								ProviderMetadata: fantasy.ProviderMetadata{
+									Name: metadata,
+								},
+							}) {
+								return
+							}
+						}
 						args, err := json.Marshal(part.FunctionCall.Args)
 						if err != nil {
 							yield(fantasy.StreamPart{
@@ -1233,11 +1274,46 @@ func (g languageModel) mapResponse(response *genai.GenerateContentResponse, warn
 		switch {
 		case part.Text != "":
 			if part.Thought {
-				metadata := &ReasoningMetadata{
-					Signature: string(part.ThoughtSignature),
+				reasoningContent := fantasy.ReasoningContent{Text: part.Text}
+				if part.ThoughtSignature != nil {
+					metadata := &ReasoningMetadata{
+						Signature: string(part.ThoughtSignature),
+					}
+					reasoningContent.ProviderMetadata = fantasy.ProviderMetadata{
+						Name: metadata,
+					}
 				}
-				content = append(content, fantasy.ReasoningContent{Text: part.Text, ProviderMetadata: fantasy.ProviderMetadata{Name: metadata}})
+				content = append(content, reasoningContent)
 			} else {
+				foundReasoning := false
+				if part.ThoughtSignature != nil {
+					metadata := &ReasoningMetadata{
+						Signature: string(part.ThoughtSignature),
+					}
+					// find the last reasoning content and add the signature
+					for i := len(content) - 1; i >= 0; i-- {
+						c := content[i]
+						if c.GetType() == fantasy.ContentTypeReasoning {
+							reasoningContent, ok := fantasy.AsContentType[fantasy.ReasoningContent](c)
+							if !ok {
+								continue
+							}
+							reasoningContent.ProviderMetadata = fantasy.ProviderMetadata{
+								Name: metadata,
+							}
+							content[i] = reasoningContent
+							foundReasoning = true
+							break
+						}
+					}
+					if !foundReasoning {
+						content = append(content, fantasy.ReasoningContent{
+							ProviderMetadata: fantasy.ProviderMetadata{
+								Name: metadata,
+							},
+						})
+					}
+				}
 				content = append(content, fantasy.TextContent{Text: part.Text})
 			}
 		case part.FunctionCall != nil:
@@ -1246,6 +1322,36 @@ func (g languageModel) mapResponse(response *genai.GenerateContentResponse, warn
 				return nil, err
 			}
 			toolCallID := cmp.Or(part.FunctionCall.ID, g.providerOptions.toolCallIDFunc())
+			foundReasoning := false
+			if part.ThoughtSignature != nil {
+				metadata := &ReasoningMetadata{
+					Signature: string(part.ThoughtSignature),
+					ToolID:    toolCallID,
+				}
+				// find the last reasoning content and add the signature
+				for i := len(content) - 1; i >= 0; i-- {
+					c := content[i]
+					if c.GetType() == fantasy.ContentTypeReasoning {
+						reasoningContent, ok := fantasy.AsContentType[fantasy.ReasoningContent](c)
+						if !ok {
+							continue
+						}
+						reasoningContent.ProviderMetadata = fantasy.ProviderMetadata{
+							Name: metadata,
+						}
+						content[i] = reasoningContent
+						foundReasoning = true
+						break
+					}
+				}
+				if !foundReasoning {
+					content = append(content, fantasy.ReasoningContent{
+						ProviderMetadata: fantasy.ProviderMetadata{
+							Name: metadata,
+						},
+					})
+				}
+			}
 			content = append(content, fantasy.ToolCallContent{
 				ToolCallID:       toolCallID,
 				ToolName:         part.FunctionCall.Name,
@@ -1273,6 +1379,16 @@ func (g languageModel) mapResponse(response *genai.GenerateContentResponse, warn
 	}, nil
 }
 
+// GetReasoningMetadata extracts reasoning metadata from provider options for google models.
+func GetReasoningMetadata(providerOptions fantasy.ProviderOptions) *ReasoningMetadata {
+	if googleOptions, ok := providerOptions[Name]; ok {
+		if reasoning, ok := googleOptions.(*ReasoningMetadata); ok {
+			return reasoning
+		}
+	}
+	return nil
+}
+
 func mapFinishReason(reason genai.FinishReason) fantasy.FinishReason {
 	switch reason {
 	case genai.FinishReasonStop:

providers/google/provider_options.go ๐Ÿ”—

@@ -40,6 +40,7 @@ type ThinkingConfig struct {
 // ReasoningMetadata represents reasoning metadata for the Google provider.
 type ReasoningMetadata struct {
 	Signature string `json:"signature"`
+	ToolID    string `json:"tool_id"`
 }
 
 // Options implements the ProviderOptionsData interface for ReasoningMetadata.

providers/openrouter/language_model_hooks.go ๐Ÿ”—

@@ -9,6 +9,7 @@ import (
 
 	"charm.land/fantasy"
 	"charm.land/fantasy/providers/anthropic"
+	"charm.land/fantasy/providers/google"
 	"charm.land/fantasy/providers/openai"
 	openaisdk "github.com/openai/openai-go/v2"
 	"github.com/openai/openai-go/v2/packages/param"
@@ -81,9 +82,14 @@ func languageModelExtraContent(choice openaisdk.ChatCompletionChoice) []fantasy.
 		text     string
 		metadata *anthropic.ReasoningOptionMetadata
 	}
+	type googleReasoningBlock struct {
+		text     string
+		metadata *google.ReasoningMetadata
+	}
 
 	responsesReasoningBlocks := make([]openai.ResponsesReasoningMetadata, 0)
 	anthropicReasoningBlocks := make([]anthropicReasoningBlock, 0)
+	googleReasoningBlocks := make([]googleReasoningBlock, 0)
 	otherReasoning := make([]string, 0)
 	for _, detail := range reasoningData.ReasoningDetails {
 		if strings.HasPrefix(detail.Format, "openai-responses") || strings.HasPrefix(detail.Format, "xai-responses") {
@@ -108,6 +114,26 @@ func languageModelExtraContent(choice openaisdk.ChatCompletionChoice) []fantasy.
 			responsesReasoningBlocks[detail.Index] = thinkingBlock
 			continue
 		}
+		if strings.HasPrefix(detail.Format, "google-gemini") {
+			var thinkingBlock googleReasoningBlock
+			if len(googleReasoningBlocks)-1 >= detail.Index {
+				thinkingBlock = googleReasoningBlocks[detail.Index]
+			} else {
+				thinkingBlock = googleReasoningBlock{metadata: &google.ReasoningMetadata{}}
+				googleReasoningBlocks = append(googleReasoningBlocks, thinkingBlock)
+			}
+
+			switch detail.Type {
+			case "reasoning.text":
+				thinkingBlock.text = detail.Text
+			case "reasoning.encrypted":
+				thinkingBlock.metadata.Signature = detail.Data
+				thinkingBlock.metadata.ToolID = detail.ID
+			}
+
+			googleReasoningBlocks[detail.Index] = thinkingBlock
+			continue
+		}
 
 		if strings.HasPrefix(detail.Format, "anthropic-claude") {
 			anthropicReasoningBlocks = append(anthropicReasoningBlocks, anthropicReasoningBlock{
@@ -141,6 +167,14 @@ func languageModelExtraContent(choice openaisdk.ChatCompletionChoice) []fantasy.
 			},
 		})
 	}
+	for _, block := range googleReasoningBlocks {
+		content = append(content, fantasy.ReasoningContent{
+			Text: block.text,
+			ProviderMetadata: fantasy.ProviderMetadata{
+				google.Name: block.metadata,
+			},
+		})
+	}
 
 	for _, reasoning := range otherReasoning {
 		content = append(content, fantasy.ReasoningContent{
@@ -151,7 +185,9 @@ func languageModelExtraContent(choice openaisdk.ChatCompletionChoice) []fantasy.
 }
 
 type currentReasoningState struct {
-	metadata *openai.ResponsesReasoningMetadata
+	metadata       *openai.ResponsesReasoningMetadata
+	googleMetadata *google.ReasoningMetadata
+	googleText     string
 }
 
 func extractReasoningContext(ctx map[string]any) *currentReasoningState {
@@ -227,11 +263,43 @@ func languageModelStreamExtra(chunk openaisdk.ChatCompletionChunk, yield func(fa
 			}
 		}
 
+		if strings.HasPrefix(detail.Format, "google-gemini") {
+			// this means there is only encrypted data available start and finish right away
+			if detail.Type == "reasoning.encrypted" {
+				ctx[reasoningStartedCtx] = nil
+				if !yield(fantasy.StreamPart{
+					Type: fantasy.StreamPartTypeReasoningStart,
+					ID:   fmt.Sprintf("%d", inx),
+				}) {
+					return ctx, false
+				}
+				return ctx, yield(fantasy.StreamPart{
+					Type: fantasy.StreamPartTypeReasoningEnd,
+					ID:   fmt.Sprintf("%d", inx),
+					ProviderMetadata: fantasy.ProviderMetadata{
+						google.Name: &google.ReasoningMetadata{
+							Signature: detail.Data,
+							ToolID:    detail.ID,
+						},
+					},
+				})
+			}
+			currentState.googleMetadata = &google.ReasoningMetadata{}
+			currentState.googleText = detail.Text
+			metadata = fantasy.ProviderMetadata{
+				google.Name: currentState.googleMetadata,
+			}
+		}
+
 		ctx[reasoningStartedCtx] = currentState
+		delta := detail.Summary
+		if strings.HasPrefix(detail.Format, "google-gemini") {
+			delta = detail.Text
+		}
 		return ctx, yield(fantasy.StreamPart{
 			Type:             fantasy.StreamPartTypeReasoningStart,
 			ID:               fmt.Sprintf("%d", inx),
-			Delta:            detail.Summary,
+			Delta:            delta,
 			ProviderMetadata: metadata,
 		})
 	}
@@ -313,6 +381,34 @@ func languageModelStreamExtra(chunk openaisdk.ChatCompletionChunk, yield func(fa
 		})
 	}
 
+	if strings.HasPrefix(detail.Format, "google-gemini") {
+		// reasoning.text type - accumulate text
+		if detail.Type == "reasoning.text" {
+			currentState.googleText += detail.Text
+			ctx[reasoningStartedCtx] = currentState
+			return ctx, yield(fantasy.StreamPart{
+				Type:  fantasy.StreamPartTypeReasoningDelta,
+				ID:    fmt.Sprintf("%d", inx),
+				Delta: detail.Text,
+			})
+		}
+
+		// reasoning.encrypted type - end reasoning with signature
+		if detail.Type == "reasoning.encrypted" {
+			currentState.googleMetadata.Signature = detail.Data
+			currentState.googleMetadata.ToolID = detail.ID
+			metadata := fantasy.ProviderMetadata{
+				google.Name: currentState.googleMetadata,
+			}
+			ctx[reasoningStartedCtx] = nil
+			return ctx, yield(fantasy.StreamPart{
+				Type:             fantasy.StreamPartTypeReasoningEnd,
+				ID:               fmt.Sprintf("%d", inx),
+				ProviderMetadata: metadata,
+			})
+		}
+	}
+
 	return ctx, yield(fantasy.StreamPart{
 		Type:  fantasy.StreamPartTypeReasoningDelta,
 		ID:    fmt.Sprintf("%d", inx),
@@ -793,7 +889,38 @@ func languageModelToPrompt(prompt fantasy.Prompt, _, model string) ([]openaisdk.
 						assistantMsg.SetExtraFields(map[string]any{
 							"reasoning_details": reasoningDetailsMap,
 						})
-
+					case strings.HasPrefix(model, "google/"):
+						metadata := google.GetReasoningMetadata(reasoningPart.Options())
+						if metadata == nil {
+							text := fmt.Sprintf("<thoughts>%s</thoughts>", reasoningPart.Text)
+							if assistantMsg.Content.OfString.Valid() {
+								text = assistantMsg.Content.OfString.Value + "\n" + text
+							}
+							// this reasoning did not come from anthropic just add a text content
+							assistantMsg.Content = openaisdk.ChatCompletionAssistantMessageParamContentUnion{
+								OfString: param.NewOpt(text),
+							}
+							continue
+						}
+						if reasoningPart.Text != "" {
+							reasoningDetails = append(reasoningDetails, ReasoningDetail{
+								Type:   "reasoning.text",
+								Format: "google-gemini-v1",
+								Text:   reasoningPart.Text,
+							})
+						}
+						reasoningDetails = append(reasoningDetails, ReasoningDetail{
+							Type:   "reasoning.encrypted",
+							Format: "google-gemini-v1",
+							Data:   metadata.Signature,
+							ID:     metadata.ToolID,
+						})
+						data, _ := json.Marshal(reasoningDetails)
+						reasoningDetailsMap := []map[string]any{}
+						_ = json.Unmarshal(data, &reasoningDetailsMap)
+						assistantMsg.SetExtraFields(map[string]any{
+							"reasoning_details": reasoningDetailsMap,
+						})
 					default:
 						reasoningDetails = append(reasoningDetails, ReasoningDetail{
 							Type:   "reasoning.text",

providertests/google_test.go ๐Ÿ”—

@@ -14,6 +14,7 @@ import (
 )
 
 var geminiTestModels = []testModel{
+	{"gemini-3-pro-preview", "gemini-3-pro-preview", true},
 	{"gemini-2.5-flash", "gemini-2.5-flash", true},
 	{"gemini-2.5-pro", "gemini-2.5-pro", true},
 }

providertests/openrouter_test.go ๐Ÿ”—

@@ -20,6 +20,7 @@ var openrouterTestModels = []testModel{
 	{"deepseek-chat-v3.1-free", "deepseek/deepseek-chat-v3.1:free", false},
 	{"qwen3-235b-a22b-2507", "qwen/qwen3-235b-a22b-2507", false},
 	{"gpt-5", "openai/gpt-5", true},
+	{"gemini-3-pro-preview", "google/gemini-3-pro-preview", true},
 	{"glm-4.5", "z-ai/glm-4.5", false},
 	{"glm-4.6", "z-ai/glm-4.6", true},
 }

providertests/testdata/TestGoogleCommon/gemini-2.5-flash/multi_tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -37,7 +37,7 @@ interactions:
                       "b": 3
                     }
                   },
-                  "thoughtSignature": "CrwBAdHtim+wl6784Zk4lDQyf935vvgPxSmTr5FU84nEUq8ijt+y5Ajfd9AXfYybZQjoWoSaAORt4/EsHJNCd45DrAwz8UZYKIvpGgw9k5aKjLYYgw5GkRc2Cgs6uy4AlHHRIkyWMQfaxIcyV2a0Mm4aiT419RVlLd5vIVxEVHlUVawR/9Sds+EuksQP/EKQfuNaAAFXhunEQmJJiMdyGWKMhXYF+L2jMBTN9DxGpoXBiNeu4w/a32l1OTtxdog="
+                  "thoughtSignature": "Cr4BAdHtim/Tq8T9XkqzcvcAqMXcurtfsNWvF+glFr+dbbGawdwSHuZ7mw9Xlm6KJ8Cie6v/uKr/LuTDVu+O1FD2kHVHH63fBYS4jt0jJdUs2xRL9+TdlgkrB1SyYzciPTdvzFrtCoM/iUQhtwohV0gr+3TWRYFtuOhW/WEDzYAJFjIPMftG0Jngtz2O59EN10sdngWQaAEYu2CUaPG47rqBITRumXdfX3+0nMCNpmbjqPCpJNg93O7EhMU8gJxs0g=="
                 },
                 {
                   "functionCall": {
@@ -59,38 +59,38 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 125,
           "candidatesTokenCount": 36,
-          "totalTokenCount": 201,
+          "totalTokenCount": 200,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 125
             }
           ],
-          "thoughtsTokenCount": 40
+          "thoughtsTokenCount": 39
         },
         "modelVersion": "gemini-2.5-flash",
-        "responseId": "9AcJad7SDPSGz7IPjsKs6A0"
+        "responseId": "c6IdafipKOX-vdIPoJuZsAs"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 3.031359958s
+    duration: 974.216125ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 1155
+    content_length: 1437
     host: generativelanguage.googleapis.com
     body: |

providertests/testdata/TestGoogleCommon/gemini-2.5-flash/multi_tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1
-    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"add\",\"args\": {\"b\": 3,\"a\": 2}},\"thoughtSignature\": \"CikB0e2Kb/HMQc6i7UBRyFsYt3Py//kiN1i+ogTc09WPsRdhdlrPbqY0dQpYAdHtim8DpoYoaf6/9WaPOuM4ieoyrooxEGgr+rAl5vIIQ4mHHGPK3ES36kZb5fJGPx3mhtjks/+IGCakkpTqeVM5b8/uRyU+wFaI0KauqOwXHOhzt7euogp/AdHtim+wDPZH2rIZ9gMZsEEmpRPJB6D9vvfWb5DkLAc6lIG7AFW4Kzih+bkvgt96liwfadjYmkq/yepyTwMlArb+AA2NyudR0MgHxyh+l5BN/gxRZNmGhKfZprKbIPDiHstjnpJXZy136L25YwkcerUaVSUUi/bUUrScZW6IXQ==\"},{\"functionCall\": {\"name\": \"multiply\",\"args\": {\"b\": 3,\"a\": 2}}}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0,\"finishMessage\": \"Model generated function call(s).\"}],\"usageMetadata\": {\"promptTokenCount\": 121,\"candidatesTokenCount\": 36,\"totalTokenCount\": 196,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 121}],\"thoughtsTokenCount\": 39},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"9gcJaf-cE-uJz7IPu5TY2QE\"}\r\n\r\n"
+    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"add\",\"args\": {\"b\": 3,\"a\": 2}},\"thoughtSignature\": \"CikB0e2KbzJ53cZQAbVmS3FT2mrSIPh4SqG9C0hmU6Af0IhPFXcFgoc5twptAdHtim8trKjd4oXwYT0oCz0ruME+ffJ75W/FCaehBo4LLnMuwRYanvHpWA8knHwPzDPADfYQCldBCzW+B2pcMTLxlHfoaaY+7mGGOqb9eyzyKxGJmmCBD80fHvEY0zNwjnLyLhrQjjLPjQOJJwpnAdHtim/XR83WyBkpOGrXLvmZ2ZNz16pdlWavvk2U+RyzJH2ca5szuZ3ZlepealN3RCzYHo2vUpwBqPKx2NGNVTfI8jUAueIO8tb/0Z+VJHpktNds5qCJgvCZUfQwN8MEWO0vMOgqww==\"},{\"functionCall\": {\"name\": \"multiply\",\"args\": {\"a\": 2,\"b\": 3}}}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0,\"finishMessage\": \"Model generated function call(s).\"}],\"usageMetadata\": {\"promptTokenCount\": 121,\"candidatesTokenCount\": 36,\"totalTokenCount\": 195,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 121}],\"thoughtsTokenCount\": 38},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"dKIdacS5OILaxs0PwvHjwQ4\"}\r\n\r\n"
     headers:
       Content-Type:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.219170666s
+    duration: 897.297ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 1138
+    content_length: 1508
     host: generativelanguage.googleapis.com
     body: |

providertests/testdata/TestGoogleCommon/gemini-2.5-flash/simple.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -42,21 +42,21 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 11,
           "candidatesTokenCount": 2,
-          "totalTokenCount": 42,
+          "totalTokenCount": 35,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 11
             }
           ],
-          "thoughtsTokenCount": 29
+          "thoughtsTokenCount": 22
         },
         "modelVersion": "gemini-2.5-flash",
-        "responseId": "6gcJafzNJPSHz7IPwvXNgAs"
+        "responseId": "bqIdadvABK-8xN8Plpr0oAY"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.003357083s
+    duration: 517.171875ms

providertests/testdata/TestGoogleCommon/gemini-2.5-flash/simple_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,10 +25,10 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1
-    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"Olรก!\\n\\nIn Portuguese, \\\"hi\\\" is **Olรก!**\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 11,\"candidatesTokenCount\": 14,\"totalTokenCount\": 49,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 11}],\"thoughtsTokenCount\": 24},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"6wcJab6wEJucz7IP3f6J4Qk\"}\r\n\r\n"
+    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"Olรก! In Portuguese, you can say:\\n\\n**Olรก!**\\n\\nIt's a versatile greeting that works for \\\"hi,\\\" \\\"hello,\\\" and even \\\"hey.\\\"\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 11,\"candidatesTokenCount\": 35,\"totalTokenCount\": 78,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 11}],\"thoughtsTokenCount\": 32},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"bqIdacLAGozKvdIP5Nu3oAg\"}\r\n\r\n"
     headers:
       Content-Type:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 835.455625ms
+    duration: 733.998792ms

providertests/testdata/TestGoogleCommon/gemini-2.5-flash/tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -36,7 +36,7 @@ interactions:
                       "location": "Florence, Italy"
                     }
                   },
-                  "thoughtSignature": "CvYBAdHtim+VrL2UvucUTXguiAiFr1B+yVyHmXWGv262dyNf/DOFOwEVrAAoqSE8NbBv/nkGGVn7PkdDdEKEa+1uCDOMMa0K8FUj6zu3ZivA2JYeqY/ASmq6BnC8JMrvHObNh7KxKI7H7TJ4GzG7uoWUBuwTmmecQcN19f59Zf36Gekwa10X673O1v02WK4D2H+hGfnnNYauwrlMHjDYkruYSrb2u6QcEoLnASnW5WU9ESLGbZy0uqKMztlFvhDcoUCEPboy4p4KjUt0S/iEpjHc2bDjq+EqYS8icqu9zo2UeVREa6nPSOspkW0AGVedfMheSaeJHw4A"
+                  "thoughtSignature": "CoICAdHtim+oSIAY8uUYR6EfmWAxA3fQg7sAam3Jw4sK1xvXAvTmomotsL1uIgSO4Kx79F3+SQ3iVydWojoLVRBdLbdc+U0K2rXqTzc739H/3nUgqnfYELuBXKYE7W5ON5r2y2LzanK4lbUpHh8M4PYAtY8yIn8wonpr1KL+Ec6ykafkiT4nGHQHmmqndKKsdkLXboxtBxeKp2ZV0aCv1NiNvuwz0kucUx1AXBTI2SUpvAEsz2BfpmJg1i3eBwHtCyuz/I7/K2hqWHsO1NY1M0mL2c+1uwRhwTO5kNJ2i5q+la5MP6GN4Un5yceWmI4LNWInHfL0PUJ1MiCkurtsFMGqNA5+"
                 }
               ],
               "role": "model"
@@ -49,38 +49,38 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 54,
           "candidatesTokenCount": 15,
-          "totalTokenCount": 120,
+          "totalTokenCount": 122,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 54
             }
           ],
-          "thoughtsTokenCount": 51
+          "thoughtsTokenCount": 53
         },
         "modelVersion": "gemini-2.5-flash",
-        "responseId": "7QcJadHhA7zQz7IP_7Hy4AY"
+        "responseId": "b6IdafT6Kd6evdIPrZ2kqAU"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.571397s
+    duration: 903.990542ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 723
+    content_length: 1093
     host: generativelanguage.googleapis.com
     body: |
-      {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence, Italy"},"id":"1","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"1","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}

providertests/testdata/TestGoogleCommon/gemini-2.5-flash/tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/gemini-2.5-pro/multi_tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -37,14 +37,14 @@ interactions:
                       "b": 3
                     }
                   },
-                  "thoughtSignature": "CpECAdHtim+6+kabSNJ55G1aHXgyrJEt4/hov4uGHkcSqzlgfBd4clna+c9UpSL1rvSqMOb2E8NohfunKGm4ZHHOX9X+dBKww0ekyLz+83CF28LbsOzDHrPtIiRYoDaL/75h/HzhboaPK+aunAUglNLxM/b5yrr2tT0jKvz4LzuymTYHCpzBCcoIecoeuT0RO/WaUsjB8CMRGxnigv2XtuFkBxxzk2OWPmhSM6KTeIQTVe0d3T4HjKe2L76XG1WeaV3weeMxeCyrqX4ycxH2fJ1h5cG5EONLNxqA9eHREWu/j5ABiOGxZv2ih6xU/xyo5apwpLAwVSYtyDKXiTH4T6Wp/V7t8E7Urj4smOABFupCATUl"
+                  "thoughtSignature": "Ct4DAdHtim86WQIPk3bh2XALNHL2XEV9TyeNz9k+Z06RPzFlt9c10RhGIIiLApE4rqlKdDjjly0ZJY0+UYfFkA1ZnAYgz8v/GnqX822cM936bMf2yQ3BLMQn9KYN2iabIhiS0wy9eF2MYE/xjlaYrAfH6Ek6/gmyTSjmstOU0/ipD+XcmqRiryIEEDINK4SjFK4aGAy6pkVYtNPT/1mm5l01Nr8b6IJaPq5YyPTHud14tw0ZnJaqff0TfM4t0NLYV0cgFTCR9phlWyR2ByE0xLigMSVOwNqWow4JPanV4CmxliGwuzJzrhhc7Olc9oIX0CVE8sLJwgH2I4lCUBx4g2JxvLI4flrY4d3nVbAbOtjLgAB0jQO24VL1tjRM+N/TP1KcdGKMhqLvv8TPAuKLsuoreI70Ggfph0ZstnQt/CgRIrvdG1q1j6+3S5H9l+5OL1JHwqPNfEcxawFtWbE1etM0EHXG0c1lRa090y+e2lLMDxNUyiUXl9UfLeQR0dCWqW+lL98DBYpT8eVF4VUCaxKR2uDlKuoBrP9KchziKXh4W61Guj3dGXSOQvo3UrQXna80k0rcIWnJ93Ri2/b6zjWUJoGPPr74qAID2ld3dA4DwsSG2oaVZ9SkDuO1RfdkUA=="
                 },
                 {
                   "functionCall": {
                     "name": "multiply",
                     "args": {
-                      "a": 2,
-                      "b": 3
+                      "b": 3,
+                      "a": 2
                     }
                   }
                 }
@@ -59,38 +59,38 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 125,
           "candidatesTokenCount": 36,
-          "totalTokenCount": 234,
+          "totalTokenCount": 292,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 125
             }
           ],
-          "thoughtsTokenCount": 73
+          "thoughtsTokenCount": 131
         },
         "modelVersion": "gemini-2.5-pro",
-        "responseId": "DQkJadesHOWzqtsP98mO8Ao"
+        "responseId": "kKIdaerxBqH6xs0P87WrgAk"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.444643917s
+    duration: 2.442287917s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 1155
+    content_length: 1821
     host: generativelanguage.googleapis.com
     body: |

providertests/testdata/TestGoogleCommon/gemini-2.5-pro/multi_tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/gemini-2.5-pro/simple.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -30,7 +30,7 @@ interactions:
             "content": {
               "parts": [
                 {
-                  "text": "Of course!\n\nThe most common ways to say \"hi\" in Portuguese are:\n\n*   **Olรก** (This is the standard \"hello,\" and it works in any situation.)\n*   **Oi** (This is a more informal and very common \"hi,\" especially in Brazil.)\n\nYou might also hear people greet each other with:\n\n*   **Tudo bem?** (Which means \"How are you?\" or \"Is everything okay?\")"
+                  "text": "Of course!\n\nThe most common ways to say \"hi\" in Portuguese are:\n\n*   **Olรก** (oh-LAH) - This is the direct translation of \"hello\" and can be used in any situation, formal or informal.\n*   **Oi** (oy) - This is more informal and very common, just like \"hi\" in English.\n\nYou can also use:\n\n*   **Tudo bem?** (too-doh beng?) - Which means \"How are you?\" or \"Is everything good?\" and is a very common way to greet someone."
                 }
               ],
               "role": "model"
@@ -41,22 +41,22 @@ interactions:
         ],
         "usageMetadata": {
           "promptTokenCount": 11,
-          "candidatesTokenCount": 94,
-          "totalTokenCount": 802,
+          "candidatesTokenCount": 122,
+          "totalTokenCount": 849,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 11
             }
           ],
-          "thoughtsTokenCount": 697
+          "thoughtsTokenCount": 716
         },
         "modelVersion": "gemini-2.5-pro",
-        "responseId": "AQgJabbjM5rQz7IPgq_yiAc"
+        "responseId": "fqIdabztHPjXxs0P146HoQk"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 8.976729125s
+    duration: 8.426214208s

providertests/testdata/TestGoogleCommon/gemini-2.5-pro/simple_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,10 +25,10 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/gemini-2.5-pro/tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -36,7 +36,7 @@ interactions:
                       "location": "Florence, Italy"
                     }
                   },
-                  "thoughtSignature": "CoUDAdHtim8N4HKZPr0LvOdoOCBZCvZIDq+277VOB/Ee7dBu8J4m0pT+8u9m55SqUFvQcQVSxjJEIvR/o6eUzbeSKwJ9s9MgEnQoNXUktpSUuiJ7HJhdapcQnZbCRPrcs+zdqSQGdXHdpjRguIVDRG+r5GnD40lYk1AurV31uEe6Jpox1MIfPxNOLnhuVDwjhAv2zqW0e6hf9ZtmlXk6qtIoLOnFxRAAx2NqZYA22kkoA0s0DtSTAUDQTMr+NrXTbOELd3ZeVjLBsWutkYNwIRWAnzNJ1il3A8xbmEh8YL4Uy+nH48ROgams6PCuxtxTEyOk0sAOKQkfid1STQfDO3VAoB4ne7cgNDh80y1fAo/5cXSGkeMPLqgyZr2jeIx7lWWWDaOHw/ieZDTaJGInBy5blOEkWxKl8mKKgAbvALOEFCdVDwFN+maw17w/Y0FtKWgk8zrdsM8naF/mBtGkulhMDoqjB0XNcIihur24NuD8vyifQl+s7MkkdctYLxdSXVFhfiB5D8w="
+                  "thoughtSignature": "CtcDAdHtim8sltjSbCOxCM3sW652tUKKCiplDIoViEhKUuXpAUkg8vvhGpNwIBQdUOU091dd13FYdNYoTg/N62xtEIbin8xsVkDAhEBNTyciVa1cUORxFwTjID5b4z8/byy0Zf/e6sbKXMxbf9BpAVMHQW0mF6Yz82BQsczMi3B00lOO+0VV82ClVs4tBXYf7o3kekAAVD+XGCfuB/YGr9V6CeJCMXc8+gVpLIFS4DaPlNMoG3Lv4PnZp4beJ4puuIxh+3ipmGv8hJKAwUFAZmuU/knnUMqc09ddXtJdPKyssWbuR51SIU49+eVtxOib43fUOILlOO+J0oukfCSt2JS6EuVVSNYDMC7HOUkkY9T7V9IbCEtiuL42gvWbCAEwbta/QuGH1L9emajt2yiX+bIcuCl3GuRU0wQ/AB4mMBFwmnATUiaEKAmtSpiSvHy20SUHMh/KPNEOfQ0J6IyBWWhKhEaiAezRaKZSao6g68ymM5xOAyY0Vkrq3pWeUjboR9Z65I/tKiE2Qs6PuQJWI1sL67D9a885x10iR6NpaJyETpOYqGDqjZ3zs8ZiibLy0iitwibDwXzJyCLrJzEoTRmtotxoSkTm2wQVUpVpQzZBl4pzMbY2CRoR"
                 }
               ],
               "role": "model"
@@ -49,38 +49,38 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 54,
           "candidatesTokenCount": 15,
-          "totalTokenCount": 162,
+          "totalTokenCount": 181,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 54
             }
           ],
-          "thoughtsTokenCount": 93
+          "thoughtsTokenCount": 112
         },
         "modelVersion": "gemini-2.5-pro",
-        "responseId": "DQgJaczjHfHAz7IPo92A4QY"
+        "responseId": "iKIdafbaFtX8vdIPueXoyAk"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.028702667s
+    duration: 2.134031542s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 723
+    content_length: 1377
     host: generativelanguage.googleapis.com
     body: |
-      {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence, Italy"},"id":"1","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"1","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}

providertests/testdata/TestGoogleCommon/gemini-2.5-pro/tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/multi_tool.yaml ๐Ÿ”—

@@ -0,0 +1,137 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 826
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Add and multiply the number 2 and 3"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS."}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Add two numbers","name":"add","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}},{"description":"Multiply two numbers","name":"multiply","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}}]}]}
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "candidates": [
+          {
+            "content": {
+              "parts": [
+                {
+                  "functionCall": {
+                    "name": "add",
+                    "args": {
+                      "b": 3,
+                      "a": 2
+                    }
+                  },
+                  "thoughtSignature": "Ep8DCpwDAdHtim9QdO0y9bZ65Rujicbol+wCUJKbtFVKI8R2aVL5g9KNn25HRk9RQTnn6Mf/bHwNDvm17S/NkwMNRHTnsrgsFhCnID3D3UUhs2a0PJAw2qr4I2JkLlDxSarHaYQL8FkzDJCyEfaKHa4wPEFCTQL4DYtVutBbO5/f8meUiUhZxBBuKshtXWlqO0ecRIKJ1UD+wMZ0BlFGdJGYoVVpYFlbk3/MJzmKzy21oDuzYLPSpHFi79QB6QucplXCYu37zxdYlzr6Hq5aGYf2Cw6qKr5j8F85I+zX5S0MPfVdK68nuPC4qb/qYGRUhMHzb05e13X1SotaSS8hZJo+u9pUXhwrSnNbSoVZEBKC+dSqoksI6YHm89pUKA94eC++gJ1ul/HHMHrF49r1wvAKO7EUP0TBCtemyZYtVSrh0TmIkucyU9pUCzNB375Kmox8qbARrUXdlHjCkdisVqJMIZhEn34dfNah7Uc/lQj975ZR5k0zetyhnUHG7E/Blv1Nezo8rB2n4HxhTrKKLyRDXl3dtt2fDSr5UvzzZEBEiQ=="
+                },
+                {
+                  "functionCall": {
+                    "name": "multiply",
+                    "args": {
+                      "a": 2,
+                      "b": 3
+                    }
+                  }
+                }
+              ],
+              "role": "model"
+            },
+            "finishReason": "STOP",
+            "index": 0,
+            "finishMessage": "Model generated function call(s)."
+          }
+        ],
+        "usageMetadata": {
+          "promptTokenCount": 161,
+          "candidatesTokenCount": 32,
+          "totalTokenCount": 289,
+          "promptTokensDetails": [
+            {
+              "modality": "TEXT",
+              "tokenCount": 161
+            }
+          ],
+          "thoughtsTokenCount": 96
+        },
+        "modelVersion": "gemini-3-pro-preview",
+        "responseId": "Z6IdadLwMIDXvdIPwbrDyAY"
+      }
+    headers:
+      Content-Type:
+      - application/json; charset=UTF-8
+    status: 200 OK
+    code: 200
+    duration: 2.545695292s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1737
+    host: generativelanguage.googleapis.com
+    body: |

providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/multi_tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 809
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Add and multiply the number 2 and 3"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant. Always use both add and multiply at the same time."}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Add two numbers","name":"add","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}},{"description":"Multiply two numbers","name":"multiply","parameters":{"properties":{"a":{"description":"first number","type":"INTEGER"},"b":{"description":"second number","type":"INTEGER"}},"required":["a","b"],"type":"OBJECT"}}]}]}
+    form:
+      alt:
+      - sse
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:streamGenerateContent?alt=sse
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1

providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/simple.yaml ๐Ÿ”—

@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 202
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "candidates": [
+          {
+            "content": {
+              "parts": [
+                {
+                  "text": "You can say **\"Oi\"** or **\"Olรก\"**.",

providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,34 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 202
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Say hi in Portuguese"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"}}
+    form:
+      alt:
+      - sse
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:streamGenerateContent?alt=sse
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1

providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/tool.yaml ๐Ÿ”—

@@ -0,0 +1,127 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 509
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "candidates": [
+          {
+            "content": {
+              "parts": [
+                {
+                  "functionCall": {
+                    "name": "weather",
+                    "args": {
+                      "location": "Florence, Italy"
+                    }
+                  },
+                  "thoughtSignature": "EvwCCvkCAdHtim+PQmLlXBFlyn5zkH9Ulj6upBtzURUlM9dI26vPsj3LG2Q4KeqoH5XyWdqCkF+ruALELNIQ27gg7Xp6EkWYYMBus01fmwUubUKhjIu0zV/3qpAfK44Zsg9QXONIVDKMwPJxDHd4XUIehDG0y1JICa9Om9hSdrcLcelx9wRMb79NsdBWO3JRwxAfaVlmtfnCdTRBfuQ1Vzs//ZxCQr9RHWnL9Z+ZXllJNvusWfUVEsyY288zIkOb4EJElnK7vto2gBY7vwlFsXg4JBjeBu9WLBu0Y3pQSZ35ktLDpO9W07OSDE57Id68JBtLxqb6XzxINYUdWTh2908VC6dnpEWSKN76uRq6G/5DVqUq5TGosYSvGsqRMLmEISxjy0g3j/foXQWeFMlLAG7Xn9sp0FHZraQ1AhlboTBW43uAJmJWmOLcti4JM/EQ0b1gc4heejJXRSjc6XOfvkczVBA4psJv4hgOXZvtoD5VwRD0WkOB5zMoo1MyqWI="
+                }
+              ],
+              "role": "model"
+            },
+            "finishReason": "STOP",
+            "index": 0,
+            "finishMessage": "Model generated function call(s)."
+          }
+        ],
+        "usageMetadata": {
+          "promptTokenCount": 65,
+          "candidatesTokenCount": 16,
+          "totalTokenCount": 148,
+          "promptTokensDetails": [
+            {
+              "modality": "TEXT",
+              "tokenCount": 65
+            }
+          ],
+          "thoughtsTokenCount": 67
+        },
+        "modelVersion": "gemini-3-pro-preview",
+        "responseId": "X6IdacDzD7jZvdIP6qu5mQk"
+      }
+    headers:
+      Content-Type:
+      - application/json; charset=UTF-8
+    status: 200 OK
+    code: 200
+    duration: 2.275361292s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1257
+    host: generativelanguage.googleapis.com
+    body: |

providertests/testdata/TestGoogleCommon/gemini-3-pro-preview/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 509
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+    form:
+      alt:
+      - sse
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:streamGenerateContent?alt=sse
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1

providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/simple.yaml ๐Ÿ”—

@@ -24,10 +24,10 @@ interactions:
     proto_minor: 0
     content_length: -1
     uncompressed: true
-    body: '{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_01E4ctksfNxnHxb8NL7AzY7L","type":"message","role":"assistant","content":[{"type":"text","text":"Olรก! That''s \"hi\" in Portuguese. How can I help you today?"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":22}}'
+    body: '{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_011D8f9pw4KabWttPrkbaAL6","type":"message","role":"assistant","content":[{"type":"text","text":"Olรก! Como posso ajudar vocรช hoje?"}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":16}}'
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 1.867139833s
+    duration: 1.980568375s

providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/simple_streaming.yaml ๐Ÿ”—

@@ -26,56 +26,38 @@ interactions:
     uncompressed: true
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_011vbTX9zC2NZRQEamT4cSJf","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":4}}             }
+      data: {"type":"message_start","message":{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_013va9SBUhdmyiMNdWQdAJXr","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":5}}       }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}         }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}      }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Olรก!"}   }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"Olรก! Como"}       }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Como"}             }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" pos"}    }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" vai vocรช"}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"so aju"}          }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"?\n\nThis"}    }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" is a"}}
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" greeting"}          }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" in Portuguese that"}               }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" means"}            }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" \"Hello! How are"}      }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" you?\""}      }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"dar vocรช hoje?"}      }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0   }
+      data: {"type":"content_block_stop","index":0        }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":27} }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":16}   }
 
       event: message_stop
-      data: {"type":"message_stop"              }
+      data: {"type":"message_stop"       }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.338077792s
+    duration: 1.261146292s

providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/tool.yaml ๐Ÿ”—

@@ -24,21 +24,21 @@ interactions:
     proto_minor: 0
     content_length: -1
     uncompressed: true
-    body: '{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_013DoXQqRt9hn5cxD1GPCcbj","type":"message","role":"assistant","content":[{"type":"text","text":"I''ll get the current weather information for Florence, Italy for you."},{"type":"tool_use","id":"toolu_vrtx_01AbaFbEuoSmuk9UyZaC4byG","name":"weather","input":{"location":"Florence,Italy"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":68}}'
+    body: '{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_018rHJHvE1H6hfLm167nmkRj","type":"message","role":"assistant","content":[{"type":"text","text":"I''ll check the current weather in Florence, Italy for you."},{"type":"tool_use","id":"toolu_vrtx_01EKDu37P36gfuCEwCpy6fer","name":"weather","input":{"location":"Florence,Italy"}}],"stop_reason":"tool_use","stop_sequence":null,"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":67}}'
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 1.495076667s
+    duration: 2.085536084s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 892
+    content_length: 881
     host: ""
-    body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"},{"content":[{"text":"I''ll get the current weather information for Florence, Italy for you.","type":"text"},{"id":"toolu_vrtx_01AbaFbEuoSmuk9UyZaC4byG","input":{"location":"Florence,Italy"},"name":"weather","type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_vrtx_01AbaFbEuoSmuk9UyZaC4byG","content":[{"text":"40 C","type":"text"}],"type":"tool_result"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"anthropic_version":"vertex-2023-10-16"}'
+    body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"},{"content":[{"text":"I''ll check the current weather in Florence, Italy for you.","type":"text"},{"id":"toolu_vrtx_01EKDu37P36gfuCEwCpy6fer","input":{"location":"Florence,Italy"},"name":"weather","type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_vrtx_01EKDu37P36gfuCEwCpy6fer","content":[{"text":"40 C","type":"text"}],"type":"tool_result"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"anthropic_version":"vertex-2023-10-16"}'
     headers:
       Accept:
       - application/json
@@ -54,10 +54,10 @@ interactions:
     proto_minor: 0
     content_length: -1
     uncompressed: true
-    body: '{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_01MrnUMp85dMAcyhkjGeX2we","type":"message","role":"assistant","content":[{"type":"text","text":"The current temperature in Florence, Italy is 40ยฐC (104ยฐF), which is quite hot. If you''re planning to be outdoors, I recommend staying hydrated, wearing light clothing, and seeking shade when possible."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":476,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":51}}'
+    body: '{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_014QWCD9SGFBuL4dWvcDrX48","type":"message","role":"assistant","content":[{"type":"text","text":"The current temperature in Florence, Italy is 40ยฐC (104ยฐF), which is very hot. Make sure to stay hydrated and try to avoid prolonged exposure to the sun if you''re there or planning to visit soon."}],"stop_reason":"end_turn","stop_sequence":null,"usage":{"input_tokens":475,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":52}}'
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 1.353360875s
+    duration: 1.480864125s

providertests/testdata/TestGoogleCommon/vertex-claude-3-7-sonnet/tool_streaming.yaml ๐Ÿ”—

@@ -26,76 +26,76 @@ interactions:
     uncompressed: true
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_015uS6fGm1egYvRuSAr5jmF8","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":3}}         }
+      data: {"type":"message_start","message":{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_01BskFKCoRmtNwwLEZceS2hN","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":2}}         }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}             }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}       }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll check"}     }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"I'll"}          }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" the current weather in"}  }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" get the"}             }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Florence, Italy for you"}         }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" weather"}              }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"."}   }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" information for Florence, Italy"}               }
+
+      event: content_block_delta
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" for you."}  }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0      }
+      data: {"type":"content_block_stop","index":0}
 
       event: content_block_start
-      data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_vrtx_01HCzehdpw6xDu3CDVXSFHFh","name":"weather","input":{}}          }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}   }
+      data: {"type":"content_block_start","index":1,"content_block":{"type":"tool_use","id":"toolu_vrtx_01Ko1dsGPQQd4y3nsTPLMQcM","name":"weather","input":{}}}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"lo"}        }
+      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":""}      }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"cation\":"}         }
+      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"{\"lo"}  }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":" \"F"}              }
+      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"cation\""}            }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"loren"}           }
+      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":": \"Floren"}      }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"ce,"}           }
+      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"ce,Italy"}             }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"Italy\"}"}          }
+      data: {"type":"content_block_delta","index":1,"delta":{"type":"input_json_delta","partial_json":"\"}"}            }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":1               }
+      data: {"type":"content_block_stop","index":1  }
 
       event: message_delta
       data: {"type":"message_delta","delta":{"stop_reason":"tool_use","stop_sequence":null},"usage":{"output_tokens":67}     }
 
       event: message_stop
-      data: {"type":"message_stop"            }
+      data: {"type":"message_stop"             }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.281991291s
+    duration: 752.193583ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 895
+    content_length: 898
     host: ""
-    body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"},{"content":[{"text":"I''ll check the current weather in Florence, Italy for you.","type":"text"},{"id":"toolu_vrtx_01HCzehdpw6xDu3CDVXSFHFh","input":{"location":"Florence,Italy"},"name":"weather","type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_vrtx_01HCzehdpw6xDu3CDVXSFHFh","content":[{"text":"40 C","type":"text"}],"type":"tool_result"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"stream":true,"anthropic_version":"vertex-2023-10-16"}'
+    body: '{"max_tokens":4000,"messages":[{"content":[{"text":"What''s the weather in Florence,Italy?","type":"text"}],"role":"user"},{"content":[{"text":"I''ll get the weather information for Florence, Italy for you.","type":"text"},{"id":"toolu_vrtx_01Ko1dsGPQQd4y3nsTPLMQcM","input":{"location":"Florence,Italy"},"name":"weather","type":"tool_use"}],"role":"assistant"},{"content":[{"tool_use_id":"toolu_vrtx_01Ko1dsGPQQd4y3nsTPLMQcM","content":[{"text":"40 C","type":"text"}],"type":"tool_result"}],"role":"user"}],"system":[{"text":"You are a helpful assistant","type":"text"}],"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}],"stream":true,"anthropic_version":"vertex-2023-10-16"}'
     headers:
       Accept:
       - application/json
@@ -113,71 +113,68 @@ interactions:
     uncompressed: true
     body: |+
       event: message_start
-      data: {"type":"message_start","message":{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_012cLcdjR2yjtxpzQjqjrHua","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":475,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":5}}           }
+      data: {"type":"message_start","message":{"model":"claude-3-7-sonnet-20250219","id":"msg_vrtx_01Lnb15G6n5yup7eiSG1MJP3","type":"message","role":"assistant","content":[],"stop_reason":null,"stop_sequence":null,"usage":{"input_tokens":475,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"output_tokens":2}}         }
 
       event: ping
       data: {"type": "ping"}
 
       event: content_block_start
-      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}             }
-
-      event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"The current temperature in"}         }
+      data: {"type":"content_block_start","index":0,"content_block":{"type":"text","text":""}               }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Florence, Italy is "}             }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"It"}             }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"40ยฐC (104"}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'s currently 40 "}            }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"ยฐF),"}              }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"degrees Celsius in Florence"}     }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" which is very"}          }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":", Italy."}       }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" hot. If"}          }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" That"}     }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" you're in"}          }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"'s quite"}        }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" Florence or"}    }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" hot"}            }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" planning to visit soon"}    }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"! Make"}      }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":", I'd recommend staying"}  }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" sure to stay"}    }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" hydrated and trying"} }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" hydrated and try"}}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" to avoid extende"}          }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" to avoid being"}      }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":"d periods outdoors during the"}          }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" outside during the peak"}}
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" hottest parts"}              }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" heat of the day if"}   }
 
       event: content_block_delta
-      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" of the day."}       }
+      data: {"type":"content_block_delta","index":0,"delta":{"type":"text_delta","text":" possible."}           }
 
       event: content_block_stop
-      data: {"type":"content_block_stop","index":0}
+      data: {"type":"content_block_stop","index":0     }
 
       event: message_delta
-      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":60}               }
+      data: {"type":"message_delta","delta":{"stop_reason":"end_turn","stop_sequence":null},"usage":{"output_tokens":45}             }
 
       event: message_stop
-      data: {"type":"message_stop"        }
+      data: {"type":"message_stop"   }
 
     headers:
       Content-Type:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 3.504416334s
+    duration: 1.308048041s

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/multi_tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -38,7 +38,7 @@ interactions:
                       "b": 3
                     }
                   },
-                  "thoughtSignature": "CqECAePx/16hu6jpQBsua/6D0znPjMbbAuwTIAxACow0BHlZjpuJ2bAGyr7Wo7paE6FNx84jcAd1AMLIJAWscUNukGCRiDORASgswHP16BSSB6jN5dLjTJ0UpUoxESXEW4U0iyrruAkortreKykTPMnW63wWjao8KQESbO/Q7g7WOQPGUzpmOCw9cvKt6I/DRZLjiJ1S8BmgEbc8ix2C4YBguza0iJ28V3ggewHiXumC3RxijchXLLkLx9Y5ww3XoJk1QaaWN3puEeWyVpEOQQJHa0pQVLYIp+IkQ0t0oe3jKDI05FBjn+h1lvbHoPuImyLtjUZFAMBqh76BWHQAYsfVUEzzSWplygLX0RP+NABj/9jDMK22/+DjBnBpEL1dv0lXvQ=="
+                  "thoughtSignature": "CtQBAePx/16Zez8Umc39OZNkaQcoaJ1i+yLTUes4eYNcobNd2vH2Jza1Q9tqpUP3e9MCA7Az0IRM9hVbj63fFwx8AT9u4FhaQRdazvEkYMqe+jGLiO6yex245G4qobHLIydnzgPJA6OMCVsuxxjHM1QhmT31E5Qg/ZVeh6Fc6ZI3S+q3TC1+tNxGr2EBlWfWyfHIOtr2qsGfZSSVOaB9Wj1jY/alOSKrSFC0PiCGhvmMwnawJWlzYkshIfAssUetPp+bDW5grOJoKWATcF3kTFShItAs6Xc="
                 },
                 {
                   "functionCall": {
@@ -52,13 +52,13 @@ interactions:
               ]
             },
             "finishReason": "STOP",
-            "avgLogprobs": -0.99647712707519531
+            "avgLogprobs": -0.58420848846435547
           }
         ],
         "usageMetadata": {
           "promptTokenCount": 60,
           "candidatesTokenCount": 10,
-          "totalTokenCount": 140,
+          "totalTokenCount": 119,
           "trafficType": "ON_DEMAND",
           "promptTokensDetails": [
             {
@@ -72,32 +72,32 @@ interactions:
               "tokenCount": 10
             }
           ],
-          "thoughtsTokenCount": 70
+          "thoughtsTokenCount": 49
         },
         "modelVersion": "gemini-2.5-flash",
-        "createTime": "2025-11-03T19:52:55.484773Z",
-        "responseId": "FwgJaaXLHe2iptQP__zTsAs"
+        "createTime": "2025-11-19T11:04:06.032691Z",
+        "responseId": "JqQdabP_AfrJptQP15PtmQI"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.145860833s
+    duration: 989.592584ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 1155
+    content_length: 1465
     host: us-east5-aiplatform.googleapis.com
     body: |

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/multi_tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/simple.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -36,13 +36,13 @@ interactions:
               ]
             },
             "finishReason": "STOP",
-            "avgLogprobs": -2.3644888401031494
+            "avgLogprobs": -0.58062881231307983
           }
         ],
         "usageMetadata": {
           "promptTokenCount": 9,
           "candidatesTokenCount": 2,
-          "totalTokenCount": 38,
+          "totalTokenCount": 37,
           "trafficType": "ON_DEMAND",
           "promptTokensDetails": [
             {
@@ -56,15 +56,15 @@ interactions:
               "tokenCount": 2
             }
           ],
-          "thoughtsTokenCount": 27
+          "thoughtsTokenCount": 26
         },
         "modelVersion": "gemini-2.5-flash",
-        "createTime": "2025-11-03T19:52:49.131611Z",
-        "responseId": "EQgJaZuECPfyptQPiO7F0Qw"
+        "createTime": "2025-11-19T11:04:00.570529Z",
+        "responseId": "IKQdaaHpIuyAptQPvKrv8AI"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.398007208s
+    duration: 1.624110084s

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/simple_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,10 +25,10 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1
-    body: "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"Olรก!\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 9,\"candidatesTokenCount\": 2,\"totalTokenCount\": 37,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 9}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 2}],\"thoughtsTokenCount\": 26},\"modelVersion\": \"gemini-2.5-flash\",\"createTime\": \"2025-11-03T19:52:50.051639Z\",\"responseId\": \"EggJabeTA8_PptQPo-GH8QQ\"}\r\n\r\n"
+    body: "data: {\"candidates\": [{\"content\": {\"role\": \"model\",\"parts\": [{\"text\": \"Olรก!\"}]},\"finishReason\": \"STOP\"}],\"usageMetadata\": {\"promptTokenCount\": 9,\"candidatesTokenCount\": 2,\"totalTokenCount\": 37,\"trafficType\": \"ON_DEMAND\",\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 9}],\"candidatesTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 2}],\"thoughtsTokenCount\": 26},\"modelVersion\": \"gemini-2.5-flash\",\"createTime\": \"2025-11-19T11:04:01.771732Z\",\"responseId\": \"IaQdaZSNL_rJptQP15PtmQI\"}\r\n\r\n"
     headers:
       Content-Type:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.190780917s
+    duration: 725.084625ms

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -37,18 +37,18 @@ interactions:
                       "location": "Florence,Italy"
                     }
                   },
-                  "thoughtSignature": "CqoCAePx/17/8Q8KZZMun2Jh8nZkCjH+u0w5GCukRd4aSFxz4PI0YFXB/lvok+cVkxL3Fv0ZrP45+NDbGDDT+4Gf7lNe21zmmu3xQWaXmR+/EaYhuaHiFj8icU2IzVr0ra22AJ2SQFJNMB5g5Uu1TSJsYD1IkrB4NnkyudqlctBE1400PoB9wOzxM5kNtWseTLDw0a3XPgh0sV82nkHOyt8ogFkqNwIovTrvqQ+9HB0bTGqYk5U2XikPiCRzjJ9/g3CRzydE5eg6oLn7E5qR4WD25xOcHBki9RxITWSglwG3tYYDI8s/UG7eNc6aDiX72LL8xwEQMwOT6DQUzQanoQC7nlIqnHXas2eiq1zCkS7O6HGfuuXtcz0euBKxndi/3ESgzzQGKY8rCa065Q=="
+                  "thoughtSignature": "Cq4CAePx/17lfvNzeD1UgoF8F6LxiSlPe5DfakwGl5buoL2pFazz+R2IYIE4Z5S71KgiO9VbYj/6bJK5FBJm21GoJref0w1PDVF+/93xJylQhMB6ID/QCMDzRQfucel2hkwuhQscItWpTbvh5+/0NGY3Uo/bO5F4FLgrwmCRfqXl3EIkavxBOfk8Z4/H7SCd7/fYFvvTgCu+7ycBYyLYhvzYyGxTH7Ups0SWNaYueSPusvRa3FG8Y4BQKENgTWVlReJyuCHjyFHSxCtuDL8xEGaBE24ltsiN6qXw5F4uZyZndKskWLtdedDAjxOW/2bAwb5l9UZhfSmBDV4mHEz8JeMoejbUdSnBZk+hoahL6NhTLyEB6tHsnFqHC5bI4FOJmCgH6LsguTmD2Fmjf+QE5yw="
                 }
               ]
             },
             "finishReason": "STOP",
-            "avgLogprobs": -1.3909281730651855
+            "avgLogprobs": -1.5359557151794434
           }
         ],
         "usageMetadata": {
           "promptTokenCount": 28,
           "candidatesTokenCount": 5,
-          "totalTokenCount": 96,
+          "totalTokenCount": 95,
           "trafficType": "ON_DEMAND",
           "promptTokensDetails": [
             {
@@ -62,32 +62,32 @@ interactions:
               "tokenCount": 5
             }
           ],
-          "thoughtsTokenCount": 63
+          "thoughtsTokenCount": 62
         },
         "modelVersion": "gemini-2.5-flash",
-        "createTime": "2025-11-03T19:52:51.509145Z",
-        "responseId": "EwgJadmJH9nEptQP9fCJyQY"
+        "createTime": "2025-11-19T11:04:02.601478Z",
+        "responseId": "IqQdaYbbJNmDptQP7qyZuAE"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.300916167s
+    duration: 882.023417ms
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 722
+    content_length: 1152
     host: us-east5-aiplatform.googleapis.com
     body: |
-      {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence,Italy"},"id":"1","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"1","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-flash/tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/multi_tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -34,11 +34,11 @@ interactions:
                   "functionCall": {
                     "name": "add",
                     "args": {
-                      "a": 2,
-                      "b": 3
+                      "b": 3,
+                      "a": 2
                     }
                   },
-                  "thoughtSignature": "CvQCAePx/14NVLo2aFENXN4pX/kIk4bZ+IIn9SuGEcAodTztmaxrh2n1PlLJ2/ahqKl6yf4+5ePV1sDDDPThVhBFNHHlpI4V64pGAIpFRkpvz/Xr9FNvIf/6q6sCfpEOv0YAZs0tbFI9uWJkENhgaTd7iJBKIxlKCyWxIMtIez4bV7QTk0I7sQriQojCQgN+IK0Gmuy5GI5OUSyrfjjz6FOnNc4fNAy+05QgKHKuCBCXSeu5pB15zKV5XQFC5JhwL46h0nvW+h21F8OzQnKLMyRZoZauHd7xJXStNn3Hs0KTSgeuDgzEG9KbMd+xUHQST0mI3Ve2Uj25yVmSp/na4/LhuVM/k7ad2IkmDfhPDbZKiF6rKb1ScPgAFp6FxOyLATAWg3kv1sVF+LdeeS6Of+4xJpS/gB/DGNhfvupvaIxo6N/UTKys0NdIIVUcQiVO8zsfQ9MlUhhzxN01qOVis1gnmEw1ou+S30yHwlSe2F15fX/5crr1"
+                  "thoughtSignature": "CukEAePx/15QJY0aW7MHjQUB+ypu3XOoG34numgtrxgqkyaR0fEZ6GidH4rlWetcv9trdN9jcp+uPvzLT6T24tPBx5XFJdZJn1ZtouXhZhcPHqTcl4a10cV5aL21bSWLls81NkGLTKqs1cAvaERIxIBcgAnw+IyilHbLMii3/axH5VzzpKkfcutk7k/1E0en0cp4HxV49f1jIGA3UrUWTEd4F9ntyCONE4gwOZSAmGJj/ZQv/O4dM2cWehyIgzGhlZ/Wg6cd9kQHU1FCgWBRSgAWmMKhq81PdeXwOBqPC25fyGjba2jRUN9+o1LalYwTK19XDy62YIaNa3XBkouKTyLisalJG7rs6Ch/5oBGWkOCgrIumkAFV1dkqiFpFEcZO++RLblx3yaTIltm0RAD2cohnwXe80RXek7V6Z07fIT9C7SLcFPyl9NIYTnWzT1AI0YLj3J7BK1BFzjRpVsuXE7tWp0uRzVdR2Up/iZYoMuFKJEDx3oqOBlEMFlKytCWU8+c9NgRKEkOlDzyf033XU0kth6YNlXab08xkxwPSVQps+pqyuIYaGvtZncB6lpnGznQ/x5x33Td6/0xgLH2A+QVNME/GVIEXIGOHvVQ09WTKRYAYLxWFY3U+ybXUh5gLaTa2bEuF588YQUL0fIka8KiMUbBvRi78QRWAEQNks/Z/zFNhmMzseiOSfAuhBZ3rlGsvSc676kIWziYC/kq710p5DQP0jTFbPV1InSnqToaXFY766vK6yjZJ8FVHlqRM+YK6g5pxpmJu05TS1V1xYCu+g2o7lQVtCZI1O0ELqnZkU8ESk2kxtw8qrU="
                 },
                 {
                   "functionCall": {
@@ -52,13 +52,13 @@ interactions:
               ]
             },
             "finishReason": "STOP",
-            "avgLogprobs": -0.84448261260986324
+            "avgLogprobs": -1.2367894172668457
           }
         ],
         "usageMetadata": {
           "promptTokenCount": 60,
           "candidatesTokenCount": 10,
-          "totalTokenCount": 163,
+          "totalTokenCount": 241,
           "trafficType": "ON_DEMAND",
           "promptTokensDetails": [
             {
@@ -72,32 +72,32 @@ interactions:
               "tokenCount": 10
             }
           ],
-          "thoughtsTokenCount": 93
+          "thoughtsTokenCount": 171
         },
         "modelVersion": "gemini-2.5-pro",
-        "createTime": "2025-11-03T19:53:25.624359Z",
-        "responseId": "NQgJaeeNJsKN0ekP4f-yiAg"
+        "createTime": "2025-11-19T11:04:37.627146Z",
+        "responseId": "RaQdacqjJrCI0ekP8tCGkAk"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.020324083s
+    duration: 3.051268875s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 1155
+    content_length: 2005
     host: us-east5-aiplatform.googleapis.com
     body: |

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/multi_tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/simple.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -31,18 +31,18 @@ interactions:
               "role": "model",
               "parts": [
                 {
-                  "text": "Of course! Here are the most common ways:\n\n*   **Oi** (This is the most common and informal, like \"hi\")\n*   **Olรก** (This is like \"hello\" and can be used in both formal and informal situations)\n\nYou can also combine them with \"how are you?\":\n\n*   **Oi, tudo bem?** (Hi, how are you?)"
+                  "text": "Of course! The most common ways to say \"hi\" in Portuguese are:\n\n*   **Olรก** (pronounced *oh-LAH*) - This is the direct translation of \"Hello\" and can be used in any situation, formal or informal.\n*   **Oi** (pronounced *OY*) - This is more casual, like \"Hi,\" and is what you'll hear most often in Brazil.\n\nYou can also combine them with \"How are you?\":\n\n*   **Oi, tudo bem?** (Hi, how are you?)"
                 }
               ]
             },
             "finishReason": "STOP",
-            "avgLogprobs": -1.3811639073383377
+            "avgLogprobs": -1.1641908612167626
           }
         ],
         "usageMetadata": {
           "promptTokenCount": 9,
-          "candidatesTokenCount": 83,
-          "totalTokenCount": 811,
+          "candidatesTokenCount": 114,
+          "totalTokenCount": 1001,
           "trafficType": "ON_DEMAND",
           "promptTokensDetails": [
             {
@@ -53,18 +53,18 @@ interactions:
           "candidatesTokensDetails": [
             {
               "modality": "TEXT",
-              "tokenCount": 83
+              "tokenCount": 114
             }
           ],
-          "thoughtsTokenCount": 719
+          "thoughtsTokenCount": 878
         },
         "modelVersion": "gemini-2.5-pro",
-        "createTime": "2025-11-03T19:52:59.997761Z",
-        "responseId": "GwgJaYHzPNnEptQP9fCJyQY"
+        "createTime": "2025-11-19T11:04:09.768454Z",
+        "responseId": "KaQdacbzLpTEptQP6pORgAo"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 9.378146209s
+    duration: 10.878821375s

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/simple_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,10 +25,10 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/tool.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -34,21 +34,21 @@ interactions:
                   "functionCall": {
                     "name": "weather",
                     "args": {
-                      "location": "Florence, Italy"
+                      "location": "Florence,Italy"
                     }
                   },
-                  "thoughtSignature": "CowEAePx/16C696DNWj4PuxMNS0zO6v+tdCJF1yJnn07eZuEPLPnvQ6p+oyw3hrynhBTBfnV4DLp94IKgX2qrApBR+CmZ3tqxhvwAG3luoBPWFlXTHfTGClpOrLI3Un76DOTzl3LCtmclum3o8kXE4V5PmRCeO2WXfLnwdy/hxs86ksrxyN6Y5edf1q/9tfu4PIJU+DpsJ7dNO6VZ5Lg0+FHxmVbXJq6Gpe/0FlwCXqolzyPeKMfhcTFUQtjr99pmS4rHWLDIF2ftwUBWzZembLj24OF+vWikxaWRcojZ5rh3KTluf+czMQWbGmmZUOsuRiOd84J/n1HDkqJ9RRGXSOrbiHpRasvNaMbLG6ufvkPSKm++DYe+tVmx40dwbr7hStfhAgKyNcBjRctIj9lHFlX1jczygVAxsv+6DK6UjEgZNWKtzkecZTzJWCzwLoQqpa56DD9eiMvq2Btfw47SxRkRTbQTOyJvPGVPBqaJksU2qOOprUdCqVCcxbJJfcFcVrTRiz1TNVTs89U1JiWm71RBJqXQBgLYYfryqSJ6E6lAlejy+7nc0q6YPleHC+4K3XyL2I5Q5HUwoEjEHnMCYAe+J68ztkjRablCHICIWJI08O+Ii9hgF9wIEkoZlA2A3deHYWfDh1mMjdZEZ2IibwroGaRaSq6AOJUyfWL9GgJb3/OnNWhpw6MlLV0Ol4="
+                  "thoughtSignature": "Cu4EAePx/14ljyE7z5hE6T9t7Cpe3xNFuB93gWa2T9NLfeE459sJp1VDMgbMx/6eM/sTYTOGkK/KU5UiVl+Kc5sQB3S6DYZfyn0K/yJmKxcXH27PwGXE7mBs4u45F3Tb+7mQHr0E5LroPO8LXN4J/UFb6g977nMHeJFXFxuQWU+tqtRy7gHRF+5ykdRmzHCkjHiCxuMO+KlJbU7PvX76b1seSG47Y+jaa/saPxnVSV1tLpTV+N6jujTYPcsgY/0+zzyERBve0PVpbGTlD2BBGOaOCG+6C0fQjS2kqgIceGWhzwfbAbl+LvaruGqmjx8lGLcXcOlbtKOlZtPQJg8gyIHGG1JB9Ufg5XD94MZ1ie4z+WCsfqtigiKKu6ndLSsycnntb1XLEhhAh+aoSab+MJf83SWnM7hvNCwLzIt7AFyWLKEDPW2sOYBtIyvR1RSCUEZqcbEwnsLdt4vzTVDsktoSpKAybdnN9MZ58z8AXsYhhumOCOxTn4mZvMXd6UBAmcOafK3awfh8CWrEc/+l1PBzsYWMepHXxEiYk53uXfz8eUTERXe9snKacpDiZTjiljFvtxMUSFXrcUjGL9GgH+2aQ9d4tunJ6sObwLodMJlYTrLNMIbEcKehmW4vEJ56ETT+6J9CfxB2SeQmfbLMsrUCmcY3yaP5qwNx6PQc/Wwi2lrYWec70EopPuOIT9/Yo/QcPTlqhsm7QrMLfflMtmGkqTUBUFOCOovA1ZzLhz+k+QsZNBjaGs62AXlgW5Y4779WMgoTOyFWdDAld6kVOOzHjHACVEfIdMlpSnbLQytA+Ri7GwoxxFv1TXlmYSXZXQ=="
                 }
               ]
             },
             "finishReason": "STOP",
-            "avgLogprobs": -0.95030345916748049
+            "avgLogprobs": -0.74591360092163084
           }
         ],
         "usageMetadata": {
           "promptTokenCount": 28,
           "candidatesTokenCount": 5,
-          "totalTokenCount": 155,
+          "totalTokenCount": 180,
           "trafficType": "ON_DEMAND",
           "promptTokensDetails": [
             {
@@ -62,32 +62,32 @@ interactions:
               "tokenCount": 5
             }
           ],
-          "thoughtsTokenCount": 122
+          "thoughtsTokenCount": 147
         },
         "modelVersion": "gemini-2.5-pro",
-        "createTime": "2025-11-03T19:53:18.064499Z",
-        "responseId": "LggJafP3A62G0ekP9tjQmAk"
+        "createTime": "2025-11-19T11:04:30.222222Z",
+        "responseId": "PqQdaY7IDaOA0ekP6aHL2Ac"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.300412708s
+    duration: 2.247443792s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 723
+    content_length: 1580
     host: us-east5-aiplatform.googleapis.com
     body: |
-      {"contents":[{"parts":[{"text":"What's the weather in Florence,Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence, Italy"},"id":"1","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"1","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}

providertests/testdata/TestGoogleCommon/vertex-gemini-2-5-pro/tool_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://us-east5-aiplatform.googleapis.com/v1beta1/projects/fantasy-playground-472418/locations/us-east5/publishers/google/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/complex_object.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.34.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -42,21 +42,21 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 38,
           "candidatesTokenCount": 41,
-          "totalTokenCount": 218,
+          "totalTokenCount": 230,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 38
             }
           ],
-          "thoughtsTokenCount": 139
+          "thoughtsTokenCount": 151
         },
         "modelVersion": "gemini-2.5-flash",
-        "responseId": "stsRaZqEJ9qO28oPiaHWwQ4"
+        "responseId": "yaIdaduGCfahxN8P3p7vwQc"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.554350125s
+    duration: 1.690439333s

providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/simple_object.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.34.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -30,7 +30,7 @@ interactions:
             "content": {
               "parts": [
                 {
-                  "text": "{\"age\": 30, \"city\": \"Paris\", \"name\": \"Alice\"}"
+                  "text": "{\n\"age\": 30,\n\"city\": \"Paris\",\n\"name\": \"Alice\"\n}"
                 }
               ],
               "role": "model"
@@ -41,7 +41,7 @@ interactions:
         ],
         "usageMetadata": {
           "promptTokenCount": 20,
-          "candidatesTokenCount": 19,
+          "candidatesTokenCount": 25,
           "totalTokenCount": 127,
           "promptTokensDetails": [
             {
@@ -49,14 +49,14 @@ interactions:
               "tokenCount": 20
             }
           ],
-          "thoughtsTokenCount": 88
+          "thoughtsTokenCount": 82
         },
         "modelVersion": "gemini-2.5-flash",
-        "responseId": "r9sRaffqJa-jvdIPwMT46A8"
+        "responseId": "xqIdab_LEP7hxN8PyeLZ6Ac"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 1.129109875s
+    duration: 1.1166025s

providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-flash/simple_object_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.34.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,10 +25,10 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1
-    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"{\\\"age\\\": 30, \\\"city\\\": \\\"Paris\\\", \\\"name\\\": \\\"Alice\\\"}\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 20,\"candidatesTokenCount\": 19,\"totalTokenCount\": 138,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 20}],\"thoughtsTokenCount\": 99},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"sNsRad21He_hxN8PlPed0Qs\"}\r\n\r\n"
+    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"{\\\"age\\\": 30, \\\"city\\\": \\\"Paris\\\", \\\"name\\\": \\\"Alice\\\"}\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 20,\"candidatesTokenCount\": 19,\"totalTokenCount\": 133,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 20}],\"thoughtsTokenCount\": 94},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"xqIdabK5MLfbvdIP6NWWuQk\"}\r\n\r\n"
     headers:
       Content-Type:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 1.556089083s
+    duration: 1.214252541s

providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/complex_object.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.34.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -30,7 +30,7 @@ interactions:
             "content": {
               "parts": [
                 {
-                  "text": "{\n  \"author\": {\n    \"name\": \"J.R.R. Tolkien\",\n    \"nationality\": \"British\"\n  },\n  \"genres\": [\n    \"Fantasy\",\n    \"Adventure\"\n  ],\n  \"published_year\": 1954,\n  \"title\": \"The Lord of the Rings\"\n}"
+                  "text": "{\n  \"author\": {\n    \"name\": \"J.R.R. Tolkien\",\n    \"nationality\": \"British\"\n  },\n  \"genres\": [\n    \"Fantasy\",\n    \"Adventure\",\n    \"High fantasy\"\n  ],\n  \"published_year\": 1954,\n  \"title\": \"The Lord of the Rings\"\n}"
                 }
               ],
               "role": "model"
@@ -41,22 +41,22 @@ interactions:
         ],
         "usageMetadata": {
           "promptTokenCount": 38,
-          "candidatesTokenCount": 78,
-          "totalTokenCount": 352,
+          "candidatesTokenCount": 84,
+          "totalTokenCount": 195,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 38
             }
           ],
-          "thoughtsTokenCount": 236
+          "thoughtsTokenCount": 73
         },
         "modelVersion": "gemini-2.5-pro",
-        "responseId": "v9sRad3jAc_7xs0P77zDwQE"
+        "responseId": "0qIdaciCFffPvdIPp-ycyAk"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 4.027611625s
+    duration: 2.813791334s

providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/simple_object.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.34.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -42,21 +42,21 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 20,
           "candidatesTokenCount": 28,
-          "totalTokenCount": 109,
+          "totalTokenCount": 112,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 20
             }
           ],
-          "thoughtsTokenCount": 61
+          "thoughtsTokenCount": 64
         },
         "modelVersion": "gemini-2.5-pro",
-        "responseId": "ttsRacXtC86PvdIP1Zjy8AE"
+        "responseId": "zKIdabLLD5GavdIPxvbZkQ8"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.077859292s
+    duration: 1.691421375s

providertests/testdata/TestGoogleObjectGeneration/gemini-2.5-pro/simple_object_streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.34.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,10 +25,10 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1
-    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"{\\n  \\\"age\\\": 30,\\n  \\\"city\\\":\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 20,\"candidatesTokenCount\": 15,\"totalTokenCount\": 189,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 20}],\"thoughtsTokenCount\": 154},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"udsRabusHJH_xN8PppGAiQ8\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \" \\\"Paris\\\",\\n  \\\"name\\\": \\\"Alice\\\"\\n}\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 20,\"candidatesTokenCount\": 28,\"totalTokenCount\": 202,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 20}],\"thoughtsTokenCount\": 154},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"udsRabusHJH_xN8PppGAiQ8\"}\r\n\r\n"
+    body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"{\\\"age\\\":30,\\\"city\\\":\\\"Paris\\\",\\\"name\\\":\\\"Alice\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 20,\"candidatesTokenCount\": 13,\"totalTokenCount\": 296,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 20}],\"thoughtsTokenCount\": 263},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"zaIdafuIG7KlxN8P_d3JsAg\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"\\\"}\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 20,\"candidatesTokenCount\": 14,\"totalTokenCount\": 297,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 20}],\"thoughtsTokenCount\": 263},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"zaIdafuIG7KlxN8P_d3JsAg\"}\r\n\r\n"
     headers:
       Content-Type:
       - text/event-stream
     status: 200 OK
     code: 200
-    duration: 4.791360833s
+    duration: 3.282518084s

providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/complex_object.yaml ๐Ÿ”—

@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 817
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Generate information about 'The Lord of the Rings' book by J.R.R. Tolkien, including genres like fantasy and adventure, and its publication year (1954)."}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000,"responseJsonSchema":{"properties":{"author":{"properties":{"name":{"description":"Author's name","type":"string"},"nationality":{"description":"Author's nationality","type":"string"}},"required":["name","nationality"],"type":"object"},"genres":{"description":"List of genres","items":{"type":"string"},"type":"array"},"published_year":{"description":"Year the book was published","type":"integer"},"title":{"description":"The book title","type":"string"}},"required":["title","author","genres","published_year"],"type":"object"},"responseMimeType":"application/json"}}
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "candidates": [
+          {
+            "content": {
+              "parts": [
+                {
+                  "text": "{\"author\": {\"name\": \"J.R.R. Tolkien\", \"nationality\": \"British\"}, \"genres\": [\"Fantasy\", \"Adventure\"], \"published_year\": 1954, \"title\": \"The Lord of the Rings\"}",

providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/complex_object_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,34 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 817
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Generate information about 'The Lord of the Rings' book by J.R.R. Tolkien, including genres like fantasy and adventure, and its publication year (1954)."}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000,"responseJsonSchema":{"properties":{"author":{"properties":{"name":{"description":"Author's name","type":"string"},"nationality":{"description":"Author's nationality","type":"string"}},"required":["name","nationality"],"type":"object"},"genres":{"description":"List of genres","items":{"type":"string"},"type":"array"},"published_year":{"description":"Year the book was published","type":"integer"},"title":{"description":"The book title","type":"string"}},"required":["title","author","genres","published_year"],"type":"object"},"responseMimeType":"application/json"}}
+    form:
+      alt:
+      - sse
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:streamGenerateContent?alt=sse
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1

providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/simple_object.yaml ๐Ÿ”—

@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 499
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Generate information about a person named Alice who is 30 years old and lives in Paris."}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000,"responseJsonSchema":{"properties":{"age":{"description":"The person's age","type":"integer"},"city":{"description":"The city where the person lives","type":"string"},"name":{"description":"The person's name","type":"string"}},"required":["name","age","city"],"type":"object"},"responseMimeType":"application/json"}}
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "candidates": [
+          {
+            "content": {
+              "parts": [
+                {
+                  "text": "{\n  \"age\": 30,\n  \"city\": \"Paris\",\n  \"name\": \"Alice\"\n}",
+                  "thoughtSignature": "EvQDCvEDAdHtim/cb1dWV6U1RcEIEknDD+tQ7jQ1cgOCFASlsLpobD0ejF9JGoUh6SZgWrjo54SGYwoEHM2DTRHS5UV44kUrVhIqPkXIsxhNZJyjplQsuL0+JJ3jriwV7dMSx3N6sFeTMzmFWrjzIXWsIG/S6yscqlMp9awgUisApHJXiQmTHsfCh4kxHdLsCuCl+WFrxYRTmGpsgNtgYhNFFw5xUAFtzSocFvlIepFglzOI4ccIrXEn32g2n0bgvq6CX4p2aBDRAcdRztxlblo0cUSRjDPQCsj4rRMpY2yeSI+PIXwsD+w8Vfy4sjGBafSh4bRnoQhc0U6SFRnEKaVxiZhoeWKhSc6usmjcuQDSR8mMFvVul8lsY3vPgn/KC/QCrlIwVYBsLMbhhsG9/LAeijGFzuYRX75D4pVvHxxWyEgdbvHrhT1wVmNJz01F+ZzwrtdWZjMiojhQAMWL8V9ujfQcrBG5JA2oRK/K18fW67seVo2BB3t0Us/jTTULNIqtp7mFz2JaK659n8YOe4IsMXHcQJmFxF793KNGdsQpkyACW9zENV+Idjh7zeABKrpXjmKgJ3wpdhQirzbwNuJG6gphCLDdUUeUUvjSQACjwvtJ0DWdLbJU65WEaBVTLf+hig3mEpwMANItd2caBaU7+fXFBH4="
+                }
+              ],
+              "role": "model"
+            },
+            "finishReason": "STOP",
+            "index": 0
+          }
+        ],
+        "usageMetadata": {
+          "promptTokenCount": 20,
+          "candidatesTokenCount": 28,
+          "totalTokenCount": 183,
+          "promptTokensDetails": [
+            {
+              "modality": "TEXT",
+              "tokenCount": 20
+            }
+          ],
+          "thoughtsTokenCount": 135
+        },
+        "modelVersion": "gemini-3-pro-preview",
+        "responseId": "s6Idaf6qKo-7vdIP1aSIwAk"
+      }
+    headers:
+      Content-Type:
+      - application/json; charset=UTF-8
+    status: 200 OK
+    code: 200
+    duration: 2.925005834s

providertests/testdata/TestGoogleObjectGeneration/gemini-3-pro-preview/simple_object_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,34 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 499
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"Generate information about a person named Alice who is 30 years old and lives in Paris."}],"role":"user"}],"generationConfig":{"maxOutputTokens":4000,"responseJsonSchema":{"properties":{"age":{"description":"The person's age","type":"integer"},"city":{"description":"The city where the person lives","type":"string"},"name":{"description":"The person's name","type":"string"}},"required":["name","age","city"],"type":"object"},"responseMimeType":"application/json"}}
+    form:
+      alt:
+      - sse
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:streamGenerateContent?alt=sse
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1

providertests/testdata/TestGoogleThinking/gemini-2.5-flash/thinking-streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleThinking/gemini-2.5-flash/thinking.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:generateContent
     method: POST
   response:
@@ -30,7 +30,7 @@ interactions:
             "content": {
               "parts": [
                 {
-                  "text": "**Processing a Weather Inquiry**\n\nOkay, so someone's asking for the weather. Specifically, they want to know the conditions in \"Florence, Italy\". Right, I get it. The `weather` tool is the perfect resource for this. I need to make sure I supply it with the correct `location` parameter. Let me see, that's straightforward enough: \"Florence, Italy\" needs to be passed directly to the `weather` tool as the `location`. That should be all it takes to get them the weather information they're looking for. Easy peasy.\n",
+                  "text": "**Weather Inquiry: Florence, Italy**\n\nOkay, so the user wants to know the weather. Seems straightforward enough. They've specified \"Florence, Italy,\" which is great, because I need a location to work with. Fortunately, I have a \"weather\" tool at my disposal, and it appears it's designed to take a `location` as input. Therefore, my next step is clear: I'll use the \"weather\" tool, feeding it \"Florence, Italy\" as the `location` parameter. That should give me the weather information the user is after.\n",
                   "thought": true
                 },
                 {
@@ -40,7 +40,7 @@ interactions:
                       "location": "Florence, Italy"
                     }
                   },
-                  "thoughtSignature": "CvYBAdHtim+r4pwvSzMD/Aa47oeAg6vLs//D5qB7buLxjadu+G2D8/R0OG5BbKoIl9STM65l/6ETZA5NxOxaKyEQmKQK9Wg319kKYLoWyA0vVr2lOa+yEDCNHam2FzEUpS/+5xL/AcTIuk7LGTdGdzf306tz8cOGvt5grdEIzl3G5xAaT/YIp/0mboeKkLS5gMRFibvX+q7/QuI49iNfzO6UPD3O4il9yeue8JsN1zjuVP7O0qbThAiMKQaFBJ/7XzRTwPY6mlKCaYS/SWB3vo3Vd/5eeUOZj1WQymKNt9WQHeGjOChZEBRdoyUTsIJNULD3rwuDgim+"
+                  "thoughtSignature": "CvYBAdHtim9qsdgUovUUbgAa9oML5LNXaG6UCnPcGzw1zOO0g3lKC3BMnvd5uNr1Dbu4iv/D1RFKhdpNvKq36C4OgfmARWRVkb6SCFEB2HliZgcq0eH24m1h1Wc3TgGsGNTm4Ppy61sth++CxfYNEZLnw+7xD/VhRMJn5a6/faKS4+MGzsH63NHx0DYdfpFpMytkoCa551Aunb8VOPy9KG2auvUT5KfWqf32mrjbeRhe3ngFDM7gBzYq/1AiVyQVluHSlvmHQ738klIpV7rZelCWzr+QgcPrc+T2MjHoXFtQQ5W24CHqHdW+ViYmcgpQT7QIM/1qCohh"
                 }
               ],
               "role": "model"
@@ -63,28 +63,28 @@ interactions:
           "thoughtsTokenCount": 51
         },
         "modelVersion": "gemini-2.5-flash",
-        "responseId": "UwgJaZTvAoidz7IPpOCG6QY"
+        "responseId": "o6Idaab7Kdj9xN8PsaeMoAU"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 2.398826334s
+    duration: 1.776984417s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 764
+    content_length: 1118
     host: generativelanguage.googleapis.com
     body: |
-      {"contents":[{"parts":[{"text":"What's the weather in Florence, Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence, Italy"},"id":"1","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"1","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"thinkingConfig":{"includeThoughts":true,"thinkingBudget":128}},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}

providertests/testdata/TestGoogleThinking/gemini-2.5-pro/thinking-streaming.yaml ๐Ÿ”—

@@ -17,7 +17,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse
     method: POST
   response:
@@ -25,22 +25,22 @@ interactions:
     proto_major: 2
     proto_minor: 0
     content_length: -1

providertests/testdata/TestGoogleThinking/gemini-2.5-pro/thinking.yaml ๐Ÿ”—

@@ -14,7 +14,7 @@ interactions:
       Content-Type:
       - application/json
       User-Agent:
-      - google-genai-sdk/1.33.0 gl-go/go1.25.0
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
     url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:generateContent
     method: POST
   response:
@@ -30,7 +30,7 @@ interactions:
             "content": {
               "parts": [
                 {
-                  "text": "**Thinking about Weather in Florence**\n\nOkay, so I'm trying to figure out the weather in Florence, Italy. That immediately makes me think of my `weather.get_weather` function. It's the perfect tool for this task. I know it's designed to give me the current conditions, and that's precisely what I'm after. Now, the `get_weather` function, like any good API call, needs specific parameters to work. In this case, I need to provide it with a `location`. Luckily, the user has given me exactly what I need: \"Florence, Italy\". That's perfect. Time to feed that into the function and get some weather data!\n",
+                  "text": "**Getting the Weather in Florence**\n\nOkay, so I see the user wants to know the weather in Florence, Italy. That's straightforward; that query directly corresponds to my `weather.get_weather` function.  It's pretty clear-cut, the function takes a `location` parameter, and in this case, that `location` is simply \"Florence, Italy\". Nothing complicated here, I can just set that parameter and move on.\n",
                   "thought": true
                 },
                 {
@@ -40,7 +40,7 @@ interactions:
                       "location": "Florence, Italy"
                     }
                   },
-                  "thoughtSignature": "CpUCAdHtim9UGVogupwPjEF0fV0+J6hlvZgmWKm2F8vODxdWDQn0sHeqH52T3A7eVFc3qq1mgbgKexwBwUY+LaJS6qmkEp/BQp+YhKn+KkADS5m9uSkVYtQHrSpr6w1PXOeZHKL9S4fda1Tw3wp486PgTNd0UI4P0XI0aJOWzT6QY4Zq54e7xt2Ju7+hocGRFBPS9nZbMajRNZW5rgelw9MWeLAed0Kl+7gxL931NKSOf7pN2VJR8QYo8V5bSy7NKSE12qFRb0HeHJW62RSO9CVDzjljtN8mFMgEdmAJOYZ902x19NzAZRTLs+/shIW1llcXc2kEllhblFKzRoKpFRI65l4iLIjS6HhG5zyqthmp9c6girWfRQ=="
+                  "thoughtSignature": "CpwCAdHtim+0FmI+WFq9+osYttd0V3wq5L6xpmfD+s3Xy+iz1L6F5MmUgDo3Vop462ydmq46DgqFSLYj33RAcxmXMnfJMnqdDbLkR00eT6FtPNKk1HxBIDg+d8nxH5LBRnQ4+/Py4nOa4oMiTfNaOuMpZZnIyJBRLFSOw0ZQftvmXoKCB/hZEW6dYve3wxGH+o4BZ/sdxO/3IdPhk2eRlcieDEVN/F4Fg1xAmdc/60inB/SsuSIMRRKHW/48nlCOwlJbbTRI9FIhtqLkDwjXMMWxwovwhstRb4+frvLsOIsBNQk+q5MByNI+waAOxhSVVvHChLh9vQTM4xZ0g14GGZ6SbLz+ujRWdPYjN1ON25uMX00ZTwM2S5K8IZUeJsM="
                 }
               ],
               "role": "model"
@@ -53,38 +53,38 @@ interactions:
         "usageMetadata": {
           "promptTokenCount": 54,
           "candidatesTokenCount": 15,
-          "totalTokenCount": 133,
+          "totalTokenCount": 135,
           "promptTokensDetails": [
             {
               "modality": "TEXT",
               "tokenCount": 54
             }
           ],
-          "thoughtsTokenCount": 64
+          "thoughtsTokenCount": 66
         },
         "modelVersion": "gemini-2.5-pro",
-        "responseId": "WggJafeCDKugz7IPnKO9kQk"
+        "responseId": "qqIdaZ73A_ClvdIPvJaP0Ak"
       }
     headers:
       Content-Type:
       - application/json; charset=UTF-8
     status: 200 OK
     code: 200
-    duration: 3.181730208s
+    duration: 3.080074125s
 - id: 1
   request:
     proto: HTTP/1.1
     proto_major: 1
     proto_minor: 1
-    content_length: 764
+    content_length: 1170
     host: generativelanguage.googleapis.com
     body: |
-      {"contents":[{"parts":[{"text":"What's the weather in Florence, Italy?"}],"role":"user"},{"parts":[{"functionCall":{"args":{"location":"Florence, Italy"},"id":"1","name":"weather"}}],"role":"model"},{"parts":[{"functionResponse":{"id":"1","name":"weather","response":{"result":"40 C"}}}],"role":"user"}],"generationConfig":{"thinkingConfig":{"includeThoughts":true,"thinkingBudget":128}},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}

providertests/testdata/TestGoogleThinking/gemini-3-pro-preview/thinking-streaming.yaml ๐Ÿ”—

@@ -0,0 +1,65 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 550
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"What's the weather in Florence, Italy?"}],"role":"user"}],"generationConfig":{"thinkingConfig":{"includeThoughts":true,"thinkingBudget":128}},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+    form:
+      alt:
+      - sse
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:streamGenerateContent?alt=sse
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1

providertests/testdata/TestGoogleThinking/gemini-3-pro-preview/thinking.yaml ๐Ÿ”—

@@ -0,0 +1,131 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 550
+    host: generativelanguage.googleapis.com
+    body: |
+      {"contents":[{"parts":[{"text":"What's the weather in Florence, Italy?"}],"role":"user"}],"generationConfig":{"thinkingConfig":{"includeThoughts":true,"thinkingBudget":128}},"systemInstruction":{"parts":[{"text":"You are a helpful assistant"}],"role":"user"},"toolConfig":{"functionCallingConfig":{"mode":"AUTO"}},"tools":[{"functionDeclarations":[{"description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"STRING"}},"required":["location"],"type":"OBJECT"}}]}]}
+    headers:
+      Content-Type:
+      - application/json
+      User-Agent:
+      - google-genai-sdk/1.34.0 gl-go/go1.25.4
+    url: https://generativelanguage.googleapis.com/v1beta/models/gemini-3-pro-preview:generateContent
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "candidates": [
+          {
+            "content": {
+              "parts": [
+                {
+                  "text": "**Breaking Down the Weather Query**\n\nOkay, here's what I'm processing. A user is asking about the weather in Florence, Italy. That's straightforward enough - they want current weather data. Looking at my toolset, I see the `weather` tool is perfect for this. It's explicitly designed for retrieving weather information based on a location. Easy. This is a classic example of intent recognition and tool selection. My next step would be to formulate the `weather` function call with the correct parameters, specifically the location, \"Florence, Italy\". I'm ready to get this user the information they need.\n\n\n",
+                  "thought": true
+                },
+                {
+                  "functionCall": {
+                    "name": "weather",
+                    "args": {
+                      "location": "Florence, Italy"
+                    }
+                  },
+                  "thoughtSignature": "EtMDCtADAdHtim/Qznjl3jYdbqtczyFkf1sarL7CYPmwkwMTU8qifm7AQe1i21NWqWvbSGT+KG/NkCBhcC0Zc8MusHqgFm2Iw+2TP0Ckp8nL5k+1G7jffxPRKsXcyq/6jvRtGvcxb199vZTNapt2/vYas7tEOZahNr/Xiuic7yVEcEEQD8Vdsp9qgRy8qu4RO1nc8Q5cnbd8fOEKfjusde2ehpTA47PUNhhIWlLBEGeMOowAoaEf9/W7cMxlg21omQYaYiIVgvI1qi2U/4nSOKDBlTA2N0LDuygPTtRsz2ZMwJGC8CIrrCW0apY1X2QcgO+s/9tNurJp/D9tiIFnwRXT8q7V90nAng9dSqHrChr2jvr4n3j5wgbvHnqLJouCKR8ME+leQZUHefdJyHeXNSjv9Rzs7cqiaUgWR7Rn11BQld3Q/myVqq7/r0LI/IchztYQVKDvE0XXbc0o8x4cfQTmtdlSwcAQxE5OG6sLNoRPAJmPfkwlppeHwNGG7ntkCKX/nG/o40w2OyFwk6WnkyNhnqTiA5knDyP51fnOiwKhFYxtDa7f2WdUPsILiJjqT7hDjtYTCnYvuWgTvqkaRtfLWES9QIVVZP63zK6PDFQLtLp8kd0="
+                }
+              ],
+              "role": "model"
+            },
+            "finishReason": "STOP",
+            "index": 0,
+            "finishMessage": "Model generated function call(s)."
+          }
+        ],
+        "usageMetadata": {
+          "promptTokenCount": 65,
+          "candidatesTokenCount": 16,
+          "totalTokenCount": 189,
+          "promptTokensDetails": [
+            {
+              "modality": "TEXT",
+              "tokenCount": 65
+            }
+          ],
+          "thoughtsTokenCount": 108
+        },
+        "modelVersion": "gemini-3-pro-preview",
+        "responseId": "mqIdabO3C5S3vdIPuPm34Ak"
+      }
+    headers:
+      Content-Type:
+      - application/json; charset=UTF-8
+    status: 200 OK
+    code: 200
+    duration: 3.163927334s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1414
+    host: generativelanguage.googleapis.com
+    body: |

providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/multi_tool.yaml ๐Ÿ”—

@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 857
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}],"usage":{"include":true}}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true

providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/multi_tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,81 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 894
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}],"usage":{"include":true},"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+

providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/simple.yaml ๐Ÿ”—

@@ -0,0 +1,33 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 202
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"usage":{"include":true}}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true

providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,44 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 256
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"usage":{"include":true},"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"gen-1763546708-WlSEiEPr7nn7Uso3yUg7","provider":"Google AI Studio","model":"google/gemini-3-pro-preview","object":"chat.completion.chunk","created":1763546708,"choices":[{"index":0,"delta":{"role":"assistant","content":"","reasoning":"**Considering the Greeting**\n\nI've narrowed it down to the essentials: \"Oi\" is the go-to informal greeting in Portuguese, and it's perfect for a casual \"hi.\" No need to overcomplicate things!\n\n\n","reasoning_details":[{"type":"reasoning.text","text":"**Considering the Greeting**\n\nI've narrowed it down to the essentials: \"Oi\" is the go-to informal greeting in Portuguese, and it's perfect for a casual \"hi.\" No need to overcomplicate things!\n\n\n","format":"google-gemini-v1","index":0}]},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1763546708-WlSEiEPr7nn7Uso3yUg7","provider":"Google AI Studio","model":"google/gemini-3-pro-preview","object":"chat.completion.chunk","created":1763546708,"choices":[{"index":0,"delta":{"role":"assistant","content":"","reasoning":"**Refining the Response**\n\nI've decided to include both options: \"Oi\" for \"Hi\" and \"Olรก\" for \"Hello.\" I've considered that context is key, but providing both will give a richer response, especially for learners. I've also verified the pronunciation for clarity.\n\n\n","reasoning_details":[{"type":"reasoning.text","text":"**Refining the Response**\n\nI've decided to include both options: \"Oi\" for \"Hi\" and \"Olรก\" for \"Hello.\" I've considered that context is key, but providing both will give a richer response, especially for learners. I've also verified the pronunciation for clarity.\n\n\n","format":"google-gemini-v1","index":0}]},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+
+      data: {"id":"gen-1763546708-WlSEiEPr7nn7Uso3yUg7","provider":"Google AI Studio","model":"google/gemini-3-pro-preview","object":"chat.completion.chunk","created":1763546708,"choices":[{"index":0,"delta":{"role":"assistant","content":"**Oi**\n\nYou can also say **Olรก** (which is more like \"Hello\").","reasoning":null,"reasoning_details":[]},"finish_reason":null,"native_finish_reason":null,"logprobs":null}]}
+

providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/tool.yaml ๐Ÿ”—

@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 494
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"usage":{"include":true}}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true

providertests/testdata/TestOpenRouterCommon/gemini-3-pro-preview/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,81 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 548
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"usage":{"include":true},"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+

providertests/testdata/TestOpenRouterThinking/gemini-3-pro-preview/thinking-streaming.yaml ๐Ÿ”—

@@ -0,0 +1,77 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 563
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"effort":"medium"},"usage":{"include":true},"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+

providertests/testdata/TestOpenRouterThinking/gemini-3-pro-preview/thinking.yaml ๐Ÿ”—

@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 509
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"effort":"medium"},"usage":{"include":true}}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.7.1
+    url: https://openrouter.ai/api/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true