feat: add openai reasponses api (#20)

Kujtim Hoxha created

* feat: add openai reasponses api

* fix(lint): some lint issues

Change summary

ai/agent.go                                                                                          |   13 
ai/agent_stream_test.go                                                                              |    2 
ai/util.go                                                                                           |   16 
cspell.json                                                                                          |    2 
examples/simple/main.go                                                                              |    2 
examples/stream/main.go                                                                              |    2 
examples/streaming-agent/main.go                                                                     |    2 
google/google.go                                                                                     |    2 
openai/openai.go                                                                                     |   17 
openai/openai_test.go                                                                                |   30 
openai/responses_language_model.go                                                                   | 1058 
openai/responses_options.go                                                                          |  128 
providertests/common_test.go                                                                         |   15 
providertests/google_test.go                                                                         |    4 
providertests/openai_responses_test.go                                                               |   85 
providertests/openai_test.go                                                                         |   45 
providertests/testdata/TestOpenAICommon/gpt-4o-mini/simple_streaming.yaml                            |   44 
providertests/testdata/TestOpenAICommon/gpt-4o/multi_tool_streaming.yaml                             |   67 
providertests/testdata/TestOpenAICommon/gpt-4o/tool_streaming.yaml                                   |  117 
providertests/testdata/TestOpenAICommon/gpt-5/tool_streaming.yaml                                    |  143 
providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/multi_tool.yaml                           |   10 
providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/multi_tool_streaming.yaml                 |   28 
providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/simple.yaml                               |   12 
providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/simple_streaming.yaml                     |   60 
providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/tool.yaml                                 |   22 
providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/tool_streaming.yaml                       |   58 
providertests/testdata/TestOpenAICommon/openai-gpt-4o/multi_tool.yaml                                |   12 
providertests/testdata/TestOpenAICommon/openai-gpt-4o/multi_tool_streaming.yaml                      |   67 
providertests/testdata/TestOpenAICommon/openai-gpt-4o/simple.yaml                                    |    8 
providertests/testdata/TestOpenAICommon/openai-gpt-4o/simple_streaming.yaml                          |   12 
providertests/testdata/TestOpenAICommon/openai-gpt-4o/tool.yaml                                      |   22 
providertests/testdata/TestOpenAICommon/openai-gpt-4o/tool_streaming.yaml                            |  117 
providertests/testdata/TestOpenAICommon/openai-gpt-5/multi_tool.yaml                                 |   16 
providertests/testdata/TestOpenAICommon/openai-gpt-5/multi_tool_streaming.yaml                       |   28 
providertests/testdata/TestOpenAICommon/openai-gpt-5/simple.yaml                                     |   12 
providertests/testdata/TestOpenAICommon/openai-gpt-5/simple_streaming.yaml                           |   12 
providertests/testdata/TestOpenAICommon/openai-gpt-5/tool.yaml                                       |   30 
providertests/testdata/TestOpenAICommon/openai-gpt-5/tool_streaming.yaml                             |  125 
providertests/testdata/TestOpenAICommon/openai-o4-mini/simple.yaml                                   |   68 
providertests/testdata/TestOpenAICommon/openai-o4-mini/simple_streaming.yaml                         |   44 
providertests/testdata/TestOpenAICommon/openai-o4-mini/tool.yaml                                     |  143 
providertests/testdata/TestOpenAICommon/openai-o4-mini/tool_streaming.yaml                           |  149 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/multi_tool.yaml                  |  156 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/multi_tool_streaming.yaml        |   27 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/simple.yaml                      |  100 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/simple_streaming.yaml            |   54 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/tool.yaml                        |  229 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/tool_streaming.yaml              |   66 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/multi_tool.yaml                       |  156 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/multi_tool_streaming.yaml             |   27 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/simple.yaml                           |  100 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/simple_streaming.yaml                 |   54 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/tool.yaml                             |  229 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/tool_streaming.yaml                   |   66 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/multi_tool.yaml                        |  161 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/multi_tool_streaming.yaml              |   27 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/simple.yaml                            |  105 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/simple_streaming.yaml                  |   60 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/tool.yaml                              |  239 
providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/tool_streaming.yaml                    |   72 
providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/simple.yaml                          |  105 
providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/simple_streaming.yaml                |   60 
providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/tool.yaml                            |  234 
providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/tool_streaming.yaml                  |   72 
providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-gpt-5/thinking-streaming.yaml   |   33 
providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-gpt-5/thinking.yaml             |   46 
providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-o4-mini/thinking-streaming.yaml |   33 
providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-o4-mini/thinking.yaml           |   46 
68 files changed, 4,821 insertions(+), 585 deletions(-)

Detailed changes

ai/agent.go ๐Ÿ”—

@@ -192,7 +192,7 @@ type (
 	OnTextEndFunc func(id string) error
 
 	// OnReasoningStartFunc is called when reasoning starts.
-	OnReasoningStartFunc func(id string) error
+	OnReasoningStartFunc func(id string, reasoning ReasoningContent) error
 
 	// OnReasoningDeltaFunc is called for reasoning deltas.
 	OnReasoningDeltaFunc func(id, text string) error
@@ -1135,9 +1135,13 @@ func (a *agent) processStepStream(ctx context.Context, stream StreamResponse, op
 			}
 
 		case StreamPartTypeReasoningStart:
-			activeReasoningContent[part.ID] = reasoningContent{content: ""}
+			activeReasoningContent[part.ID] = reasoningContent{content: "", options: part.ProviderMetadata}
 			if opts.OnReasoningStart != nil {
-				err := opts.OnReasoningStart(part.ID)
+				content := ReasoningContent{
+					Text:             "",
+					ProviderMetadata: part.ProviderMetadata,
+				}
+				err := opts.OnReasoningStart(part.ID, content)
 				if err != nil {
 					return StepResult{}, false, err
 				}
@@ -1158,6 +1162,9 @@ func (a *agent) processStepStream(ctx context.Context, stream StreamResponse, op
 
 		case StreamPartTypeReasoningEnd:
 			if active, exists := activeReasoningContent[part.ID]; exists {
+				if part.ProviderMetadata != nil {
+					active.options = part.ProviderMetadata
+				}
 				content := ReasoningContent{
 					Text:             active.content,
 					ProviderMetadata: active.options,

ai/agent_stream_test.go ๐Ÿ”—

@@ -157,7 +157,7 @@ func TestStreamingAgentCallbacks(t *testing.T) {
 			callbacks["OnTextEnd"] = true
 			return nil
 		},
-		OnReasoningStart: func(id string) error {
+		OnReasoningStart: func(id string, _ ReasoningContent) error {
 			callbacks["OnReasoningStart"] = true
 			return nil
 		},

ai/util.go ๐Ÿ”—

@@ -2,20 +2,8 @@ package ai
 
 import "github.com/go-viper/mapstructure/v2"
 
-func FloatOption(f float64) *float64 {
-	return &f
-}
-
-func BoolOption(b bool) *bool {
-	return &b
-}
-
-func StringOption(s string) *string {
-	return &s
-}
-
-func IntOption(i int64) *int64 {
-	return &i
+func Opt[T any](v T) *T {
+	return &v
 }
 
 func ParseOptions[T any](options map[string]any, m *T) error {

cspell.json ๐Ÿ”—

@@ -1 +1 @@
-{"flagWords":[],"language":"en","version":"0.2","words":["mapstructure","mapstructure","charmbracelet","providertests","joho","godotenv","stretchr","Quantizations","Logit","Probs","openrouter","openaisdk"]}
+{"flagWords":[],"words":["mapstructure","mapstructure","charmbracelet","providertests","joho","godotenv","stretchr","Quantizations","Logit","Probs","openrouter","openaisdk","Logprobs","Includable"],"version":"0.2","language":"en"}

examples/simple/main.go ๐Ÿ”—

@@ -21,7 +21,7 @@ func main() {
 		Prompt: ai.Prompt{
 			ai.NewUserMessage("Hello"),
 		},
-		Temperature: ai.FloatOption(0.7),
+		Temperature: ai.Opt(0.7),
 	})
 	if err != nil {
 		fmt.Println(err)

examples/stream/main.go ๐Ÿ”—

@@ -22,7 +22,7 @@ func main() {
 		Prompt: ai.Prompt{
 			ai.NewUserMessage("Whats the weather in pristina."),
 		},
-		Temperature: ai.FloatOption(0.7),
+		Temperature: ai.Opt(0.7),
 		Tools: []ai.Tool{
 			ai.FunctionTool{
 				Name:        "weather",

examples/streaming-agent/main.go ๐Ÿ”—

@@ -166,7 +166,7 @@ func main() {
 			fmt.Println()
 			return nil
 		},
-		OnReasoningStart: func(id string) error {
+		OnReasoningStart: func(id string, _ ai.ReasoningContent) error {
 			fmt.Print("๐Ÿค” Thinking: ")
 			return nil
 		},

google/google.go ๐Ÿ”—

@@ -190,7 +190,7 @@ func (a languageModel) prepareParams(call ai.Call) (*genai.GenerateContentConfig
 				Type:    ai.CallWarningTypeOther,
 				Message: "The 'thinking_budget' option can not be under 128 and will be set to 128 by default",
 			})
-			providerOptions.ThinkingConfig.ThinkingBudget = ai.IntOption(128)
+			providerOptions.ThinkingConfig.ThinkingBudget = ai.Opt(int64(128))
 		}
 	}
 

openai/openai.go ๐Ÿ”—

@@ -1,3 +1,4 @@
+// Package openai contains the openai provider
 package openai
 
 import (
@@ -24,6 +25,7 @@ type options struct {
 	organization         string
 	project              string
 	name                 string
+	useResponsesAPI      bool
 	headers              map[string]string
 	client               option.HTTPClient
 	sdkOptions           []option.RequestOption
@@ -108,6 +110,13 @@ func WithLanguageModelOptions(opts ...LanguageModelOption) Option {
 	}
 }
 
+// WithUseResponsesAPI makes it so the provider uses responses API for models that support it.
+func WithUseResponsesAPI() Option {
+	return func(o *options) {
+		o.useResponsesAPI = true
+	}
+}
+
 // LanguageModel implements ai.Provider.
 func (o *provider) LanguageModel(modelID string) (ai.LanguageModel, error) {
 	openaiClientOptions := make([]option.RequestOption, 0, 5+len(o.options.headers)+len(o.options.sdkOptions))
@@ -129,10 +138,16 @@ func (o *provider) LanguageModel(modelID string) (ai.LanguageModel, error) {
 
 	openaiClientOptions = append(openaiClientOptions, o.options.sdkOptions...)
 
+	client := openai.NewClient(openaiClientOptions...)
+
+	if o.options.useResponsesAPI && IsResponsesModel(modelID) {
+		return newResponsesLanguageModel(modelID, o.options.name, client), nil
+	}
+
 	return newLanguageModel(
 		modelID,
 		o.options.name,
-		openai.NewClient(openaiClientOptions...),
+		client,
 		o.options.languageModelOptions...,
 	), nil
 }

openai/openai_test.go ๐Ÿ”—

@@ -940,7 +940,7 @@ func TestDoGenerate(t *testing.T) {
 		result, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				LogProbs: ai.BoolOption(true),
+				LogProbs: ai.Opt(true),
 			}),
 		})
 
@@ -1057,8 +1057,8 @@ func TestDoGenerate(t *testing.T) {
 				LogitBias: map[string]int64{
 					"50256": -100,
 				},
-				ParallelToolCalls: ai.BoolOption(false),
-				User:              ai.StringOption("test-user-id"),
+				ParallelToolCalls: ai.Opt(false),
+				User:              ai.Opt("test-user-id"),
 			}),
 		})
 
@@ -1136,7 +1136,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				TextVerbosity: ai.StringOption("low"),
+				TextVerbosity: ai.Opt("low"),
 			}),
 		})
 
@@ -1528,7 +1528,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				MaxCompletionTokens: ai.IntOption(255),
+				MaxCompletionTokens: ai.Opt(int64(255)),
 			}),
 		})
 
@@ -1610,7 +1610,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				Store: ai.BoolOption(true),
+				Store: ai.Opt(true),
 			}),
 		})
 
@@ -1690,7 +1690,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				PromptCacheKey: ai.StringOption("test-cache-key-123"),
+				PromptCacheKey: ai.Opt("test-cache-key-123"),
 			}),
 		})
 
@@ -1728,7 +1728,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				SafetyIdentifier: ai.StringOption("test-safety-identifier-123"),
+				SafetyIdentifier: ai.Opt("test-safety-identifier-123"),
 			}),
 		})
 
@@ -1798,7 +1798,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				ServiceTier: ai.StringOption("flex"),
+				ServiceTier: ai.Opt("flex"),
 			}),
 		})
 
@@ -1834,7 +1834,7 @@ func TestDoGenerate(t *testing.T) {
 		result, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				ServiceTier: ai.StringOption("flex"),
+				ServiceTier: ai.Opt("flex"),
 			}),
 		})
 
@@ -1867,7 +1867,7 @@ func TestDoGenerate(t *testing.T) {
 		_, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				ServiceTier: ai.StringOption("priority"),
+				ServiceTier: ai.Opt("priority"),
 			}),
 		})
 
@@ -1903,7 +1903,7 @@ func TestDoGenerate(t *testing.T) {
 		result, err := model.Generate(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				ServiceTier: ai.StringOption("priority"),
+				ServiceTier: ai.Opt("priority"),
 			}),
 		})
 
@@ -2573,7 +2573,7 @@ func TestDoStream(t *testing.T) {
 		_, err := model.Stream(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				Store: ai.BoolOption(true),
+				Store: ai.Opt(true),
 			}),
 		})
 
@@ -2661,7 +2661,7 @@ func TestDoStream(t *testing.T) {
 		_, err := model.Stream(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				ServiceTier: ai.StringOption("flex"),
+				ServiceTier: ai.Opt("flex"),
 			}),
 		})
 
@@ -2703,7 +2703,7 @@ func TestDoStream(t *testing.T) {
 		_, err := model.Stream(context.Background(), ai.Call{
 			Prompt: testPrompt,
 			ProviderOptions: NewProviderOptions(&ProviderOptions{
-				ServiceTier: ai.StringOption("priority"),
+				ServiceTier: ai.Opt("priority"),
 			}),
 		})
 

openai/responses_language_model.go ๐Ÿ”—

@@ -0,0 +1,1058 @@
+package openai
+
+import (
+	"context"
+	"encoding/base64"
+	"encoding/json"
+	"errors"
+	"fmt"
+	"strings"
+
+	"github.com/charmbracelet/fantasy/ai"
+	"github.com/google/uuid"
+	"github.com/openai/openai-go/v2"
+	"github.com/openai/openai-go/v2/packages/param"
+	"github.com/openai/openai-go/v2/responses"
+	"github.com/openai/openai-go/v2/shared"
+)
+
+const topLogprobsMax = 20
+
+type responsesLanguageModel struct {
+	provider string
+	modelID  string
+	client   openai.Client
+}
+
+// newResponsesLanguageModel implements a responses api model
+// INFO: (kujtim) currently we do not support stored parameter we default it to false.
+func newResponsesLanguageModel(modelID string, provider string, client openai.Client) responsesLanguageModel {
+	return responsesLanguageModel{
+		modelID:  modelID,
+		provider: provider,
+		client:   client,
+	}
+}
+
+func (o responsesLanguageModel) Model() string {
+	return o.modelID
+}
+
+func (o responsesLanguageModel) Provider() string {
+	return o.provider
+}
+
+type responsesModelConfig struct {
+	isReasoningModel           bool
+	systemMessageMode          string
+	requiredAutoTruncation     bool
+	supportsFlexProcessing     bool
+	supportsPriorityProcessing bool
+}
+
+func getResponsesModelConfig(modelID string) responsesModelConfig {
+	supportsFlexProcessing := strings.HasPrefix(modelID, "o3") ||
+		strings.HasPrefix(modelID, "o4-mini") ||
+		(strings.HasPrefix(modelID, "gpt-5") && !strings.HasPrefix(modelID, "gpt-5-chat"))
+
+	supportsPriorityProcessing := strings.HasPrefix(modelID, "gpt-4") ||
+		strings.HasPrefix(modelID, "gpt-5-mini") ||
+		(strings.HasPrefix(modelID, "gpt-5") &&
+			!strings.HasPrefix(modelID, "gpt-5-nano") &&
+			!strings.HasPrefix(modelID, "gpt-5-chat")) ||
+		strings.HasPrefix(modelID, "o3") ||
+		strings.HasPrefix(modelID, "o4-mini")
+
+	defaults := responsesModelConfig{
+		requiredAutoTruncation:     false,
+		systemMessageMode:          "system",
+		supportsFlexProcessing:     supportsFlexProcessing,
+		supportsPriorityProcessing: supportsPriorityProcessing,
+	}
+
+	if strings.HasPrefix(modelID, "gpt-5-chat") {
+		return responsesModelConfig{
+			isReasoningModel:           false,
+			systemMessageMode:          defaults.systemMessageMode,
+			requiredAutoTruncation:     defaults.requiredAutoTruncation,
+			supportsFlexProcessing:     defaults.supportsFlexProcessing,
+			supportsPriorityProcessing: defaults.supportsPriorityProcessing,
+		}
+	}
+
+	if strings.HasPrefix(modelID, "o") ||
+		strings.HasPrefix(modelID, "gpt-5") ||
+		strings.HasPrefix(modelID, "codex-") ||
+		strings.HasPrefix(modelID, "computer-use") {
+		if strings.HasPrefix(modelID, "o1-mini") || strings.HasPrefix(modelID, "o1-preview") {
+			return responsesModelConfig{
+				isReasoningModel:           true,
+				systemMessageMode:          "remove",
+				requiredAutoTruncation:     defaults.requiredAutoTruncation,
+				supportsFlexProcessing:     defaults.supportsFlexProcessing,
+				supportsPriorityProcessing: defaults.supportsPriorityProcessing,
+			}
+		}
+
+		return responsesModelConfig{
+			isReasoningModel:           true,
+			systemMessageMode:          "developer",
+			requiredAutoTruncation:     defaults.requiredAutoTruncation,
+			supportsFlexProcessing:     defaults.supportsFlexProcessing,
+			supportsPriorityProcessing: defaults.supportsPriorityProcessing,
+		}
+	}
+
+	return responsesModelConfig{
+		isReasoningModel:           false,
+		systemMessageMode:          defaults.systemMessageMode,
+		requiredAutoTruncation:     defaults.requiredAutoTruncation,
+		supportsFlexProcessing:     defaults.supportsFlexProcessing,
+		supportsPriorityProcessing: defaults.supportsPriorityProcessing,
+	}
+}
+
+func (o responsesLanguageModel) prepareParams(call ai.Call) (*responses.ResponseNewParams, []ai.CallWarning) {
+	var warnings []ai.CallWarning
+	params := &responses.ResponseNewParams{
+		Store: param.NewOpt(false),
+	}
+
+	modelConfig := getResponsesModelConfig(o.modelID)
+
+	if call.TopK != nil {
+		warnings = append(warnings, ai.CallWarning{
+			Type:    ai.CallWarningTypeUnsupportedSetting,
+			Setting: "topK",
+		})
+	}
+
+	if call.PresencePenalty != nil {
+		warnings = append(warnings, ai.CallWarning{
+			Type:    ai.CallWarningTypeUnsupportedSetting,
+			Setting: "presencePenalty",
+		})
+	}
+
+	if call.FrequencyPenalty != nil {
+		warnings = append(warnings, ai.CallWarning{
+			Type:    ai.CallWarningTypeUnsupportedSetting,
+			Setting: "frequencyPenalty",
+		})
+	}
+
+	var openaiOptions *ResponsesProviderOptions
+	if opts, ok := call.ProviderOptions[Name]; ok {
+		if typedOpts, ok := opts.(*ResponsesProviderOptions); ok {
+			openaiOptions = typedOpts
+		}
+	}
+
+	input, inputWarnings := toResponsesPrompt(call.Prompt, modelConfig.systemMessageMode)
+	warnings = append(warnings, inputWarnings...)
+
+	var include []IncludeType
+
+	addInclude := func(key IncludeType) {
+		include = append(include, key)
+	}
+
+	topLogprobs := 0
+	if openaiOptions != nil && openaiOptions.Logprobs != nil {
+		switch v := openaiOptions.Logprobs.(type) {
+		case bool:
+			if v {
+				topLogprobs = topLogprobsMax
+			}
+		case float64:
+			topLogprobs = int(v)
+		case int:
+			topLogprobs = v
+		}
+	}
+
+	if topLogprobs > 0 {
+		addInclude(IncludeMessageOutputTextLogprobs)
+	}
+
+	params.Model = o.modelID
+	params.Input = responses.ResponseNewParamsInputUnion{
+		OfInputItemList: input,
+	}
+
+	if call.Temperature != nil {
+		params.Temperature = param.NewOpt(*call.Temperature)
+	}
+	if call.TopP != nil {
+		params.TopP = param.NewOpt(*call.TopP)
+	}
+	if call.MaxOutputTokens != nil {
+		params.MaxOutputTokens = param.NewOpt(*call.MaxOutputTokens)
+	}
+
+	if openaiOptions != nil {
+		if openaiOptions.MaxToolCalls != nil {
+			params.MaxToolCalls = param.NewOpt(*openaiOptions.MaxToolCalls)
+		}
+		if openaiOptions.Metadata != nil {
+			metadata := make(shared.Metadata)
+			for k, v := range openaiOptions.Metadata {
+				if str, ok := v.(string); ok {
+					metadata[k] = str
+				}
+			}
+			params.Metadata = metadata
+		}
+		if openaiOptions.ParallelToolCalls != nil {
+			params.ParallelToolCalls = param.NewOpt(*openaiOptions.ParallelToolCalls)
+		}
+		if openaiOptions.User != nil {
+			params.User = param.NewOpt(*openaiOptions.User)
+		}
+		if openaiOptions.Instructions != nil {
+			params.Instructions = param.NewOpt(*openaiOptions.Instructions)
+		}
+		if openaiOptions.ServiceTier != nil {
+			params.ServiceTier = responses.ResponseNewParamsServiceTier(*openaiOptions.ServiceTier)
+		}
+		if openaiOptions.PromptCacheKey != nil {
+			params.PromptCacheKey = param.NewOpt(*openaiOptions.PromptCacheKey)
+		}
+		if openaiOptions.SafetyIdentifier != nil {
+			params.SafetyIdentifier = param.NewOpt(*openaiOptions.SafetyIdentifier)
+		}
+		if topLogprobs > 0 {
+			params.TopLogprobs = param.NewOpt(int64(topLogprobs))
+		}
+
+		if len(openaiOptions.Include) > 0 {
+			include = append(include, openaiOptions.Include...)
+		}
+
+		if modelConfig.isReasoningModel && (openaiOptions.ReasoningEffort != nil || openaiOptions.ReasoningSummary != nil) {
+			reasoning := shared.ReasoningParam{}
+			if openaiOptions.ReasoningEffort != nil {
+				reasoning.Effort = shared.ReasoningEffort(*openaiOptions.ReasoningEffort)
+			}
+			if openaiOptions.ReasoningSummary != nil {
+				reasoning.Summary = shared.ReasoningSummary(*openaiOptions.ReasoningSummary)
+			}
+			params.Reasoning = reasoning
+		}
+	}
+
+	if modelConfig.requiredAutoTruncation {
+		params.Truncation = responses.ResponseNewParamsTruncationAuto
+	}
+
+	if len(include) > 0 {
+		includeParams := make([]responses.ResponseIncludable, len(include))
+		for i, inc := range include {
+			includeParams[i] = responses.ResponseIncludable(string(inc))
+		}
+		params.Include = includeParams
+	}
+
+	if modelConfig.isReasoningModel {
+		if call.Temperature != nil {
+			params.Temperature = param.Opt[float64]{}
+			warnings = append(warnings, ai.CallWarning{
+				Type:    ai.CallWarningTypeUnsupportedSetting,
+				Setting: "temperature",
+				Details: "temperature is not supported for reasoning models",
+			})
+		}
+
+		if call.TopP != nil {
+			params.TopP = param.Opt[float64]{}
+			warnings = append(warnings, ai.CallWarning{
+				Type:    ai.CallWarningTypeUnsupportedSetting,
+				Setting: "topP",
+				Details: "topP is not supported for reasoning models",
+			})
+		}
+	} else {
+		if openaiOptions != nil {
+			if openaiOptions.ReasoningEffort != nil {
+				warnings = append(warnings, ai.CallWarning{
+					Type:    ai.CallWarningTypeUnsupportedSetting,
+					Setting: "reasoningEffort",
+					Details: "reasoningEffort is not supported for non-reasoning models",
+				})
+			}
+
+			if openaiOptions.ReasoningSummary != nil {
+				warnings = append(warnings, ai.CallWarning{
+					Type:    ai.CallWarningTypeUnsupportedSetting,
+					Setting: "reasoningSummary",
+					Details: "reasoningSummary is not supported for non-reasoning models",
+				})
+			}
+		}
+	}
+
+	if openaiOptions != nil && openaiOptions.ServiceTier != nil {
+		if *openaiOptions.ServiceTier == ServiceTierFlex && !modelConfig.supportsFlexProcessing {
+			warnings = append(warnings, ai.CallWarning{
+				Type:    ai.CallWarningTypeUnsupportedSetting,
+				Setting: "serviceTier",
+				Details: "flex processing is only available for o3, o4-mini, and gpt-5 models",
+			})
+			params.ServiceTier = ""
+		}
+
+		if *openaiOptions.ServiceTier == ServiceTierPriority && !modelConfig.supportsPriorityProcessing {
+			warnings = append(warnings, ai.CallWarning{
+				Type:    ai.CallWarningTypeUnsupportedSetting,
+				Setting: "serviceTier",
+				Details: "priority processing is only available for supported models (gpt-4, gpt-5, gpt-5-mini, o3, o4-mini) and requires Enterprise access. gpt-5-nano is not supported",
+			})
+			params.ServiceTier = ""
+		}
+	}
+
+	tools, toolChoice, toolWarnings := toResponsesTools(call.Tools, call.ToolChoice, openaiOptions)
+	warnings = append(warnings, toolWarnings...)
+
+	if len(tools) > 0 {
+		params.Tools = tools
+		params.ToolChoice = toolChoice
+	}
+
+	return params, warnings
+}
+
+func toResponsesPrompt(prompt ai.Prompt, systemMessageMode string) (responses.ResponseInputParam, []ai.CallWarning) {
+	var input responses.ResponseInputParam
+	var warnings []ai.CallWarning
+
+	for _, msg := range prompt {
+		switch msg.Role {
+		case ai.MessageRoleSystem:
+			var systemText string
+			for _, c := range msg.Content {
+				if c.GetType() != ai.ContentTypeText {
+					warnings = append(warnings, ai.CallWarning{
+						Type:    ai.CallWarningTypeOther,
+						Message: "system prompt can only have text content",
+					})
+					continue
+				}
+				textPart, ok := ai.AsContentType[ai.TextPart](c)
+				if !ok {
+					warnings = append(warnings, ai.CallWarning{
+						Type:    ai.CallWarningTypeOther,
+						Message: "system prompt text part does not have the right type",
+					})
+					continue
+				}
+				if strings.TrimSpace(textPart.Text) != "" {
+					systemText += textPart.Text
+				}
+			}
+
+			if systemText == "" {
+				warnings = append(warnings, ai.CallWarning{
+					Type:    ai.CallWarningTypeOther,
+					Message: "system prompt has no text parts",
+				})
+				continue
+			}
+
+			switch systemMessageMode {
+			case "system":
+				input = append(input, responses.ResponseInputItemParamOfMessage(systemText, responses.EasyInputMessageRoleSystem))
+			case "developer":
+				input = append(input, responses.ResponseInputItemParamOfMessage(systemText, responses.EasyInputMessageRoleDeveloper))
+			case "remove":
+				warnings = append(warnings, ai.CallWarning{
+					Type:    ai.CallWarningTypeOther,
+					Message: "system messages are removed for this model",
+				})
+			}
+
+		case ai.MessageRoleUser:
+			var contentParts responses.ResponseInputMessageContentListParam
+			for i, c := range msg.Content {
+				switch c.GetType() {
+				case ai.ContentTypeText:
+					textPart, ok := ai.AsContentType[ai.TextPart](c)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "user message text part does not have the right type",
+						})
+						continue
+					}
+					contentParts = append(contentParts, responses.ResponseInputContentUnionParam{
+						OfInputText: &responses.ResponseInputTextParam{
+							Type: "input_text",
+							Text: textPart.Text,
+						},
+					})
+
+				case ai.ContentTypeFile:
+					filePart, ok := ai.AsContentType[ai.FilePart](c)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "user message file part does not have the right type",
+						})
+						continue
+					}
+
+					if strings.HasPrefix(filePart.MediaType, "image/") {
+						base64Encoded := base64.StdEncoding.EncodeToString(filePart.Data)
+						imageURL := fmt.Sprintf("data:%s;base64,%s", filePart.MediaType, base64Encoded)
+						contentParts = append(contentParts, responses.ResponseInputContentUnionParam{
+							OfInputImage: &responses.ResponseInputImageParam{
+								Type:     "input_image",
+								ImageURL: param.NewOpt(imageURL),
+							},
+						})
+					} else if filePart.MediaType == "application/pdf" {
+						base64Encoded := base64.StdEncoding.EncodeToString(filePart.Data)
+						fileData := fmt.Sprintf("data:application/pdf;base64,%s", base64Encoded)
+						filename := filePart.Filename
+						if filename == "" {
+							filename = fmt.Sprintf("part-%d.pdf", i)
+						}
+						contentParts = append(contentParts, responses.ResponseInputContentUnionParam{
+							OfInputFile: &responses.ResponseInputFileParam{
+								Type:     "input_file",
+								Filename: param.NewOpt(filename),
+								FileData: param.NewOpt(fileData),
+							},
+						})
+					} else {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: fmt.Sprintf("file part media type %s not supported", filePart.MediaType),
+						})
+					}
+				}
+			}
+
+			input = append(input, responses.ResponseInputItemParamOfMessage(contentParts, responses.EasyInputMessageRoleUser))
+
+		case ai.MessageRoleAssistant:
+			for _, c := range msg.Content {
+				switch c.GetType() {
+				case ai.ContentTypeText:
+					textPart, ok := ai.AsContentType[ai.TextPart](c)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "assistant message text part does not have the right type",
+						})
+						continue
+					}
+					input = append(input, responses.ResponseInputItemParamOfMessage(textPart.Text, responses.EasyInputMessageRoleAssistant))
+
+				case ai.ContentTypeToolCall:
+					toolCallPart, ok := ai.AsContentType[ai.ToolCallPart](c)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "assistant message tool call part does not have the right type",
+						})
+						continue
+					}
+
+					if toolCallPart.ProviderExecuted {
+						continue
+					}
+
+					inputJSON, err := json.Marshal(toolCallPart.Input)
+					if err != nil {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: fmt.Sprintf("failed to marshal tool call input: %v", err),
+						})
+						continue
+					}
+
+					input = append(input, responses.ResponseInputItemParamOfFunctionCall(string(inputJSON), toolCallPart.ToolCallID, toolCallPart.ToolName))
+				case ai.ContentTypeReasoning:
+					reasoningMetadata := getReasoningMetadata(c.Options())
+					if reasoningMetadata == nil || reasoningMetadata.ItemID == "" {
+						continue
+					}
+					if len(reasoningMetadata.Summary) == 0 && reasoningMetadata.EncryptedContent == nil {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "assistant message reasoning part does is empty",
+						})
+						continue
+					}
+					// we want to always send an empty array
+					summary := []responses.ResponseReasoningItemSummaryParam{}
+					for _, s := range reasoningMetadata.Summary {
+						summary = append(summary, responses.ResponseReasoningItemSummaryParam{
+							Type: "summary_text",
+							Text: s,
+						})
+					}
+					reasoning := &responses.ResponseReasoningItemParam{
+						ID:      reasoningMetadata.ItemID,
+						Summary: summary,
+					}
+					if reasoningMetadata.EncryptedContent != nil {
+						reasoning.EncryptedContent = param.NewOpt(*reasoningMetadata.EncryptedContent)
+					}
+					input = append(input, responses.ResponseInputItemUnionParam{
+						OfReasoning: reasoning,
+					})
+				}
+			}
+
+		case ai.MessageRoleTool:
+			for _, c := range msg.Content {
+				if c.GetType() != ai.ContentTypeToolResult {
+					warnings = append(warnings, ai.CallWarning{
+						Type:    ai.CallWarningTypeOther,
+						Message: "tool message can only have tool result content",
+					})
+					continue
+				}
+
+				toolResultPart, ok := ai.AsContentType[ai.ToolResultPart](c)
+				if !ok {
+					warnings = append(warnings, ai.CallWarning{
+						Type:    ai.CallWarningTypeOther,
+						Message: "tool message result part does not have the right type",
+					})
+					continue
+				}
+
+				var outputStr string
+				switch toolResultPart.Output.GetType() {
+				case ai.ToolResultContentTypeText:
+					output, ok := ai.AsToolResultOutputType[ai.ToolResultOutputContentText](toolResultPart.Output)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "tool result output does not have the right type",
+						})
+						continue
+					}
+					outputStr = output.Text
+				case ai.ToolResultContentTypeError:
+					output, ok := ai.AsToolResultOutputType[ai.ToolResultOutputContentError](toolResultPart.Output)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "tool result output does not have the right type",
+						})
+						continue
+					}
+					outputStr = output.Error.Error()
+				case ai.ToolResultContentTypeMedia:
+					output, ok := ai.AsToolResultOutputType[ai.ToolResultOutputContentMedia](toolResultPart.Output)
+					if !ok {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: "tool result output does not have the right type",
+						})
+						continue
+					}
+					// For media content, encode as JSON with data and media type
+					mediaContent := map[string]string{
+						"data":       output.Data,
+						"media_type": output.MediaType,
+					}
+					jsonBytes, err := json.Marshal(mediaContent)
+					if err != nil {
+						warnings = append(warnings, ai.CallWarning{
+							Type:    ai.CallWarningTypeOther,
+							Message: fmt.Sprintf("failed to marshal tool result: %v", err),
+						})
+						continue
+					}
+					outputStr = string(jsonBytes)
+				}
+
+				input = append(input, responses.ResponseInputItemParamOfFunctionCallOutput(toolResultPart.ToolCallID, outputStr))
+			}
+		}
+	}
+
+	return input, warnings
+}
+
+func toResponsesTools(tools []ai.Tool, toolChoice *ai.ToolChoice, options *ResponsesProviderOptions) ([]responses.ToolUnionParam, responses.ResponseNewParamsToolChoiceUnion, []ai.CallWarning) {
+	warnings := make([]ai.CallWarning, 0)
+	var openaiTools []responses.ToolUnionParam
+
+	if len(tools) == 0 {
+		return nil, responses.ResponseNewParamsToolChoiceUnion{}, nil
+	}
+
+	strictJSONSchema := false
+	if options != nil && options.StrictJSONSchema != nil {
+		strictJSONSchema = *options.StrictJSONSchema
+	}
+
+	for _, tool := range tools {
+		if tool.GetType() == ai.ToolTypeFunction {
+			ft, ok := tool.(ai.FunctionTool)
+			if !ok {
+				continue
+			}
+			openaiTools = append(openaiTools, responses.ToolUnionParam{
+				OfFunction: &responses.FunctionToolParam{
+					Name:        ft.Name,
+					Description: param.NewOpt(ft.Description),
+					Parameters:  ft.InputSchema,
+					Strict:      param.NewOpt(strictJSONSchema),
+					Type:        "function",
+				},
+			})
+			continue
+		}
+
+		warnings = append(warnings, ai.CallWarning{
+			Type:    ai.CallWarningTypeUnsupportedTool,
+			Tool:    tool,
+			Message: "tool is not supported",
+		})
+	}
+
+	if toolChoice == nil {
+		return openaiTools, responses.ResponseNewParamsToolChoiceUnion{}, warnings
+	}
+
+	var openaiToolChoice responses.ResponseNewParamsToolChoiceUnion
+
+	switch *toolChoice {
+	case ai.ToolChoiceAuto:
+		openaiToolChoice = responses.ResponseNewParamsToolChoiceUnion{
+			OfToolChoiceMode: param.NewOpt(responses.ToolChoiceOptionsAuto),
+		}
+	case ai.ToolChoiceNone:
+		openaiToolChoice = responses.ResponseNewParamsToolChoiceUnion{
+			OfToolChoiceMode: param.NewOpt(responses.ToolChoiceOptionsNone),
+		}
+	case ai.ToolChoiceRequired:
+		openaiToolChoice = responses.ResponseNewParamsToolChoiceUnion{
+			OfToolChoiceMode: param.NewOpt(responses.ToolChoiceOptionsRequired),
+		}
+	default:
+		openaiToolChoice = responses.ResponseNewParamsToolChoiceUnion{
+			OfFunctionTool: &responses.ToolChoiceFunctionParam{
+				Type: "function",
+				Name: string(*toolChoice),
+			},
+		}
+	}
+
+	return openaiTools, openaiToolChoice, warnings
+}
+
+func (o responsesLanguageModel) handleError(err error) error {
+	var apiErr *openai.Error
+	if errors.As(err, &apiErr) {
+		requestDump := apiErr.DumpRequest(true)
+		responseDump := apiErr.DumpResponse(true)
+		headers := map[string]string{}
+		for k, h := range apiErr.Response.Header {
+			v := h[len(h)-1]
+			headers[strings.ToLower(k)] = v
+		}
+		return ai.NewAPICallError(
+			apiErr.Message,
+			apiErr.Request.URL.String(),
+			string(requestDump),
+			apiErr.StatusCode,
+			headers,
+			string(responseDump),
+			apiErr,
+			false,
+		)
+	}
+	return err
+}
+
+func (o responsesLanguageModel) Generate(ctx context.Context, call ai.Call) (*ai.Response, error) {
+	params, warnings := o.prepareParams(call)
+	response, err := o.client.Responses.New(ctx, *params)
+	if err != nil {
+		return nil, o.handleError(err)
+	}
+
+	if response.Error.Message != "" {
+		return nil, o.handleError(fmt.Errorf("response error: %s (code: %s)", response.Error.Message, response.Error.Code))
+	}
+
+	var content []ai.Content
+	hasFunctionCall := false
+
+	for _, outputItem := range response.Output {
+		switch outputItem.Type {
+		case "message":
+			for _, contentPart := range outputItem.Content {
+				if contentPart.Type == "output_text" {
+					content = append(content, ai.TextContent{
+						Text: contentPart.Text,
+					})
+
+					for _, annotation := range contentPart.Annotations {
+						switch annotation.Type {
+						case "url_citation":
+							content = append(content, ai.SourceContent{
+								SourceType: ai.SourceTypeURL,
+								ID:         uuid.NewString(),
+								URL:        annotation.URL,
+								Title:      annotation.Title,
+							})
+						case "file_citation":
+							title := "Document"
+							if annotation.Filename != "" {
+								title = annotation.Filename
+							}
+							filename := annotation.Filename
+							if filename == "" {
+								filename = annotation.FileID
+							}
+							content = append(content, ai.SourceContent{
+								SourceType: ai.SourceTypeDocument,
+								ID:         uuid.NewString(),
+								MediaType:  "text/plain",
+								Title:      title,
+								Filename:   filename,
+							})
+						}
+					}
+				}
+			}
+
+		case "function_call":
+			hasFunctionCall = true
+			content = append(content, ai.ToolCallContent{
+				ProviderExecuted: false,
+				ToolCallID:       outputItem.CallID,
+				ToolName:         outputItem.Name,
+				Input:            outputItem.Arguments,
+			})
+
+		case "reasoning":
+			metadata := &ResponsesReasoningMetadata{
+				ItemID: outputItem.ID,
+			}
+			if outputItem.EncryptedContent != "" {
+				metadata.EncryptedContent = &outputItem.EncryptedContent
+			}
+
+			if len(outputItem.Summary) == 0 && metadata.EncryptedContent == nil {
+				continue
+			}
+
+			// When there are no summary parts, add an empty reasoning part
+			summaries := outputItem.Summary
+			if len(summaries) == 0 {
+				summaries = []responses.ResponseReasoningItemSummary{{Type: "summary_text", Text: ""}}
+			}
+
+			var summaryParts []string
+
+			for _, s := range summaries {
+				metadata.Summary = append(metadata.Summary, s.Text)
+				summaryParts = append(summaryParts, s.Text)
+			}
+
+			content = append(content, ai.ReasoningContent{
+				Text: strings.Join(summaryParts, "\n"),
+				ProviderMetadata: ai.ProviderMetadata{
+					Name: metadata,
+				},
+			})
+		}
+	}
+
+	usage := ai.Usage{
+		InputTokens:  response.Usage.InputTokens,
+		OutputTokens: response.Usage.OutputTokens,
+		TotalTokens:  response.Usage.InputTokens + response.Usage.OutputTokens,
+	}
+
+	if response.Usage.OutputTokensDetails.ReasoningTokens != 0 {
+		usage.ReasoningTokens = response.Usage.OutputTokensDetails.ReasoningTokens
+	}
+	if response.Usage.InputTokensDetails.CachedTokens != 0 {
+		usage.CacheReadTokens = response.Usage.InputTokensDetails.CachedTokens
+	}
+
+	finishReason := mapResponsesFinishReason(response.IncompleteDetails.Reason, hasFunctionCall)
+
+	return &ai.Response{
+		Content:          content,
+		Usage:            usage,
+		FinishReason:     finishReason,
+		ProviderMetadata: ai.ProviderMetadata{},
+		Warnings:         warnings,
+	}, nil
+}
+
+func mapResponsesFinishReason(reason string, hasFunctionCall bool) ai.FinishReason {
+	if hasFunctionCall {
+		return ai.FinishReasonToolCalls
+	}
+
+	switch reason {
+	case "":
+		return ai.FinishReasonStop
+	case "max_tokens", "max_output_tokens":
+		return ai.FinishReasonLength
+	case "content_filter":
+		return ai.FinishReasonContentFilter
+	default:
+		return ai.FinishReasonOther
+	}
+}
+
+func (o responsesLanguageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamResponse, error) {
+	params, warnings := o.prepareParams(call)
+
+	stream := o.client.Responses.NewStreaming(ctx, *params)
+
+	finishReason := ai.FinishReasonUnknown
+	var usage ai.Usage
+	ongoingToolCalls := make(map[int64]*ongoingToolCall)
+	hasFunctionCall := false
+	activeReasoning := make(map[string]*reasoningState)
+
+	return func(yield func(ai.StreamPart) bool) {
+		if len(warnings) > 0 {
+			if !yield(ai.StreamPart{
+				Type:     ai.StreamPartTypeWarnings,
+				Warnings: warnings,
+			}) {
+				return
+			}
+		}
+
+		for stream.Next() {
+			event := stream.Current()
+
+			switch event.Type {
+			case "response.created":
+				_ = event.AsResponseCreated()
+
+			case "response.output_item.added":
+				added := event.AsResponseOutputItemAdded()
+				switch added.Item.Type {
+				case "function_call":
+					ongoingToolCalls[added.OutputIndex] = &ongoingToolCall{
+						toolName:   added.Item.Name,
+						toolCallID: added.Item.CallID,
+					}
+					if !yield(ai.StreamPart{
+						Type:         ai.StreamPartTypeToolInputStart,
+						ID:           added.Item.CallID,
+						ToolCallName: added.Item.Name,
+					}) {
+						return
+					}
+
+				case "message":
+					if !yield(ai.StreamPart{
+						Type: ai.StreamPartTypeTextStart,
+						ID:   added.Item.ID,
+					}) {
+						return
+					}
+
+				case "reasoning":
+					metadata := &ResponsesReasoningMetadata{
+						ItemID:  added.Item.ID,
+						Summary: []string{},
+					}
+					if added.Item.EncryptedContent != "" {
+						metadata.EncryptedContent = &added.Item.EncryptedContent
+					}
+
+					activeReasoning[added.Item.ID] = &reasoningState{
+						metadata: metadata,
+					}
+					if !yield(ai.StreamPart{
+						Type: ai.StreamPartTypeReasoningStart,
+						ID:   added.Item.ID,
+						ProviderMetadata: ai.ProviderMetadata{
+							Name: metadata,
+						},
+					}) {
+						return
+					}
+				}
+
+			case "response.output_item.done":
+				done := event.AsResponseOutputItemDone()
+				switch done.Item.Type {
+				case "function_call":
+					tc := ongoingToolCalls[done.OutputIndex]
+					if tc != nil {
+						delete(ongoingToolCalls, done.OutputIndex)
+						hasFunctionCall = true
+
+						if !yield(ai.StreamPart{
+							Type: ai.StreamPartTypeToolInputEnd,
+							ID:   done.Item.CallID,
+						}) {
+							return
+						}
+						if !yield(ai.StreamPart{
+							Type:          ai.StreamPartTypeToolCall,
+							ID:            done.Item.CallID,
+							ToolCallName:  done.Item.Name,
+							ToolCallInput: done.Item.Arguments,
+						}) {
+							return
+						}
+					}
+
+				case "message":
+					if !yield(ai.StreamPart{
+						Type: ai.StreamPartTypeTextEnd,
+						ID:   done.Item.ID,
+					}) {
+						return
+					}
+
+				case "reasoning":
+					state := activeReasoning[done.Item.ID]
+					if state != nil {
+						if !yield(ai.StreamPart{
+							Type: ai.StreamPartTypeReasoningEnd,
+							ID:   done.Item.ID,
+							ProviderMetadata: ai.ProviderMetadata{
+								Name: state.metadata,
+							},
+						}) {
+							return
+						}
+						delete(activeReasoning, done.Item.ID)
+					}
+				}
+
+			case "response.function_call_arguments.delta":
+				delta := event.AsResponseFunctionCallArgumentsDelta()
+				tc := ongoingToolCalls[delta.OutputIndex]
+				if tc != nil {
+					if !yield(ai.StreamPart{
+						Type:  ai.StreamPartTypeToolInputDelta,
+						ID:    tc.toolCallID,
+						Delta: delta.Delta,
+					}) {
+						return
+					}
+				}
+
+			case "response.output_text.delta":
+				textDelta := event.AsResponseOutputTextDelta()
+				if !yield(ai.StreamPart{
+					Type:  ai.StreamPartTypeTextDelta,
+					ID:    textDelta.ItemID,
+					Delta: textDelta.Delta,
+				}) {
+					return
+				}
+
+			case "response.reasoning_summary_part.added":
+				added := event.AsResponseReasoningSummaryPartAdded()
+				state := activeReasoning[added.ItemID]
+				if state != nil {
+					state.metadata.Summary = append(state.metadata.Summary, "")
+					activeReasoning[added.ItemID] = state
+					if !yield(ai.StreamPart{
+						Type:  ai.StreamPartTypeReasoningDelta,
+						ID:    added.ItemID,
+						Delta: "\n",
+						ProviderMetadata: ai.ProviderMetadata{
+							Name: state.metadata,
+						},
+					}) {
+						return
+					}
+				}
+
+			case "response.reasoning_summary_text.delta":
+				textDelta := event.AsResponseReasoningSummaryTextDelta()
+				state := activeReasoning[textDelta.ItemID]
+				if state != nil {
+					if len(state.metadata.Summary)-1 >= int(textDelta.SummaryIndex) {
+						state.metadata.Summary[textDelta.SummaryIndex] += textDelta.Delta
+					}
+					activeReasoning[textDelta.ItemID] = state
+					if !yield(ai.StreamPart{
+						Type:  ai.StreamPartTypeReasoningDelta,
+						ID:    textDelta.ItemID,
+						Delta: textDelta.Delta,
+						ProviderMetadata: ai.ProviderMetadata{
+							Name: state.metadata,
+						},
+					}) {
+						return
+					}
+				}
+
+			case "response.completed", "response.incomplete":
+				completed := event.AsResponseCompleted()
+				finishReason = mapResponsesFinishReason(completed.Response.IncompleteDetails.Reason, hasFunctionCall)
+				usage = ai.Usage{
+					InputTokens:  completed.Response.Usage.InputTokens,
+					OutputTokens: completed.Response.Usage.OutputTokens,
+					TotalTokens:  completed.Response.Usage.InputTokens + completed.Response.Usage.OutputTokens,
+				}
+				if completed.Response.Usage.OutputTokensDetails.ReasoningTokens != 0 {
+					usage.ReasoningTokens = completed.Response.Usage.OutputTokensDetails.ReasoningTokens
+				}
+				if completed.Response.Usage.InputTokensDetails.CachedTokens != 0 {
+					usage.CacheReadTokens = completed.Response.Usage.InputTokensDetails.CachedTokens
+				}
+
+			case "error":
+				errorEvent := event.AsError()
+				if !yield(ai.StreamPart{
+					Type:  ai.StreamPartTypeError,
+					Error: fmt.Errorf("response error: %s (code: %s)", errorEvent.Message, errorEvent.Code),
+				}) {
+					return
+				}
+				return
+			}
+		}
+
+		err := stream.Err()
+		if err != nil {
+			yield(ai.StreamPart{
+				Type:  ai.StreamPartTypeError,
+				Error: o.handleError(err),
+			})
+			return
+		}
+
+		yield(ai.StreamPart{
+			Type:         ai.StreamPartTypeFinish,
+			Usage:        usage,
+			FinishReason: finishReason,
+		})
+	}, nil
+}
+
+func getReasoningMetadata(providerOptions ai.ProviderOptions) *ResponsesReasoningMetadata {
+	if openaiResponsesOptions, ok := providerOptions[Name]; ok {
+		if reasoning, ok := openaiResponsesOptions.(*ResponsesReasoningMetadata); ok {
+			return reasoning
+		}
+	}
+	return nil
+}
+
+type ongoingToolCall struct {
+	toolName   string
+	toolCallID string
+}
+
+type reasoningState struct {
+	metadata *ResponsesReasoningMetadata
+}

openai/responses_options.go ๐Ÿ”—

@@ -0,0 +1,128 @@
+package openai
+
+import (
+	"slices"
+
+	"github.com/charmbracelet/fantasy/ai"
+)
+
+type ResponsesReasoningMetadata struct {
+	ItemID           string   `json:"item_id"`
+	EncryptedContent *string  `json:"encrypted_content"`
+	Summary          []string `json:"summary"`
+}
+
+func (*ResponsesReasoningMetadata) Options() {}
+
+type IncludeType string
+
+const (
+	IncludeReasoningEncryptedContent IncludeType = "reasoning.encrypted_content"
+	IncludeFileSearchCallResults     IncludeType = "file_search_call.results"
+	IncludeMessageOutputTextLogprobs IncludeType = "message.output_text.logprobs"
+)
+
+type ServiceTier string
+
+const (
+	ServiceTierAuto     ServiceTier = "auto"
+	ServiceTierFlex     ServiceTier = "flex"
+	ServiceTierPriority ServiceTier = "priority"
+)
+
+type TextVerbosity string
+
+const (
+	TextVerbosityLow    TextVerbosity = "low"
+	TextVerbosityMedium TextVerbosity = "medium"
+	TextVerbosityHigh   TextVerbosity = "high"
+)
+
+type ResponsesProviderOptions struct {
+	Include           []IncludeType    `json:"include"`
+	Instructions      *string          `json:"instructions"`
+	Logprobs          any              `json:"logprobs"`
+	MaxToolCalls      *int64           `json:"max_tool_calls"`
+	Metadata          map[string]any   `json:"metadata"`
+	ParallelToolCalls *bool            `json:"parallel_tool_calls"`
+	PromptCacheKey    *string          `json:"prompt_cache_key"`
+	ReasoningEffort   *ReasoningEffort `json:"reasoning_effort"`
+	ReasoningSummary  *string          `json:"reasoning_summary"`
+	SafetyIdentifier  *string          `json:"safety_identifier"`
+	ServiceTier       *ServiceTier     `json:"service_tier"`
+	StrictJSONSchema  *bool            `json:"strict_json_schema"`
+	TextVerbosity     *TextVerbosity   `json:"text_verbosity"`
+	User              *string          `json:"user"`
+}
+
+var responsesReasoningModelIds = []string{
+	"o1",
+	"o1-2024-12-17",
+	"o3-mini",
+	"o3-mini-2025-01-31",
+	"o3",
+	"o3-2025-04-16",
+	"o4-mini",
+	"o4-mini-2025-04-16",
+	"codex-mini-latest",
+	"gpt-5",
+	"gpt-5-2025-08-07",
+	"gpt-5-mini",
+	"gpt-5-mini-2025-08-07",
+	"gpt-5-nano",
+	"gpt-5-nano-2025-08-07",
+	"gpt-5-codex",
+}
+
+var responsesModelIds = append([]string{
+	"gpt-4.1",
+	"gpt-4.1-2025-04-14",
+	"gpt-4.1-mini",
+	"gpt-4.1-mini-2025-04-14",
+	"gpt-4.1-nano",
+	"gpt-4.1-nano-2025-04-14",
+	"gpt-4o",
+	"gpt-4o-2024-05-13",
+	"gpt-4o-2024-08-06",
+	"gpt-4o-2024-11-20",
+	"gpt-4o-mini",
+	"gpt-4o-mini-2024-07-18",
+	"gpt-4-turbo",
+	"gpt-4-turbo-2024-04-09",
+	"gpt-4-turbo-preview",
+	"gpt-4-0125-preview",
+	"gpt-4-1106-preview",
+	"gpt-4",
+	"gpt-4-0613",
+	"gpt-4.5-preview",
+	"gpt-4.5-preview-2025-02-27",
+	"gpt-3.5-turbo-0125",
+	"gpt-3.5-turbo",
+	"gpt-3.5-turbo-1106",
+	"chatgpt-4o-latest",
+	"gpt-5-chat-latest",
+}, responsesReasoningModelIds...)
+
+func (*ResponsesProviderOptions) Options() {}
+
+func NewResponsesProviderOptions(opts *ResponsesProviderOptions) ai.ProviderOptions {
+	return ai.ProviderOptions{
+		Name: opts,
+	}
+}
+
+func ParseResponsesOptions(data map[string]any) (*ResponsesProviderOptions, error) {
+	var options ResponsesProviderOptions
+	if err := ai.ParseOptions(data, &options); err != nil {
+		return nil, err
+	}
+	return &options, nil
+}
+
+func IsResponsesModel(modelID string) bool {
+	return slices.Contains(responsesModelIds, modelID)
+}
+
+func IsResponsesReasoningModel(modelID string) bool {
+	return slices.Contains(responsesReasoningModelIds, modelID)
+}

providertests/common_test.go ๐Ÿ”—

@@ -65,7 +65,7 @@ func testSimple(t *testing.T, pair builderPair) {
 		result, err := agent.Generate(t.Context(), ai.AgentCall{
 			Prompt:          "Say hi in Portuguese",
 			ProviderOptions: pair.providerOptions,
-			MaxOutputTokens: ai.IntOption(4000),
+			MaxOutputTokens: ai.Opt(int64(4000)),
 		})
 		require.NoError(t, err, "failed to generate")
 		checkResult(t, result)
@@ -83,7 +83,7 @@ func testSimple(t *testing.T, pair builderPair) {
 		result, err := agent.Stream(t.Context(), ai.AgentStreamCall{
 			Prompt:          "Say hi in Portuguese",
 			ProviderOptions: pair.providerOptions,
-			MaxOutputTokens: ai.IntOption(4000),
+			MaxOutputTokens: ai.Opt(int64(4000)),
 		})
 		require.NoError(t, err, "failed to generate")
 		checkResult(t, result)
@@ -137,7 +137,7 @@ func testTool(t *testing.T, pair builderPair) {
 		result, err := agent.Generate(t.Context(), ai.AgentCall{
 			Prompt:          "What's the weather in Florence,Italy?",
 			ProviderOptions: pair.providerOptions,
-			MaxOutputTokens: ai.IntOption(4000),
+			MaxOutputTokens: ai.Opt(int64(4000)),
 		})
 		require.NoError(t, err, "failed to generate")
 		checkResult(t, result)
@@ -156,7 +156,7 @@ func testTool(t *testing.T, pair builderPair) {
 		result, err := agent.Stream(t.Context(), ai.AgentStreamCall{
 			Prompt:          "What's the weather in Florence,Italy?",
 			ProviderOptions: pair.providerOptions,
-			MaxOutputTokens: ai.IntOption(4000),
+			MaxOutputTokens: ai.Opt(int64(4000)),
 		})
 		require.NoError(t, err, "failed to generate")
 		checkResult(t, result)
@@ -174,6 +174,9 @@ func testMultiTool(t *testing.T, pair builderPair) {
 	if strings.Contains(pair.name, "bedrock") && strings.Contains(pair.name, "claude") {
 		t.Skip("skipping multi-tool tests for bedrock claude as it does not support parallel multi-tool calls")
 	}
+	if strings.Contains(pair.name, "openai") && strings.Contains(pair.name, "o4-mini") {
+		t.Skip("skipping multi-tool tests for openai o4-mini it for some reason is not doing parallel tool calls even if asked")
+	}
 
 	type CalculatorInput struct {
 		A int `json:"a" description:"first number"`
@@ -230,7 +233,7 @@ func testMultiTool(t *testing.T, pair builderPair) {
 		result, err := agent.Generate(t.Context(), ai.AgentCall{
 			Prompt:          "Add and multiply the number 2 and 3",
 			ProviderOptions: pair.providerOptions,
-			MaxOutputTokens: ai.IntOption(4000),
+			MaxOutputTokens: ai.Opt(int64(4000)),
 		})
 		require.NoError(t, err, "failed to generate")
 		checkResult(t, result)
@@ -250,7 +253,7 @@ func testMultiTool(t *testing.T, pair builderPair) {
 		result, err := agent.Stream(t.Context(), ai.AgentStreamCall{
 			Prompt:          "Add and multiply the number 2 and 3",
 			ProviderOptions: pair.providerOptions,
-			MaxOutputTokens: ai.IntOption(4000),
+			MaxOutputTokens: ai.Opt(int64(4000)),
 		})
 		require.NoError(t, err, "failed to generate")
 		checkResult(t, result)

providertests/google_test.go ๐Ÿ”—

@@ -38,8 +38,8 @@ func TestGoogleThinking(t *testing.T) {
 	opts := ai.ProviderOptions{
 		google.Name: &google.ProviderOptions{
 			ThinkingConfig: &google.ThinkingConfig{
-				ThinkingBudget:  ai.IntOption(100),
-				IncludeThoughts: ai.BoolOption(true),
+				ThinkingBudget:  ai.Opt(int64(100)),
+				IncludeThoughts: ai.Opt(true),
 			},
 		},
 	}

providertests/openai_responses_test.go ๐Ÿ”—

@@ -0,0 +1,85 @@
+package providertests
+
+import (
+	"net/http"
+	"os"
+	"testing"
+
+	"github.com/charmbracelet/fantasy/ai"
+	"github.com/charmbracelet/fantasy/openai"
+	"github.com/stretchr/testify/require"
+	"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
+)
+
+func TestOpenAIResponsesCommon(t *testing.T) {
+	var pairs []builderPair
+	for _, m := range openaiTestModels {
+		pairs = append(pairs, builderPair{m.name, openAIReasoningBuilder(m.model), nil})
+	}
+	testCommon(t, pairs)
+}
+
+func openAIReasoningBuilder(model string) builderFunc {
+	return func(r *recorder.Recorder) (ai.LanguageModel, error) {
+		provider := openai.New(
+			openai.WithAPIKey(os.Getenv("FANTASY_OPENAI_API_KEY")),
+			openai.WithHTTPClient(&http.Client{Transport: r}),
+			openai.WithUseResponsesAPI(),
+		)
+		return provider.LanguageModel(model)
+	}
+}
+
+func TestOpenAIResponsesWithSummaryThinking(t *testing.T) {
+	opts := ai.ProviderOptions{
+		openai.Name: &openai.ResponsesProviderOptions{
+			Include: []openai.IncludeType{
+				openai.IncludeReasoningEncryptedContent,
+			},
+			ReasoningEffort:  openai.ReasoningEffortOption(openai.ReasoningEffortHigh),
+			ReasoningSummary: ai.Opt("auto"),
+		},
+	}
+	var pairs []builderPair
+	for _, m := range openaiTestModels {
+		if !m.reasoning {
+			continue
+		}
+		pairs = append(pairs, builderPair{m.name, openAIReasoningBuilder(m.model), opts})
+	}
+	testThinking(t, pairs, testOpenAIResponsesThinkingWithSummaryThinking)
+}
+
+func testOpenAIResponsesThinkingWithSummaryThinking(t *testing.T, result *ai.AgentResult) {
+	reasoningContentCount := 0
+	encryptedData := 0
+	// Test if we got the signature
+	for _, step := range result.Steps {
+		for _, msg := range step.Messages {
+			for _, content := range msg.Content {
+				if content.GetType() == ai.ContentTypeReasoning {
+					reasoningContentCount += 1
+					reasoningContent, ok := ai.AsContentType[ai.ReasoningPart](content)
+					if !ok {
+						continue
+					}
+					if len(reasoningContent.ProviderOptions) == 0 {
+						continue
+					}
+
+					openaiReasoningMetadata, ok := reasoningContent.ProviderOptions[openai.Name]
+					if !ok {
+						continue
+					}
+					if typed, ok := openaiReasoningMetadata.(*openai.ResponsesReasoningMetadata); ok {
+						require.NotEmpty(t, typed.EncryptedContent)
+						encryptedData += 1
+					}
+				}
+			}
+		}
+	}
+	require.Greater(t, reasoningContentCount, 0)
+	require.Greater(t, encryptedData, 0)
+	require.Equal(t, reasoningContentCount, encryptedData)
+}

providertests/openai_test.go ๐Ÿ”—

@@ -10,34 +10,27 @@ import (
 	"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
 )
 
-func TestOpenAICommon(t *testing.T) {
-	testCommon(t, []builderPair{
-		{"gpt-4o", builderOpenaiGpt4o, nil},
-		{"gpt-4o-mini", builderOpenaiGpt4oMini, nil},
-		{"gpt-5", builderOpenaiGpt5, nil},
-	})
-}
-
-func builderOpenaiGpt4o(r *recorder.Recorder) (ai.LanguageModel, error) {
-	provider := openai.New(
-		openai.WithAPIKey(os.Getenv("FANTASY_OPENAI_API_KEY")),
-		openai.WithHTTPClient(&http.Client{Transport: r}),
-	)
-	return provider.LanguageModel("gpt-4o")
+var openaiTestModels = []testModel{
+	{"openai-gpt-4o", "gpt-4o", false},
+	{"openai-gpt-4o-mini", "gpt-4o-mini", false},
+	{"openai-gpt-5", "gpt-5", true},
+	{"openai-o4-mini", "o4-mini", true},
 }
 
-func builderOpenaiGpt4oMini(r *recorder.Recorder) (ai.LanguageModel, error) {
-	provider := openai.New(
-		openai.WithAPIKey(os.Getenv("FANTASY_OPENAI_API_KEY")),
-		openai.WithHTTPClient(&http.Client{Transport: r}),
-	)
-	return provider.LanguageModel("gpt-4o-mini")
+func TestOpenAICommon(t *testing.T) {
+	var pairs []builderPair
+	for _, m := range openaiTestModels {
+		pairs = append(pairs, builderPair{m.name, openAIBuilder(m.model), nil})
+	}
+	testCommon(t, pairs)
 }
 
-func builderOpenaiGpt5(r *recorder.Recorder) (ai.LanguageModel, error) {
-	provider := openai.New(
-		openai.WithAPIKey(os.Getenv("FANTASY_OPENAI_API_KEY")),
-		openai.WithHTTPClient(&http.Client{Transport: r}),
-	)
-	return provider.LanguageModel("gpt-5")
+func openAIBuilder(model string) builderFunc {
+	return func(r *recorder.Recorder) (ai.LanguageModel, error) {
+		provider := openai.New(
+			openai.WithAPIKey(os.Getenv("FANTASY_OPENAI_API_KEY")),
+			openai.WithHTTPClient(&http.Client{Transport: r}),
+		)
+		return provider.LanguageModel(model)
+	}
 }

providertests/testdata/TestOpenAICommon/gpt-4o-mini/simple_streaming.yaml ๐Ÿ”—

@@ -1,44 +0,0 @@
----
-version: 2
-interactions:
-- id: 0
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 215
-    host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"gpt-4o-mini","max_tokens":4000,"stream_options":{"include_usage":true},"stream":true}'
-    headers:
-      Accept:
-      - application/json
-      Content-Type:
-      - application/json
-      User-Agent:
-      - OpenAI/Go 2.3.0
-    url: https://api.openai.com/v1/chat/completions
-    method: POST
-  response:
-    proto: HTTP/2.0
-    proto_major: 2
-    proto_minor: 0
-    content_length: -1
-    body: |+
-      data: {"id":"chatcmpl-CK0XEa10Hau7DKHUO2epNihUILBAk","object":"chat.completion.chunk","created":1758884652,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mTQZfrLcd"}
-
-      data: {"id":"chatcmpl-CK0XEa10Hau7DKHUO2epNihUILBAk","object":"chat.completion.chunk","created":1758884652,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"Olรก"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"kFGU8bXe"}
-
-      data: {"id":"chatcmpl-CK0XEa10Hau7DKHUO2epNihUILBAk","object":"chat.completion.chunk","created":1758884652,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6WTCbco7Wv"}
-
-      data: {"id":"chatcmpl-CK0XEa10Hau7DKHUO2epNihUILBAk","object":"chat.completion.chunk","created":1758884652,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"pJDRU"}
-
-      data: {"id":"chatcmpl-CK0XEa10Hau7DKHUO2epNihUILBAk","object":"chat.completion.chunk","created":1758884652,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":20,"completion_tokens":2,"total_tokens":22,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"bo3PrVK8BB3"}
-
-      data: [DONE]
-
-    headers:
-      Content-Type:
-      - text/event-stream; charset=utf-8
-    status: 200 OK
-    code: 200
-    duration: 709.002458ms

providertests/testdata/TestOpenAICommon/gpt-4o/multi_tool_streaming.yaml ๐Ÿ”—

@@ -1,151 +0,0 @@
----
-version: 2
-interactions:
-- id: 0
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 848
-    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":"gpt-4o","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"}],"stream":true}'
-    headers:
-      Accept:
-      - application/json
-      Content-Type:
-      - application/json
-      User-Agent:
-      - OpenAI/Go 2.3.0
-    url: https://api.openai.com/v1/chat/completions
-    method: POST
-  response:
-    proto: HTTP/2.0
-    proto_major: 2
-    proto_minor: 0
-    content_length: -1
-    body: |+
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}],"obfuscation":"qnpNwYTQFp4"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_MBriMTSHw1UFtzQAduPP0Mkj","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"73"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"t"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"CrvdpBgVuwx3Xz"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"2INCr"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_7sVj20JsN3VYpXv8pZuLDruY","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"4mr5kRbqRoraJ"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"0"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"fxhC40qt4dPvrJ"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"xjieU"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"fYPH"}
-
-      data: {"id":"chatcmpl-CK0XBiHwsrgUyuIOsQJ7L2KjpG0pb","object":"chat.completion.chunk","created":1758884649,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":106,"completion_tokens":50,"total_tokens":156,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"xSLkv2SDLIEKV"}
-
-      data: [DONE]
-
-    headers:
-      Content-Type:
-      - text/event-stream; charset=utf-8
-    status: 200 OK
-    code: 200
-    duration: 948.292334ms
-- id: 1
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 1279
-    host: ""

providertests/testdata/TestOpenAICommon/gpt-4o/tool_streaming.yaml ๐Ÿ”—

@@ -1,117 +0,0 @@
----
-version: 2
-interactions:
-- id: 0
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 502
-    host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"gpt-4o","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"}],"stream":true}'
-    headers:
-      Accept:
-      - application/json
-      Content-Type:
-      - application/json
-      User-Agent:
-      - OpenAI/Go 2.3.0
-    url: https://api.openai.com/v1/chat/completions
-    method: POST
-  response:
-    proto: HTTP/2.0
-    proto_major: 2
-    proto_minor: 0
-    content_length: -1
-    body: |+
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_9ljXFCM8IxQxKHyEsUQVijHp","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"UAGY3b30VnPgY"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"OgK"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Q3DcqpRbSwpb3R"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"p"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"AR"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MA"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ARQ9S"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":""}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"gGD"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"U9KT"}
-
-      data: {"id":"chatcmpl-CK0X7SLV8PNKV91i8JXuZrQ5mP03w","object":"chat.completion.chunk","created":1758884645,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[],"usage":{"prompt_tokens":61,"completion_tokens":16,"total_tokens":77,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"NJ7nx5YCufYwsl5"}
-
-      data: [DONE]
-
-    headers:
-      Content-Type:
-      - text/event-stream; charset=utf-8
-    status: 200 OK
-    code: 200
-    duration: 791.905875ms
-- id: 1
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 754
-    host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_9ljXFCM8IxQxKHyEsUQVijHp","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_9ljXFCM8IxQxKHyEsUQVijHp","role":"tool"}],"model":"gpt-4o","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"}],"stream":true}'
-    headers:
-      Accept:
-      - application/json
-      Content-Type:
-      - application/json
-      User-Agent:
-      - OpenAI/Go 2.3.0
-    url: https://api.openai.com/v1/chat/completions
-    method: POST
-  response:
-    proto: HTTP/2.0
-    proto_major: 2
-    proto_minor: 0
-    content_length: -1
-    body: |+
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ot2BLWJZM4mQCF"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"mRJkBDkrUI2ci"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"1L6dJjW9"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" temperature"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"paCu"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"jr3Q8VcSKhEoL"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"fW43Xry"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wrIYFJtAid7igZY"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" Italy"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ggB92W1IhU"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oz7GPYuLjC8YF"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"BkYtBy1jdlqB4yU"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":"40"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2yi0arRy2iRUkk"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":"ยฐC"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"oyLNpZLu7c19qd"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"RjlnTLetR4N1OZC"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"GEcdbaZ1IU"}
-
-      data: {"id":"chatcmpl-CK0X8AngXdsZNpiHAr4nAL68UhG4O","object":"chat.completion.chunk","created":1758884646,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_f33640a400","choices":[],"usage":{"prompt_tokens":86,"completion_tokens":13,"total_tokens":99,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"W54neIykgflNQwN"}
-
-      data: [DONE]
-
-    headers:
-      Content-Type:
-      - text/event-stream; charset=utf-8
-    status: 200 OK
-    code: 200
-    duration: 733.489417ms

providertests/testdata/TestOpenAICommon/gpt-5/tool_streaming.yaml ๐Ÿ”—

@@ -1,143 +0,0 @@
----
-version: 2
-interactions:
-- id: 0
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 512
-    host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"gpt-5","max_completion_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"}],"stream":true}'
-    headers:
-      Accept:
-      - application/json
-      Content-Type:
-      - application/json
-      User-Agent:
-      - OpenAI/Go 2.3.0
-    url: https://api.openai.com/v1/chat/completions
-    method: POST
-  response:
-    proto: HTTP/2.0
-    proto_major: 2
-    proto_minor: 0
-    content_length: -1
-    body: |+
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_R6xW0RTSZLIX6N8k9assZBi6","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"gD6Jtbj4f"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"Mp2kWW2NQYHWbWR"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"finish_reason":null}],"usage":null,"obfuscation":"eYcxIjga47"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"EDTLdzBMQA4Fu"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"finish_reason":null}],"usage":null,"obfuscation":"nt5fI6wBEoQ7RL"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ALfx9Lp79jtGNE"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"finish_reason":null}],"usage":null,"obfuscation":"J"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"finish_reason":null}],"usage":null,"obfuscation":"KxzKpGDg69qm"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"finish_reason":null}],"usage":null,"obfuscation":"9BLLcr0UYPn5fcR"}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null,"obfuscation":""}
-
-      data: {"id":"chatcmpl-CK0XhIKDGZ1uM1c703bF4VNG9Iwdr","object":"chat.completion.chunk","created":1758884681,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":145,"completion_tokens":89,"total_tokens":234,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":64,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"aNuoJMq8"}
-
-      data: [DONE]
-
-    headers:
-      Content-Type:
-      - text/event-stream; charset=utf-8
-    status: 200 OK
-    code: 200
-    duration: 2.150256292s
-- id: 1
-  request:
-    proto: HTTP/1.1
-    proto_major: 1
-    proto_minor: 1
-    content_length: 764
-    host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_R6xW0RTSZLIX6N8k9assZBi6","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_R6xW0RTSZLIX6N8k9assZBi6","role":"tool"}],"model":"gpt-5","max_completion_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"}],"stream":true}'
-    headers:
-      Accept:
-      - application/json
-      Content-Type:
-      - application/json
-      User-Agent:
-      - OpenAI/Go 2.3.0
-    url: https://api.openai.com/v1/chat/completions
-    method: POST
-  response:
-    proto: HTTP/2.0
-    proto_major: 2
-    proto_minor: 0
-    content_length: -1
-    body: |+
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"1QwDd8Ke63"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"It"},"finish_reason":null}],"usage":null,"obfuscation":"0yJ0HwOjeE"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"โ€™s"},"finish_reason":null}],"usage":null,"obfuscation":"VNddxQuik0"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" currently"},"finish_reason":null}],"usage":null,"obfuscation":"G8"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" about"},"finish_reason":null}],"usage":null,"obfuscation":"3zOerF"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" "},"finish_reason":null}],"usage":null,"obfuscation":"Rn08jDfgDZ6"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"40"},"finish_reason":null}],"usage":null,"obfuscation":"SAq4MKX1tU"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ยฐC"},"finish_reason":null}],"usage":null,"obfuscation":"hjG5RtTJEr"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" in"},"finish_reason":null}],"usage":null,"obfuscation":"CMAmDZpK1"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Florence"},"finish_reason":null}],"usage":null,"obfuscation":"Qe2"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":","},"finish_reason":null}],"usage":null,"obfuscation":"84OPfcO8SSl"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Italy"},"finish_reason":null}],"usage":null,"obfuscation":"MwI72m"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}],"usage":null,"obfuscation":"7evHde6w0ci"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Would"},"finish_reason":null}],"usage":null,"obfuscation":"H4cgYK"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" you"},"finish_reason":null}],"usage":null,"obfuscation":"K1Z94VsI"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" like"},"finish_reason":null}],"usage":null,"obfuscation":"s2z6de3"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" the"},"finish_reason":null}],"usage":null,"obfuscation":"zkMR0F71"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" hourly"},"finish_reason":null}],"usage":null,"obfuscation":"KjnAr"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" or"},"finish_reason":null}],"usage":null,"obfuscation":"X99Z6vjPI"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" "},"finish_reason":null}],"usage":null,"obfuscation":"dQe993jbPM1"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"7"},"finish_reason":null}],"usage":null,"obfuscation":"BYBiweUr5ri"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"-day"},"finish_reason":null}],"usage":null,"obfuscation":"yb8PgNjS"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" forecast"},"finish_reason":null}],"usage":null,"obfuscation":"Mo4"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" as"},"finish_reason":null}],"usage":null,"obfuscation":"tEIYgn6d5"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" well"},"finish_reason":null}],"usage":null,"obfuscation":"7HlqGyB"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"?"},"finish_reason":null}],"usage":null,"obfuscation":"EfVBOumj9S1"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"3c3k2U"}
-
-      data: {"id":"chatcmpl-CK0XjsfRcuJKkovHfxUB7XypOCIdK","object":"chat.completion.chunk","created":1758884683,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":176,"completion_tokens":162,"total_tokens":338,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":128,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"QKSbao"}
-
-      data: [DONE]
-
-    headers:
-      Content-Type:
-      - text/event-stream; charset=utf-8
-    status: 200 OK
-    code: 200
-    duration: 3.872249167s

providertests/testdata/TestOpenAICommon/gpt-4o-mini/multi_tool.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/multi_tool.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XJEkzXehFvxL0bZtmn3X8bgEgl",
+        "id": "chatcmpl-CRdyxdsCExOS7bMCJ0q5fBEN9lCYM",
         "object": "chat.completion",
-        "created": 1758884657,
+        "created": 1760704583,
         "model": "gpt-4o-mini-2024-07-18",
         "choices": [
           {
@@ -38,7 +38,7 @@ interactions:
               "content": null,
               "tool_calls": [
                 {
-                  "id": "call_FCjSdfiDyZbfKofJ8aYgjarN",
+                  "id": "call_H0yMeWt85QiaFMjrlPqAyCYY",
                   "type": "function",
                   "function": {
                     "name": "add",
@@ -46,7 +46,7 @@ interactions:
                   }
                 },
                 {
-                  "id": "call_AgpIWMgz4cq1cKBsv6Mziy64",
+                  "id": "call_Xh3xOMoQueLZUgW7HYVvwwql",
                   "type": "function",
                   "function": {
                     "name": "multiply",
@@ -84,7 +84,7 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 1.27362425s
+    duration: 2.030219167s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -92,7 +92,7 @@ interactions:
     proto_minor: 1
     content_length: 1247
     host: ""

providertests/testdata/TestOpenAICommon/gpt-4o-mini/multi_tool_streaming.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/multi_tool_streaming.yaml ๐Ÿ”—

@@ -24,31 +24,31 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}],"obfuscation":"Jc55JP"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}],"obfuscation":"icfARx"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_CGT5idjqbJEWyLlJgPfsmFYb","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"OmSduDa945dbJ"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_vgTL4QSVMl9ocwrlDENBvKCl","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"feBbOJXFBL4EO"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"JGWO5LWiKSK"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"VkgJFOcIZbR"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"hiqHPmiezH46"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"3w2natY0RoGc"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"OSQtmBsHX"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"36y1gHQIT"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_OrChv4bx3cZusgzSYcsNBXxI","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"zeRuqxfB"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_0163ysRAfpd1kX8JEsq8piJv","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"dWNz2rVl"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"p7UhRLOP29K"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"ko1uYx2756e"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"tlEc9WchAOF2"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"8ty7XqR7h2EW"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"iobxrSeLl"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"iD4RWBFbS"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"rVIe1UbTRO4Fjt4"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"vknFSfxKgFJlLl9"}
 
-      data: {"id":"chatcmpl-CK0XL6hjKzmU1T07yvr9rjTCPOnAh","object":"chat.completion.chunk","created":1758884659,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":106,"completion_tokens":50,"total_tokens":156,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"XSLg3zvv"}
+      data: {"id":"chatcmpl-CRdz0aS9mqbcyCuvqkNMoVXDUraLn","object":"chat.completion.chunk","created":1760704586,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":106,"completion_tokens":50,"total_tokens":156,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"hms0Yf0n"}
 
       data: [DONE]
 
@@ -57,7 +57,7 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 1.289823791s
+    duration: 1.538896292s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -65,7 +65,7 @@ interactions:
     proto_minor: 1
     content_length: 1284
     host: ""

providertests/testdata/TestOpenAICommon/gpt-4o-mini/simple.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/simple.yaml ๐Ÿ”—

@@ -26,16 +26,16 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XDJXMRJFIQoawW09BP2SyM4Ot8",
+        "id": "chatcmpl-CRdysIxOQVTFiu9TMRyxiiYHHQyTj",
         "object": "chat.completion",
-        "created": 1758884651,
+        "created": 1760704578,
         "model": "gpt-4o-mini-2024-07-18",
         "choices": [
           {
             "index": 0,
             "message": {
               "role": "assistant",
-              "content": "Hi! In Portuguese, you would say \"Olรก!\"",
+              "content": "Olรก!",
               "refusal": null,
               "annotations": []
             },
@@ -45,8 +45,8 @@ interactions:
         ],
         "usage": {
           "prompt_tokens": 20,
-          "completion_tokens": 11,
-          "total_tokens": 31,
+          "completion_tokens": 2,
+          "total_tokens": 22,
           "prompt_tokens_details": {
             "cached_tokens": 0,
             "audio_tokens": 0
@@ -66,4 +66,4 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 761.996916ms
+    duration: 902.366208ms

providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,60 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 215
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"gpt-4o-mini","max_tokens":4000,"stream_options":{"include_usage":true},"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dNrgk6KCj"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"Hi"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wRjU25PHG"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"li6Xgje1BS"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" In"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"3rRemht7"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" Portuguese"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":""}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"S0Wp8u71lq"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"gsbpPtV"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" say"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LBoNQFN"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" \""},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Bgm7GOfe"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"Olรก"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CmJzapI9"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"!\""},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dtukc2xn"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"nYn46"}
+
+      data: {"id":"chatcmpl-CRdytk5LO0hrSMS9Co5OPHLFCuLSF","object":"chat.completion.chunk","created":1760704579,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":20,"completion_tokens":10,"total_tokens":30,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"wXXaHiliFF"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 566.636417ms

providertests/testdata/TestOpenAICommon/gpt-4o-mini/tool.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/tool.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XFLvJhhbJXQpYZSq0bUsexpP18",
+        "id": "chatcmpl-CRdyuS0DEOR3GgR76SLPKqPiwPIAt",
         "object": "chat.completion",
-        "created": 1758884653,
+        "created": 1760704580,
         "model": "gpt-4o-mini-2024-07-18",
         "choices": [
           {
@@ -38,7 +38,7 @@ interactions:
               "content": null,
               "tool_calls": [
                 {
-                  "id": "call_KJtOtoO7dF2DgTI8nctku9EC",
+                  "id": "call_2uH56RhZZbC8djqCn7cxRyKl",
                   "type": "function",
                   "function": {
                     "name": "weather",
@@ -76,7 +76,7 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 1.169646666s
+    duration: 1.057664375s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -84,7 +84,7 @@ interactions:
     proto_minor: 1
     content_length: 705
     host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_KJtOtoO7dF2DgTI8nctku9EC","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_KJtOtoO7dF2DgTI8nctku9EC","role":"tool"}],"model":"gpt-4o-mini","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"}]}'
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_2uH56RhZZbC8djqCn7cxRyKl","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_2uH56RhZZbC8djqCn7cxRyKl","role":"tool"}],"model":"gpt-4o-mini","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"}]}'
     headers:
       Accept:
       - application/json
@@ -102,16 +102,16 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XGrDAk6At7slQfnVXf7SWIPNI9",
+        "id": "chatcmpl-CRdyvMVFPOfa2G1IC80Js9jy1xIE0",
         "object": "chat.completion",
-        "created": 1758884654,
+        "created": 1760704581,
         "model": "gpt-4o-mini-2024-07-18",
         "choices": [
           {
             "index": 0,
             "message": {
               "role": "assistant",
-              "content": "The current weather in Florence, Italy, is 40ยฐC.",
+              "content": "The weather in Florence, Italy is currently 40ยฐC.",
               "refusal": null,
               "annotations": []
             },
@@ -121,8 +121,8 @@ interactions:
         ],
         "usage": {
           "prompt_tokens": 86,
-          "completion_tokens": 14,
-          "total_tokens": 100,
+          "completion_tokens": 13,
+          "total_tokens": 99,
           "prompt_tokens_details": {
             "cached_tokens": 0,
             "audio_tokens": 0
@@ -142,4 +142,4 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 772.468958ms
+    duration: 933.192292ms

providertests/testdata/TestOpenAICommon/gpt-4o-mini/tool_streaming.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o-mini/tool_streaming.yaml ๐Ÿ”—

@@ -24,27 +24,27 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_DETfkgrMGPDgJzwS62NSuRPa","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"LX9odVHb"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_eOpGKcIP7rzEsLNRtEm9K6mx","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"M7LBWEuz"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"c1yYSDZaI1UDYV"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"y0wRfvzAfc7Gwp"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZToBjCwft"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"l4ftT9t8s"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SXENj4krMldO"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"egmKNDffXaU3"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"O4dIvyXTiV9nE"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GG1ybnr1YrkNG"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CHahf3pIqTc5c"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"bSU8KmpVhJmCU"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":""}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":""}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"RCwjNsUKEVK"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"iRxnuJP3cpr"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dpgaKu5zTDw8CZ"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QBAmqhvyRFjbCZ"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"cYYcBlfkMvDVd07"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"3ebmRJY6jIoVVSq"}
 
-      data: {"id":"chatcmpl-CK0XH1YEf20Nk6A5GRZVFbdBy8NvS","object":"chat.completion.chunk","created":1758884655,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":61,"completion_tokens":16,"total_tokens":77,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"aX8SEVMo9D"}
+      data: {"id":"chatcmpl-CRdywA4dbuMAJLXVP860cVgCKV8Jz","object":"chat.completion.chunk","created":1760704582,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":61,"completion_tokens":16,"total_tokens":77,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"9htLycow0a"}
 
       data: [DONE]
 
@@ -53,7 +53,7 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 713.193958ms
+    duration: 680.827667ms
 - id: 1
   request:
     proto: HTTP/1.1
@@ -61,7 +61,7 @@ interactions:
     proto_minor: 1
     content_length: 759
     host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_DETfkgrMGPDgJzwS62NSuRPa","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_DETfkgrMGPDgJzwS62NSuRPa","role":"tool"}],"model":"gpt-4o-mini","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"}],"stream":true}'
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_eOpGKcIP7rzEsLNRtEm9K6mx","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_eOpGKcIP7rzEsLNRtEm9K6mx","role":"tool"}],"model":"gpt-4o-mini","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"}],"stream":true}'
     headers:
       Accept:
       - application/json
@@ -77,35 +77,35 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Nld6m4L8f"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"uB0vXwmAg"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Tt22VYUt"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"bXKWncif"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HSH"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"5VH"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" temperature"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"YVBXBDODyk7cIJS"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"cOVYqBuN"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"0owI6QAQ"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"qn"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"A8"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ETVXMoB3wo"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Koc2bQX8BA"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" Italy"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"TJueB"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" Italy"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MN5Jc"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2dXikvHR"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MmkAFvX2"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" currently"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"U"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"EdhYi7wxQ1"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SJvYbm15DI"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"40"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"AQOB4uaLd"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"40"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"MmF8rVRCD"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"ยฐC"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"u3tu0x3Af"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"ยฐC"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6apyDO2Sn"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"RpzcBAg3HO"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"10hdWpCjhh"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"NfRGq"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"CFuXa"}
 
-      data: {"id":"chatcmpl-CK0XIUwrhgZGexhOP9ECHm2D0DZLr","object":"chat.completion.chunk","created":1758884656,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":86,"completion_tokens":13,"total_tokens":99,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"QW8EXr68zX"}
+      data: {"id":"chatcmpl-CRdyx1hGexd66KC0T4iMnborWhkbJ","object":"chat.completion.chunk","created":1760704583,"model":"gpt-4o-mini-2024-07-18","service_tier":"default","system_fingerprint":"fp_560af6e559","choices":[],"usage":{"prompt_tokens":86,"completion_tokens":13,"total_tokens":99,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"G7mYdCwtgy"}
 
       data: [DONE]
 
@@ -114,4 +114,4 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 631.400833ms
+    duration: 434.186417ms

providertests/testdata/TestOpenAICommon/gpt-4o/multi_tool.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o/multi_tool.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XA5ghLRvKpjSC7Rg3T1y9lcS4l",
+        "id": "chatcmpl-CRdyoWcDq406PCUaEpBjaiqUGhoI3",
         "object": "chat.completion",
-        "created": 1758884648,
+        "created": 1760704574,
         "model": "gpt-4o-2024-08-06",
         "choices": [
           {
@@ -38,7 +38,7 @@ interactions:
               "content": null,
               "tool_calls": [
                 {
-                  "id": "call_xzBAj3TQym7plpg6LQrUqzNb",
+                  "id": "call_Cg9itjRbJ4NYAZEbIwcSiEJZ",
                   "type": "function",
                   "function": {
                     "name": "add",
@@ -46,7 +46,7 @@ interactions:
                   }
                 },
                 {
-                  "id": "call_EhG6PUMSJoTy4yH4uYeOL1fB",
+                  "id": "call_sSIhNbcU2Ap95fBjcsScrTMz",
                   "type": "function",
                   "function": {
                     "name": "multiply",
@@ -77,14 +77,14 @@ interactions:
           }
         },
         "service_tier": "default",
-        "system_fingerprint": "fp_cbf1785567"
+        "system_fingerprint": "fp_f64f290af2"
       }
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 888.207625ms
+    duration: 1.503138709s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -92,7 +92,7 @@ interactions:
     proto_minor: 1
     content_length: 1242
     host: ""

providertests/testdata/TestOpenAICommon/openai-gpt-4o/multi_tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,135 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 848
+    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":"gpt-4o","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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"logprobs":null,"finish_reason":null}],"obfuscation":"OHGcRuhO4A4"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_43EjiXfsjRlSfqUDWptDvMBZ","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"Zz"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"X"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"m5lvJ0jw20BTZs"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"uM0Ca"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_xHjbYtQqq9gsbadfjB3Vpjde","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"u39m7n3pFddmq"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\""}}]},"logprobs":null,"finish_reason":null}],"obfuscation":""}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 2, "}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"Z"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\": 3"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"fk12n2in3eYPHY"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"logprobs":null,"finish_reason":null}],"obfuscation":"XS0QR"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"J1Fr"}
+
+      data: {"id":"chatcmpl-CRdyrlpgfyiFlAAnoiflUbvXhNUGP","object":"chat.completion.chunk","created":1760704577,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":106,"completion_tokens":50,"total_tokens":156,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"8X9w9cqTHQGUY"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 772.991416ms
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1279
+    host: ""

providertests/testdata/TestOpenAICommon/gpt-4o/simple.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o/simple.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0X4bZcI8nrXIcHWmKudgvXDxrDA",
+        "id": "chatcmpl-CRdyjdJswbbI6kuVNScObDe3tYnu2",
         "object": "chat.completion",
-        "created": 1758884642,
+        "created": 1760704569,
         "model": "gpt-4o-2024-08-06",
         "choices": [
           {
@@ -59,11 +59,11 @@ interactions:
           }
         },
         "service_tier": "default",
-        "system_fingerprint": "fp_f33640a400"
+        "system_fingerprint": "fp_cbf1785567"
       }
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 1.155694458s
+    duration: 740.354167ms

providertests/testdata/TestOpenAICommon/gpt-4o/simple_streaming.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o/simple_streaming.yaml ๐Ÿ”—

@@ -24,15 +24,15 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CK0X5ZDGxyhuWeT5rVCHaFGRgbccv","object":"chat.completion.chunk","created":1758884643,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HqD71AKa50tXXh"}
+      data: {"id":"chatcmpl-CRdyjrv70pWoCSnjiX81dksuhZK0H","object":"chat.completion.chunk","created":1760704569,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"dW8LjvG3FnxHr9"}
 
-      data: {"id":"chatcmpl-CK0X5ZDGxyhuWeT5rVCHaFGRgbccv","object":"chat.completion.chunk","created":1758884643,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Olรก"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"40xIFsLyWvteo"}
+      data: {"id":"chatcmpl-CRdyjrv70pWoCSnjiX81dksuhZK0H","object":"chat.completion.chunk","created":1760704569,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"Olรก"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"HhaSik3KUWGzk"}
 
-      data: {"id":"chatcmpl-CK0X5ZDGxyhuWeT5rVCHaFGRgbccv","object":"chat.completion.chunk","created":1758884643,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"2FARzZxtjhy5wgw"}
+      data: {"id":"chatcmpl-CRdyjrv70pWoCSnjiX81dksuhZK0H","object":"chat.completion.chunk","created":1760704569,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"XoNpCCkgDMpPelm"}
 
-      data: {"id":"chatcmpl-CK0X5ZDGxyhuWeT5rVCHaFGRgbccv","object":"chat.completion.chunk","created":1758884643,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"Y6BYwTwbLh"}
+      data: {"id":"chatcmpl-CRdyjrv70pWoCSnjiX81dksuhZK0H","object":"chat.completion.chunk","created":1760704569,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"FbHAsgWpZy"}
 
-      data: {"id":"chatcmpl-CK0X5ZDGxyhuWeT5rVCHaFGRgbccv","object":"chat.completion.chunk","created":1758884643,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":20,"completion_tokens":2,"total_tokens":22,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":""}
+      data: {"id":"chatcmpl-CRdyjrv70pWoCSnjiX81dksuhZK0H","object":"chat.completion.chunk","created":1760704569,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":20,"completion_tokens":2,"total_tokens":22,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":""}
 
       data: [DONE]
 
@@ -41,4 +41,4 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 683.806291ms
+    duration: 626.391292ms

providertests/testdata/TestOpenAICommon/gpt-4o/tool.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-4o/tool.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0X6hYUe2ObsAoS3agGWpVx6KAIF",
+        "id": "chatcmpl-CRdykecyitTrtBgxG3cAhHM82R3ar",
         "object": "chat.completion",
-        "created": 1758884644,
+        "created": 1760704570,
         "model": "gpt-4o-2024-08-06",
         "choices": [
           {
@@ -38,7 +38,7 @@ interactions:
               "content": null,
               "tool_calls": [
                 {
-                  "id": "call_PzVhbfSC5fkOlTTPrPLKF3og",
+                  "id": "call_zKl0GvROtopAKaVzafvOYfPu",
                   "type": "function",
                   "function": {
                     "name": "weather",
@@ -69,14 +69,14 @@ interactions:
           }
         },
         "service_tier": "default",
-        "system_fingerprint": "fp_f33640a400"
+        "system_fingerprint": "fp_cbf1785567"
       }
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 870.074417ms
+    duration: 1.142721375s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -84,7 +84,7 @@ interactions:
     proto_minor: 1
     content_length: 700
     host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_PzVhbfSC5fkOlTTPrPLKF3og","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_PzVhbfSC5fkOlTTPrPLKF3og","role":"tool"}],"model":"gpt-4o","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"}]}'
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_zKl0GvROtopAKaVzafvOYfPu","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_zKl0GvROtopAKaVzafvOYfPu","role":"tool"}],"model":"gpt-4o","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"}]}'
     headers:
       Accept:
       - application/json
@@ -102,16 +102,16 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0X7Hzh8cJn4geVw2dn4qX583KOX",
+        "id": "chatcmpl-CRdyljyj1IrCMsT69QVozUugzhlwd",
         "object": "chat.completion",
-        "created": 1758884645,
+        "created": 1760704571,
         "model": "gpt-4o-2024-08-06",
         "choices": [
           {
             "index": 0,
             "message": {
               "role": "assistant",
-              "content": "The weather in Florence, Italy is currently 40ยฐC.",
+              "content": "The current temperature in Florence, Italy is 40ยฐC.",
               "refusal": null,
               "annotations": []
             },
@@ -135,11 +135,11 @@ interactions:
           }
         },
         "service_tier": "default",
-        "system_fingerprint": "fp_f33640a400"
+        "system_fingerprint": "fp_cbf1785567"
       }
     headers:
       Content-Type:
       - application/json
     status: 200 OK
     code: 200
-    duration: 578.292709ms
+    duration: 1.414555709s

providertests/testdata/TestOpenAICommon/openai-gpt-4o/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,117 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 502
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"gpt-4o","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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_9W0PDPMmK2SHo8Ph5qmngr60","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"SKTBYmVhUa37r"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ISP"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wTarJRBKmxWzEe"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"b"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"Dt"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"lK"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"ZEEqt"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":""}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"tsM"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"hAQV"}
+
+      data: {"id":"chatcmpl-CRdynEXtk7T39drPlGlAxtuaMPYtO","object":"chat.completion.chunk","created":1760704573,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":61,"completion_tokens":16,"total_tokens":77,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"1fPE9DL5GVNekQj"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 828.397667ms
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 754
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_9W0PDPMmK2SHo8Ph5qmngr60","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_9W0PDPMmK2SHo8Ph5qmngr60","role":"tool"}],"model":"gpt-4o","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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"redbGckJxoV9Sf"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"hokBzzfi9soMV"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GYmp4NHd"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" temperature"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"V72K"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"J4dE5Y0oVkTnc"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"embLD68"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"QxOjL2vP9UUb8DE"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" Italy"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"xVq2JhUM0m"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"wR1prrEQ6cTc3"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"8tMP4q2OCLlkRy3"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"40"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"GOjJVxLP9sk8u4"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"ยฐC"},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"CCwAe3AFhmdpna"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"usage":null,"obfuscation":"6DQeIz589eDMca5"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[{"index":0,"delta":{},"logprobs":null,"finish_reason":"stop"}],"usage":null,"obfuscation":"gnoMeZSJgE"}
+
+      data: {"id":"chatcmpl-CRdyomJ9SewTkG1C99SPqHd6NWByb","object":"chat.completion.chunk","created":1760704574,"model":"gpt-4o-2024-08-06","service_tier":"default","system_fingerprint":"fp_cbf1785567","choices":[],"usage":{"prompt_tokens":86,"completion_tokens":13,"total_tokens":99,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"ImGWeSBRNjxx71V"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 637.852666ms

providertests/testdata/TestOpenAICommon/gpt-5/multi_tool.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-5/multi_tool.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XnxWhgtkMe0wP3vgmBDyXKUnRG",
+        "id": "chatcmpl-CRdzUDVMIrCJUYwgqR69TFp8L2Swc",
         "object": "chat.completion",
-        "created": 1758884687,
+        "created": 1760704616,
         "model": "gpt-5-2025-08-07",
         "choices": [
           {
@@ -38,7 +38,7 @@ interactions:
               "content": null,
               "tool_calls": [
                 {
-                  "id": "call_owMpyw7UQNzI7NZYQdaRAHuw",
+                  "id": "call_md2XuaM6Rk2D4bTo2L6U2rC4",
                   "type": "function",
                   "function": {
                     "name": "add",
@@ -46,7 +46,7 @@ interactions:
                   }
                 },
                 {
-                  "id": "call_UMUj2rz9wz4i1f0yViOfELBg",
+                  "id": "call_uSejWXP98W4wT6BU62WnSFkD",
                   "type": "function",
                   "function": {
                     "name": "multiply",
@@ -62,14 +62,14 @@ interactions:
         ],
         "usage": {
           "prompt_tokens": 194,
-          "completion_tokens": 379,
-          "total_tokens": 573,
+          "completion_tokens": 315,
+          "total_tokens": 509,
           "prompt_tokens_details": {
             "cached_tokens": 0,
             "audio_tokens": 0
           },
           "completion_tokens_details": {
-            "reasoning_tokens": 320,
+            "reasoning_tokens": 256,
             "audio_tokens": 0,
             "accepted_prediction_tokens": 0,
             "rejected_prediction_tokens": 0
@@ -83,7 +83,7 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 4.394474708s
+    duration: 5.788909416s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -91,7 +91,7 @@ interactions:
     proto_minor: 1
     content_length: 1252
     host: ""

providertests/testdata/TestOpenAICommon/gpt-5/multi_tool_streaming.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-5/multi_tool_streaming.yaml ๐Ÿ”—

@@ -24,31 +24,31 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"finish_reason":null}],"obfuscation":"A267Qlz"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null},"finish_reason":null}],"obfuscation":"NvBRsp2"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_AXhYybFxqFkolGcqOgAFoSFX","type":"function","function":{"name":"add","arguments":""}}]},"finish_reason":null}],"obfuscation":"RFeaNwHIAYBsVY"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_4ebZx1iZmHY4sPZ1h1iMHaWD","type":"function","function":{"name":"add","arguments":""}}]},"finish_reason":null}],"obfuscation":"5qQkfsMd6Ydd9V"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\""}}]},"finish_reason":null}],"obfuscation":"WJMeoEiRsqUQ"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\""}}]},"finish_reason":null}],"obfuscation":"VeWK0cIPeocT"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 2, "}}]},"finish_reason":null}],"obfuscation":"ICdxIqu5A6utx"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 2, "}}]},"finish_reason":null}],"obfuscation":"ROMuHEfrgbrS7"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"b\": 3"}}]},"finish_reason":null}],"obfuscation":"EEVOXd76AO"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"b\": 3"}}]},"finish_reason":null}],"obfuscation":"xE9kB40afY"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}],"obfuscation":"b"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"}"}}]},"finish_reason":null}],"obfuscation":"4"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_3coDGg9Vq8TWdNxqZhONlTvf","type":"function","function":{"name":"multiply","arguments":""}}]},"finish_reason":null}],"obfuscation":"FlbQ1NJFg"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_wyeHgH870UHPvm0tKc4MwvDD","type":"function","function":{"name":"multiply","arguments":""}}]},"finish_reason":null}],"obfuscation":"IneSneP7z"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\""}}]},"finish_reason":null}],"obfuscation":"cT6Z7pBgiudL"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\""}}]},"finish_reason":null}],"obfuscation":"HGrCNThdZNii"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 2, "}}]},"finish_reason":null}],"obfuscation":"hBepHW4ne1PKa"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 2, "}}]},"finish_reason":null}],"obfuscation":"5ZULYIdry7hus"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\": 3"}}]},"finish_reason":null}],"obfuscation":"8cRTwxjNfk"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\": 3"}}]},"finish_reason":null}],"obfuscation":"3iFLy71PX6"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"finish_reason":null}],"obfuscation":"n"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"usage":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"}"}}]},"finish_reason":null}],"obfuscation":"d"}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null,"obfuscation":""}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null,"obfuscation":""}
 
-      data: {"id":"chatcmpl-CK0XtZlLMkqbw0LEkkXg7xLSmvy9K","object":"chat.completion.chunk","created":1758884693,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":190,"completion_tokens":315,"total_tokens":505,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":256,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"9PJ53E"}
+      data: {"id":"chatcmpl-CRdzc7GhPT7mc2HunXDSslDWG7Bhx","object":"chat.completion.chunk","created":1760704624,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":190,"completion_tokens":507,"total_tokens":697,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":448,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"Em6PO8"}
 
       data: [DONE]
 
@@ -57,7 +57,7 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 3.330712625s
+    duration: 7.672726292s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -65,7 +65,7 @@ interactions:
     proto_minor: 1
     content_length: 1289
     host: ""

providertests/testdata/TestOpenAICommon/gpt-5/simple.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-5/simple.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XOu05MsCCjlsUQ8FMCiweyNIzy",
+        "id": "chatcmpl-CRdz3IlGIW2lfJ0VP6n8tkysshWP6",
         "object": "chat.completion",
-        "created": 1758884662,
+        "created": 1760704589,
         "model": "gpt-5-2025-08-07",
         "choices": [
           {
@@ -44,14 +44,14 @@ interactions:
         ],
         "usage": {
           "prompt_tokens": 19,
-          "completion_tokens": 267,
-          "total_tokens": 286,
+          "completion_tokens": 203,
+          "total_tokens": 222,
           "prompt_tokens_details": {
             "cached_tokens": 0,
             "audio_tokens": 0
           },
           "completion_tokens_details": {
-            "reasoning_tokens": 256,
+            "reasoning_tokens": 192,
             "audio_tokens": 0,
             "accepted_prediction_tokens": 0,
             "rejected_prediction_tokens": 0
@@ -65,4 +65,4 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 7.980275959s
+    duration: 5.250838625s

providertests/testdata/TestOpenAICommon/gpt-5/simple_streaming.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-5/simple_streaming.yaml ๐Ÿ”—

@@ -24,15 +24,15 @@ interactions:
     proto_minor: 0
     content_length: -1
     body: |+
-      data: {"id":"chatcmpl-CK0XVjPg2s2l38Jp4lk55TNIOTFhX","object":"chat.completion.chunk","created":1758884669,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"DkFHOAsKPT"}
+      data: {"id":"chatcmpl-CRdz8RCAgBM561aJOMPL9YeHB957W","object":"chat.completion.chunk","created":1760704594,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"SFRj4fNgeY"}
 
-      data: {"id":"chatcmpl-CK0XVjPg2s2l38Jp4lk55TNIOTFhX","object":"chat.completion.chunk","created":1758884669,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"Olรก"},"finish_reason":null}],"usage":null,"obfuscation":"DDecr705I"}
+      data: {"id":"chatcmpl-CRdz8RCAgBM561aJOMPL9YeHB957W","object":"chat.completion.chunk","created":1760704594,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"Olรก"},"finish_reason":null}],"usage":null,"obfuscation":"x2Y1eWqda"}
 
-      data: {"id":"chatcmpl-CK0XVjPg2s2l38Jp4lk55TNIOTFhX","object":"chat.completion.chunk","created":1758884669,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}],"usage":null,"obfuscation":"xXHCpUUBS0F"}
+      data: {"id":"chatcmpl-CRdz8RCAgBM561aJOMPL9YeHB957W","object":"chat.completion.chunk","created":1760704594,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}],"usage":null,"obfuscation":"tDJ7zpDqgTi"}
 
-      data: {"id":"chatcmpl-CK0XVjPg2s2l38Jp4lk55TNIOTFhX","object":"chat.completion.chunk","created":1758884669,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"YGdqo0"}
+      data: {"id":"chatcmpl-CRdz8RCAgBM561aJOMPL9YeHB957W","object":"chat.completion.chunk","created":1760704594,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"85W83X"}
 
-      data: {"id":"chatcmpl-CK0XVjPg2s2l38Jp4lk55TNIOTFhX","object":"chat.completion.chunk","created":1758884669,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":19,"completion_tokens":75,"total_tokens":94,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":64,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"W9Y009RwUv"}
+      data: {"id":"chatcmpl-CRdz8RCAgBM561aJOMPL9YeHB957W","object":"chat.completion.chunk","created":1760704594,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":19,"completion_tokens":75,"total_tokens":94,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":64,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"gUl972lllc"}
 
       data: [DONE]
 
@@ -41,4 +41,4 @@ interactions:
       - text/event-stream; charset=utf-8
     status: 200 OK
     code: 200
-    duration: 2.723195042s
+    duration: 2.890382667s

providertests/testdata/TestOpenAICommon/gpt-5/tool.yaml โ†’ providertests/testdata/TestOpenAICommon/openai-gpt-5/tool.yaml ๐Ÿ”—

@@ -26,9 +26,9 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XYLtrTcQa9MlwDz9fensX4gebx",
+        "id": "chatcmpl-CRdzCfnkaQoMYKAvfAXds0hUUaCog",
         "object": "chat.completion",
-        "created": 1758884672,
+        "created": 1760704598,
         "model": "gpt-5-2025-08-07",
         "choices": [
           {
@@ -38,7 +38,7 @@ interactions:
               "content": null,
               "tool_calls": [
                 {
-                  "id": "call_f7ty26Ui6FOEcr62i17rpqTm",
+                  "id": "call_iENK0JiZIVgIwVhzXgr2vqAb",
                   "type": "function",
                   "function": {
                     "name": "weather",
@@ -54,14 +54,14 @@ interactions:
         ],
         "usage": {
           "prompt_tokens": 145,
-          "completion_tokens": 153,
-          "total_tokens": 298,
+          "completion_tokens": 89,
+          "total_tokens": 234,
           "prompt_tokens_details": {
             "cached_tokens": 0,
             "audio_tokens": 0
           },
           "completion_tokens_details": {
-            "reasoning_tokens": 128,
+            "reasoning_tokens": 64,
             "audio_tokens": 0,
             "accepted_prediction_tokens": 0,
             "rejected_prediction_tokens": 0
@@ -75,7 +75,7 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 3.940455375s
+    duration: 4.061672083s
 - id: 1
   request:
     proto: HTTP/1.1
@@ -83,7 +83,7 @@ interactions:
     proto_minor: 1
     content_length: 710
     host: ""
-    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_f7ty26Ui6FOEcr62i17rpqTm","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_f7ty26Ui6FOEcr62i17rpqTm","role":"tool"}],"model":"gpt-5","max_completion_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"}]}'
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_iENK0JiZIVgIwVhzXgr2vqAb","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_iENK0JiZIVgIwVhzXgr2vqAb","role":"tool"}],"model":"gpt-5","max_completion_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"}]}'
     headers:
       Accept:
       - application/json
@@ -101,16 +101,16 @@ interactions:
     uncompressed: true
     body: |
       {
-        "id": "chatcmpl-CK0XcDcYqMxxiRhTx5TCZV8YODtaI",
+        "id": "chatcmpl-CRdzFTi2wOwwtpFFMfez7pGHYh07c",
         "object": "chat.completion",
-        "created": 1758884676,
+        "created": 1760704601,
         "model": "gpt-5-2025-08-07",
         "choices": [
           {
             "index": 0,
             "message": {
               "role": "assistant",
-              "content": "Itโ€™s currently around 40ยฐC in Florence, Italy. Would you like details like conditions, wind, or a forecast?",
+              "content": "Itโ€™s currently about 40ยฐC (104ยฐF) in Florence, Italy. Would you like a forecast or more details (humidity, wind, etc.)?",
               "refusal": null,
               "annotations": []
             },
@@ -119,14 +119,14 @@ interactions:
         ],
         "usage": {
           "prompt_tokens": 176,
-          "completion_tokens": 226,
-          "total_tokens": 402,
+          "completion_tokens": 297,
+          "total_tokens": 473,
           "prompt_tokens_details": {
             "cached_tokens": 0,
             "audio_tokens": 0
           },
           "completion_tokens_details": {
-            "reasoning_tokens": 192,
+            "reasoning_tokens": 256,
             "audio_tokens": 0,
             "accepted_prediction_tokens": 0,
             "rejected_prediction_tokens": 0
@@ -140,4 +140,4 @@ interactions:
       - application/json
     status: 200 OK
     code: 200
-    duration: 4.914360584s
+    duration: 6.021670833s

providertests/testdata/TestOpenAICommon/openai-gpt-5/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,125 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 512
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"gpt-5","max_completion_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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_HclHssdmN42q5djc4MO0fnIH","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"wW0mB4WAi"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"Djas7aoZyHzDdg5"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"finish_reason":null}],"usage":null,"obfuscation":"9OsYZ12UtG"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"YIo7qOV9nxFX5"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"finish_reason":null}],"usage":null,"obfuscation":"0t9tM3wGusJNdp"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"finish_reason":null}],"usage":null,"obfuscation":"B5LwqW2HhJ6FQv"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"finish_reason":null}],"usage":null,"obfuscation":"4"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"finish_reason":null}],"usage":null,"obfuscation":"Bxlp9FKSsSrt"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"finish_reason":null}],"usage":null,"obfuscation":"zX7DDFi6nMXYRWx"}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null,"obfuscation":""}
+
+      data: {"id":"chatcmpl-CRdzLjfDek4NLenFzdYH7xA7ZwhXR","object":"chat.completion.chunk","created":1760704607,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":145,"completion_tokens":89,"total_tokens":234,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":64,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"9A0uIEuB"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 3.656144208s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 764
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_HclHssdmN42q5djc4MO0fnIH","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_HclHssdmN42q5djc4MO0fnIH","role":"tool"}],"model":"gpt-5","max_completion_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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"Zo8VekTq7A"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"It"},"finish_reason":null}],"usage":null,"obfuscation":"0XPFHlQbT1"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"โ€™s"},"finish_reason":null}],"usage":null,"obfuscation":"VqFEMOFD6V"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" currently"},"finish_reason":null}],"usage":null,"obfuscation":"05"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" about"},"finish_reason":null}],"usage":null,"obfuscation":"Hmjn6u"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" "},"finish_reason":null}],"usage":null,"obfuscation":"R6mJbjdENZ1"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"40"},"finish_reason":null}],"usage":null,"obfuscation":"aVWsABpE1B"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ยฐC"},"finish_reason":null}],"usage":null,"obfuscation":"vRN6vWf8xs"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" ("},"finish_reason":null}],"usage":null,"obfuscation":"qf1rIt73k5"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"104"},"finish_reason":null}],"usage":null,"obfuscation":"lkJ8qhLqA"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ยฐF"},"finish_reason":null}],"usage":null,"obfuscation":"x76W7W30bt"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":")"},"finish_reason":null}],"usage":null,"obfuscation":"X46lgG61m9r"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" in"},"finish_reason":null}],"usage":null,"obfuscation":"IXf4EbHLq"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Florence"},"finish_reason":null}],"usage":null,"obfuscation":"MQT"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":","},"finish_reason":null}],"usage":null,"obfuscation":"dxfY7jhGQdw"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Italy"},"finish_reason":null}],"usage":null,"obfuscation":"WKm2x1"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}],"usage":null,"obfuscation":"pCxaTBsDTC8"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"uEVTHt"}
+
+      data: {"id":"chatcmpl-CRdzPGEdWul8J6am5jOSgWZXVK6c8","object":"chat.completion.chunk","created":1760704611,"model":"gpt-5-2025-08-07","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":176,"completion_tokens":217,"total_tokens":393,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":192,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"PJkBnc"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 4.725152125s

providertests/testdata/TestOpenAICommon/openai-o4-mini/simple.yaml ๐Ÿ”—

@@ -0,0 +1,68 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 168
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"o4-mini","max_completion_tokens":4000}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "id": "chatcmpl-CRdzlFzVyGYYxdsq9AKdmXfr7MukL",
+        "object": "chat.completion",
+        "created": 1760704633,
+        "model": "o4-mini-2025-04-16",
+        "choices": [
+          {
+            "index": 0,
+            "message": {
+              "role": "assistant",
+              "content": "Olรก!",
+              "refusal": null,
+              "annotations": []
+            },
+            "finish_reason": "stop"
+          }
+        ],
+        "usage": {
+          "prompt_tokens": 19,
+          "completion_tokens": 84,
+          "total_tokens": 103,
+          "prompt_tokens_details": {
+            "cached_tokens": 0,
+            "audio_tokens": 0
+          },
+          "completion_tokens_details": {
+            "reasoning_tokens": 64,
+            "audio_tokens": 0,
+            "accepted_prediction_tokens": 0,
+            "rejected_prediction_tokens": 0
+          }
+        },
+        "service_tier": "default",
+        "system_fingerprint": null
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 2.321425625s

providertests/testdata/TestOpenAICommon/openai-o4-mini/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: 222
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"o4-mini","max_completion_tokens":4000,"stream_options":{"include_usage":true},"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdznBTZHwiwBn3wgDxF7dJBJmoV8","object":"chat.completion.chunk","created":1760704635,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"In0BspKy"}
+
+      data: {"id":"chatcmpl-CRdznBTZHwiwBn3wgDxF7dJBJmoV8","object":"chat.completion.chunk","created":1760704635,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"Oi"},"finish_reason":null}],"usage":null,"obfuscation":"RHZ9L7BA"}
+
+      data: {"id":"chatcmpl-CRdznBTZHwiwBn3wgDxF7dJBJmoV8","object":"chat.completion.chunk","created":1760704635,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"!"},"finish_reason":null}],"usage":null,"obfuscation":"X8LMBUcZV"}
+
+      data: {"id":"chatcmpl-CRdznBTZHwiwBn3wgDxF7dJBJmoV8","object":"chat.completion.chunk","created":1760704635,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"q1Yq"}
+
+      data: {"id":"chatcmpl-CRdznBTZHwiwBn3wgDxF7dJBJmoV8","object":"chat.completion.chunk","created":1760704635,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":19,"completion_tokens":148,"total_tokens":167,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":128,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"VkPeD"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 3.133094s

providertests/testdata/TestOpenAICommon/openai-o4-mini/tool.yaml ๐Ÿ”—

@@ -0,0 +1,143 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 460
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"o4-mini","max_completion_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"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "id": "chatcmpl-CRdzrg9Xy1ovxuEsdeaIh5HbAmzlq",
+        "object": "chat.completion",
+        "created": 1760704639,
+        "model": "o4-mini-2025-04-16",
+        "choices": [
+          {
+            "index": 0,
+            "message": {
+              "role": "assistant",
+              "content": null,
+              "tool_calls": [
+                {
+                  "id": "call_ZvgvJnyxcLxfnrw1vvy9QVMu",
+                  "type": "function",
+                  "function": {
+                    "name": "weather",
+                    "arguments": "{\"location\":\"Florence,Italy\"}"
+                  }
+                }
+              ],
+              "refusal": null,
+              "annotations": []
+            },
+            "finish_reason": "tool_calls"
+          }
+        ],
+        "usage": {
+          "prompt_tokens": 64,
+          "completion_tokens": 89,
+          "total_tokens": 153,
+          "prompt_tokens_details": {
+            "cached_tokens": 0,
+            "audio_tokens": 0
+          },
+          "completion_tokens_details": {
+            "reasoning_tokens": 64,
+            "audio_tokens": 0,
+            "accepted_prediction_tokens": 0,
+            "rejected_prediction_tokens": 0
+          }
+        },
+        "service_tier": "default",
+        "system_fingerprint": null
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 2.706478833s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 711
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_ZvgvJnyxcLxfnrw1vvy9QVMu","function":{"arguments":"{\"location\":\"Florence,Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_ZvgvJnyxcLxfnrw1vvy9QVMu","role":"tool"}],"model":"o4-mini","max_completion_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"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |
+      {
+        "id": "chatcmpl-CRdzu4C4EiqGRGJMYLhi1nnaygxRb",
+        "object": "chat.completion",
+        "created": 1760704642,
+        "model": "o4-mini-2025-04-16",
+        "choices": [
+          {
+            "index": 0,
+            "message": {
+              "role": "assistant",
+              "content": "The current temperature in Florence, Italy is 40ยฐC. It's quite hot, so stay hydrated and try to stay in the shade or indoors with air conditioning if you can!",
+              "refusal": null,
+              "annotations": []
+            },
+            "finish_reason": "stop"
+          }
+        ],
+        "usage": {
+          "prompt_tokens": 95,
+          "completion_tokens": 47,
+          "total_tokens": 142,
+          "prompt_tokens_details": {
+            "cached_tokens": 0,
+            "audio_tokens": 0
+          },
+          "completion_tokens_details": {
+            "reasoning_tokens": 0,
+            "audio_tokens": 0,
+            "accepted_prediction_tokens": 0,
+            "rejected_prediction_tokens": 0
+          }
+        },
+        "service_tier": "default",
+        "system_fingerprint": null
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 1.575507083s

providertests/testdata/TestOpenAICommon/openai-o4-mini/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,149 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 514
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"o4-mini","max_completion_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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":null,"tool_calls":[{"index":0,"id":"call_XevDuUMYIPg4YiA0oGOYlJTt","type":"function","function":{"name":"weather","arguments":""}}],"refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"kPmohDP"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"l8ZBA4sqknndZ"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"finish_reason":null}],"usage":null,"obfuscation":"uDtteUEc"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"finish_reason":null}],"usage":null,"obfuscation":"RLch0C57YvN"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ubrkTTBECEch"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"finish_reason":null}],"usage":null,"obfuscation":"ymKoTibZF2Wx"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"finish_reason":null}],"usage":null,"obfuscation":"lunIUN6UnqixGVS"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"finish_reason":null}],"usage":null,"obfuscation":"0R7CM90wrz"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"finish_reason":null}],"usage":null,"obfuscation":"UoUH2orSC5M6H"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"tool_calls"}],"usage":null,"obfuscation":"kyr6C4vgS6KpIx"}
+
+      data: {"id":"chatcmpl-CRdzvzjPGfHTfxYWBuHOE6Fqgbd3w","object":"chat.completion.chunk","created":1760704643,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":64,"completion_tokens":25,"total_tokens":89,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"BMYaOAORX"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 1.742662959s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 766
+    host: ""
+    body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"call_XevDuUMYIPg4YiA0oGOYlJTt","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"call_XevDuUMYIPg4YiA0oGOYlJTt","role":"tool"}],"model":"o4-mini","max_completion_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"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/chat/completions
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"role":"assistant","content":"","refusal":null},"finish_reason":null}],"usage":null,"obfuscation":"J9fqcxQ0"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"The"},"finish_reason":null}],"usage":null,"obfuscation":"9psTh4S"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" current"},"finish_reason":null}],"usage":null,"obfuscation":"qC"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" temperature"},"finish_reason":null}],"usage":null,"obfuscation":"IWaJutlGMgxvCa"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" in"},"finish_reason":null}],"usage":null,"obfuscation":"7GnoJrO"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Florence"},"finish_reason":null}],"usage":null,"obfuscation":"C"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":","},"finish_reason":null}],"usage":null,"obfuscation":"7uviSp1f4"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Italy"},"finish_reason":null}],"usage":null,"obfuscation":"OIuc"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" is"},"finish_reason":null}],"usage":null,"obfuscation":"FefXEvV"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" "},"finish_reason":null}],"usage":null,"obfuscation":"zMQLb8hcU"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"40"},"finish_reason":null}],"usage":null,"obfuscation":"dqTN5maD"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"ยฐC"},"finish_reason":null}],"usage":null,"obfuscation":"zmWzszVf"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"."},"finish_reason":null}],"usage":null,"obfuscation":"wcGkYYod2"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" Would"},"finish_reason":null}],"usage":null,"obfuscation":"Y3wl"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" you"},"finish_reason":null}],"usage":null,"obfuscation":"whFvbn"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" like"},"finish_reason":null}],"usage":null,"obfuscation":"zleYy"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" more"},"finish_reason":null}],"usage":null,"obfuscation":"LvKVS"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" details"},"finish_reason":null}],"usage":null,"obfuscation":"6S"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" ("},"finish_reason":null}],"usage":null,"obfuscation":"CN2vr0cw"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":"e"},"finish_reason":null}],"usage":null,"obfuscation":"MnqKVTshP"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".g"},"finish_reason":null}],"usage":null,"obfuscation":"3dgCtAmi"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":".,"},"finish_reason":null}],"usage":null,"obfuscation":"3PssNymm"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" humidity"},"finish_reason":null}],"usage":null,"obfuscation":"2"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":","},"finish_reason":null}],"usage":null,"obfuscation":"YOzesgDGD"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" wind"},"finish_reason":null}],"usage":null,"obfuscation":"WcWEd"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" speed"},"finish_reason":null}],"usage":null,"obfuscation":"22yU"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":","},"finish_reason":null}],"usage":null,"obfuscation":"YM4evRNHw"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":" forecast"},"finish_reason":null}],"usage":null,"obfuscation":"X"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{"content":")?"},"finish_reason":null}],"usage":null,"obfuscation":"kWnwQGZK"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[{"index":0,"delta":{},"finish_reason":"stop"}],"usage":null,"obfuscation":"u1V5"}
+
+      data: {"id":"chatcmpl-CRdzxUM84mYwaVLVUEQ0BMkH7N3rK","object":"chat.completion.chunk","created":1760704645,"model":"o4-mini-2025-04-16","service_tier":"default","system_fingerprint":null,"choices":[],"usage":{"prompt_tokens":95,"completion_tokens":40,"total_tokens":135,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"completion_tokens_details":{"reasoning_tokens":0,"audio_tokens":0,"accepted_prediction_tokens":0,"rejected_prediction_tokens":0}},"obfuscation":"WOSHdxIx"}
+
+      data: [DONE]
+
+    headers:
+      Content-Type:
+      - text/event-stream; charset=utf-8
+    status: 200 OK
+    code: 200
+    duration: 905.154333ms

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/multi_tool.yaml ๐Ÿ”—

@@ -0,0 +1,293 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 839
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":[{"text":"Add and multiply the number 2 and 3","type":"input_text"}],"role":"user"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"add","description":"Add two numbers","type":"function"},{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"multiply","description":"Multiply two numbers","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0e6e91029b6ada300168f237eec6608195ad0152f869ad01dc",
+        "object": "response",
+        "created_at": 1760704494,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-mini-2024-07-18",
+        "output": [
+          {
+            "id": "fc_0e6e91029b6ada300168f237efd70c8195aa55d25207351903",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"a\":2,\"b\":3}",
+            "call_id": "call_OHopAt0ZeLfG0Th5YYgklQUA",
+            "name": "add"
+          },
+          {
+            "id": "fc_0e6e91029b6ada300168f237f056848195b392f4da0c8c085c",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"a\":2,\"b\":3}",
+            "call_id": "call_CuDiIyPSC4zAkb7l4cjiEBot",
+            "name": "multiply"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "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"
+            },
+            "strict": false
+          },
+          {
+            "type": "function",
+            "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"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 54,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 50,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 104
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 1.986247916s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1266
+    host: ""

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/multi_tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,232 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 836
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system"},{"content":[{"text":"Add and multiply the number 2 and 3","type":"input_text"}],"role":"user"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"add","description":"Add two numbers","type":"function"},{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"multiply","description":"Multiply two numbers","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/simple.yaml ๐Ÿ”—

@@ -0,0 +1,100 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 210
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"gpt-4o-mini"}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_02fb59ed5cb3cadf0168f237e8ce908195baa9463cad5776cb",
+        "object": "response",
+        "created_at": 1760704488,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-mini-2024-07-18",
+        "output": [
+          {
+            "id": "msg_02fb59ed5cb3cadf0168f237e93f388195afee2cc6277cfaa0",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "Oi!"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 20,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 3,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 23
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 701.807792ms

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,62 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 224
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"gpt-4o-mini","stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_05eea6934a1b65980168f237e98214819693e879eb9deb3718","object":"response","created_at":1760704489,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_05eea6934a1b65980168f237e98214819693e879eb9deb3718","object":"response","created_at":1760704489,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","type":"message","status":"in_progress","content":[],"role":"assistant"}}
+
+      event: response.content_part.added
+      data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","output_index":0,"content_index":0,"delta":"Oi","logprobs":[],"obfuscation":"PLeCwMMZIiZ7tE"}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","output_index":0,"content_index":0,"delta":"!","logprobs":[],"obfuscation":"VYhGbSW2JCl6w1K"}
+
+      event: response.output_text.done
+      data: {"type":"response.output_text.done","sequence_number":6,"item_id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","output_index":0,"content_index":0,"text":"Oi!","logprobs":[]}
+
+      event: response.content_part.done
+      data: {"type":"response.content_part.done","sequence_number":7,"item_id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"Oi!"}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":8,"output_index":0,"item":{"id":"msg_05eea6934a1b65980168f237ea15448196bb4186395ed2288d","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Oi!"}],"role":"assistant"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/tool.yaml ๐Ÿ”—

@@ -0,0 +1,229 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 489
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_010f0015da2b88280168f237ea6c18819e8ce2b72d44ac08b4",
+        "object": "response",
+        "created_at": 1760704490,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-mini-2024-07-18",
+        "output": [
+          {
+            "id": "fc_010f0015da2b88280168f237eb2b7c819eae6470cdee55da77",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"location\":\"Florence, Italy\"}",
+            "call_id": "call_59vzLlFlML0RoHvlJxgWZZ7m",
+            "name": "weather"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 58,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 17,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 75
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 1.0454615s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 724
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"},{"arguments":"\"{\\\"location\\\":\\\"Florence, Italy\\\"}\"","call_id":"call_59vzLlFlML0RoHvlJxgWZZ7m","name":"weather","type":"function_call"},{"call_id":"call_59vzLlFlML0RoHvlJxgWZZ7m","output":"40 C","type":"function_call_output"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0de529b5396cb7cc0168f237eb7d9c81a3aca3fef6a9749a5f",
+        "object": "response",
+        "created_at": 1760704491,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-mini-2024-07-18",
+        "output": [
+          {
+            "id": "msg_0de529b5396cb7cc0168f237ebf0ec81a39a23afc61ca30582",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "The current temperature in Florence, Italy, is 40\u00b0C. If you need more details like humidity or forecast, just let me know!"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 83,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 30,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 113
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 1.421569667s

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o-mini/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,211 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 503
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-4o-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0915a342b22b18d50168f237ece814819fbbac6dc48dd0edb2","object":"response","created_at":1760704492,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0915a342b22b18d50168f237ece814819fbbac6dc48dd0edb2","object":"response","created_at":1760704492,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-mini-2024-07-18","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","type":"function_call","status":"in_progress","arguments":"","call_id":"call_ytBD13XK47ACiCTAyn4RZCSb","name":"weather"}}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":3,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":"{\"","obfuscation":"Hrtnjbqy71fTf2"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":4,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":"location","obfuscation":"pzYupDDV"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":5,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":"\":\"","obfuscation":"l8BCOLb4pKgPH"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":6,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":"Flor","obfuscation":"XuNP9JDMdMXF"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":7,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":"ence","obfuscation":"TFnsqDERhUnk"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":8,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":",","obfuscation":"Ot0Lx95tLZ6T2MK"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":9,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":" Italy","obfuscation":"6x0z1jEIf7"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":10,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"delta":"\"}","obfuscation":"XxvQGBcCf9Gh8t"}
+
+      event: response.function_call_arguments.done
+      data: {"type":"response.function_call_arguments.done","sequence_number":11,"item_id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","output_index":0,"arguments":"{\"location\":\"Florence, Italy\"}"}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":12,"output_index":0,"item":{"id":"fc_0915a342b22b18d50168f237ed7be4819fb7686ac852408033","type":"function_call","status":"completed","arguments":"{\"location\":\"Florence, Italy\"}","call_id":"call_ytBD13XK47ACiCTAyn4RZCSb","name":"weather"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/multi_tool.yaml ๐Ÿ”—

@@ -0,0 +1,293 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 834
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":[{"text":"Add and multiply the number 2 and 3","type":"input_text"}],"role":"user"}],"model":"gpt-4o","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"add","description":"Add two numbers","type":"function"},{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"multiply","description":"Multiply two numbers","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0e4ad943aeeb6f440168f237e4ba68819d82d960503add3455",
+        "object": "response",
+        "created_at": 1760704484,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-2024-08-06",
+        "output": [
+          {
+            "id": "fc_0e4ad943aeeb6f440168f237e55708819dbb4bacb951338226",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"a\":2,\"b\":3}",
+            "call_id": "call_fWTsR6VaKuyav2YHicLHxgUu",
+            "name": "add"
+          },
+          {
+            "id": "fc_0e4ad943aeeb6f440168f237e57510819db015d8ff8e768bdb",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"a\":2,\"b\":3}",
+            "call_id": "call_KLpoIGIQ4rbE8b3AWCUaui6g",
+            "name": "multiply"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "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"
+            },
+            "strict": false
+          },
+          {
+            "type": "function",
+            "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"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 54,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 50,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 104
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 991.245209ms
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1261
+    host: ""

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/multi_tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,211 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 831
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system"},{"content":[{"text":"Add and multiply the number 2 and 3","type":"input_text"}],"role":"user"}],"model":"gpt-4o","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"add","description":"Add two numbers","type":"function"},{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"multiply","description":"Multiply two numbers","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/simple.yaml ๐Ÿ”—

@@ -0,0 +1,100 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 205
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"gpt-4o"}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_07891da4b653e1470168f237de167081909c53deff29e333b8",
+        "object": "response",
+        "created_at": 1760704478,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-2024-08-06",
+        "output": [
+          {
+            "id": "msg_07891da4b653e1470168f237deab0c8190be2fd9591e3d9afa",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "Ol\u00e1!"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 20,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 3,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 23
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 941.245125ms

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,62 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 219
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"gpt-4o","stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_02a83fea833f7e430168f237dee7b08192a3ee0794d16e8574","object":"response","created_at":1760704478,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_02a83fea833f7e430168f237dee7b08192a3ee0794d16e8574","object":"response","created_at":1760704478,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","type":"message","status":"in_progress","content":[],"role":"assistant"}}
+
+      event: response.content_part.added
+      data: {"type":"response.content_part.added","sequence_number":3,"item_id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":4,"item_id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","output_index":0,"content_index":0,"delta":"Olรก","logprobs":[],"obfuscation":"PURwA0yAiQYg4"}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":5,"item_id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","output_index":0,"content_index":0,"delta":"!","logprobs":[],"obfuscation":"J47DmBbNkTc5h5k"}
+
+      event: response.output_text.done
+      data: {"type":"response.output_text.done","sequence_number":6,"item_id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","output_index":0,"content_index":0,"text":"Olรก!","logprobs":[]}
+
+      event: response.content_part.done
+      data: {"type":"response.content_part.done","sequence_number":7,"item_id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","output_index":0,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"Olรก!"}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":8,"output_index":0,"item":{"id":"msg_02a83fea833f7e430168f237df67988192ae502a743f847a80","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Olรก!"}],"role":"assistant"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/tool.yaml ๐Ÿ”—

@@ -0,0 +1,229 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 484
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-4o","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_05f862a82ed768dc0168f237df9eac81a09b83a647320323a6",
+        "object": "response",
+        "created_at": 1760704479,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-2024-08-06",
+        "output": [
+          {
+            "id": "fc_05f862a82ed768dc0168f237e0123c81a090b0b89afe5c9f72",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"location\":\"Florence, Italy\"}",
+            "call_id": "call_jPXpCiiHqnkbYK8RbeLZfkLR",
+            "name": "weather"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 58,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 17,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 75
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 777.148541ms
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 719
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"},{"arguments":"\"{\\\"location\\\":\\\"Florence, Italy\\\"}\"","call_id":"call_jPXpCiiHqnkbYK8RbeLZfkLR","name":"weather","type":"function_call"},{"call_id":"call_jPXpCiiHqnkbYK8RbeLZfkLR","output":"40 C","type":"function_call_output"}],"model":"gpt-4o","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0122dddaaa9675250168f237e06e9481948f2a870e82765495",
+        "object": "response",
+        "created_at": 1760704480,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-4o-2024-08-06",
+        "output": [
+          {
+            "id": "msg_0122dddaaa9675250168f237e16ed481948bdad89376f1431a",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "The current temperature in Florence, Italy is 40\u00b0C. Stay cool and hydrated!"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": null,
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 83,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 19,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 102
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 1.512680875s

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-4o/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,163 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 498
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"system"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-4o","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0ac5f2ba0b4c0b830168f237e1ee10819dbe53070aa00ae06a","object":"response","created_at":1760704481,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0ac5f2ba0b4c0b830168f237e1ee10819dbe53070aa00ae06a","object":"response","created_at":1760704481,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-4o-2024-08-06","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":null,"summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","type":"function_call","status":"in_progress","arguments":"","call_id":"call_Zvcj4GFYqfvf8AcNIB0Ra8is","name":"weather"}}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":3,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"{\"","obfuscation":"2GAUmPtuwiNdYV"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":4,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"location","obfuscation":"au0PIDR3"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":5,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"\":\"","obfuscation":"FJYeCiQOcRosn"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":6,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"Flor","obfuscation":"E9SXHAGEvpMC"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":7,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"ence","obfuscation":"Sezl9leQQI91"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":8,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":",","obfuscation":"EL65bbUJbktS4Tq"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":9,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"Italy","obfuscation":"3paXU4gUFjJ"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":10,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"delta":"\"}","obfuscation":"RWw8uxX409IAgP"}
+
+      event: response.function_call_arguments.done
+      data: {"type":"response.function_call_arguments.done","sequence_number":11,"item_id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","output_index":0,"arguments":"{\"location\":\"Florence,Italy\"}"}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":12,"output_index":0,"item":{"id":"fc_0ac5f2ba0b4c0b830168f237e2f3d0819d8b008d01089913c8","type":"function_call","status":"completed","arguments":"{\"location\":\"Florence,Italy\"}","call_id":"call_Zvcj4GFYqfvf8AcNIB0Ra8is","name":"weather"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/multi_tool.yaml ๐Ÿ”—

@@ -0,0 +1,298 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 836
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"developer"},{"content":[{"text":"Add and multiply the number 2 and 3","type":"input_text"}],"role":"user"}],"model":"gpt-5","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"add","description":"Add two numbers","type":"function"},{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"multiply","description":"Multiply two numbers","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0a67406c0312cd3d0168f23808e21081a19469bdae7c79e9a1",
+        "object": "response",
+        "created_at": 1760704520,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-5-2025-08-07",
+        "output": [
+          {
+            "id": "rs_0a67406c0312cd3d0168f238093ecc81a1bdba7329dca10274",
+            "type": "reasoning",
+            "summary": []
+          },
+          {
+            "id": "fc_0a67406c0312cd3d0168f2380c363c81a185a8cb8507231fa5",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"a\":2,\"b\":3}",
+            "call_id": "call_4zp4utiXe14bjLO4jtMZEjT9",
+            "name": "add"
+          },
+          {
+            "id": "fc_0a67406c0312cd3d0168f2380c544081a18909136702882f58",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"a\":2,\"b\":3}",
+            "call_id": "call_4RkbJhNCkvdVClgNEsmTa3lb",
+            "name": "multiply"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "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"
+            },
+            "strict": false
+          },
+          {
+            "type": "function",
+            "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"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 58,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 248,
+          "output_tokens_details": {
+            "reasoning_tokens": 192
+          },
+          "total_tokens": 306
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 3.821118208s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 1263
+    host: ""

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/multi_tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,202 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 833
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"developer"},{"content":[{"text":"Add and multiply the number 2 and 3","type":"input_text"}],"role":"user"}],"model":"gpt-5","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"add","description":"Add two numbers","type":"function"},{"strict":false,"parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"},"name":"multiply","description":"Multiply two numbers","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/simple.yaml ๐Ÿ”—

@@ -0,0 +1,105 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 207
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"gpt-5"}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0b81ac5fdc5483560168f237f54ccc81968efa75aba7162889",
+        "object": "response",
+        "created_at": 1760704501,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-5-2025-08-07",
+        "output": [
+          {
+            "id": "rs_0b81ac5fdc5483560168f237f6618881968521aadd267daa6a",
+            "type": "reasoning",
+            "summary": []
+          },
+          {
+            "id": "msg_0b81ac5fdc5483560168f237f84b6c81968619287b3bf9dee9",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "Oi!"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 19,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 136,
+          "output_tokens_details": {
+            "reasoning_tokens": 128
+          },
+          "total_tokens": 155
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 3.478110792s

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,68 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 221
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"gpt-5","stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_06f879733b735e3a0168f237f8c33481a2ba14b36d6b67d967","object":"response","created_at":1760704504,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-5-2025-08-07","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_06f879733b735e3a0168f237f8c33481a2ba14b36d6b67d967","object":"response","created_at":1760704504,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-5-2025-08-07","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"rs_06f879733b735e3a0168f237f941a481a28d55b9bcf8fe577c","type":"reasoning","summary":[]}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"rs_06f879733b735e3a0168f237f941a481a28d55b9bcf8fe577c","type":"reasoning","summary":[]}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":4,"output_index":1,"item":{"id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","type":"message","status":"in_progress","content":[],"role":"assistant"}}
+
+      event: response.content_part.added
+      data: {"type":"response.content_part.added","sequence_number":5,"item_id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","output_index":1,"content_index":0,"delta":"Olรก","logprobs":[],"obfuscation":"UqLDi4LzR6EDJ"}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","output_index":1,"content_index":0,"delta":"!","logprobs":[],"obfuscation":"nohgR94nfxqT0xc"}
+
+      event: response.output_text.done
+      data: {"type":"response.output_text.done","sequence_number":8,"item_id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","output_index":1,"content_index":0,"text":"Olรก!","logprobs":[]}
+
+      event: response.content_part.done
+      data: {"type":"response.content_part.done","sequence_number":9,"item_id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"Olรก!"}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":10,"output_index":1,"item":{"id":"msg_06f879733b735e3a0168f237fac9c481a2b3a561bc2c54232c","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Olรก!"}],"role":"assistant"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/tool.yaml ๐Ÿ”—

@@ -0,0 +1,239 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 486
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-5","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_03c1862e0741d1d40168f237fb21e88191bbe5c97d0994130f",
+        "object": "response",
+        "created_at": 1760704507,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-5-2025-08-07",
+        "output": [
+          {
+            "id": "rs_03c1862e0741d1d40168f237fb807c819194656e80eb126a65",
+            "type": "reasoning",
+            "summary": []
+          },
+          {
+            "id": "fc_03c1862e0741d1d40168f237fce0c88191a227de0e0fc29c2c",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"location\":\"Florence, Italy\"}",
+            "call_id": "call_pG7sDgSfcLvcZrGGJrH3Z3aQ",
+            "name": "weather"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 66,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 86,
+          "output_tokens_details": {
+            "reasoning_tokens": 64
+          },
+          "total_tokens": 152
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 2.09006325s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 721
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"},{"arguments":"\"{\\\"location\\\":\\\"Florence, Italy\\\"}\"","call_id":"call_pG7sDgSfcLvcZrGGJrH3Z3aQ","name":"weather","type":"function_call"},{"call_id":"call_pG7sDgSfcLvcZrGGJrH3Z3aQ","output":"40 C","type":"function_call_output"}],"model":"gpt-5","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_00c0656fa55dff4a0168f237fd3b9c8196bd4e4de8737e9452",
+        "object": "response",
+        "created_at": 1760704509,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "gpt-5-2025-08-07",
+        "output": [
+          {
+            "id": "rs_00c0656fa55dff4a0168f237fdc064819691999ce73a7ce97a",
+            "type": "reasoning",
+            "summary": []
+          },
+          {
+            "id": "msg_00c0656fa55dff4a0168f2380148748196b3987065a61dba12",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "Right now in Florence, Italy it\u2019s about 40\u00b0C. Would you like the forecast or details like humidity and wind?"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 97,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 287,
+          "output_tokens_details": {
+            "reasoning_tokens": 256
+          },
+          "total_tokens": 384
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 4.618793667s

providertests/testdata/TestOpenAIResponsesCommon/openai-gpt-5/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,217 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 500
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-5","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0f08b04cd21bd82c0168f23801d5c881a2b0d9b07784b8413a","object":"response","created_at":1760704513,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-5-2025-08-07","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0f08b04cd21bd82c0168f23801d5c881a2b0d9b07784b8413a","object":"response","created_at":1760704513,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"gpt-5-2025-08-07","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"rs_0f08b04cd21bd82c0168f2380221f881a290014a36b8e479a4","type":"reasoning","summary":[]}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"rs_0f08b04cd21bd82c0168f2380221f881a290014a36b8e479a4","type":"reasoning","summary":[]}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":4,"output_index":1,"item":{"id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","type":"function_call","status":"in_progress","arguments":"","call_id":"call_kGfQAVJ6MRnp9dXE2d0uYojD","name":"weather"}}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":5,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":"{\"","obfuscation":"xcxYsutrsF2Mr3"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":6,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":"location","obfuscation":"wSCxPmqE"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":7,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":"\":\"","obfuscation":"UNB0sKeiNNVya"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":8,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":"Flor","obfuscation":"nmio6Y5KgBCY"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":9,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":"ence","obfuscation":"dnccg49kl0GV"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":10,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":",","obfuscation":"zwu8CHinn8HhyUq"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":11,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":" Italy","obfuscation":"JrzifooHsu"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":12,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"delta":"\"}","obfuscation":"EOPhpWvCbvwgkS"}
+
+      event: response.function_call_arguments.done
+      data: {"type":"response.function_call_arguments.done","sequence_number":13,"item_id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","output_index":1,"arguments":"{\"location\":\"Florence, Italy\"}"}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":14,"output_index":1,"item":{"id":"fc_0f08b04cd21bd82c0168f23803cc1481a28dc92074ab71c2e0","type":"function_call","status":"completed","arguments":"{\"location\":\"Florence, Italy\"}","call_id":"call_kGfQAVJ6MRnp9dXE2d0uYojD","name":"weather"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/simple.yaml ๐Ÿ”—

@@ -0,0 +1,105 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 209
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"o4-mini"}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_05edda4810c41de00168f23812e34481909c921eeab19085a0",
+        "object": "response",
+        "created_at": 1760704531,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "o4-mini-2025-04-16",
+        "output": [
+          {
+            "id": "rs_05edda4810c41de00168f2381383e08190b96c0313059265a9",
+            "type": "reasoning",
+            "summary": []
+          },
+          {
+            "id": "msg_05edda4810c41de00168f23814db48819083a54f56411e35a5",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "Oi!"
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 19,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 136,
+          "output_tokens_details": {
+            "reasoning_tokens": 128
+          },
+          "total_tokens": 155
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 2.327569333s

providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/simple_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,68 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 223
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"Say hi in Portuguese","type":"input_text"}],"role":"user"}],"model":"o4-mini","stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0374dd39c9ea81bb0168f2381531e88192bcc27c60d5000651","object":"response","created_at":1760704533,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"o4-mini-2025-04-16","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0374dd39c9ea81bb0168f2381531e88192bcc27c60d5000651","object":"response","created_at":1760704533,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"o4-mini-2025-04-16","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"rs_0374dd39c9ea81bb0168f23815fe108192a9693e4138d05838","type":"reasoning","summary":[]}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"rs_0374dd39c9ea81bb0168f23815fe108192a9693e4138d05838","type":"reasoning","summary":[]}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":4,"output_index":1,"item":{"id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","type":"message","status":"in_progress","content":[],"role":"assistant"}}
+
+      event: response.content_part.added
+      data: {"type":"response.content_part.added","sequence_number":5,"item_id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":""}}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":6,"item_id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","output_index":1,"content_index":0,"delta":"Olรก","logprobs":[],"obfuscation":"XyHUJi8uWmgQ3"}
+
+      event: response.output_text.delta
+      data: {"type":"response.output_text.delta","sequence_number":7,"item_id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","output_index":1,"content_index":0,"delta":"!","logprobs":[],"obfuscation":"CKZwM0j52RoATdL"}
+
+      event: response.output_text.done
+      data: {"type":"response.output_text.done","sequence_number":8,"item_id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","output_index":1,"content_index":0,"text":"Olรก!","logprobs":[]}
+
+      event: response.content_part.done
+      data: {"type":"response.content_part.done","sequence_number":9,"item_id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","output_index":1,"content_index":0,"part":{"type":"output_text","annotations":[],"logprobs":[],"text":"Olรก!"}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":10,"output_index":1,"item":{"id":"msg_0374dd39c9ea81bb0168f23816fc108192bbffb179beace674","type":"message","status":"completed","content":[{"type":"output_text","annotations":[],"logprobs":[],"text":"Olรก!"}],"role":"assistant"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/tool.yaml ๐Ÿ”—

@@ -0,0 +1,234 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 488
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"o4-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_063e69ebba23c6e60168f238176014819580347bfecdcc350e",
+        "object": "response",
+        "created_at": 1760704535,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "o4-mini-2025-04-16",
+        "output": [
+          {
+            "id": "rs_063e69ebba23c6e60168f2381811ac8195bb719fa83683583a",
+            "type": "reasoning",
+            "summary": []
+          },
+          {
+            "id": "fc_063e69ebba23c6e60168f238191b248195a04018e0d0c747bb",
+            "type": "function_call",
+            "status": "completed",
+            "arguments": "{\"location\":\"Florence, Italy\"}",
+            "call_id": "call_3gTKulKFbPDpkRO7k5I0ffH2",
+            "name": "weather"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 60,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 150,
+          "output_tokens_details": {
+            "reasoning_tokens": 128
+          },
+          "total_tokens": 210
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 2.194950333s
+- id: 1
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 723
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"},{"arguments":"\"{\\\"location\\\":\\\"Florence, Italy\\\"}\"","call_id":"call_3gTKulKFbPDpkRO7k5I0ffH2","name":"weather","type":"function_call"},{"call_id":"call_3gTKulKFbPDpkRO7k5I0ffH2","output":"40 C","type":"function_call_output"}],"model":"o4-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0bed20b0e88328550168f238198a5c81a0947a649d11fb2237",
+        "object": "response",
+        "created_at": 1760704537,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": 4000,
+        "max_tool_calls": null,
+        "model": "o4-mini-2025-04-16",
+        "output": [
+          {
+            "id": "msg_0bed20b0e88328550168f23819fad081a090a3ce83d605449e",
+            "type": "message",
+            "status": "completed",
+            "content": [
+              {
+                "type": "output_text",
+                "annotations": [],
+                "logprobs": [],
+                "text": "The current temperature in Florence, Italy is 40\u00b0C. It\u2019s quite hot! Make sure to stay hydrated, wear light clothing, and seek shade or air-conditioned places when possible. If you plan to be outdoors, consider going early in the morning or later in the evening to avoid peak heat."
+              }
+            ],
+            "role": "assistant"
+          }
+        ],
+        "parallel_tool_calls": true,
+        "previous_response_id": null,
+        "prompt_cache_key": null,
+        "reasoning": {
+          "effort": "medium",
+          "summary": null
+        },
+        "safety_identifier": null,
+        "service_tier": "default",
+        "store": false,
+        "temperature": 1.0,
+        "text": {
+          "format": {
+            "type": "text"
+          },
+          "verbosity": "medium"
+        },
+        "tool_choice": "auto",
+        "tools": [
+          {
+            "type": "function",
+            "description": "Get weather information for a location",
+            "name": "weather",
+            "parameters": {
+              "properties": {
+                "location": {
+                  "description": "the city",
+                  "type": "string"
+                }
+              },
+              "required": [
+                "location"
+              ],
+              "type": "object"
+            },
+            "strict": false
+          }
+        ],
+        "top_logprobs": 0,
+        "top_p": 1.0,
+        "truncation": "disabled",
+        "usage": {
+          "input_tokens": 91,
+          "input_tokens_details": {
+            "cached_tokens": 0
+          },
+          "output_tokens": 64,
+          "output_tokens_details": {
+            "reasoning_tokens": 0
+          },
+          "total_tokens": 155
+        },
+        "user": null,
+        "metadata": {}
+      }
+    headers:
+      Content-Type:
+      - application/json
+    status: 200 OK
+    code: 200
+    duration: 1.272683542s

providertests/testdata/TestOpenAIResponsesCommon/openai-o4-mini/tool_streaming.yaml ๐Ÿ”—

@@ -0,0 +1,169 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 502
+    host: ""
+    body: '{"max_output_tokens":4000,"store":false,"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence,Italy?","type":"input_text"}],"role":"user"}],"model":"o4-mini","tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0fff4a7c1f563e500168f2381ad21c819e8d405acd7b5d620a","object":"response","created_at":1760704538,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"o4-mini-2025-04-16","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0fff4a7c1f563e500168f2381ad21c819e8d405acd7b5d620a","object":"response","created_at":1760704538,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":4000,"max_tool_calls":null,"model":"o4-mini-2025-04-16","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"medium","summary":null},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":2,"output_index":0,"item":{"id":"rs_0fff4a7c1f563e500168f2381b32b0819ead0ce19c5404dec1","type":"reasoning","summary":[]}}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":3,"output_index":0,"item":{"id":"rs_0fff4a7c1f563e500168f2381b32b0819ead0ce19c5404dec1","type":"reasoning","summary":[]}}
+
+      event: response.output_item.added
+      data: {"type":"response.output_item.added","sequence_number":4,"output_index":1,"item":{"id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","type":"function_call","status":"in_progress","arguments":"","call_id":"call_UszlYsP9zWWt4KA9WuQwyxdm","name":"weather"}}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":5,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":"{\"","obfuscation":"0VOTJGynsRMloj"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":6,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":"location","obfuscation":"43dCYsDX"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":7,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":"\":\"","obfuscation":"rc3sKD04Npkkf"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":8,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":"Flor","obfuscation":"s3bnH4WQP4Cb"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":9,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":"ence","obfuscation":"y9JNPlQMT6YX"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":10,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":",","obfuscation":"w8Zt7ULkOyHEuSK"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":11,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":" Italy","obfuscation":"6GaIjNSMTu"}
+
+      event: response.function_call_arguments.delta
+      data: {"type":"response.function_call_arguments.delta","sequence_number":12,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"delta":"\"}","obfuscation":"4eavzEAMPbOXlx"}
+
+      event: response.function_call_arguments.done
+      data: {"type":"response.function_call_arguments.done","sequence_number":13,"item_id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","output_index":1,"arguments":"{\"location\":\"Florence, Italy\"}"}
+
+      event: response.output_item.done
+      data: {"type":"response.output_item.done","sequence_number":14,"output_index":1,"item":{"id":"fc_0fff4a7c1f563e500168f2381c9e38819e9f1631fafe9b714d","type":"function_call","status":"completed","arguments":"{\"location\":\"Florence, Italy\"}","call_id":"call_UszlYsP9zWWt4KA9WuQwyxdm","name":"weather"}}
+
+      event: response.completed

providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-gpt-5/thinking-streaming.yaml ๐Ÿ”—

@@ -0,0 +1,499 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 565
+    host: ""
+    body: '{"store":false,"include":["reasoning.encrypted_content"],"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence, Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-5","reasoning":{"effort":"high","summary":"auto"},"tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_00564a370f8761470168f239a3f90c819492eb21bd9b25c369","object":"response","created_at":1760704932,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-2025-08-07","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"high","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_00564a370f8761470168f239a3f90c819492eb21bd9b25c369","object":"response","created_at":1760704932,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"gpt-5-2025-08-07","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"high","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added

providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-gpt-5/thinking.yaml ๐Ÿ”—

@@ -0,0 +1,259 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 551
+    host: ""
+    body: '{"store":false,"include":["reasoning.encrypted_content"],"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence, Italy?","type":"input_text"}],"role":"user"}],"model":"gpt-5","reasoning":{"effort":"high","summary":"auto"},"tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_0e319212d3811f510168f2398edbc8819eb99fffb643dfa9c3",
+        "object": "response",
+        "created_at": 1760704910,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": null,
+        "max_tool_calls": null,
+        "model": "gpt-5-2025-08-07",
+        "output": [
+          {
+            "id": "rs_0e319212d3811f510168f2398f6140819ea426c36bb590abee",
+            "type": "reasoning",

providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-o4-mini/thinking-streaming.yaml ๐Ÿ”—

@@ -0,0 +1,232 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 567
+    host: ""
+    body: '{"store":false,"include":["reasoning.encrypted_content"],"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence, Italy?","type":"input_text"}],"role":"user"}],"model":"o4-mini","reasoning":{"effort":"high","summary":"auto"},"tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}],"stream":true}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    body: |+
+      event: response.created
+      data: {"type":"response.created","sequence_number":0,"response":{"id":"resp_0d54375cbcd869820168f239bca94c819cb1dd488b92e67279","object":"response","created_at":1760704956,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"o4-mini-2025-04-16","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"high","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.in_progress
+      data: {"type":"response.in_progress","sequence_number":1,"response":{"id":"resp_0d54375cbcd869820168f239bca94c819cb1dd488b92e67279","object":"response","created_at":1760704956,"status":"in_progress","background":false,"error":null,"incomplete_details":null,"instructions":null,"max_output_tokens":null,"max_tool_calls":null,"model":"o4-mini-2025-04-16","output":[],"parallel_tool_calls":true,"previous_response_id":null,"prompt_cache_key":null,"reasoning":{"effort":"high","summary":"detailed"},"safety_identifier":null,"service_tier":"auto","store":false,"temperature":1.0,"text":{"format":{"type":"text"},"verbosity":"medium"},"tool_choice":"auto","tools":[{"type":"function","description":"Get weather information for a location","name":"weather","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"strict":false}],"top_logprobs":0,"top_p":1.0,"truncation":"disabled","usage":null,"user":null,"metadata":{}}}
+
+      event: response.output_item.added

providertests/testdata/TestOpenAIResponsesWithSummaryThinking/openai-o4-mini/thinking.yaml ๐Ÿ”—

@@ -0,0 +1,235 @@
+---
+version: 2
+interactions:
+- id: 0
+  request:
+    proto: HTTP/1.1
+    proto_major: 1
+    proto_minor: 1
+    content_length: 553
+    host: ""
+    body: '{"store":false,"include":["reasoning.encrypted_content"],"input":[{"content":"You are a helpful assistant","role":"developer"},{"content":[{"text":"What''s the weather in Florence, Italy?","type":"input_text"}],"role":"user"}],"model":"o4-mini","reasoning":{"effort":"high","summary":"auto"},"tool_choice":"auto","tools":[{"strict":false,"parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location","type":"function"}]}'
+    headers:
+      Accept:
+      - application/json
+      Content-Type:
+      - application/json
+      User-Agent:
+      - OpenAI/Go 2.3.0
+    url: https://api.openai.com/v1/responses
+    method: POST
+  response:
+    proto: HTTP/2.0
+    proto_major: 2
+    proto_minor: 0
+    content_length: -1
+    uncompressed: true
+    body: |-
+      {
+        "id": "resp_00f45739b037a2600168f239ace760819697f5959cb071a64f",
+        "object": "response",
+        "created_at": 1760704941,
+        "status": "completed",
+        "background": false,
+        "billing": {
+          "payer": "developer"
+        },
+        "error": null,
+        "incomplete_details": null,
+        "instructions": null,
+        "max_output_tokens": null,
+        "max_tool_calls": null,
+        "model": "o4-mini-2025-04-16",
+        "output": [
+          {
+            "id": "rs_00f45739b037a2600168f239ada3208196b9f9ec02572cc644",
+            "type": "reasoning",