From 30a5f02b59547fedbaee550ce58e991c87809fae Mon Sep 17 00:00:00 2001 From: Kujtim Hoxha Date: Mon, 2 Feb 2026 15:11:01 +0100 Subject: [PATCH] feat: add vercel provider (#129) --- providers/vercel/language_model_hooks.go | 1052 +++++++++++++++++ providers/vercel/provider_options.go | 191 +++ providers/vercel/vercel.go | 114 ++ .../claude-sonnet-4/multi_tool.yaml | 63 + .../claude-sonnet-4/multi_tool_streaming.yaml | 113 ++ .../claude-sonnet-4/simple.yaml | 33 + .../claude-sonnet-4/simple_streaming.yaml | 62 + .../claude-sonnet-4/tool.yaml | 63 + .../claude-sonnet-4/tool_streaming.yaml | 121 ++ .../gemini-2.5-flash/multi_tool.yaml | 63 + .../multi_tool_streaming.yaml | 87 ++ .../gemini-2.5-flash/simple.yaml | 33 + .../gemini-2.5-flash/simple_streaming.yaml | 40 + .../gemini-2.5-flash/tool.yaml | 63 + .../gemini-2.5-flash/tool_streaming.yaml | 81 ++ .../gemini-3-pro-preview/multi_tool.yaml | 63 + .../multi_tool_streaming.yaml | 85 ++ .../gemini-3-pro-preview/simple.yaml | 33 + .../simple_streaming.yaml | 42 + .../gemini-3-pro-preview/tool.yaml | 63 + .../gemini-3-pro-preview/tool_streaming.yaml | 81 ++ .../TestVercelCommon/gpt-5/multi_tool.yaml | 63 + .../gpt-5/multi_tool_streaming.yaml | 101 ++ .../TestVercelCommon/gpt-5/simple.yaml | 33 + .../gpt-5/simple_streaming.yaml | 44 + .../testdata/TestVercelCommon/gpt-5/tool.yaml | 63 + .../gpt-5/tool_streaming.yaml | 119 ++ .../claude-sonnet-4/multi_tool.yaml | 63 + .../claude-sonnet-4/multi_tool_streaming.yaml | 119 ++ .../claude-sonnet-4/simple.yaml | 33 + .../claude-sonnet-4/simple_streaming.yaml | 60 + .../claude-sonnet-4/tool.yaml | 63 + .../claude-sonnet-4/tool_streaming.yaml | 117 ++ .../thinking-streaming.yaml | 137 +++ .../claude-sonnet-4-sig/thinking.yaml | 63 + .../claude-sonnet-4/thinking-streaming.yaml | 171 +++ .../claude-sonnet-4/thinking.yaml | 63 + .../thinking-streaming.yaml | 87 ++ .../gemini-3-pro-preview/thinking.yaml | 63 + .../gpt-5/thinking-streaming.yaml | 343 ++++++ .../TestVercelThinking/gpt-5/thinking.yaml | 63 + providertests/vercel_test.go | 124 ++ 42 files changed, 4538 insertions(+) create mode 100644 providers/vercel/language_model_hooks.go create mode 100644 providers/vercel/provider_options.go create mode 100644 providers/vercel/vercel.go create mode 100644 providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/claude-sonnet-4/simple.yaml create mode 100644 providertests/testdata/TestVercelCommon/claude-sonnet-4/simple_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/claude-sonnet-4/tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/claude-sonnet-4/tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gpt-5/multi_tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/gpt-5/multi_tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gpt-5/simple.yaml create mode 100644 providertests/testdata/TestVercelCommon/gpt-5/simple_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommon/gpt-5/tool.yaml create mode 100644 providertests/testdata/TestVercelCommon/gpt-5/tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool.yaml create mode 100644 providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple.yaml create mode 100644 providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple_streaming.yaml create mode 100644 providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool.yaml create mode 100644 providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool_streaming.yaml create mode 100644 providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking-streaming.yaml create mode 100644 providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking.yaml create mode 100644 providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking-streaming.yaml create mode 100644 providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking.yaml create mode 100644 providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking-streaming.yaml create mode 100644 providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking.yaml create mode 100644 providertests/testdata/TestVercelThinking/gpt-5/thinking-streaming.yaml create mode 100644 providertests/testdata/TestVercelThinking/gpt-5/thinking.yaml create mode 100644 providertests/vercel_test.go diff --git a/providers/vercel/language_model_hooks.go b/providers/vercel/language_model_hooks.go new file mode 100644 index 0000000000000000000000000000000000000000..d243e57f65d982b9d7739aeda1f1a6addbe4f868 --- /dev/null +++ b/providers/vercel/language_model_hooks.go @@ -0,0 +1,1052 @@ +package vercel + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "maps" + "strings" + + "charm.land/fantasy" + "charm.land/fantasy/providers/anthropic" + "charm.land/fantasy/providers/google" + openaipkg "charm.land/fantasy/providers/openai" + openaisdk "github.com/openai/openai-go/v2" + "github.com/openai/openai-go/v2/packages/param" +) + +const reasoningStartedCtx = "reasoning_started" + +type currentReasoningState struct { + metadata *openaipkg.ResponsesReasoningMetadata + googleMetadata *google.ReasoningMetadata + googleText string + anthropicSig string +} + +func languagePrepareModelCall(_ fantasy.LanguageModel, params *openaisdk.ChatCompletionNewParams, call fantasy.Call) ([]fantasy.CallWarning, error) { + providerOptions := &ProviderOptions{} + if v, ok := call.ProviderOptions[Name]; ok { + providerOptions, ok = v.(*ProviderOptions) + if !ok { + return nil, &fantasy.Error{Title: "invalid argument", Message: "vercel provider options should be *vercel.ProviderOptions"} + } + } + + extraFields := make(map[string]any) + + // Handle reasoning options + if providerOptions.Reasoning != nil { + data, err := structToMapJSON(providerOptions.Reasoning) + if err != nil { + return nil, err + } + extraFields["reasoning"] = data + } + + // Handle provider options for gateway routing + if providerOptions.ProviderOptions != nil { + data, err := structToMapJSON(providerOptions.ProviderOptions) + if err != nil { + return nil, err + } + extraFields["providerOptions"] = map[string]any{ + "gateway": data, + } + } + + // Handle BYOK (Bring Your Own Key) + if providerOptions.BYOK != nil { + data, err := structToMapJSON(providerOptions.BYOK) + if err != nil { + return nil, err + } + if gatewayOpts, ok := extraFields["providerOptions"].(map[string]any); ok { + gatewayOpts["byok"] = data + } else { + extraFields["providerOptions"] = map[string]any{ + "gateway": map[string]any{ + "byok": data, + }, + } + } + } + + // Handle standard OpenAI options + if providerOptions.LogitBias != nil { + params.LogitBias = providerOptions.LogitBias + } + if providerOptions.LogProbs != nil { + params.Logprobs = param.NewOpt(*providerOptions.LogProbs) + } + if providerOptions.TopLogProbs != nil { + params.TopLogprobs = param.NewOpt(*providerOptions.TopLogProbs) + } + if providerOptions.User != nil { + params.User = param.NewOpt(*providerOptions.User) + } + if providerOptions.ParallelToolCalls != nil { + params.ParallelToolCalls = param.NewOpt(*providerOptions.ParallelToolCalls) + } + + // Handle model fallbacks - direct models field + if providerOptions.ProviderOptions != nil && len(providerOptions.ProviderOptions.Models) > 0 { + extraFields["models"] = providerOptions.ProviderOptions.Models + } + + maps.Copy(extraFields, providerOptions.ExtraBody) + params.SetExtraFields(extraFields) + return nil, nil +} + +func languageModelExtraContent(choice openaisdk.ChatCompletionChoice) []fantasy.Content { + content := make([]fantasy.Content, 0) + reasoningData := ReasoningData{} + err := json.Unmarshal([]byte(choice.Message.RawJSON()), &reasoningData) + if err != nil { + return content + } + + responsesReasoningBlocks := make([]openaipkg.ResponsesReasoningMetadata, 0) + anthropicReasoningBlocks := make([]struct { + text string + metadata *anthropic.ReasoningOptionMetadata + }, 0) + googleReasoningBlocks := make([]struct { + text string + metadata *google.ReasoningMetadata + }, 0) + otherReasoning := make([]string, 0) + + for _, detail := range reasoningData.ReasoningDetails { + if strings.HasPrefix(detail.Format, "openai-responses") || strings.HasPrefix(detail.Format, "xai-responses") { + var thinkingBlock openaipkg.ResponsesReasoningMetadata + if len(responsesReasoningBlocks)-1 >= detail.Index { + thinkingBlock = responsesReasoningBlocks[detail.Index] + } else { + thinkingBlock = openaipkg.ResponsesReasoningMetadata{} + responsesReasoningBlocks = append(responsesReasoningBlocks, thinkingBlock) + } + + switch detail.Type { + case "reasoning.summary": + thinkingBlock.Summary = append(thinkingBlock.Summary, detail.Summary) + case "reasoning.encrypted": + thinkingBlock.EncryptedContent = &detail.Data + } + if detail.ID != "" { + thinkingBlock.ItemID = detail.ID + } + responsesReasoningBlocks[detail.Index] = thinkingBlock + continue + } + + if strings.HasPrefix(detail.Format, "google-gemini") { + var thinkingBlock struct { + text string + metadata *google.ReasoningMetadata + } + if len(googleReasoningBlocks)-1 >= detail.Index { + thinkingBlock = googleReasoningBlocks[detail.Index] + } else { + thinkingBlock = struct { + text string + metadata *google.ReasoningMetadata + }{metadata: &google.ReasoningMetadata{}} + googleReasoningBlocks = append(googleReasoningBlocks, thinkingBlock) + } + + switch detail.Type { + case "reasoning.text": + thinkingBlock.text = detail.Text + case "reasoning.encrypted": + thinkingBlock.metadata.Signature = detail.Data + thinkingBlock.metadata.ToolID = detail.ID + } + googleReasoningBlocks[detail.Index] = thinkingBlock + continue + } + + if strings.HasPrefix(detail.Format, "anthropic-claude") { + anthropicReasoningBlocks = append(anthropicReasoningBlocks, struct { + text string + metadata *anthropic.ReasoningOptionMetadata + }{ + text: detail.Text, + metadata: &anthropic.ReasoningOptionMetadata{ + Signature: detail.Signature, + }, + }) + continue + } + + otherReasoning = append(otherReasoning, detail.Text) + } + + // Fallback to simple reasoning field if no details + if reasoningData.Reasoning != "" && len(reasoningData.ReasoningDetails) == 0 { + otherReasoning = append(otherReasoning, reasoningData.Reasoning) + } + + for _, block := range responsesReasoningBlocks { + if len(block.Summary) == 0 { + block.Summary = []string{""} + } + content = append(content, fantasy.ReasoningContent{ + Text: strings.Join(block.Summary, "\n"), + ProviderMetadata: fantasy.ProviderMetadata{ + openaipkg.Name: &block, + }, + }) + } + + for _, block := range anthropicReasoningBlocks { + content = append(content, fantasy.ReasoningContent{ + Text: block.text, + ProviderMetadata: fantasy.ProviderMetadata{ + anthropic.Name: block.metadata, + }, + }) + } + + for _, block := range googleReasoningBlocks { + content = append(content, fantasy.ReasoningContent{ + Text: block.text, + ProviderMetadata: fantasy.ProviderMetadata{ + google.Name: block.metadata, + }, + }) + } + + for _, reasoning := range otherReasoning { + if reasoning != "" { + content = append(content, fantasy.ReasoningContent{ + Text: reasoning, + }) + } + } + + return content +} + +func extractReasoningContext(ctx map[string]any) *currentReasoningState { + reasoningStarted, ok := ctx[reasoningStartedCtx] + if !ok { + return nil + } + state, ok := reasoningStarted.(*currentReasoningState) + if !ok { + return nil + } + return state +} + +func languageModelStreamExtra(chunk openaisdk.ChatCompletionChunk, yield func(fantasy.StreamPart) bool, ctx map[string]any) (map[string]any, bool) { + if len(chunk.Choices) == 0 { + return ctx, true + } + + currentState := extractReasoningContext(ctx) + + inx := 0 + choice := chunk.Choices[inx] + reasoningData := ReasoningData{} + err := json.Unmarshal([]byte(choice.Delta.RawJSON()), &reasoningData) + if err != nil { + yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeError, + Error: &fantasy.Error{Title: "stream error", Message: "error unmarshalling delta", Cause: err}, + }) + return ctx, false + } + + // Reasoning Start + if currentState == nil { + if len(reasoningData.ReasoningDetails) == 0 && reasoningData.Reasoning == "" { + return ctx, true + } + + var metadata fantasy.ProviderMetadata + currentState = ¤tReasoningState{} + + if len(reasoningData.ReasoningDetails) > 0 { + detail := reasoningData.ReasoningDetails[0] + + if strings.HasPrefix(detail.Format, "openai-responses") || strings.HasPrefix(detail.Format, "xai-responses") { + currentState.metadata = &openaipkg.ResponsesReasoningMetadata{ + Summary: []string{detail.Summary}, + } + metadata = fantasy.ProviderMetadata{ + openaipkg.Name: currentState.metadata, + } + if detail.Data != "" { + shouldContinue := yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningStart, + ID: fmt.Sprintf("%d", inx), + Delta: detail.Summary, + ProviderMetadata: metadata, + }) + if !shouldContinue { + return ctx, false + } + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + ProviderMetadata: fantasy.ProviderMetadata{ + openaipkg.Name: &openaipkg.ResponsesReasoningMetadata{ + Summary: []string{detail.Summary}, + EncryptedContent: &detail.Data, + ItemID: detail.ID, + }, + }, + }) + } + } + + if strings.HasPrefix(detail.Format, "google-gemini") { + if detail.Type == "reasoning.encrypted" { + ctx[reasoningStartedCtx] = nil + if !yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningStart, + ID: fmt.Sprintf("%d", inx), + }) { + return ctx, false + } + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + ProviderMetadata: fantasy.ProviderMetadata{ + google.Name: &google.ReasoningMetadata{ + Signature: detail.Data, + ToolID: detail.ID, + }, + }, + }) + } + currentState.googleMetadata = &google.ReasoningMetadata{} + currentState.googleText = detail.Text + metadata = fantasy.ProviderMetadata{ + google.Name: currentState.googleMetadata, + } + } + + if strings.HasPrefix(detail.Format, "anthropic-claude") { + currentState.anthropicSig = detail.Signature + } + } + + ctx[reasoningStartedCtx] = currentState + delta := reasoningData.Reasoning + if len(reasoningData.ReasoningDetails) > 0 { + delta = reasoningData.ReasoningDetails[0].Summary + if strings.HasPrefix(reasoningData.ReasoningDetails[0].Format, "google-gemini") { + delta = reasoningData.ReasoningDetails[0].Text + } + if strings.HasPrefix(reasoningData.ReasoningDetails[0].Format, "anthropic-claude") { + delta = reasoningData.ReasoningDetails[0].Text + } + } + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningStart, + ID: fmt.Sprintf("%d", inx), + Delta: delta, + ProviderMetadata: metadata, + }) + } + + if len(reasoningData.ReasoningDetails) == 0 && reasoningData.Reasoning == "" { + if choice.Delta.Content != "" || len(choice.Delta.ToolCalls) > 0 { + ctx[reasoningStartedCtx] = nil + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + }) + } + return ctx, true + } + + if len(reasoningData.ReasoningDetails) > 0 { + detail := reasoningData.ReasoningDetails[0] + + if strings.HasPrefix(detail.Format, "openai-responses") || strings.HasPrefix(detail.Format, "xai-responses") { + if detail.Data != "" { + currentState.metadata.EncryptedContent = &detail.Data + currentState.metadata.ItemID = detail.ID + ctx[reasoningStartedCtx] = nil + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + ProviderMetadata: fantasy.ProviderMetadata{ + openaipkg.Name: currentState.metadata, + }, + }) + } + var textDelta string + if len(currentState.metadata.Summary)-1 >= detail.Index { + currentState.metadata.Summary[detail.Index] += detail.Summary + textDelta = detail.Summary + } else { + currentState.metadata.Summary = append(currentState.metadata.Summary, detail.Summary) + textDelta = "\n" + detail.Summary + } + ctx[reasoningStartedCtx] = currentState + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: textDelta, + ProviderMetadata: fantasy.ProviderMetadata{ + openaipkg.Name: currentState.metadata, + }, + }) + } + + if strings.HasPrefix(detail.Format, "anthropic-claude") { + if detail.Signature != "" { + metadata := fantasy.ProviderMetadata{ + anthropic.Name: &anthropic.ReasoningOptionMetadata{ + Signature: detail.Signature, + }, + } + shouldContinue := yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: detail.Text, + ProviderMetadata: metadata, + }) + if !shouldContinue { + return ctx, false + } + ctx[reasoningStartedCtx] = nil + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + }) + } + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: detail.Text, + }) + } + + if strings.HasPrefix(detail.Format, "google-gemini") { + if detail.Type == "reasoning.text" { + currentState.googleText += detail.Text + ctx[reasoningStartedCtx] = currentState + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: detail.Text, + }) + } + if detail.Type == "reasoning.encrypted" { + currentState.googleMetadata.Signature = detail.Data + currentState.googleMetadata.ToolID = detail.ID + metadata := fantasy.ProviderMetadata{ + google.Name: currentState.googleMetadata, + } + ctx[reasoningStartedCtx] = nil + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + ProviderMetadata: metadata, + }) + } + } + + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: detail.Text, + }) + } + + if reasoningData.Reasoning != "" { + return ctx, yield(fantasy.StreamPart{ + Type: fantasy.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: reasoningData.Reasoning, + }) + } + + return ctx, true +} + +func languageModelUsage(response openaisdk.ChatCompletion) (fantasy.Usage, fantasy.ProviderOptionsData) { + if len(response.Choices) == 0 { + return fantasy.Usage{}, nil + } + + usage := response.Usage + completionTokenDetails := usage.CompletionTokensDetails + promptTokenDetails := usage.PromptTokensDetails + + var provider string + if p, ok := response.JSON.ExtraFields["provider"]; ok { + provider = p.Raw() + } + + providerMetadata := &ProviderMetadata{ + Provider: provider, + } + + return fantasy.Usage{ + InputTokens: usage.PromptTokens, + OutputTokens: usage.CompletionTokens, + TotalTokens: usage.TotalTokens, + ReasoningTokens: completionTokenDetails.ReasoningTokens, + CacheReadTokens: promptTokenDetails.CachedTokens, + }, providerMetadata +} + +func languageModelStreamUsage(chunk openaisdk.ChatCompletionChunk, _ map[string]any, metadata fantasy.ProviderMetadata) (fantasy.Usage, fantasy.ProviderMetadata) { + usage := chunk.Usage + if usage.TotalTokens == 0 { + return fantasy.Usage{}, nil + } + + streamProviderMetadata := &ProviderMetadata{} + if metadata != nil { + if providerMetadata, ok := metadata[Name]; ok { + converted, ok := providerMetadata.(*ProviderMetadata) + if ok { + streamProviderMetadata = converted + } + } + } + + if p, ok := chunk.JSON.ExtraFields["provider"]; ok { + streamProviderMetadata.Provider = p.Raw() + } + + completionTokenDetails := usage.CompletionTokensDetails + promptTokenDetails := usage.PromptTokensDetails + aiUsage := fantasy.Usage{ + InputTokens: usage.PromptTokens, + OutputTokens: usage.CompletionTokens, + TotalTokens: usage.TotalTokens, + ReasoningTokens: completionTokenDetails.ReasoningTokens, + CacheReadTokens: promptTokenDetails.CachedTokens, + } + + return aiUsage, fantasy.ProviderMetadata{ + Name: streamProviderMetadata, + } +} + +func languageModelToPrompt(prompt fantasy.Prompt, _, model string) ([]openaisdk.ChatCompletionMessageParamUnion, []fantasy.CallWarning) { + var messages []openaisdk.ChatCompletionMessageParamUnion + var warnings []fantasy.CallWarning + + for _, msg := range prompt { + switch msg.Role { + case fantasy.MessageRoleSystem: + var systemPromptParts []string + for _, c := range msg.Content { + if c.GetType() != fantasy.ContentTypeText { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "system prompt can only have text content", + }) + continue + } + textPart, ok := fantasy.AsContentType[fantasy.TextPart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "system prompt text part does not have the right type", + }) + continue + } + text := textPart.Text + if strings.TrimSpace(text) != "" { + systemPromptParts = append(systemPromptParts, textPart.Text) + } + } + if len(systemPromptParts) == 0 { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "system prompt has no text parts", + }) + continue + } + systemMsg := openaisdk.SystemMessage(strings.Join(systemPromptParts, "\n")) + anthropicCache := anthropic.GetCacheControl(msg.ProviderOptions) + if anthropicCache != nil { + systemMsg.OfSystem.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": anthropicCache.Type, + }, + }) + } + messages = append(messages, systemMsg) + + case fantasy.MessageRoleUser: + if len(msg.Content) == 1 && msg.Content[0].GetType() == fantasy.ContentTypeText { + textPart, ok := fantasy.AsContentType[fantasy.TextPart](msg.Content[0]) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "user message text part does not have the right type", + }) + continue + } + userMsg := openaisdk.UserMessage(textPart.Text) + anthropicCache := anthropic.GetCacheControl(msg.ProviderOptions) + if anthropicCache != nil { + userMsg.OfUser.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": anthropicCache.Type, + }, + }) + } + messages = append(messages, userMsg) + continue + } + + var content []openaisdk.ChatCompletionContentPartUnionParam + for i, c := range msg.Content { + isLastPart := i == len(msg.Content)-1 + cacheControl := anthropic.GetCacheControl(c.Options()) + if cacheControl == nil && isLastPart { + cacheControl = anthropic.GetCacheControl(msg.ProviderOptions) + } + switch c.GetType() { + case fantasy.ContentTypeText: + textPart, ok := fantasy.AsContentType[fantasy.TextPart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "user message text part does not have the right type", + }) + continue + } + part := openaisdk.ChatCompletionContentPartUnionParam{ + OfText: &openaisdk.ChatCompletionContentPartTextParam{ + Text: textPart.Text, + }, + } + if cacheControl != nil { + part.OfText.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + content = append(content, part) + case fantasy.ContentTypeFile: + filePart, ok := fantasy.AsContentType[fantasy.FilePart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "user message file part does not have the right type", + }) + continue + } + switch { + case strings.HasPrefix(filePart.MediaType, "image/"): + base64Encoded := base64.StdEncoding.EncodeToString(filePart.Data) + data := "data:" + filePart.MediaType + ";base64," + base64Encoded + imageURL := openaisdk.ChatCompletionContentPartImageImageURLParam{URL: data} + if providerOptions, ok := filePart.ProviderOptions[openaipkg.Name]; ok { + if detail, ok := providerOptions.(*openaipkg.ProviderFileOptions); ok { + imageURL.Detail = detail.ImageDetail + } + } + imageBlock := openaisdk.ChatCompletionContentPartImageParam{ImageURL: imageURL} + if cacheControl != nil { + imageBlock.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + content = append(content, openaisdk.ChatCompletionContentPartUnionParam{OfImageURL: &imageBlock}) + + case filePart.MediaType == "audio/wav": + base64Encoded := base64.StdEncoding.EncodeToString(filePart.Data) + audioBlock := openaisdk.ChatCompletionContentPartInputAudioParam{ + InputAudio: openaisdk.ChatCompletionContentPartInputAudioInputAudioParam{ + Data: base64Encoded, + Format: "wav", + }, + } + if cacheControl != nil { + audioBlock.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + content = append(content, openaisdk.ChatCompletionContentPartUnionParam{OfInputAudio: &audioBlock}) + + case filePart.MediaType == "audio/mpeg" || filePart.MediaType == "audio/mp3": + base64Encoded := base64.StdEncoding.EncodeToString(filePart.Data) + audioBlock := openaisdk.ChatCompletionContentPartInputAudioParam{ + InputAudio: openaisdk.ChatCompletionContentPartInputAudioInputAudioParam{ + Data: base64Encoded, + Format: "mp3", + }, + } + if cacheControl != nil { + audioBlock.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + content = append(content, openaisdk.ChatCompletionContentPartUnionParam{OfInputAudio: &audioBlock}) + + case filePart.MediaType == "application/pdf": + dataStr := string(filePart.Data) + if strings.HasPrefix(dataStr, "file-") { + fileBlock := openaisdk.ChatCompletionContentPartFileParam{ + File: openaisdk.ChatCompletionContentPartFileFileParam{ + FileID: param.NewOpt(dataStr), + }, + } + if cacheControl != nil { + fileBlock.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + content = append(content, openaisdk.ChatCompletionContentPartUnionParam{OfFile: &fileBlock}) + } else { + base64Encoded := base64.StdEncoding.EncodeToString(filePart.Data) + data := "data:application/pdf;base64," + base64Encoded + filename := filePart.Filename + if filename == "" { + filename = fmt.Sprintf("part-%d.pdf", len(content)) + } + fileBlock := openaisdk.ChatCompletionContentPartFileParam{ + File: openaisdk.ChatCompletionContentPartFileFileParam{ + Filename: param.NewOpt(filename), + FileData: param.NewOpt(data), + }, + } + if cacheControl != nil { + fileBlock.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + content = append(content, openaisdk.ChatCompletionContentPartUnionParam{OfFile: &fileBlock}) + } + + default: + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: fmt.Sprintf("file part media type %s not supported", filePart.MediaType), + }) + } + } + } + if !hasVisibleUserContent(content) { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "dropping empty user message (contains neither user-facing content nor tool results)", + }) + continue + } + messages = append(messages, openaisdk.UserMessage(content)) + + case fantasy.MessageRoleAssistant: + if len(msg.Content) == 1 && msg.Content[0].GetType() == fantasy.ContentTypeText { + textPart, ok := fantasy.AsContentType[fantasy.TextPart](msg.Content[0]) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "assistant message text part does not have the right type", + }) + continue + } + assistantMsg := openaisdk.AssistantMessage(textPart.Text) + anthropicCache := anthropic.GetCacheControl(msg.ProviderOptions) + if anthropicCache != nil { + assistantMsg.OfAssistant.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": anthropicCache.Type, + }, + }) + } + messages = append(messages, assistantMsg) + continue + } + + assistantMsg := openaisdk.ChatCompletionAssistantMessageParam{ + Role: "assistant", + } + for i, c := range msg.Content { + isLastPart := i == len(msg.Content)-1 + cacheControl := anthropic.GetCacheControl(c.Options()) + if cacheControl == nil && isLastPart { + cacheControl = anthropic.GetCacheControl(msg.ProviderOptions) + } + switch c.GetType() { + case fantasy.ContentTypeText: + textPart, ok := fantasy.AsContentType[fantasy.TextPart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "assistant message text part does not have the right type", + }) + continue + } + if assistantMsg.Content.OfString.Valid() { + textPart.Text = assistantMsg.Content.OfString.Value + "\n" + textPart.Text + } + assistantMsg.Content = openaisdk.ChatCompletionAssistantMessageParamContentUnion{ + OfString: param.NewOpt(textPart.Text), + } + if cacheControl != nil { + assistantMsg.Content.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + case fantasy.ContentTypeReasoning: + reasoningPart, ok := fantasy.AsContentType[fantasy.ReasoningPart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "assistant message reasoning part does not have the right type", + }) + continue + } + var reasoningDetails []ReasoningDetail + switch { + case strings.HasPrefix(model, "anthropic/") && reasoningPart.Text != "": + metadata := anthropic.GetReasoningMetadata(reasoningPart.Options()) + if metadata == nil { + text := fmt.Sprintf("%s", reasoningPart.Text) + if assistantMsg.Content.OfString.Valid() { + text = assistantMsg.Content.OfString.Value + "\n" + text + } + assistantMsg.Content = openaisdk.ChatCompletionAssistantMessageParamContentUnion{ + OfString: param.NewOpt(text), + } + if cacheControl != nil { + assistantMsg.Content.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + continue + } + reasoningDetails = append(reasoningDetails, ReasoningDetail{ + Format: "anthropic-claude-v1", + Type: "reasoning.text", + Text: reasoningPart.Text, + Signature: metadata.Signature, + }) + data, _ := json.Marshal(reasoningDetails) + reasoningDetailsMap := []map[string]any{} + _ = json.Unmarshal(data, &reasoningDetailsMap) + assistantMsg.SetExtraFields(map[string]any{ + "reasoning_details": reasoningDetailsMap, + "reasoning": reasoningPart.Text, + }) + case strings.HasPrefix(model, "openai/"): + metadata := openaipkg.GetReasoningMetadata(reasoningPart.Options()) + if metadata == nil { + text := fmt.Sprintf("%s", reasoningPart.Text) + if assistantMsg.Content.OfString.Valid() { + text = assistantMsg.Content.OfString.Value + "\n" + text + } + assistantMsg.Content = openaisdk.ChatCompletionAssistantMessageParamContentUnion{ + OfString: param.NewOpt(text), + } + continue + } + for inx, summary := range metadata.Summary { + if summary == "" { + continue + } + reasoningDetails = append(reasoningDetails, ReasoningDetail{ + Type: "reasoning.summary", + Format: "openai-responses-v1", + Summary: summary, + Index: inx, + }) + } + reasoningDetails = append(reasoningDetails, ReasoningDetail{ + Type: "reasoning.encrypted", + Format: "openai-responses-v1", + Data: *metadata.EncryptedContent, + ID: metadata.ItemID, + }) + data, _ := json.Marshal(reasoningDetails) + reasoningDetailsMap := []map[string]any{} + _ = json.Unmarshal(data, &reasoningDetailsMap) + assistantMsg.SetExtraFields(map[string]any{ + "reasoning_details": reasoningDetailsMap, + }) + case strings.HasPrefix(model, "google/"): + metadata := google.GetReasoningMetadata(reasoningPart.Options()) + if metadata == nil { + text := fmt.Sprintf("%s", reasoningPart.Text) + if assistantMsg.Content.OfString.Valid() { + text = assistantMsg.Content.OfString.Value + "\n" + text + } + assistantMsg.Content = openaisdk.ChatCompletionAssistantMessageParamContentUnion{ + OfString: param.NewOpt(text), + } + continue + } + if reasoningPart.Text != "" { + reasoningDetails = append(reasoningDetails, ReasoningDetail{ + Type: "reasoning.text", + Format: "google-gemini-v1", + Text: reasoningPart.Text, + }) + } + reasoningDetails = append(reasoningDetails, ReasoningDetail{ + Type: "reasoning.encrypted", + Format: "google-gemini-v1", + Data: metadata.Signature, + ID: metadata.ToolID, + }) + data, _ := json.Marshal(reasoningDetails) + reasoningDetailsMap := []map[string]any{} + _ = json.Unmarshal(data, &reasoningDetailsMap) + assistantMsg.SetExtraFields(map[string]any{ + "reasoning_details": reasoningDetailsMap, + }) + default: + reasoningDetails = append(reasoningDetails, ReasoningDetail{ + Type: "reasoning.text", + Text: reasoningPart.Text, + Format: "unknown", + }) + data, _ := json.Marshal(reasoningDetails) + reasoningDetailsMap := []map[string]any{} + _ = json.Unmarshal(data, &reasoningDetailsMap) + assistantMsg.SetExtraFields(map[string]any{ + "reasoning_details": reasoningDetailsMap, + }) + } + case fantasy.ContentTypeToolCall: + toolCallPart, ok := fantasy.AsContentType[fantasy.ToolCallPart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "assistant message tool part does not have the right type", + }) + continue + } + tc := openaisdk.ChatCompletionMessageToolCallUnionParam{ + OfFunction: &openaisdk.ChatCompletionMessageFunctionToolCallParam{ + ID: toolCallPart.ToolCallID, + Type: "function", + Function: openaisdk.ChatCompletionMessageFunctionToolCallFunctionParam{ + Name: toolCallPart.ToolName, + Arguments: toolCallPart.Input, + }, + }, + } + if cacheControl != nil { + tc.OfFunction.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + assistantMsg.ToolCalls = append(assistantMsg.ToolCalls, tc) + } + } + messages = append(messages, openaisdk.ChatCompletionMessageParamUnion{ + OfAssistant: &assistantMsg, + }) + + case fantasy.MessageRoleTool: + for i, c := range msg.Content { + isLastPart := i == len(msg.Content)-1 + cacheControl := anthropic.GetCacheControl(c.Options()) + if cacheControl == nil && isLastPart { + cacheControl = anthropic.GetCacheControl(msg.ProviderOptions) + } + if c.GetType() != fantasy.ContentTypeToolResult { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "tool message can only have tool result content", + }) + continue + } + toolResultPart, ok := fantasy.AsContentType[fantasy.ToolResultPart](c) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "tool message result part does not have the right type", + }) + continue + } + switch toolResultPart.Output.GetType() { + case fantasy.ToolResultContentTypeText: + output, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentText](toolResultPart.Output) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "tool result output does not have the right type", + }) + continue + } + tr := openaisdk.ToolMessage(output.Text, toolResultPart.ToolCallID) + if cacheControl != nil { + tr.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + messages = append(messages, tr) + case fantasy.ToolResultContentTypeError: + output, ok := fantasy.AsToolResultOutputType[fantasy.ToolResultOutputContentError](toolResultPart.Output) + if !ok { + warnings = append(warnings, fantasy.CallWarning{ + Type: fantasy.CallWarningTypeOther, + Message: "tool result output does not have the right type", + }) + continue + } + tr := openaisdk.ToolMessage(output.Error.Error(), toolResultPart.ToolCallID) + if cacheControl != nil { + tr.SetExtraFields(map[string]any{ + "cache_control": map[string]string{ + "type": cacheControl.Type, + }, + }) + } + messages = append(messages, tr) + } + } + } + } + return messages, warnings +} + +func hasVisibleUserContent(content []openaisdk.ChatCompletionContentPartUnionParam) bool { + for _, part := range content { + if part.OfText != nil || part.OfImageURL != nil || part.OfInputAudio != nil || part.OfFile != nil { + return true + } + } + return false +} + +func structToMapJSON(s any) (map[string]any, error) { + var result map[string]any + jsonBytes, err := json.Marshal(s) + if err != nil { + return nil, err + } + err = json.Unmarshal(jsonBytes, &result) + if err != nil { + return nil, err + } + return result, nil +} diff --git a/providers/vercel/provider_options.go b/providers/vercel/provider_options.go new file mode 100644 index 0000000000000000000000000000000000000000..046ba940d981117234d72a10747708f699bd4c70 --- /dev/null +++ b/providers/vercel/provider_options.go @@ -0,0 +1,191 @@ +// Package vercel provides an implementation of the fantasy AI SDK for Vercel AI Gateway. +package vercel + +import ( + "encoding/json" + + "charm.land/fantasy" +) + +// Global type identifiers for Vercel-specific provider data. +const ( + TypeProviderOptions = Name + ".options" + TypeProviderMetadata = Name + ".metadata" +) + +// Register Vercel provider-specific types with the global registry. +func init() { + fantasy.RegisterProviderType(TypeProviderOptions, func(data []byte) (fantasy.ProviderOptionsData, error) { + var v ProviderOptions + if err := json.Unmarshal(data, &v); err != nil { + return nil, err + } + return &v, nil + }) + fantasy.RegisterProviderType(TypeProviderMetadata, func(data []byte) (fantasy.ProviderOptionsData, error) { + var v ProviderMetadata + if err := json.Unmarshal(data, &v); err != nil { + return nil, err + } + return &v, nil + }) +} + +// ReasoningEffort represents the reasoning effort level for Vercel AI Gateway. +type ReasoningEffort string + +const ( + // ReasoningEffortNone disables reasoning. + ReasoningEffortNone ReasoningEffort = "none" + // ReasoningEffortMinimal represents minimal reasoning effort (~10% of max_tokens). + ReasoningEffortMinimal ReasoningEffort = "minimal" + // ReasoningEffortLow represents low reasoning effort (~20% of max_tokens). + ReasoningEffortLow ReasoningEffort = "low" + // ReasoningEffortMedium represents medium reasoning effort (~50% of max_tokens). + ReasoningEffortMedium ReasoningEffort = "medium" + // ReasoningEffortHigh represents high reasoning effort (~80% of max_tokens). + ReasoningEffortHigh ReasoningEffort = "high" + // ReasoningEffortXHigh represents extra high reasoning effort (~95% of max_tokens). + ReasoningEffortXHigh ReasoningEffort = "xhigh" +) + +// ReasoningOptions represents reasoning configuration for Vercel AI Gateway. +type ReasoningOptions struct { + // Enabled enables reasoning output. When true, the model will provide its reasoning process. + Enabled *bool `json:"enabled,omitempty"` + // MaxTokens is the maximum number of tokens to allocate for reasoning. + // Cannot be used with Effort. + MaxTokens *int64 `json:"max_tokens,omitempty"` + // Effort controls reasoning effort level. + // Mutually exclusive with MaxTokens. + Effort *ReasoningEffort `json:"effort,omitempty"` + // Exclude excludes reasoning content from the response but still generates it internally. + Exclude *bool `json:"exclude,omitempty"` +} + +// GatewayProviderOptions represents provider routing preferences for Vercel AI Gateway. +type GatewayProviderOptions struct { + // Order is the list of provider slugs to try in order (e.g. ["vertex", "anthropic"]). + Order []string `json:"order,omitempty"` + // Models is the list of fallback models to try if the primary model fails. + Models []string `json:"models,omitempty"` +} + +// BYOKCredential represents a single provider credential for BYOK. +type BYOKCredential struct { + APIKey string `json:"apiKey,omitempty"` +} + +// BYOKOptions represents Bring Your Own Key options for Vercel AI Gateway. +type BYOKOptions struct { + Anthropic map[string][]BYOKCredential `json:"anthropic,omitempty"` + OpenAI map[string][]BYOKCredential `json:"openai,omitempty"` + Vertex map[string][]BYOKCredential `json:"vertex,omitempty"` + Bedrock map[string][]BYOKCredential `json:"bedrock,omitempty"` +} + +// ProviderOptions represents additional options for Vercel AI Gateway provider. +type ProviderOptions struct { + // Reasoning configuration for models that support extended thinking. + Reasoning *ReasoningOptions `json:"reasoning,omitempty"` + // ProviderOptions for gateway routing preferences. + ProviderOptions *GatewayProviderOptions `json:"providerOptions,omitempty"` + // BYOK for request-scoped provider credentials. + BYOK *BYOKOptions `json:"byok,omitempty"` + // User is a unique identifier representing your end-user. + User *string `json:"user,omitempty"` + // LogitBias modifies the likelihood of specified tokens appearing in the completion. + LogitBias map[string]int64 `json:"logit_bias,omitempty"` + // LogProbs returns the log probabilities of the tokens. + LogProbs *bool `json:"logprobs,omitempty"` + // TopLogProbs is the number of top log probabilities to return. + TopLogProbs *int64 `json:"top_logprobs,omitempty"` + // ParallelToolCalls enables parallel function calling during tool use. + ParallelToolCalls *bool `json:"parallel_tool_calls,omitempty"` + // ExtraBody for additional request body fields. + ExtraBody map[string]any `json:"extra_body,omitempty"` +} + +// Options implements the ProviderOptionsData interface for ProviderOptions. +func (*ProviderOptions) Options() {} + +// MarshalJSON implements custom JSON marshaling with type info for ProviderOptions. +func (o ProviderOptions) MarshalJSON() ([]byte, error) { + type plain ProviderOptions + return fantasy.MarshalProviderType(TypeProviderOptions, plain(o)) +} + +// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderOptions. +func (o *ProviderOptions) UnmarshalJSON(data []byte) error { + type plain ProviderOptions + var p plain + if err := fantasy.UnmarshalProviderType(data, &p); err != nil { + return err + } + *o = ProviderOptions(p) + return nil +} + +// ProviderMetadata represents metadata from Vercel AI Gateway provider. +type ProviderMetadata struct { + Provider string `json:"provider,omitempty"` +} + +// Options implements the ProviderOptionsData interface for ProviderMetadata. +func (*ProviderMetadata) Options() {} + +// MarshalJSON implements custom JSON marshaling with type info for ProviderMetadata. +func (m ProviderMetadata) MarshalJSON() ([]byte, error) { + type plain ProviderMetadata + return fantasy.MarshalProviderType(TypeProviderMetadata, plain(m)) +} + +// UnmarshalJSON implements custom JSON unmarshaling with type info for ProviderMetadata. +func (m *ProviderMetadata) UnmarshalJSON(data []byte) error { + type plain ProviderMetadata + var p plain + if err := fantasy.UnmarshalProviderType(data, &p); err != nil { + return err + } + *m = ProviderMetadata(p) + return nil +} + +// ReasoningDetail represents a reasoning detail from Vercel AI Gateway. +type ReasoningDetail struct { + ID string `json:"id,omitempty"` + Type string `json:"type,omitempty"` + Text string `json:"text,omitempty"` + Data string `json:"data,omitempty"` + Format string `json:"format,omitempty"` + Summary string `json:"summary,omitempty"` + Signature string `json:"signature,omitempty"` + Index int `json:"index"` +} + +// ReasoningData represents reasoning data from Vercel AI Gateway response. +type ReasoningData struct { + Reasoning string `json:"reasoning,omitempty"` + ReasoningDetails []ReasoningDetail `json:"reasoning_details,omitempty"` +} + +// ReasoningEffortOption creates a pointer to a ReasoningEffort value. +func ReasoningEffortOption(e ReasoningEffort) *ReasoningEffort { + return &e +} + +// NewProviderOptions creates new provider options for Vercel. +func NewProviderOptions(opts *ProviderOptions) fantasy.ProviderOptions { + return fantasy.ProviderOptions{ + Name: opts, + } +} + +// ParseOptions parses provider options from a map for Vercel. +func ParseOptions(data map[string]any) (*ProviderOptions, error) { + var options ProviderOptions + if err := fantasy.ParseOptions(data, &options); err != nil { + return nil, err + } + return &options, nil +} diff --git a/providers/vercel/vercel.go b/providers/vercel/vercel.go new file mode 100644 index 0000000000000000000000000000000000000000..af87db5eba02a3f7ebea4935cb40ceb1d25d9f78 --- /dev/null +++ b/providers/vercel/vercel.go @@ -0,0 +1,114 @@ +// Package vercel provides an implementation of the fantasy AI SDK for Vercel AI Gateway. +package vercel + +import ( + "charm.land/fantasy" + "charm.land/fantasy/providers/openai" + "github.com/openai/openai-go/v2/option" +) + +type options struct { + openaiOptions []openai.Option + languageModelOptions []openai.LanguageModelOption + sdkOptions []option.RequestOption + objectMode fantasy.ObjectMode +} + +const ( + // DefaultURL is the default URL for the Vercel AI Gateway API. + DefaultURL = "https://ai-gateway.vercel.sh/v1" + // Name is the name of the Vercel provider. + Name = "vercel" +) + +// Option defines a function that configures Vercel provider options. +type Option = func(*options) + +// New creates a new Vercel AI Gateway provider with the given options. +func New(opts ...Option) (fantasy.Provider, error) { + providerOptions := options{ + openaiOptions: []openai.Option{ + openai.WithName(Name), + openai.WithBaseURL(DefaultURL), + }, + languageModelOptions: []openai.LanguageModelOption{ + openai.WithLanguageModelPrepareCallFunc(languagePrepareModelCall), + openai.WithLanguageModelUsageFunc(languageModelUsage), + openai.WithLanguageModelStreamUsageFunc(languageModelStreamUsage), + openai.WithLanguageModelStreamExtraFunc(languageModelStreamExtra), + openai.WithLanguageModelExtraContentFunc(languageModelExtraContent), + openai.WithLanguageModelToPromptFunc(languageModelToPrompt), + }, + objectMode: fantasy.ObjectModeTool, // Default to tool mode for vercel + } + for _, o := range opts { + o(&providerOptions) + } + + // Handle object mode: convert unsupported modes to tool + // Vercel AI Gateway doesn't support native JSON mode, so we use tool or text + objectMode := providerOptions.objectMode + if objectMode == fantasy.ObjectModeAuto || objectMode == fantasy.ObjectModeJSON { + objectMode = fantasy.ObjectModeTool + } + + providerOptions.openaiOptions = append( + providerOptions.openaiOptions, + openai.WithSDKOptions(providerOptions.sdkOptions...), + openai.WithLanguageModelOptions(providerOptions.languageModelOptions...), + openai.WithObjectMode(objectMode), + ) + return openai.New(providerOptions.openaiOptions...) +} + +// WithAPIKey sets the API key for the Vercel provider. +func WithAPIKey(apiKey string) Option { + return func(o *options) { + o.openaiOptions = append(o.openaiOptions, openai.WithAPIKey(apiKey)) + } +} + +// WithBaseURL sets the base URL for the Vercel provider. +func WithBaseURL(url string) Option { + return func(o *options) { + o.openaiOptions = append(o.openaiOptions, openai.WithBaseURL(url)) + } +} + +// WithName sets the name for the Vercel provider. +func WithName(name string) Option { + return func(o *options) { + o.openaiOptions = append(o.openaiOptions, openai.WithName(name)) + } +} + +// WithHeaders sets the headers for the Vercel provider. +func WithHeaders(headers map[string]string) Option { + return func(o *options) { + o.openaiOptions = append(o.openaiOptions, openai.WithHeaders(headers)) + } +} + +// WithHTTPClient sets the HTTP client for the Vercel provider. +func WithHTTPClient(client option.HTTPClient) Option { + return func(o *options) { + o.openaiOptions = append(o.openaiOptions, openai.WithHTTPClient(client)) + } +} + +// WithSDKOptions sets the SDK options for the Vercel provider. +func WithSDKOptions(opts ...option.RequestOption) Option { + return func(o *options) { + o.sdkOptions = append(o.sdkOptions, opts...) + } +} + +// WithObjectMode sets the object generation mode for the Vercel provider. +// Supported modes: ObjectModeTool, ObjectModeText. +// ObjectModeAuto and ObjectModeJSON are automatically converted to ObjectModeTool +// since Vercel AI Gateway doesn't support native JSON mode. +func WithObjectMode(om fantasy.ObjectMode) Option { + return func(o *options) { + o.objectMode = om + } +} diff --git a/providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool.yaml b/providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7ab9ef881a8e7732bfcfc6e37cbb0d5e13d5ef33 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 830 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"anthropic/claude-sonnet-4","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37K2HQCCQMFG024V4NNE3","object":"chat.completion","created":1770033239,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"toolu_01Pp7heoom1NFVC9pZAq7RVP","type":"function","function":{"name":"add","arguments":"{\"a\":2,\"b\":3}"}},{"id":"toolu_01CyT9hTRh1yDg65BtKKoQoJ","type":"function","function":{"name":"multiply","arguments":"{\"a\":2,\"b\":3}"}}],"provider_metadata":{"anthropic":{"usage":{"input_tokens":507,"output_tokens":135,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":335024.437964,"endTime":337607.847298,"statusCode":200,"providerResponseId":"msg_01K9VNT3Y7C6bhS39BSLDfma"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.003546","marketCost":"0.003546","generationId":"gen_01KGF37K2HQCCQMFG024V4NNE3","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":507,"completion_tokens":135,"total_tokens":642,"cost":0.003546,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003546},"system_fingerprint":"fp_lt5c47efr0","generationId":"gen_01KGF37K2HQCCQMFG024V4NNE3"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.695440458s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1259 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"},{"tool_calls":[{"id":"toolu_01Pp7heoom1NFVC9pZAq7RVP","function":{"arguments":"{\"a\":2,\"b\":3}","name":"add"},"type":"function"},{"id":"toolu_01CyT9hTRh1yDg65BtKKoQoJ","function":{"arguments":"{\"a\":2,\"b\":3}","name":"multiply"},"type":"function"}],"role":"assistant"},{"content":"5","tool_call_id":"toolu_01Pp7heoom1NFVC9pZAq7RVP","role":"tool"},{"content":"6","tool_call_id":"toolu_01CyT9hTRh1yDg65BtKKoQoJ","role":"tool"}],"model":"anthropic/claude-sonnet-4","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37NPK9H15VB93JDFXHTFA","object":"chat.completion","created":1770033242,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"I''ve performed both operations with the numbers 2 and 3:\n- Addition: 2 + 3 = 5\n- Multiplication: 2 × 3 = 6","provider_metadata":{"anthropic":{"usage":{"input_tokens":688,"output_tokens":47,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":4529729.487684,"endTime":4532485.133344,"statusCode":200,"providerResponseId":"msg_01NmyxoER7vKZW5SBBtUa98q"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002769","marketCost":"0.002769","generationId":"gen_01KGF37NPK9H15VB93JDFXHTFA","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":688,"completion_tokens":47,"total_tokens":735,"cost":0.002769,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002769},"system_fingerprint":"fp_iwzjnx4gms","generationId":"gen_01KGF37NPK9H15VB93JDFXHTFA"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.965395875s diff --git a/providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool_streaming.yaml b/providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ba630b779a4f7c1b28d213e806e15987189d9f98 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/claude-sonnet-4/multi_tool_streaming.yaml @@ -0,0 +1,113 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 867 + 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":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"I"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'ll add an"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"d multiply the"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" numbers 2 and 3 "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"for you."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"toolu_0135npjMLttuPFBue5jmkrQ7","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\": 2"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":", \""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"b\": 3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"toolu_0158fwcmJxxApeN8LydKZFKq","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\": 2"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":", \"b"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\": 3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_hia2ehn86q"} + + data: {"id":"gen_01KGF37RMDX4SKJG4WVQMM9169","object":"chat.completion.chunk","created":1770033244,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":502,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":137,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1348791.685811,"endTime":1350481.290097,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1348791.685811,"endTime":1350481.290097,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.003561","marketCost":"0.003561","generationId":"gen_01KGF37RMDX4SKJG4WVQMM9169","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":502,"completion_tokens":137,"total_tokens":639,"cost":0.003561,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003561},"system_fingerprint":"fp_hia2ehn86q","generationId":"gen_01KGF37RMDX4SKJG4WVQMM9169"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.838556459s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1365 + 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"},{"content":"I''ll add and multiply the numbers 2 and 3 for you.","tool_calls":[{"id":"toolu_0135npjMLttuPFBue5jmkrQ7","function":{"arguments":"{\"a\": 2, \"b\": 3}","name":"add"},"type":"function"},{"id":"toolu_0158fwcmJxxApeN8LydKZFKq","function":{"arguments":"{\"a\": 2, \"b\": 3}","name":"multiply"},"type":"function"}],"role":"assistant"},{"content":"5","tool_call_id":"toolu_0135npjMLttuPFBue5jmkrQ7","role":"tool"},{"content":"6","tool_call_id":"toolu_0158fwcmJxxApeN8LydKZFKq","role":"tool"}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" results"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" are"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":":\n- "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"2 + 3 = "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"5\n- 2 × "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"3 = 6"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_sdbcn0gb5k"} + + data: {"id":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","object":"chat.completion.chunk","created":1770033246,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":700,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":31,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7614629.293412,"endTime":7615648.604763,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7614629.293412,"endTime":7615648.604763,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002565","marketCost":"0.002565","generationId":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":700,"completion_tokens":31,"total_tokens":731,"cost":0.002565,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002565},"system_fingerprint":"fp_sdbcn0gb5k","generationId":"gen_01KGF37VJZFMN3ZHEKK9EGN5P1"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.108064583s diff --git a/providertests/testdata/TestVercelCommon/claude-sonnet-4/simple.yaml b/providertests/testdata/TestVercelCommon/claude-sonnet-4/simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c62fe28e87ccb13f94e2c4e92411edb4210629f4 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/claude-sonnet-4/simple.yaml @@ -0,0 +1,33 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 175 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"anthropic/claude-sonnet-4","max_tokens":4000}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF377728Q76J66SN7WNPNNP","object":"chat.completion","created":1770033226,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"Olá! \n\nThat''s \"hi\" in Portuguese. You could also say \"Oi!\" which is a bit more casual and friendly.","provider_metadata":{"anthropic":{"usage":{"input_tokens":16,"output_tokens":35,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1330927.642499,"endTime":1332861.743603,"statusCode":200,"providerResponseId":"msg_01KTuWnKf9GVVspdbvDRUbTo"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.000573","marketCost":"0.000573","generationId":"gen_01KGF377728Q76J66SN7WNPNNP","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":16,"completion_tokens":35,"total_tokens":51,"cost":0.000573,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000573},"system_fingerprint":"fp_t6mx2uhujo","generationId":"gen_01KGF377728Q76J66SN7WNPNNP"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.374222792s diff --git a/providertests/testdata/TestVercelCommon/claude-sonnet-4/simple_streaming.yaml b/providertests/testdata/TestVercelCommon/claude-sonnet-4/simple_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cf48e674de900fe50e962f0e0f165a5869f11975 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/claude-sonnet-4/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: 229 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"anthropic/claude-sonnet-4","max_tokens":4000,"stream_options":{"include_usage":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"Oi!"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"\n\n("},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"You"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" also say \"Olá!\" which"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" another"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" common way"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" to say hi"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" Portuguese)"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5a0fyewqxl"} + + data: {"id":"gen_01KGF379703450NEHTHYWRXNWC","object":"chat.completion.chunk","created":1770033227,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":30,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1333898.356903,"endTime":1334761.868909,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1333898.356903,"endTime":1334761.868909,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000498","marketCost":"0.000498","generationId":"gen_01KGF379703450NEHTHYWRXNWC","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":16,"completion_tokens":30,"total_tokens":46,"cost":0.000498,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000498},"system_fingerprint":"fp_5a0fyewqxl","generationId":"gen_01KGF379703450NEHTHYWRXNWC"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 993.576166ms diff --git a/providertests/testdata/TestVercelCommon/claude-sonnet-4/tool.yaml b/providertests/testdata/TestVercelCommon/claude-sonnet-4/tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..ca3bb5c2b87e764921bb0effa4d9abfaf9843801 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/claude-sonnet-4/tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 467 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"anthropic/claude-sonnet-4","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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37B48YTSG8HPMC0Z9AVAR","object":"chat.completion","created":1770033230,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"toolu_01NSrymFZiohT2iy9U5LE9rA","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence,Italy\"}"}}],"provider_metadata":{"anthropic":{"usage":{"input_tokens":394,"output_tokens":67,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":2429109.035804,"endTime":2430987.56251,"statusCode":200,"providerResponseId":"msg_01Ak5uPKnJHaza1hFgS4fMoY"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002187","marketCost":"0.002187","generationId":"gen_01KGF37B48YTSG8HPMC0Z9AVAR","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":394,"completion_tokens":67,"total_tokens":461,"cost":0.002187,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002187},"system_fingerprint":"fp_u1vgvb877f","generationId":"gen_01KGF37B48YTSG8HPMC0Z9AVAR"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 1.999195125s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 720 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"toolu_01NSrymFZiohT2iy9U5LE9rA","function":{"arguments":"{\"location\":\"Florence,Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"toolu_01NSrymFZiohT2iy9U5LE9rA","role":"tool"}],"model":"anthropic/claude-sonnet-4","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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37D4BQSXP782PJN0Q3KYT","object":"chat.completion","created":1770033233,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"The current weather in Florence, Italy is 40°C (104°F). That''s quite hot! It''s a very warm day there.","provider_metadata":{"anthropic":{"usage":{"input_tokens":463,"output_tokens":33,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":410587.245308,"endTime":412600.850201,"statusCode":200,"providerResponseId":"msg_01ReE5KwsYimH5AMRwEuLit9"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.001884","marketCost":"0.001884","generationId":"gen_01KGF37D4BQSXP782PJN0Q3KYT","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":463,"completion_tokens":33,"total_tokens":496,"cost":0.001884,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.001884},"system_fingerprint":"fp_dwzayvqyi3","generationId":"gen_01KGF37D4BQSXP782PJN0Q3KYT"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.1313565s diff --git a/providertests/testdata/TestVercelCommon/claude-sonnet-4/tool_streaming.yaml b/providertests/testdata/TestVercelCommon/claude-sonnet-4/tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0039e197a1ec049f3910e564a992dd923f9ce0ce --- /dev/null +++ b/providertests/testdata/TestVercelCommon/claude-sonnet-4/tool_streaming.yaml @@ -0,0 +1,121 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 521 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"I'll get the weather information for Florence"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":", Italy for you."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"toolu_01P61EhnucuCA3gRE8rXpYrt","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"location\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": \""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Florence,"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Ita"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ly\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_22ov8ctw6a"} + + data: {"id":"gen_01KGF37F6TEH1JWRE2BABW1XV7","object":"chat.completion.chunk","created":1770033234,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":67,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1339997.935348,"endTime":1341183.011845,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1339997.935348,"endTime":1341183.011845,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002187","marketCost":"0.002187","generationId":"gen_01KGF37F6TEH1JWRE2BABW1XV7","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":394,"completion_tokens":67,"total_tokens":461,"cost":0.002187,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002187},"system_fingerprint":"fp_22ov8ctw6a","generationId":"gen_01KGF37F6TEH1JWRE2BABW1XV7"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.273492958s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 850 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"content":"I''ll get the weather information for Florence, Italy for you.","tool_calls":[{"id":"toolu_01P61EhnucuCA3gRE8rXpYrt","function":{"arguments":"{\"location\": \"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"toolu_01P61EhnucuCA3gRE8rXpYrt","role":"tool"}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"The current"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" weather in Florence, Italy shows"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" temperature of 40°C (104"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"°F)."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" That"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'s quite hot"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" It woul"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"d be a good idea to stay"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" hydrated and seek"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" shade or"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" air conditioning if you're planning"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" to be"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" out"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"doors."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_xnw4h12lhy"} + + data: {"id":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","object":"chat.completion.chunk","created":1770033235,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":476,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":53,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":3034449.959696,"endTime":3035377.30027,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":3034449.959696,"endTime":3035377.30027,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002223","marketCost":"0.002223","generationId":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":476,"completion_tokens":53,"total_tokens":529,"cost":0.002223,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002223},"system_fingerprint":"fp_xnw4h12lhy","generationId":"gen_01KGF37H1H6MYNJHYZ2N1SWF5H"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.122953792s diff --git a/providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool.yaml b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5f1fc92ac8e1d7a7c225028464974c449c6bb5fb --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 828 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"google/gemini-2.5-flash","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF381BH2CF0J56H612T8RC3","object":"chat.completion","created":1770033252,"model":"google/gemini-2.5-flash","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"s3q46gVXfhyIqY2s","type":"function","function":{"name":"add","arguments":"{\"a\":2,\"b\":3}"}},{"id":"vomF7JlLjIRlW7U8","type":"function","function":{"name":"multiply","arguments":"{\"a\":2,\"b\":3}"}}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":111,"promptTokenCount":61,"candidatesTokenCount":10,"totalTokenCount":182,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":4669622.140163,"endTime":4670671.510973,"statusCode":200,"providerResponseId":"Y5CAadiYMJCgmPUPj9uV-AI"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.0003208","marketCost":"0.0003208","generationId":"gen_01KGF381BH2CF0J56H612T8RC3","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":61,"completion_tokens":10,"total_tokens":71,"cost":0.0003208,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":111,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0003208},"system_fingerprint":"fp_q0dgwe4fbo","generationId":"gen_01KGF381BH2CF0J56H612T8RC3"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 1.184203208s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1201 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"},{"tool_calls":[{"id":"s3q46gVXfhyIqY2s","function":{"arguments":"{\"a\":2,\"b\":3}","name":"add"},"type":"function"},{"id":"vomF7JlLjIRlW7U8","function":{"arguments":"{\"a\":2,\"b\":3}","name":"multiply"},"type":"function"}],"role":"assistant"},{"content":"5","tool_call_id":"s3q46gVXfhyIqY2s","role":"tool"},{"content":"6","tool_call_id":"vomF7JlLjIRlW7U8","role":"tool"}],"model":"google/gemini-2.5-flash","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF382G93A1FEHZRVZDSTMQE","object":"chat.completion","created":1770033253,"model":"google/gemini-2.5-flash","choices":[{"index":0,"message":{"role":"assistant","content":"The sum of 2 and 3 is 5, and the product of 2 and 3 is 6.","provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":197,"candidatesTokenCount":25,"totalTokenCount":222}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"google","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":false,"error":"Please ensure that the number of function response parts is equal to the number of function call parts of the function call turn.","startTime":1956234.837355,"endTime":1956397.272511,"statusCode":400},{"provider":"google","internalModelId":"google:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":1956497.822129,"endTime":1956985.150646,"statusCode":200,"providerResponseId":"ZZCAady9I-KF7M8PkM3b4AE"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.0001216","marketCost":"0.0001216","generationId":"gen_01KGF382G93A1FEHZRVZDSTMQE","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":197,"completion_tokens":25,"total_tokens":222,"cost":0.0001216,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0001216},"system_fingerprint":"fp_sxou9xxzzl","generationId":"gen_01KGF382G93A1FEHZRVZDSTMQE"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 921.5745ms diff --git a/providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool_streaming.yaml b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..25610637b38ad6a0e89aaca399ed38995ba06654 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/multi_tool_streaming.yaml @@ -0,0 +1,87 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 865 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"google/gemini-2.5-flash","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF383DF2E9FSJX95AA3ZED7","object":"chat.completion.chunk","created":1770033254,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_nkvitg7moc"} + + data: {"id":"gen_01KGF383DF2E9FSJX95AA3ZED7","object":"chat.completion.chunk","created":1770033254,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"S66o9rnUIliVpcHx","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_nkvitg7moc"} + + data: {"id":"gen_01KGF383DF2E9FSJX95AA3ZED7","object":"chat.completion.chunk","created":1770033254,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"b\":3,\"a\":2}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_nkvitg7moc"} + + data: {"id":"gen_01KGF383DF2E9FSJX95AA3ZED7","object":"chat.completion.chunk","created":1770033254,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"6e0NXuEtzAHkTRep","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_nkvitg7moc"} + + data: {"id":"gen_01KGF383DF2E9FSJX95AA3ZED7","object":"chat.completion.chunk","created":1770033254,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\":2,\"b\":3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_nkvitg7moc"} + + data: {"id":"gen_01KGF383DF2E9FSJX95AA3ZED7","object":"chat.completion.chunk","created":1770033254,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":37,"promptTokenCount":57,"candidatesTokenCount":10,"totalTokenCount":104,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":3167743.289212,"endTime":3168716.703261,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":3167743.289212,"endTime":3168716.703261,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.0001346","marketCost":"0.0001346","generationId":"gen_01KGF383DF2E9FSJX95AA3ZED7","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":57,"completion_tokens":10,"total_tokens":67,"cost":0.0001346,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":37,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0001346},"system_fingerprint":"fp_nkvitg7moc","generationId":"gen_01KGF383DF2E9FSJX95AA3ZED7"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.071326459s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1238 + 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"},{"tool_calls":[{"id":"S66o9rnUIliVpcHx","function":{"arguments":"{\"b\":3,\"a\":2}","name":"add"},"type":"function"},{"id":"6e0NXuEtzAHkTRep","function":{"arguments":"{\"a\":2,\"b\":3}","name":"multiply"},"type":"function"}],"role":"assistant"},{"content":"5","tool_call_id":"S66o9rnUIliVpcHx","role":"tool"},{"content":"6","tool_call_id":"6e0NXuEtzAHkTRep","role":"tool"}],"model":"google/gemini-2.5-flash","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF384F3XAWSR4PC2A0QPAGW","object":"chat.completion.chunk","created":1770033255,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_r6gptvhx1g"} + + data: {"id":"gen_01KGF384F3XAWSR4PC2A0QPAGW","object":"chat.completion.chunk","created":1770033255,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"content":"The sum of"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_r6gptvhx1g"} + + data: {"id":"gen_01KGF384F3XAWSR4PC2A0QPAGW","object":"chat.completion.chunk","created":1770033255,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"content":" 2 and 3 is 5, and the product of 2 and"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_r6gptvhx1g"} + + data: {"id":"gen_01KGF384F3XAWSR4PC2A0QPAGW","object":"chat.completion.chunk","created":1770033255,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"content":" 3 is 6."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_r6gptvhx1g"} + + data: {"id":"gen_01KGF384F3XAWSR4PC2A0QPAGW","object":"chat.completion.chunk","created":1770033255,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":193,"candidatesTokenCount":23,"totalTokenCount":216}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"google","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":false,"error":"Please ensure that the number of function response parts is equal to the number of function call parts of the function call turn.","startTime":3168815.590185,"endTime":3168973.53366,"statusCode":400},{"provider":"google","internalModelId":"google:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":3169095.201105,"endTime":3169473.585021,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":true,"providerAttemptCount":2,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":false,"error":"Please ensure that the number of function response parts is equal to the number of function call parts of the function call turn.","startTime":3168815.590185,"endTime":3168973.53366,"statusCode":400},{"provider":"google","internalModelId":"google:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":3169095.201105,"endTime":3169473.585021,"statusCode":200}]}],"totalProviderAttemptCount":2},"cost":"0.0001154","marketCost":"0.0001154","generationId":"gen_01KGF384F3XAWSR4PC2A0QPAGW","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":193,"completion_tokens":23,"total_tokens":216,"cost":0.0001154,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0001154},"system_fingerprint":"fp_r6gptvhx1g","generationId":"gen_01KGF384F3XAWSR4PC2A0QPAGW"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 752.724625ms diff --git a/providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple.yaml b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..9676008c622dcbc9d8d14dbc35a811f1b24f41e4 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple.yaml @@ -0,0 +1,33 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 173 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"google/gemini-2.5-flash","max_tokens":4000}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37X8BY3AB4X8CN72NQHAV","object":"chat.completion","created":1770033248,"model":"google/gemini-2.5-flash","choices":[{"index":0,"message":{"role":"assistant","content":"Olá!","provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":23,"promptTokenCount":9,"candidatesTokenCount":2,"totalTokenCount":34,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":427093.03273,"endTime":427617.793917,"statusCode":200,"providerResponseId":"X5CAaaH-Ipyy2fMP5ezVKA"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.0000652","marketCost":"0.0000652","generationId":"gen_01KGF37X8BY3AB4X8CN72NQHAV","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":9,"completion_tokens":2,"total_tokens":11,"cost":0.0000652,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":23,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0000652},"system_fingerprint":"fp_oj9j2v6wic","generationId":"gen_01KGF37X8BY3AB4X8CN72NQHAV"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 605.216666ms diff --git a/providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple_streaming.yaml b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..70274c47b015261547a2fd3c0988df0f448876b4 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/simple_streaming.yaml @@ -0,0 +1,40 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 227 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"google/gemini-2.5-flash","max_tokens":4000,"stream_options":{"include_usage":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF37XVPQFTEF88B3MN5VGHK","object":"chat.completion.chunk","created":1770033248,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_1hjld5wcik"} + + data: {"id":"gen_01KGF37XVPQFTEF88B3MN5VGHK","object":"chat.completion.chunk","created":1770033248,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"content":"Olá!"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_1hjld5wcik"} + + data: {"id":"gen_01KGF37XVPQFTEF88B3MN5VGHK","object":"chat.completion.chunk","created":1770033248,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":25,"promptTokenCount":9,"candidatesTokenCount":2,"totalTokenCount":36,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":7617027.32849,"endTime":7617674.256609,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":7617027.32849,"endTime":7617674.256609,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.0000702","marketCost":"0.0000702","generationId":"gen_01KGF37XVPQFTEF88B3MN5VGHK","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":9,"completion_tokens":2,"total_tokens":11,"cost":0.0000702,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":25,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0000702},"system_fingerprint":"fp_1hjld5wcik","generationId":"gen_01KGF37XVPQFTEF88B3MN5VGHK"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 875.25225ms diff --git a/providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool.yaml b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0c738571b4444c507aed3d049733fe833eaadb73 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 465 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"google/gemini-2.5-flash","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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37YQYT0615AXEWGQMX7A4","object":"chat.completion","created":1770033249,"model":"google/gemini-2.5-flash","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"2UEinTAmGM13bjwN","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence,Italy\"}"}}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":57,"promptTokenCount":28,"candidatesTokenCount":5,"totalTokenCount":90,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":1355937.787241,"endTime":1356631.240553,"statusCode":200,"providerResponseId":"YZCAafTaCP-xhcIP6Zz3mAQ"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.0001634","marketCost":"0.0001634","generationId":"gen_01KGF37YQYT0615AXEWGQMX7A4","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":28,"completion_tokens":5,"total_tokens":33,"cost":0.0001634,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":57,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0001634},"system_fingerprint":"fp_q7zc9ylbsc","generationId":"gen_01KGF37YQYT0615AXEWGQMX7A4"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 851.617709ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 690 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"2UEinTAmGM13bjwN","function":{"arguments":"{\"location\":\"Florence,Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"2UEinTAmGM13bjwN","role":"tool"}],"model":"google/gemini-2.5-flash","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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF37ZH945B4T7Q2YDF1YW7K","object":"chat.completion","created":1770033250,"model":"google/gemini-2.5-flash","choices":[{"index":0,"message":{"role":"assistant","content":"The weather in Florence, Italy is 40 C.","provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":40,"candidatesTokenCount":12,"totalTokenCount":52,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":347802.523594,"endTime":348287.615775,"statusCode":200,"providerResponseId":"YZCAaYSqO9X8tfAPg7j5QA"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.000042","marketCost":"0.000042","generationId":"gen_01KGF37ZH945B4T7Q2YDF1YW7K","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":40,"completion_tokens":12,"total_tokens":52,"cost":0.000042,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000042},"system_fingerprint":"fp_oqc02i8x0x","generationId":"gen_01KGF37ZH945B4T7Q2YDF1YW7K"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 587.012542ms diff --git a/providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool_streaming.yaml b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d5d4aca623dde1d7666af829ecfc2e167b41bfa2 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-2.5-flash/tool_streaming.yaml @@ -0,0 +1,81 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 519 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"google/gemini-2.5-flash","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3803YBNDA2M8B7319DJ82","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_7in70gabwf"} + + data: {"id":"gen_01KGF3803YBNDA2M8B7319DJ82","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"g8BRNPzm2XAHjElR","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_7in70gabwf"} + + data: {"id":"gen_01KGF3803YBNDA2M8B7319DJ82","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"location\":\"Florence,Italy\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_7in70gabwf"} + + data: {"id":"gen_01KGF3803YBNDA2M8B7319DJ82","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":51,"promptTokenCount":28,"candidatesTokenCount":5,"totalTokenCount":84,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":430027.607924,"endTime":430701.108841,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":430027.607924,"endTime":430701.108841,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.0001484","marketCost":"0.0001484","generationId":"gen_01KGF3803YBNDA2M8B7319DJ82","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":28,"completion_tokens":5,"total_tokens":33,"cost":0.0001484,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":51,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0001484},"system_fingerprint":"fp_7in70gabwf","generationId":"gen_01KGF3803YBNDA2M8B7319DJ82"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 758.2815ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 744 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"g8BRNPzm2XAHjElR","function":{"arguments":"{\"location\":\"Florence,Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"g8BRNPzm2XAHjElR","role":"tool"}],"model":"google/gemini-2.5-flash","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF380V9QM93HK4DBFD3050C","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_edgl953q80"} + + data: {"id":"gen_01KGF380V9QM93HK4DBFD3050C","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_edgl953q80"} + + data: {"id":"gen_01KGF380V9QM93HK4DBFD3050C","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"content":" weather in Florence, Italy is 40 C."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_edgl953q80"} + + data: {"id":"gen_01KGF380V9QM93HK4DBFD3050C","object":"chat.completion.chunk","created":1770033251,"model":"google/gemini-2.5-flash","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":40,"candidatesTokenCount":12,"totalTokenCount":52,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-2.5-flash","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-2.5-flash","internalResolvedModelId":"vertex:gemini-2.5-flash","fallbacksAvailable":["google","deepinfra"],"internalReasoning":"Selected vertex as preferred provider for gemini-2.5-flash. 2 fallback(s) available: google, deepinfra","planningReasoning":"System credentials planned for: vertex, google, deepinfra. Total execution order: vertex(system) → google(system) → deepinfra(system)","canonicalSlug":"google/gemini-2.5-flash","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":4541137.912067,"endTime":4541464.788969,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-2.5-flash","canonicalSlug":"google/gemini-2.5-flash","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-2.5-flash","providerApiModelId":"gemini-2.5-flash","credentialType":"system","success":true,"startTime":4541137.912067,"endTime":4541464.788969,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000042","marketCost":"0.000042","generationId":"gen_01KGF380V9QM93HK4DBFD3050C","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":40,"completion_tokens":12,"total_tokens":52,"cost":0.000042,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000042},"system_fingerprint":"fp_edgl953q80","generationId":"gen_01KGF380V9QM93HK4DBFD3050C"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 425.562958ms diff --git a/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool.yaml b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0e3d6bb09244641ea72a2f200b92a312c848a2fb --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 832 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF39J2GMGMAPH0F955QXJN5","object":"chat.completion","created":1770033304,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"yr8vjBiBxciYk81p","type":"function","function":{"name":"add","arguments":"{\"b\":3,\"a\":2}"}},{"id":"AmDRMtn5jFH1FM4J","type":"function","function":{"name":"multiply","arguments":"{\"b\":3,\"a\":2}"}}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":119,"promptTokenCount":61,"candidatesTokenCount":18,"totalTokenCount":198,"trafficType":"PROVISIONED_THROUGHPUT"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7050722.565232,"endTime":7053930.218976,"statusCode":200,"providerResponseId":"lZCAaejDKf6BmLAPjqmi-Qo"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.001766","marketCost":"0.001766","generationId":"gen_01KGF39J2GMGMAPH0F955QXJN5","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":61,"completion_tokens":18,"total_tokens":79,"cost":0.001766,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":119,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.001766},"system_fingerprint":"fp_sbwyjrbwm9","generationId":"gen_01KGF39J2GMGMAPH0F955QXJN5"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 3.301019917s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1205 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"},{"tool_calls":[{"id":"yr8vjBiBxciYk81p","function":{"arguments":"{\"b\":3,\"a\":2}","name":"add"},"type":"function"},{"id":"AmDRMtn5jFH1FM4J","function":{"arguments":"{\"b\":3,\"a\":2}","name":"multiply"},"type":"function"}],"role":"assistant"},{"content":"5","tool_call_id":"yr8vjBiBxciYk81p","role":"tool"},{"content":"6","tool_call_id":"AmDRMtn5jFH1FM4J","role":"tool"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF39N3ZQQNAHVCNDKGKFDXH","object":"chat.completion","created":1770033309,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":"The sum of 2 and 3 is 5, and the product of 2 and 3 is 6.","reasoning_details":[{"type":"reasoning.encrypted","data":"EowECokEAXLI2nxcmOHKFmCie8wZQj4/lvp5r14Pp4tqdLOscZ0XBOKdSP60HUPURffivhxpaKDjwvyYIf43reXC7PyAzrNjw/g82cNAjfDK7wpy9ytBDKW8Jmn0KghvDqliK1EHUa5r5phWGwyclW3coT/6X1mtcQd89uAjf3qg3HyAvSNRrpjY+5E8i1CWh9Klnz+4AJ6cAHyahhkqS6Kc/0fZWFwggkOYPetH/bLrdipfcjBOIyRsWg8YeR9iRiv2cBbHruJeops0JKxCVhr750bJiYYehM3eOgvfD6rXA9TJnv6+sjoGXK/kWkrFW84i7lJvbDZaonJwVbDe3B1qpm+cmiGRHDHBQDam9dfLnRoeuk8lvEHtJctSIGRKSG+qavsxhHsr+IyWolld74TkIc7/dFHqJvCUkp8UtIg7KFMIHsQmi0FGn2IpUK/pW47Q8wT9eUdbxr8FFkmcsTMziI1QexEK1bosMZYDYc6AnQ3HXQzGuCq/Alx8jaku4xeyl1xplmMCKPui0AvK05/uKD08xSmWouSi3iMsIxj/1QRvrejj22oT7DiHZuL/DKp8tnCR2f3M/U8OmxMr665dpyWMfrBLAFL0KL7AQGoRqpxoLEbTmISk5wDaxYdXqnLhgPw9qF4TCRYnUQNfSbzIfKmCk/ekKwX0NBROCJu5yhVEBsMEevDTC/sg8q0=","format":"google-gemini-v1","index":0}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":119,"promptTokenCount":223,"candidatesTokenCount":25,"totalTokenCount":367}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"google","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":false,"error":"Please ensure that the number of function response parts is equal to the number of function call parts of the function call turn.","startTime":7674067.523962,"endTime":7674739.16189,"statusCode":400},{"provider":"google","internalModelId":"google:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7674863.56271,"endTime":7678582.662173,"statusCode":200,"providerResponseId":"nZCAaaflFeKF7M8Pis3b4AE"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002174","marketCost":"0.002174","generationId":"gen_01KGF39N3ZQQNAHVCNDKGKFDXH","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":223,"completion_tokens":25,"total_tokens":248,"cost":0.002174,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":119,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002174},"system_fingerprint":"fp_q0jgoj8amw","generationId":"gen_01KGF39N3ZQQNAHVCNDKGKFDXH"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 4.618416166s diff --git a/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool_streaming.yaml b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..20871ca79f06f0cdeba0284c17a943d420bc7c71 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/multi_tool_streaming.yaml @@ -0,0 +1,85 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 869 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}],"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF39SRSQ5CWVF17GR4P29CK","object":"chat.completion.chunk","created":1770033312,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_4r8izhsq38"} + + data: {"id":"gen_01KGF39SRSQ5CWVF17GR4P29CK","object":"chat.completion.chunk","created":1770033312,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"Oxu2MENhE0ZsrlGm","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_4r8izhsq38"} + + data: {"id":"gen_01KGF39SRSQ5CWVF17GR4P29CK","object":"chat.completion.chunk","created":1770033312,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"b\":3,\"a\":2}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_4r8izhsq38"} + + data: {"id":"gen_01KGF39SRSQ5CWVF17GR4P29CK","object":"chat.completion.chunk","created":1770033312,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"jHpVWOzg44py3a4h","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_4r8izhsq38"} + + data: {"id":"gen_01KGF39SRSQ5CWVF17GR4P29CK","object":"chat.completion.chunk","created":1770033312,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"b\":3,\"a\":2}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_4r8izhsq38"} + + data: {"id":"gen_01KGF39SRSQ5CWVF17GR4P29CK","object":"chat.completion.chunk","created":1770033312,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":76,"promptTokenCount":57,"candidatesTokenCount":18,"totalTokenCount":151,"trafficType":"PROVISIONED_THROUGHPUT"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7678877.96491,"endTime":7682011.782537,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7678877.96491,"endTime":7682011.782537,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.001242","marketCost":"0.001242","generationId":"gen_01KGF39SRSQ5CWVF17GR4P29CK","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":57,"completion_tokens":18,"total_tokens":75,"cost":0.001242,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":76,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.001242},"system_fingerprint":"fp_4r8izhsq38","generationId":"gen_01KGF39SRSQ5CWVF17GR4P29CK"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 3.240620375s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1242 + 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"},{"tool_calls":[{"id":"Oxu2MENhE0ZsrlGm","function":{"arguments":"{\"b\":3,\"a\":2}","name":"add"},"type":"function"},{"id":"jHpVWOzg44py3a4h","function":{"arguments":"{\"b\":3,\"a\":2}","name":"multiply"},"type":"function"}],"role":"assistant"},{"content":"5","tool_call_id":"Oxu2MENhE0ZsrlGm","role":"tool"},{"content":"6","tool_call_id":"jHpVWOzg44py3a4h","role":"tool"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}],"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF39X286MHE27SNFKH25NC4","object":"chat.completion.chunk","created":1770033316,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_77ne7mn4wm"} + + data: {"id":"gen_01KGF39X286MHE27SNFKH25NC4","object":"chat.completion.chunk","created":1770033316,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":"The sum of 2 and 3 is"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_77ne7mn4wm"} + + data: {"id":"gen_01KGF39X286MHE27SNFKH25NC4","object":"chat.completion.chunk","created":1770033316,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":" 5, and the product of 2 and 3 is 6."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_77ne7mn4wm"} + + data: {"id":"gen_01KGF39X286MHE27SNFKH25NC4","object":"chat.completion.chunk","created":1770033316,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":107,"promptTokenCount":219,"candidatesTokenCount":25,"totalTokenCount":351}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"google","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":false,"error":"Please ensure that the number of function response parts is equal to the number of function call parts of the function call turn.","startTime":7682389.843352,"endTime":7682560.855095,"statusCode":400},{"provider":"google","internalModelId":"google:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7682658.945631,"endTime":7685688.640771,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":2,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":false,"error":"Please ensure that the number of function response parts is equal to the number of function call parts of the function call turn.","startTime":7682389.843352,"endTime":7682560.855095,"statusCode":400},{"provider":"google","internalModelId":"google:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7682658.945631,"endTime":7685688.640771,"statusCode":200}]}],"totalProviderAttemptCount":2},"cost":"0.002022","marketCost":"0.002022","generationId":"gen_01KGF39X286MHE27SNFKH25NC4","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":219,"completion_tokens":25,"total_tokens":244,"cost":0.002022,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":107,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002022},"system_fingerprint":"fp_77ne7mn4wm","generationId":"gen_01KGF39X286MHE27SNFKH25NC4"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 3.595823375s diff --git a/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple.yaml b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..821feca092f740dc6112183046c15f4708c3dde0 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple.yaml @@ -0,0 +1,33 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 177 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF38WR2DQ7XVWAQPMSQN05J","object":"chat.completion","created":1770033284,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":"The most common way to say \"hi\" in Portuguese is:\n\n**Oi**\n\nYou can also say **Olá** (which is closer to \"hello\").","reasoning_details":[{"type":"reasoning.encrypted","data":"CtcGAY89a1/Vs+RSuBVpzJ1TJvRE/FtqFQVib99RvrHh+gb2EIdzDDZ/SY3ZVeQvQRZIOtEXdxlbjsymY95+YrKyX3B3sDmt7Y0hdpvDVQSQo7BymSD0/qtaPPexP57xCSzdyLZo08AKW5LCUmrBI15/XipH592d0XzRuidBu+EeAlTHMv3bwpwJaJ8DB4RoHhLpG8ueW73DsRnioUPYyQKnUK/8uov5qicTsNIiT67adu/wUBytqrDgRGmtiqw3MyQBaOG7xIEg8VUy8gTAVBKc3HFUh0m8d9+GbHshh2RgKyhA47cBxgef9hHH9fcM71mDXqgNJrZhv7vxgt4GOmVIF7e9iIx4lnYxi46WRlAchSO/rym7grFHNBAZ3D/uQoIp1VyoCyySIcLRVhLyNrU4c3IHWdOs6JuE+xbZiB3Flyccvg4oqiiaN4SOJXlP5+iAo9ASQmwHVy5e4j+/7Uo5G4D+pfxAdYwTT7cbGxLwHDZC13kcFfoi7YHawIghOLdcbQ4Y1wjkHbkP3vgp6zcTsQRw8PGZ8mPaHgMeZ3BGQn+q3jheqs3vcY0zazH9j2b1Yp4R2rcqyHqTpj1pV9BScW1g9dYuTRDjkzJbQxERZ2OrDTomVD6wPV76lldVGVeOOIRY/sNwl/VyXfyp4uJvqHTd6lz1A7JvUQDblT9GMvKmZKXlXW3uCqFroJpUGZVyFBxoNg4vo2vNZdpkCKikbX+irD58WxT8//oU9utaT5TmU7iVcGez3xeED8Pcfe8b4cDBnIBdNPDYJOjLXh5PFFJHJ7ad6Qzb+4FLdXnWl132D+uhuC3nQf7fPsrr8gf4yNzefuX8OjPgCGvobT56LusnH26ef8Vq7yYppYm8oz+JEVqXz2yydWWMwfJoCBESk96rNtdQ1fThaLrwGiz30NvOFZhBQ64f9MmTzt5/Ch97xfNBQNj4nCOzwOgsijXxOV0WG0W9zOjLVaL2StHURwyRNrCjDThoenOcOzRQiHIO+Y3ugEyp2k1dLIU93pILCZKmGmErUXVJxNOdPD/JNkfUDkioIvUDX9+To+cfmsx32Ynrm6auYsZzHI6ntFbu2Yw2S7iozfOVBER1ohInrt3djXS3gZn7NlaTlg71BQ3Lhr23As0Y","format":"google-gemini-v1","index":0}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":221,"promptTokenCount":9,"candidatesTokenCount":33,"totalTokenCount":263,"trafficType":"PROVISIONED_THROUGHPUT"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7028889.551463,"endTime":7033870.641762,"statusCode":200,"providerResponseId":"f5CAaZznMrj2mLAP-aa82AU"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.003066","marketCost":"0.003066","generationId":"gen_01KGF38WR2DQ7XVWAQPMSQN05J","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":9,"completion_tokens":33,"total_tokens":42,"cost":0.003066,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":221,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003066},"system_fingerprint":"fp_kece7x1dv2","generationId":"gen_01KGF38WR2DQ7XVWAQPMSQN05J"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 5.077063708s diff --git a/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple_streaming.yaml b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a775f281b5752a2448a09ec9aaa243c49a395e1a --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/simple_streaming.yaml @@ -0,0 +1,42 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 231 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF391Q1MADSMMMS7RN0MPJX","object":"chat.completion.chunk","created":1770033289,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_s005gr6r3v"} + + data: {"id":"gen_01KGF391Q1MADSMMMS7RN0MPJX","object":"chat.completion.chunk","created":1770033289,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":"The most common way to say \"hi\" in Portuguese is **\"Oi\"**.\n\nYou can also say **\"Olá\"** (which is more like \"hello\")."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_s005gr6r3v"} + + data: {"id":"gen_01KGF391Q1MADSMMMS7RN0MPJX","object":"chat.completion.chunk","created":1770033289,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"reasoning_details":[{"type":"reasoning.encrypted","data":"CikBjz1rX1dPuLSzjatsf+kEp2Ri1nfHbqwWCwH07OuC1ZuewqSVGPoPzgpfAY89a18bv4mLFvt3bZAdiEoaZ+mjKsSaNKkndIQFXlBX/7hCWWnr1+bAbThHMnH0oIh/4vTXgk8DVKR87b2jqz0KuQG/kFftlB+5jAH9Jiq5/n2JIbFm06nvcF0dlyoKZgGPPWtfUh80MPPeLg0AMzKvrsGiCeKISEhrD6sg11jcaV4dgc/eBV9iwvHXn1LQU3GtPAsNZ4H1ZJM2+49hgdR6sN4vu81IqEdPsBItnGmr4TBm4Gm90LBPvCkcoSb3bh3q41kuaAqSAQGPPWtfYRILvpzZWl2d/sialYcYOf3UGDEFKBuz8HHUo40bCo+HQuJTal05BxWjIEzS4+wNKYrEsmo65fYSq/W1VBPGJVWbySFHDILvcVbMLJriGdWQbpAtXRAi/EoxQYjctaLyV1H77smAtachR9b7fKBfAlccpyd6QqLRi55uBIIczarwv97rFs+ylW/T/2m8CpQBAY89a198U9DZKPUsXuUCZvugyKq7U4JFHcDNk8+2W9F22IOz/lRPP4mRMj2DnaeMEZvj8NlAgN+uPpIS7pBPMWCiTsNUdTp0ZXfGZid8B/M6DFVv/DiS62f+C9LyW93Y+YLltHz0HsYgqFAhNW/TbxLFwshqad8KSAwEUJspHG5VheRkyflEReRxpNFm9MX7FTIsAQrhAQGPPWtf1NKdz86iQg+9J+FwwgJmOemZh5b7nk1s4iVyI4+SRdy5n6lGIwM/RS4brolzexTvzZU4yJHDd3kPm4eEOrATOu7g6wW4Vsdw6+LA6RkX/+TTPZbt7JmWYVbws5YUJGdKD3ddEG9faoV+kxGun8mJDEOdCKVZUDRQtU07nKEa/R9/8xkJaNBv8GBs4TuOHB56wH9rIp4I1qvaW9DU6TlcxKhw8BdtpYbD6Gg3e6asqePEUEIAXeQ5eQUfgC5lDSXRD99j4j42y3tNiKNXY+h2TZc3SIc40ohsM5XzTwqzAQGPPWtfzWc0ZYfA/k2tbqLr/45Vpgn/1yfSC1kXi+ABfbLhzZR4oNnbBlBHcmEbBF3DokgxaI7WEbopj4zbm0ZsYNJVLxD0cGd/kV+CBKbCf4j7L1fCJKlI8Mnorq5Bgp8i28XWjCydjvRAoTT49cJp0LKnKHw2Hr95yMnKPIwlOiAtQ0IFOjNXbfWQSCp42fSXDofsoufZor01El8xVfsaIQTkJtCbyE/AjOwz25v4xsp/CnkBjz1rXw6jbdgKOjllJsnqicBq0+EJ8nM5HbD25Dj1klrIvslkr8/5YyV6Fk43IYUfpLJW63qj9/4/cuRTDWBmbwOYMbf0JJCC0vGZvlz0UbLH3gEFfElZ7D8KAjc6iQ71etnHkYAHfUHlMdJ/B7qJLvQGpN8w4H/A","format":"google-gemini-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_s005gr6r3v"} + + data: {"id":"gen_01KGF391Q1MADSMMMS7RN0MPJX","object":"chat.completion.chunk","created":1770033289,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":223,"promptTokenCount":9,"candidatesTokenCount":35,"totalTokenCount":267,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":1391831.603433,"endTime":1396730.275173,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":1391831.603433,"endTime":1396730.275173,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.003114","marketCost":"0.003114","generationId":"gen_01KGF391Q1MADSMMMS7RN0MPJX","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":9,"completion_tokens":35,"total_tokens":44,"cost":0.003114,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":223,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003114},"system_fingerprint":"fp_s005gr6r3v","generationId":"gen_01KGF391Q1MADSMMMS7RN0MPJX"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 5.130387417s diff --git a/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool.yaml b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0b8ff03b8a0033f4253e8c7af414b65472164781 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 469 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF396RM9XH4DT3BKG6XYYC0","object":"chat.completion","created":1770033293,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"ixKHls2RfUCWLY8v","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence, Italy\"}"}}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":78,"promptTokenCount":28,"candidatesTokenCount":9,"totalTokenCount":115,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7659506.082926,"endTime":7662838.172979,"statusCode":200,"providerResponseId":"ipCAaZa6CeXDtfAPz8i1yAs"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.0011","marketCost":"0.0011","generationId":"gen_01KGF396RM9XH4DT3BKG6XYYC0","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":28,"completion_tokens":9,"total_tokens":37,"cost":0.0011,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":78,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0011},"system_fingerprint":"fp_oka8v3chzr","generationId":"gen_01KGF396RM9XH4DT3BKG6XYYC0"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 3.581068834s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 695 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"ixKHls2RfUCWLY8v","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"ixKHls2RfUCWLY8v","role":"tool"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF39A6QVKDAEJE16471HJ6N","object":"chat.completion","created":1770033295,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":"The weather in Florence, Italy is currently 40°C.","provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":40,"candidatesTokenCount":14,"totalTokenCount":54,"trafficType":"PROVISIONED_THROUGHPUT"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":1411069.913659,"endTime":1413447.981679,"statusCode":200,"providerResponseId":"jZCAaczqJ6HZmLAP9c_xgAs"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.000248","marketCost":"0.000248","generationId":"gen_01KGF39A6QVKDAEJE16471HJ6N","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":40,"completion_tokens":14,"total_tokens":54,"cost":0.000248,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000248},"system_fingerprint":"fp_qhfqfihebr","generationId":"gen_01KGF39A6QVKDAEJE16471HJ6N"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.530493166s diff --git a/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool_streaming.yaml b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..a8ce080bf5d25b3dfec10aee4f155a34aeba9684 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gemini-3-pro-preview/tool_streaming.yaml @@ -0,0 +1,81 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 523 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF39CMWTBAYWG62BTDA8EX5","object":"chat.completion.chunk","created":1770033298,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_n9t24sd6so"} + + data: {"id":"gen_01KGF39CMWTBAYWG62BTDA8EX5","object":"chat.completion.chunk","created":1770033298,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"mbK8hEFBfrxbyEg3","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_n9t24sd6so"} + + data: {"id":"gen_01KGF39CMWTBAYWG62BTDA8EX5","object":"chat.completion.chunk","created":1770033298,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"location\":\"Florence, Italy\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_n9t24sd6so"} + + data: {"id":"gen_01KGF39CMWTBAYWG62BTDA8EX5","object":"chat.completion.chunk","created":1770033298,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":72,"promptTokenCount":28,"candidatesTokenCount":9,"totalTokenCount":109,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7665475.024571,"endTime":7668255.526409,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7665475.024571,"endTime":7668255.526409,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.001028","marketCost":"0.001028","generationId":"gen_01KGF39CMWTBAYWG62BTDA8EX5","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":28,"completion_tokens":9,"total_tokens":37,"cost":0.001028,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":72,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.001028},"system_fingerprint":"fp_n9t24sd6so","generationId":"gen_01KGF39CMWTBAYWG62BTDA8EX5"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 2.918596875s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 749 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"mbK8hEFBfrxbyEg3","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant"},{"content":"40 C","tool_call_id":"mbK8hEFBfrxbyEg3","role":"tool"}],"model":"google/gemini-3-pro-preview","max_tokens":4000,"stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF39FC3KGNF4QFQ4V4694KD","object":"chat.completion.chunk","created":1770033301,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_et7g7hmqn5"} + + data: {"id":"gen_01KGF39FC3KGNF4QFQ4V4694KD","object":"chat.completion.chunk","created":1770033301,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":"The current temperature in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_et7g7hmqn5"} + + data: {"id":"gen_01KGF39FC3KGNF4QFQ4V4694KD","object":"chat.completion.chunk","created":1770033301,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":" Florence, Italy is 40°C."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_et7g7hmqn5"} + + data: {"id":"gen_01KGF39FC3KGNF4QFQ4V4694KD","object":"chat.completion.chunk","created":1770033301,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":40,"candidatesTokenCount":14,"totalTokenCount":54,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7668162.82122,"endTime":7670529.245941,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7668162.82122,"endTime":7670529.245941,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000248","marketCost":"0.000248","generationId":"gen_01KGF39FC3KGNF4QFQ4V4694KD","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":40,"completion_tokens":14,"total_tokens":54,"cost":0.000248,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000248},"system_fingerprint":"fp_et7g7hmqn5","generationId":"gen_01KGF39FC3KGNF4QFQ4V4694KD"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 2.526340125s diff --git a/providertests/testdata/TestVercelCommon/gpt-5/multi_tool.yaml b/providertests/testdata/TestVercelCommon/gpt-5/multi_tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8d713a40d158a782b27e143dd4e182ae36095188 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gpt-5/multi_tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 828 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"}],"model":"openai/gpt-5","max_completion_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF38JKSTNNP061DTA2R1QR6","object":"chat.completion","created":1770033273,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":null,"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJB5sMVU3E5XyBIYkGVYX_idbwIgEl6hyzl37P25LBkPxPxtSA-z_vG-ub3Ht2lLorQuxuYXJw5TvvQljT1wPC9GtS-3qVZwt_QhReZWbhESWHryCcV1WyEPUZj8oG3nUVCuV917iOoZgfkRgLG8X9Oi5ezb_M42WqRmF1XWXL302fu3bJRy_jT8mmoiLnCmS1wXX_78058GTTjjJLGqTBPni0y7sZDDHpFgUsgpoWv3gF9X9OClhk3JOfuqgNYIVTS90C6pQ-JUHWX-9q-v34qMHs-E_QnaCYQLShf4Fa04N_DY0SphPoP1UaJMp6A1spu8WjCNLr4KjkFsq3QirbYcp9pwZj_N_XmbDRSTE4DXcqLKUafsUjpQC9bNiEvZ2oh95CRmMwHznVetnUTXsmxPj3p7x8MRer9NM1LMetWxMLz28oAnDq6T1xHu1nhSdHVBG7DpVIDeXN6PYA6BLrCiVuB3K3_pooysaNVwv05EPDrCrvYotlHdbDPiU_OsF9uClsKkTguYjfCqihV48xgYqAQJqU_guhAe3NSacal5sjGMG8OBp_QrcTsRmCG-pUJ0_YkU3BKxN-h3FBBjBfnZrmJIHkV17oIvqyfd4mr_apHg_tNQJlyNr14usvYzzp65IK1jJ4UXepLHyBJfuBh6U1j9EQmRd2gS9gwwT_pvN0TVZaZZs32Pxakgq0wBNkRrto41JRHbpdYOuL_pWpcJ8fceSVv4rYxn7qewym_XxX1hFRz3on638qI70UUmPc64m3DzB60l0O83FLqHvlNEGOR6SSogOZc3M0oX9Zll-kgi02fb9deA6_HrhrGjYzAUDFQEuyFwML4u2mquXz7e1hmyKede1kBPnnZxhNODgFbRZrW_qZPf6D8fcLLR5KZHdhO4NjSGigxt3vbdBqRRPVJw5Ci9v2kXJLAczXB8Ifv5Vz9BUdQgAh_QWHmrirtcjU4Y84m1wCskcIpf_F5pduuGedRj6pnmEyYATiNxl0XCy6RmPGKjwgAz5qcQzOyHz013e4QzzB5Etmm6B01_oYpHXgmsi84z_LrSCtGSQI8S8l4RpESzGqaqQ84apbFvw4xJuA3fJPekyN6HkhK0cnD_NVxrUiEsmnhnLNSpUkwjzFGFWbasYYQj6Rik2WNOhoHpmPXzVgJsdrp94MrUGXWEgdUDcIWnH8LFizamKnBNox1e1i_phBxrQLLzqfgN2HABOE9WyDEIfpOgJOX2RfDn6q_RQ9WM79hDZJD7RUap1bC0dlxqomi0fYVqyOoW0RQyQ-_mrBK4nYFVwfDaZwrWXNzTsFvtlJzN8O8-L5J6UTx-AhSNcnI35O3AuxbNyRC72HhVzN-A0Ae4SouL25ouc582Oy8M1xzs9RjlkoSIHZYAe2wzfvD9B7N0F2tbahD-MOHCbLctCFRb_S4gO29xZgeGgdXxyykq5il4vya6f1GmTfCC9Ktg4dsdmmqbSAXV9Ck0iUhg4cZVSNliyxxUMjJfDLt8ZO0f_UxrD2RCoZL7zwRgCAldl4ndkmotvTH_0HSRxmob1Q6AwgItkWU7GcGdk_7PLUho5332sVdKbQcpLVZQNyKOVtreej8EkH47b8wEvVJ6lz2lKNKEz9tyHRUlEPBjW3yb3YvO3wyfRkkqMMXFO_PEuhQ66ceSOHJJW2zmJuZepwBMUiez3sZph3o1zjvB7tHAY7YCaTjbh8urPaYjGUrLyVmvAkwEbQQwE1-vpyhoztrqOinvOm6fUyU0HsQuQIEqCUtFqO8G755g3I_cFrgfjmgRXMMvhKk4iQ61rOL2YAPNozSdCGNtplTJIhnb2xZC-gbtK8YwcbWz7B1k2bICxfgAhX7W9cOsnGnJwB-wS_vAkmjSZrHmrkAAAEjPLaemIGxhPzZ9sU6R2TLKHL6wOA0LthE5ltRY5PGnsCK7NFcsHDcyFWCGLH10UYfV1n5_uOvUMqsHlT8iHMA2y-W0DtdzDNeEUOZj5mDAwfdTAIoXJc5-wieyLp27uLJqmJ0ZvchRT2CcM0SC_mDNaYXlJyn5uavmUkp4Ykh2LGN54lFFzbcOsVcVLzpdQJ0u2QF4QXIbzHMnw8ipejfMaN2zkXRGsex9BXcf9fIOxwPH8LTsLRArUz--pl8wq8x2_ZyRNC5ZPtZrWr3lTokTqXrb8gASoIchRTZDV8fQdPIPXIJE4A-Dn-8Hfrxnf63IKRoFv4ENTzOoycoNH4kyCh4LQSInGFeE5vAa3Iq_ctdHf6LlVnoURnZdrmC_c03UMJjv671ZYbzuS76jKRTAJF7PnJhDdAhV-xvZmRKzJpJ4k_ZmN9O19iXZVVv4ofjn3m0iOWY8N61suLBb9wErE0PJxzNQnLBFSXuC3qrd9IrVzEMUOsMloPH6bB-zGlRQP_gY3LzZ4tEF70ZuqIdwAYgjKGc9LqXfz0d5hXLLPE0MeJxiCJFuHyUCgPphf8gfCw6lw0gz7KiH87aXBbOTwcUl2bT6pDDmKSkZQPUv67c0JoB0j5IsH67XBFhYZHiyenTddXJHSKHXnLlhdZCifIDaYXElPZLdWT5SZ3Y_i1AAaLOk-h2esjagpMOWRZMzY97KHDINIMiUcW_aE5IrsGWkP8jnHu-rDHXU2L9VOzErnTMz8b-DXg==","id":"rs_09ce24a3ef4ef4c30169809075d9c881909a0602f2f9b94079","format":"openai-responses-v1","index":0}],"tool_calls":[{"id":"call_hw6yjnBO12c7jlYo4Ug0REvD","type":"function","function":{"name":"add","arguments":"{\"a\":2,\"b\":3}"}},{"id":"call_1DofUzAYzaNZecbxfrt2sRSv","type":"function","function":{"name":"multiply","arguments":"{\"a\":2,\"b\":3}"}}],"provider_metadata":{"openai":{"responseId":"resp_09ce24a3ef4ef4c30169809075837481908f0f2e352bb0536c","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1376272.617242,"endTime":1380180.418282,"statusCode":200,"providerResponseId":"resp_09ce24a3ef4ef4c30169809075837481908f0f2e352bb0536c"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.00609","marketCost":"0.00609","generationId":"gen_01KGF38JKSTNNP061DTA2R1QR6","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":56,"completion_tokens":346,"total_tokens":402,"cost":0.00609,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":256,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00609},"system_fingerprint":"fp_z6pyhzzwli","generationId":"gen_01KGF38JKSTNNP061DTA2R1QR6"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 3.998469542s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 4078 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system"},{"content":"Add and multiply the number 2 and 3","role":"user"},{"tool_calls":[{"id":"call_hw6yjnBO12c7jlYo4Ug0REvD","function":{"arguments":"{\"a\":2,\"b\":3}","name":"add"},"type":"function"},{"id":"call_1DofUzAYzaNZecbxfrt2sRSv","function":{"arguments":"{\"a\":2,\"b\":3}","name":"multiply"},"type":"function"}],"role":"assistant","reasoning_details":[{"data":"gAAAAABpgJB5sMVU3E5XyBIYkGVYX_idbwIgEl6hyzl37P25LBkPxPxtSA-z_vG-ub3Ht2lLorQuxuYXJw5TvvQljT1wPC9GtS-3qVZwt_QhReZWbhESWHryCcV1WyEPUZj8oG3nUVCuV917iOoZgfkRgLG8X9Oi5ezb_M42WqRmF1XWXL302fu3bJRy_jT8mmoiLnCmS1wXX_78058GTTjjJLGqTBPni0y7sZDDHpFgUsgpoWv3gF9X9OClhk3JOfuqgNYIVTS90C6pQ-JUHWX-9q-v34qMHs-E_QnaCYQLShf4Fa04N_DY0SphPoP1UaJMp6A1spu8WjCNLr4KjkFsq3QirbYcp9pwZj_N_XmbDRSTE4DXcqLKUafsUjpQC9bNiEvZ2oh95CRmMwHznVetnUTXsmxPj3p7x8MRer9NM1LMetWxMLz28oAnDq6T1xHu1nhSdHVBG7DpVIDeXN6PYA6BLrCiVuB3K3_pooysaNVwv05EPDrCrvYotlHdbDPiU_OsF9uClsKkTguYjfCqihV48xgYqAQJqU_guhAe3NSacal5sjGMG8OBp_QrcTsRmCG-pUJ0_YkU3BKxN-h3FBBjBfnZrmJIHkV17oIvqyfd4mr_apHg_tNQJlyNr14usvYzzp65IK1jJ4UXepLHyBJfuBh6U1j9EQmRd2gS9gwwT_pvN0TVZaZZs32Pxakgq0wBNkRrto41JRHbpdYOuL_pWpcJ8fceSVv4rYxn7qewym_XxX1hFRz3on638qI70UUmPc64m3DzB60l0O83FLqHvlNEGOR6SSogOZc3M0oX9Zll-kgi02fb9deA6_HrhrGjYzAUDFQEuyFwML4u2mquXz7e1hmyKede1kBPnnZxhNODgFbRZrW_qZPf6D8fcLLR5KZHdhO4NjSGigxt3vbdBqRRPVJw5Ci9v2kXJLAczXB8Ifv5Vz9BUdQgAh_QWHmrirtcjU4Y84m1wCskcIpf_F5pduuGedRj6pnmEyYATiNxl0XCy6RmPGKjwgAz5qcQzOyHz013e4QzzB5Etmm6B01_oYpHXgmsi84z_LrSCtGSQI8S8l4RpESzGqaqQ84apbFvw4xJuA3fJPekyN6HkhK0cnD_NVxrUiEsmnhnLNSpUkwjzFGFWbasYYQj6Rik2WNOhoHpmPXzVgJsdrp94MrUGXWEgdUDcIWnH8LFizamKnBNox1e1i_phBxrQLLzqfgN2HABOE9WyDEIfpOgJOX2RfDn6q_RQ9WM79hDZJD7RUap1bC0dlxqomi0fYVqyOoW0RQyQ-_mrBK4nYFVwfDaZwrWXNzTsFvtlJzN8O8-L5J6UTx-AhSNcnI35O3AuxbNyRC72HhVzN-A0Ae4SouL25ouc582Oy8M1xzs9RjlkoSIHZYAe2wzfvD9B7N0F2tbahD-MOHCbLctCFRb_S4gO29xZgeGgdXxyykq5il4vya6f1GmTfCC9Ktg4dsdmmqbSAXV9Ck0iUhg4cZVSNliyxxUMjJfDLt8ZO0f_UxrD2RCoZL7zwRgCAldl4ndkmotvTH_0HSRxmob1Q6AwgItkWU7GcGdk_7PLUho5332sVdKbQcpLVZQNyKOVtreej8EkH47b8wEvVJ6lz2lKNKEz9tyHRUlEPBjW3yb3YvO3wyfRkkqMMXFO_PEuhQ66ceSOHJJW2zmJuZepwBMUiez3sZph3o1zjvB7tHAY7YCaTjbh8urPaYjGUrLyVmvAkwEbQQwE1-vpyhoztrqOinvOm6fUyU0HsQuQIEqCUtFqO8G755g3I_cFrgfjmgRXMMvhKk4iQ61rOL2YAPNozSdCGNtplTJIhnb2xZC-gbtK8YwcbWz7B1k2bICxfgAhX7W9cOsnGnJwB-wS_vAkmjSZrHmrkAAAEjPLaemIGxhPzZ9sU6R2TLKHL6wOA0LthE5ltRY5PGnsCK7NFcsHDcyFWCGLH10UYfV1n5_uOvUMqsHlT8iHMA2y-W0DtdzDNeEUOZj5mDAwfdTAIoXJc5-wieyLp27uLJqmJ0ZvchRT2CcM0SC_mDNaYXlJyn5uavmUkp4Ykh2LGN54lFFzbcOsVcVLzpdQJ0u2QF4QXIbzHMnw8ipejfMaN2zkXRGsex9BXcf9fIOxwPH8LTsLRArUz--pl8wq8x2_ZyRNC5ZPtZrWr3lTokTqXrb8gASoIchRTZDV8fQdPIPXIJE4A-Dn-8Hfrxnf63IKRoFv4ENTzOoycoNH4kyCh4LQSInGFeE5vAa3Iq_ctdHf6LlVnoURnZdrmC_c03UMJjv671ZYbzuS76jKRTAJF7PnJhDdAhV-xvZmRKzJpJ4k_ZmN9O19iXZVVv4ofjn3m0iOWY8N61suLBb9wErE0PJxzNQnLBFSXuC3qrd9IrVzEMUOsMloPH6bB-zGlRQP_gY3LzZ4tEF70ZuqIdwAYgjKGc9LqXfz0d5hXLLPE0MeJxiCJFuHyUCgPphf8gfCw6lw0gz7KiH87aXBbOTwcUl2bT6pDDmKSkZQPUv67c0JoB0j5IsH67XBFhYZHiyenTddXJHSKHXnLlhdZCifIDaYXElPZLdWT5SZ3Y_i1AAaLOk-h2esjagpMOWRZMzY97KHDINIMiUcW_aE5IrsGWkP8jnHu-rDHXU2L9VOzErnTMz8b-DXg==","format":"openai-responses-v1","id":"rs_09ce24a3ef4ef4c30169809075d9c881909a0602f2f9b94079","index":0,"type":"reasoning.encrypted"}]},{"content":"5","tool_call_id":"call_hw6yjnBO12c7jlYo4Ug0REvD","role":"tool"},{"content":"6","tool_call_id":"call_1DofUzAYzaNZecbxfrt2sRSv","role":"tool"}],"model":"openai/gpt-5","max_completion_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF38PH89YBGB4JEVM3QY13Q","object":"chat.completion","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":"Sum: 5\nProduct: 6","provider_metadata":{"openai":{"responseId":"resp_09ce24a3ef4ef4c3016980907989e48190add2b3ea521eefd8","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":262916.844804,"endTime":263772.252753,"statusCode":200,"providerResponseId":"resp_09ce24a3ef4ef4c3016980907989e48190add2b3ea521eefd8"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.00070875","marketCost":"0.00070875","generationId":"gen_01KGF38PH89YBGB4JEVM3QY13Q","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":463,"completion_tokens":13,"total_tokens":476,"cost":0.00070875,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00070875},"system_fingerprint":"fp_md8g0mkmrp","generationId":"gen_01KGF38PH89YBGB4JEVM3QY13Q"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 961.776042ms diff --git a/providertests/testdata/TestVercelCommon/gpt-5/multi_tool_streaming.yaml b/providertests/testdata/TestVercelCommon/gpt-5/multi_tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f2251f0326ff81db7a266e8ef7dc338f3d2ebeca --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gpt-5/multi_tool_streaming.yaml @@ -0,0 +1,101 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 865 + 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":"openai/gpt-5","max_completion_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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_lwams5xjm0"} + + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJB6xgaIX4YGTj3EZimfLMfl7lZ7SJq0aBMWfGDeorXxt6sRPjllCKcFat69Q1kpuEDG1tvuIG_6OxUZHOP_noSA63nkkhTluixdSHPde3XgwYgrm01hBIphFo1ztgQMsVXZaqNGBJKfB35qJ7zSKEFXWcB6olUNA4UUXTup_nH8KrNf0_JcRd4JmIXeaQTTaNLYxeUNljoVsLun6RwBzKf2sDmMFqa8wdE5v159EsaN20EgWQnJGlWdyWEZBixffGM4cXbWIpmZRCv8TCy4dYMh3Nz8FQt7JbWJvCWQskP_b3AFm3TV-h8yUBFhdXRYAeZxtIZsBmjCZZtwDPGnKJ3tLtSnQ3PtlYFn1l0vvPgHh7mdmnhdbWtkUh3hQozmpwGYE5G0LE1XlEQ9KqdR6_ERfztdnbWnxJqAly_m5uXFu6ymcMDmZhkdFvRM1M8923TpttfrkNlzsQM2pzRyZYhATSrBz8eMgJY7me3UHXo3FlGnf0Capm2MNNLVytVv0mgqa8WEMhPzpuga1kbqKt884QqnjHgozx0DYM68uOwTOlMBdRSf6MCE5aqn4fYK7sp3_ZclUNtDr7cM8Pz5GJX3dh_py69qCStpAhptt0smksFcHGezX9zrDehJ9bPvW6gTK4aBKUAndr6SXQ22Boa0kRTo2YWU6mNMr0yNQomEoupdUvc5FtsJ6PiaOz7rTHDS10SCZAvSv0cE2rdVAmh_j-2uDfYkKBs_wPDiNSXCdmIBtO8w4QFABeZQut22nlPTA7a6zV2-GV5m_7FumT6mn92tVW39uuZaWLgJWqa_KADeWM35JQTHrzOOLz54vm4M","id":"rs_0023798544b250b9016980907aebec81948e9042e8de044015","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_lwams5xjm0"} + + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_tHpxKCS6xnVW3HBEkBww7S9T","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_lwams5xjm0"} + + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\":2,\"b\":3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_lwams5xjm0"} + + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"call_qj0i1JW7dlNDPv5uNW5Tq6lO","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_lwams5xjm0"} + + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\":2,\"b\":3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_lwams5xjm0"} + + data: {"id":"gen_01KGF38QHY01RX510GTJVENPPB","object":"chat.completion.chunk","created":1770033274,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_0023798544b250b9016980907a944c8194aa354cf54822893e","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":7023589.520205,"endTime":7023819.54204,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":7023589.520205,"endTime":7023819.54204,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.0049675","marketCost":"0.0049675","generationId":"gen_01KGF38QHY01RX510GTJVENPPB","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":54,"completion_tokens":298,"total_tokens":352,"cost":0.0049675,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":192,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0049675},"system_fingerprint":"fp_lwams5xjm0","generationId":"gen_01KGF38QHY01RX510GTJVENPPB"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 408.927458ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 2299 + 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"},{"tool_calls":[{"id":"call_tHpxKCS6xnVW3HBEkBww7S9T","function":{"arguments":"{\"a\":2,\"b\":3}","name":"add"},"type":"function"},{"id":"call_qj0i1JW7dlNDPv5uNW5Tq6lO","function":{"arguments":"{\"a\":2,\"b\":3}","name":"multiply"},"type":"function"}],"role":"assistant","reasoning_details":[{"data":"gAAAAABpgJB6xgaIX4YGTj3EZimfLMfl7lZ7SJq0aBMWfGDeorXxt6sRPjllCKcFat69Q1kpuEDG1tvuIG_6OxUZHOP_noSA63nkkhTluixdSHPde3XgwYgrm01hBIphFo1ztgQMsVXZaqNGBJKfB35qJ7zSKEFXWcB6olUNA4UUXTup_nH8KrNf0_JcRd4JmIXeaQTTaNLYxeUNljoVsLun6RwBzKf2sDmMFqa8wdE5v159EsaN20EgWQnJGlWdyWEZBixffGM4cXbWIpmZRCv8TCy4dYMh3Nz8FQt7JbWJvCWQskP_b3AFm3TV-h8yUBFhdXRYAeZxtIZsBmjCZZtwDPGnKJ3tLtSnQ3PtlYFn1l0vvPgHh7mdmnhdbWtkUh3hQozmpwGYE5G0LE1XlEQ9KqdR6_ERfztdnbWnxJqAly_m5uXFu6ymcMDmZhkdFvRM1M8923TpttfrkNlzsQM2pzRyZYhATSrBz8eMgJY7me3UHXo3FlGnf0Capm2MNNLVytVv0mgqa8WEMhPzpuga1kbqKt884QqnjHgozx0DYM68uOwTOlMBdRSf6MCE5aqn4fYK7sp3_ZclUNtDr7cM8Pz5GJX3dh_py69qCStpAhptt0smksFcHGezX9zrDehJ9bPvW6gTK4aBKUAndr6SXQ22Boa0kRTo2YWU6mNMr0yNQomEoupdUvc5FtsJ6PiaOz7rTHDS10SCZAvSv0cE2rdVAmh_j-2uDfYkKBs_wPDiNSXCdmIBtO8w4QFABeZQut22nlPTA7a6zV2-GV5m_7FumT6mn92tVW39uuZaWLgJWqa_KADeWM35JQTHrzOOLz54vm4M","format":"openai-responses-v1","id":"rs_0023798544b250b9016980907aebec81948e9042e8de044015","index":0,"type":"reasoning.encrypted"}]},{"content":"5","tool_call_id":"call_tHpxKCS6xnVW3HBEkBww7S9T","role":"tool"},{"content":"6","tool_call_id":"call_qj0i1JW7dlNDPv5uNW5Tq6lO","role":"tool"}],"model":"openai/gpt-5","max_completion_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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"Add"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"5"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"\n"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"Multiply"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":":"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"6"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_rb8lymwxwp"} + + data: {"id":"gen_01KGF38VW9EJPCTC0TED93SGM2","object":"chat.completion.chunk","created":1770033279,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_0023798544b250b9016980907efc7c81948203b5d78adfea6b","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":3192786.860293,"endTime":3193009.179478,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":3192786.860293,"endTime":3193009.179478,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000345","marketCost":"0.000345","generationId":"gen_01KGF38VW9EJPCTC0TED93SGM2","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":172,"completion_tokens":13,"total_tokens":185,"cost":0.000345,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000345},"system_fingerprint":"fp_rb8lymwxwp","generationId":"gen_01KGF38VW9EJPCTC0TED93SGM2"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 315.780916ms diff --git a/providertests/testdata/TestVercelCommon/gpt-5/simple.yaml b/providertests/testdata/TestVercelCommon/gpt-5/simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1fec0eebb331f02f3e7e2d1900755a0b200041dc --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gpt-5/simple.yaml @@ -0,0 +1,33 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 173 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"openai/gpt-5","max_completion_tokens":4000}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3857W5E69F2H2ANCE2CYB","object":"chat.completion","created":1770033258,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":"Olá!","reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJBqe4UanBDshmkUO5UeBgKTle4JTA6JRhnoTGSFte1-ryTvUUbT5rmqGZ7FNrxFvny6dsrNnl1pd4YxeeFus-r67hkBoXsTVYnvct-B0l_CJHcuIZGAD0KSmHfXF0VozKzfZ8Lir1W5zaRJjS_o06nJ-YlqE-V__aYAPeSAhqdscK2B0AJZH4auLrNQolMQq-9d-A7SMnqComX-a1dpu8dZug7-EN9DrypPQqfrBg311Wf4Od2HNwmZS_SqAvOofhi6gkcN2p8MqSiWZNKJRDAJjC_cJsGJ-LQ3tmyPJEzclcMbjehRvjT_IDk0qKqEJqWLSLiDbTH6QaXvSTBQAaSUT8QB6_p42tstR_Jhelyhy1GSfYyny__5FrEmoqLE4sxu16Z1nEdE8MYvcJaUl0KT5Q32GziBMefLQQq9wwhcx6rXJUc29dt6xvntz__4w_kmJismJ8Etb1eVlSLtZwNGF0OyO6K7jar7EL93mbxjmpzu4olDI93EnyxiEDmpz6UOSjFbq-Ey5Kw8AL_L9TwgIMXgLrG-UYYXyzXRhyIL_hWAzMHhcyQs1cvm_RaDmCRC_zFGyKE3cd4QDxC4mnzru7vhWSykmT4A8VyBm57hhxk7wEFxz0_KDfnmrSCUxZiMwGVujBWY6BeqzNd-fF1OvLrYiTmyLzRql_mQ4ED6WeFtq3bFGfp4VdLqJ7Huzg7r0_7o5mQwQ3JpjWE_iay8JtHQfsFXuFCmH_VRdA604UOsuYLdnoGej4hES3jqECSwvJQQXNASQyJbQ2_uGsG1C56IlCzE-vDhqp2PShFoYvEDJ3_gb6TdgiF0ASS3NyFq5PIa1J2zTk3gRJnXkYGgO4kD_iHpkTKhn75LEFLOCuWb4DBpB8qHIUDPHU8odqcGLPjng7NKat7wp5PQGQRVJ_8ulRxyLf5_rP85jB5n_eNDg1MXIO7KALnJE0X9303JThanVo9c7hgvmgE_dbwNbmdzYasxIqYpTH524aoW4Pv3Py7C13Y4PH8WeWY5PeKoEEcyeleiBC1YO1G25JG1e91p-HcOcGWxGHzmln74j9H_LO16zqJias3tT4gRLAphcrHe-a6Ao7pFxwdut9Dw2Lg_79zGR5h5gjN8LBaCJSwMg-pcZ-V1_TAbFCjbeCYfze7ndt9OWOXjS2T05xKAal_21dveRfiuK7-6phUWQ7TgruezFhpPQXoOp8sXHpieyRR8K3_DYGm4qCFbtqUM_SReW2m7qr805a-C5OaDurcQmq--ex8ORV4y6YxD2pA0uriVy60L8vTwX3o82fIhjxvkBNsR1wwjb0puBzUfxX_hvLbbZ8SV1UeNwe0tsnCD0TOtTLczGreq3HkSy25_JQ==","id":"rs_0195d9d352e85fe40169809068318c8190b2bbf966d0dcd881","format":"openai-responses-v1","index":0}],"provider_metadata":{"openai":{"responseId":"resp_0195d9d352e85fe40169809067d3bc8190a9e940c7bf350bb4","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":435303.593243,"endTime":437939.710829,"statusCode":200,"providerResponseId":"resp_0195d9d352e85fe40169809067d3bc8190a9e940c7bf350bb4"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.00168375","marketCost":"0.00168375","generationId":"gen_01KGF3857W5E69F2H2ANCE2CYB","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"completion_tokens":102,"total_tokens":121,"cost":0.00168375,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00168375},"system_fingerprint":"fp_7r70i7ytcp","generationId":"gen_01KGF3857W5E69F2H2ANCE2CYB"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.791494792s diff --git a/providertests/testdata/TestVercelCommon/gpt-5/simple_streaming.yaml b/providertests/testdata/TestVercelCommon/gpt-5/simple_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..620cf9ab29f545a6f6d683df496db838c7a639aa --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gpt-5/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: 227 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"openai/gpt-5","max_completion_tokens":4000,"stream_options":{"include_usage":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF387XY51D0GDDRCM6KB8NB","object":"chat.completion.chunk","created":1770033258,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_tmpp8eb0yq"} + + data: {"id":"gen_01KGF387XY51D0GDDRCM6KB8NB","object":"chat.completion.chunk","created":1770033258,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJBr1JtCCwq4H63wpwrzBisIFa5cozvaVKPCSa_QKdqiKVGM1bH7JXlt53SbT0JsAPDQ_zh4dp6N57-9-WHBZGeFpXVhBWOVjECwI-Sx19ug89zVfZf0Xc7GmgO2C6uR35S0kkVN76bxn8_4ofEGjaGB_P-yjp6oLE4wLzAkH082bkzjww6Yv-2Hqw1FSJsdzCEIuf_FwQkoFPnRdBb5PPPGfyRnIAiS9lFGsMLEA1k8VpOfAWsM5q_UR_pJ8YAFK9MG8gPH8qsaG9rMZSLq5kPoz6lkbX3ZEsBcnpIzJLoYGIKRHPQFXehUxj1ml0hy38aNBv22zgZc0bvQUcM7dsnX-4iaNrUa2YskUJ7TPPuaHGR79KBIwfv0qqFiFDdaa38pJEM_-gAKIv2JcBoNZnui6bCEFNIcyTn-sDU9lhqfbXvFt7jnu7ZNV4kCqe8mhrC3x4V_n7ip2Gd_nA849tPiQmeGlMAgGUiBR3-dGOo-quuJp1nBWSiUvj5DisGkI8NlG_-lAPaVQQfjCc32bn3KY2Ch5a5RltI-DJuCzvpcrDkl4RZIeMoJfaQHUImhpmpZn3Y05ckwCdy1n0difkQIXPgNGcbVXLW5RD7xYDC375nYL4qHfbIWxjPjVv7Jsc8jMWjMhHWC_XCDdon4BhZ9LSj70ppMxkaxl3wgZW8o-s1xeSOM-AbviX_ZBjj63WfeTsUS24-tRDRmfbVSApDHbt7GVJMRr-7AsNZkvuDKMC-URk5Omp8eXJVzhaPnaQVhYPyh3jYmPHWbldKPiu6HZ2QZksn-tIM4M3rse2wJXf4ffk8rbBCcsJPIgT-R9cfq","id":"rs_04b3b5ea2112e2f2016980906b0aa4819087bc5b624622f5c1","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_tmpp8eb0yq"} + + data: {"id":"gen_01KGF387XY51D0GDDRCM6KB8NB","object":"chat.completion.chunk","created":1770033258,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"Olá"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_tmpp8eb0yq"} + + data: {"id":"gen_01KGF387XY51D0GDDRCM6KB8NB","object":"chat.completion.chunk","created":1770033258,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"!"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_tmpp8eb0yq"} + + data: {"id":"gen_01KGF387XY51D0GDDRCM6KB8NB","object":"chat.completion.chunk","created":1770033258,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_04b3b5ea2112e2f2016980906a921c81908b97d5d38611d5a6","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":356384.393513,"endTime":356580.787605,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":356384.393513,"endTime":356580.787605,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.00148375","marketCost":"0.00148375","generationId":"gen_01KGF387XY51D0GDDRCM6KB8NB","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":19,"completion_tokens":82,"total_tokens":101,"cost":0.00148375,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00148375},"system_fingerprint":"fp_tmpp8eb0yq","generationId":"gen_01KGF387XY51D0GDDRCM6KB8NB"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 284.897458ms diff --git a/providertests/testdata/TestVercelCommon/gpt-5/tool.yaml b/providertests/testdata/TestVercelCommon/gpt-5/tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..b1ffe90a9d3154d2930e3a94b01f303ed67b8c4d --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gpt-5/tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 465 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"openai/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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF389FA00FX9W76TJBD2FY0","object":"chat.completion","created":1770033261,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":null,"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJBt9rDWBVUu57Qp4eDPgvhNl_yejTP7GQIvS9aR9c0rc2udBHMKWf6Lov1QwiEeQbCc8LROQ_SbUEvfyEl-9PofdGalnrJON5sqNjhFmugyAnTzQwIbCLzHhViPQYcKTeDxYUNkLO-WUzh9UcgCE3H9-JaGFMFgvpEtK2izjoSXQAfcM4N4TpIjSZVLKCARs9L3jzHHdIMx1God2c7H0MErV3MDZ_7J_xlIDaVOQPKOOMzVO6EjBEWH9TQn_C3f2h5bm6YphGwIfcI7TxOmQVmf7NV0r9e5Tl0v2NQ6L5alFvBllJiKLOsmO6jShYoPT_i119sexG8bSw0w8qqlOvJJxA3nSmKgimH9TJXIynwqntgKw2sf3TUov2ZcXBXuuWEvwwuzvJZ-IblbQ4tp3voRndpGGLL5RaUAnVJxsawXAC7ghykRDhuqBywJVrc0HuNZKsl0qLjEi22IYXAhdbVerM84pD1IMgA-9XbzPryB6R6vvwk6UBQH7H35sSIywXRK0pWMJftKwUIfh87K8iPyt2sdvdxFgeCv1zygTwsvRNIyxrdLznmOlPPEmgeapkBzXMnpnhkIDRkm0q1owi849hYpArAr5dP9KonpVSkJEx_hO4Nu125WOtKG6kt59lWzVy5ntGaQbQx0Y9Ekg-YrVAt0MRBDTHbyYFvg01tRDT5qX7RTjVrxcnBJaS4jiHsE3ThGQCvlyUKDLrBD891lSuLZHJ-b_WDXiAZW63-INaU6dm7rkw0-kCCg6f02WEiTbwrUI3la4iJ_OHvO5dX8HMzO566TT_VPay9vmSAzBcO9vYyJHqAahlce6fc8HSC6yM4FmArFa7fAI24qzACBtcwPZGufHi6SvIarOzZ_Hqhs0K1707Jlm8Nad1QR-mSS4dhXCAWyFuF7uyAA9TrsmKQHIUPXQH3ohsYNkJ-MJwm168NoHL0_Bj2j00JLENHX1oK0iUQLFy2RasyOO6-ChpeYo4GCPxbXkXRNMst9RdOwswtqZKS9lKa4mSrV8_-rlb4exerAjDg2YPPoMSsXEZEZt1BmtnA_xEk2Ba9FhOw6p8n2zakljygABYj__RQ7pwvQZL9AQdpzrDu4eiYkl538d02K0It_d39qaUF-MQVNIqUv40OTI17kDAUhq9MFcYquHywFRcBzS2h0L5siHwieTqTaCPk9LEJwen2JlDWeXovmqX-bxuByh1TNemfkHKSG4lDhIW8Jg2wcilnNEuvvMRmVEAPDen8IaOiP3-S3gjXPv2wqrpG_HD4-XxjugEB0lTmtEn-tA-8jBTTG__H4kUjAv8gX94FW4QYmA9x-xKJwb8mVI_f9xTUMgmx7OsBXoGY1ddAmKfNA5dN4wtTYwKUIoj_VQ9LpXK86DNVlIuT-OaRE_wjLPxnUc0aTXGUUUQJNhmzLRa6xLeyw1A==","id":"rs_0c750dfa299f673c016980906c83288193a268c0d2c594d1ed","format":"openai-responses-v1","index":0}],"tool_calls":[{"id":"call_Rpqo15PMdWRph6Je9FbyRkrP","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence, Italy\"}"}}],"provider_metadata":{"openai":{"responseId":"resp_0c750dfa299f673c016980906c2e748193aacbf2a1a14f5495","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":4677952.648505,"endTime":4679832.007624,"statusCode":200,"providerResponseId":"resp_0c750dfa299f673c016980906c2e748193aacbf2a1a14f5495"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.00185875","marketCost":"0.00185875","generationId":"gen_01KGF389FA00FX9W76TJBD2FY0","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":63,"completion_tokens":114,"total_tokens":177,"cost":0.00185875,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00185875},"system_fingerprint":"fp_4kn76nn85u","generationId":"gen_01KGF389FA00FX9W76TJBD2FY0"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.189340917s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 2326 + 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_Rpqo15PMdWRph6Je9FbyRkrP","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"data":"gAAAAABpgJBt9rDWBVUu57Qp4eDPgvhNl_yejTP7GQIvS9aR9c0rc2udBHMKWf6Lov1QwiEeQbCc8LROQ_SbUEvfyEl-9PofdGalnrJON5sqNjhFmugyAnTzQwIbCLzHhViPQYcKTeDxYUNkLO-WUzh9UcgCE3H9-JaGFMFgvpEtK2izjoSXQAfcM4N4TpIjSZVLKCARs9L3jzHHdIMx1God2c7H0MErV3MDZ_7J_xlIDaVOQPKOOMzVO6EjBEWH9TQn_C3f2h5bm6YphGwIfcI7TxOmQVmf7NV0r9e5Tl0v2NQ6L5alFvBllJiKLOsmO6jShYoPT_i119sexG8bSw0w8qqlOvJJxA3nSmKgimH9TJXIynwqntgKw2sf3TUov2ZcXBXuuWEvwwuzvJZ-IblbQ4tp3voRndpGGLL5RaUAnVJxsawXAC7ghykRDhuqBywJVrc0HuNZKsl0qLjEi22IYXAhdbVerM84pD1IMgA-9XbzPryB6R6vvwk6UBQH7H35sSIywXRK0pWMJftKwUIfh87K8iPyt2sdvdxFgeCv1zygTwsvRNIyxrdLznmOlPPEmgeapkBzXMnpnhkIDRkm0q1owi849hYpArAr5dP9KonpVSkJEx_hO4Nu125WOtKG6kt59lWzVy5ntGaQbQx0Y9Ekg-YrVAt0MRBDTHbyYFvg01tRDT5qX7RTjVrxcnBJaS4jiHsE3ThGQCvlyUKDLrBD891lSuLZHJ-b_WDXiAZW63-INaU6dm7rkw0-kCCg6f02WEiTbwrUI3la4iJ_OHvO5dX8HMzO566TT_VPay9vmSAzBcO9vYyJHqAahlce6fc8HSC6yM4FmArFa7fAI24qzACBtcwPZGufHi6SvIarOzZ_Hqhs0K1707Jlm8Nad1QR-mSS4dhXCAWyFuF7uyAA9TrsmKQHIUPXQH3ohsYNkJ-MJwm168NoHL0_Bj2j00JLENHX1oK0iUQLFy2RasyOO6-ChpeYo4GCPxbXkXRNMst9RdOwswtqZKS9lKa4mSrV8_-rlb4exerAjDg2YPPoMSsXEZEZt1BmtnA_xEk2Ba9FhOw6p8n2zakljygABYj__RQ7pwvQZL9AQdpzrDu4eiYkl538d02K0It_d39qaUF-MQVNIqUv40OTI17kDAUhq9MFcYquHywFRcBzS2h0L5siHwieTqTaCPk9LEJwen2JlDWeXovmqX-bxuByh1TNemfkHKSG4lDhIW8Jg2wcilnNEuvvMRmVEAPDen8IaOiP3-S3gjXPv2wqrpG_HD4-XxjugEB0lTmtEn-tA-8jBTTG__H4kUjAv8gX94FW4QYmA9x-xKJwb8mVI_f9xTUMgmx7OsBXoGY1ddAmKfNA5dN4wtTYwKUIoj_VQ9LpXK86DNVlIuT-OaRE_wjLPxnUc0aTXGUUUQJNhmzLRa6xLeyw1A==","format":"openai-responses-v1","id":"rs_0c750dfa299f673c016980906c83288193a268c0d2c594d1ed","index":0,"type":"reasoning.encrypted"}]},{"content":"40 C","tool_call_id":"call_Rpqo15PMdWRph6Je9FbyRkrP","role":"tool"}],"model":"openai/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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF38BGEDFPFYA0YSVGK53PZ","object":"chat.completion","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":"The current temperature in Florence, Italy is 40°C (104°F). Would you like a forecast or more details?","reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJBy04wiPgHZlcnRtMeJdCXiXkMzEOjA4bYMCrCHqVuCdI7vEDq8PlukdtI96JyxomTXvXxRPCIzKJdzHSXR3OLLYvNzwfNDgNQ1dW4bvh69vQpp54zP4Dhs57GgfsfZAB7q9RB0Kg-6eJD86w2NsGfTIO2ITYeN-_Y5Bqeg8rOb4V9XK1pf-bLaeZsL4uBfvriH8M_uL5nEyaaZupiXTiZfv0A6Lb-lMWH9SS0PPy5LsSx0H_w-4OR8G6J2isU7-bG12BGklNspMvMmtj5JWmZbgbb-JHvR_NO7p--3Q6QCQzg088E_Uh1lQTqvnX3AffKuPJNgxVaiivOQwZXXLEG0NYULjeB20PNsMBVTi_OF4frTljlCvvTzecAd9iaeIECwDBEJDEgqTQefE0linoyLBeey8kD6DIweziBNn8ezoWU7ACiWCqz8FtB0smGue1W949AEmHfRizTjaqEbVpUiW3CA4aVp3eNZiu1XbE3b514H7XMG-6SBBohs0YfPdlTIez7To3Ptzv2x0t7KPiPZi7uDYTscYS1AWdTeB7LJRoLy3mO74Jmq0w0ZnSF3U2zu7-cHkyk6_x1R66bH8uLTtuQRzmyZtef-7T8QGt8k_belGqnRr9o9rdvLp80rwEjjwwPK9lIcR_mA1XDZZHEqoNWOQKINWxwwrjypgRDwSxs_FI3zi-OviKBsFe8YJTn3sJx1ppVkoBU-czhIfpfeF1wqjgGxIIcGGXm8wVXGqWG1Nm-AZwNLxnf34CfhcBddIL4lbPwMa39aaGYGU2qc9Qj8egNg7Bzk0wysMxC4ttsQSpcGM1CXVuyYY9nKiNybsbFQGSB6S32blf05IVD6J1WRqRWlQjJ-doPxmRMqKkXVWOuLN6jHpjAVhtQt2a2jMOvzkuj1bkmrxwLZ6HVKdFEgTN1tVRZ8URSvN3KAQxkOmLr0qPFjqEocjCM8CCTvWSZPbEGTKmHGZBqWFRkOTTC9r0XL_NmeDPZ8x9IfRRTjHg4lJpMixQyrTpgqUHJ_YWgo_jQGFWGntrj8YVfTaOjJmDXigBb2eUr22Tu72U8sBFURrBFDvXQvrL_gbgP4KifJ9ablHQ5M7k2W-I1wD9SgW77LZYYtsDdr_bv1tLIv9zn7tien8eAv1RQN4cICC8yJSnd_8RpzVnpVg6ZyDHOMRL9fU5URSQvtl0ld8c-Hu46NRTR_Ua6b1bIrCVswrbFF0j1tvEA3UBKnuN92LNavwOlu_N7AAPy0tmSvTk0bxfuus3AHDMAEzeHbQBH2OclogxZcfnrm1dXk3ee24hksoxJjfMVTzRBaVPssUCN_ZLzu1T6GwQ4YCdMl2QKX1KWz9ONt6zDNjvkhbZKGYod9E0anXx91NMzhIwou15N1USmduEuklufFN6adsQDWyJ_dK-mS1tlVI9GcDVNnbRUbHvtNui2qwtCzLGxyY82blpFO6dZRjpzY1YRtqo9QA-3MXT1J1mwPmnP2nQh8x5DQPZ-wxs3TcC0DuPVhu-pWmc1RyUtrri3vUy6evRKkezMqybI2zSibyq96ORSAQfB6jZmkyGCNj_w3oCEgYpFJRpPdK42z7SydPItcHGyTbFIE72QqD5lbMA37vCx6iCN38tTUNRYhmeXcKAot9wN5TZ_zNs8TY6BbW1PaIGnPumEudzJCFZhlwPkN6_93U57l23S0chlyA34JN7JMrjI3gVyI0WYFY6IrgQzknsiwpmMAqi9_RQaY6wgVBHadORhAufCHOvq-Qgrcbzpgppuc6zWp7qpc-PACaXLdG2HBvD_whxNmKjaW8b4sUu0IEhHv4esQ4Cxdurb6PAsPPRyUqAyfYX3uYKePFCSGe_Gv6Zss6Lbd5hp0GBvLoVdCxa_81e0EH62Oi5OzbiUpWGY1717a9l6SepkbpbyYnllAMuNGI8whTOBJrDXNR85-lNMSEfVIg6Pjw7Imle0jFkZX1ASfHLXCta9elSYiw7pYIzW67aO3DUacyqKYUxEqO2kVWtcllcO1-_s3rJzKAM4_Qp7A80_0B9X1CfkEKWKLpdJTjfeAiMKtqOTEs0IXngkbaxppW6KdxBsj5bhGCTAXhq_yXeCkBei_aVteFzK2BO1vvLlUhMysIzxs8CLs1YLdAA6vO2dEznTujNxz9Rc=","id":"rs_0c750dfa299f673c016980906e9f1c8193a6477099ec37fe1e","format":"openai-responses-v1","index":0}],"provider_metadata":{"openai":{"responseId":"resp_0c750dfa299f673c016980906e3c00819389d21d48153004b1","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1368084.873343,"endTime":1372326.249053,"statusCode":200,"providerResponseId":"resp_0c750dfa299f673c016980906e3c00819389d21d48153004b1"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.0045725","marketCost":"0.0045725","generationId":"gen_01KGF38BGEDFPFYA0YSVGK53PZ","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":186,"completion_tokens":242,"total_tokens":428,"cost":0.0045725,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":192,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.0045725},"system_fingerprint":"fp_4lohj8xzuj","generationId":"gen_01KGF38BGEDFPFYA0YSVGK53PZ"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 4.324064375s diff --git a/providertests/testdata/TestVercelCommon/gpt-5/tool_streaming.yaml b/providertests/testdata/TestVercelCommon/gpt-5/tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..1b7e34bb5dc1ff97e3bc648d4b1a893862bb0aa7 --- /dev/null +++ b/providertests/testdata/TestVercelCommon/gpt-5/tool_streaming.yaml @@ -0,0 +1,119 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 519 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence,Italy?","role":"user"}],"model":"openai/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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJByBdy9g4TuHPa7DgknLNhMVPGBacw6RSFlD86GixiOuj40lDELdX_Q4KpFNDGcs2gWwNHn1H7rIRCRF7wxROP_609IYjQjHTHB5_0by_qtfPjubqMYZbBfLC9pD5LMt3wpLFWxvAkk-PckiEuLpg1NcdorEuBFlJgwEOKUgO51ZGJbVvpwBsqrcv2xrMSS1jp8NIwy70pS8GS8Chq74_U4FIB26Mpvi_67J_zuXCqiIL9YklAwao0gdOCNGRyKoioVhcOMpS85FvFB8Sg5HstfrBPyKxqNx65gAT9PkL-YS4Fnu403tFbWXIQEZK-oC4oMqpjZKSllX6lYRQdEMZ8TdGLX1FuzXT8apGuqpEcKKeSlUaF_4T5UzLszir9DvQRwapFdiyBrZaR1lWGvkfB6695EQLjgF0cM0qiyBmQ2QHcfEPWIvB4s_kvbE7VxZbZwzAQJwtevqnU1V4ZbG8uh60jClbHOLOiK-Ty5xntV9Pai9ISDeUpmVlfv60cvjRGyxYOIR6fu3uwZSZrje-OfnYUmC9_s6aDhbrNe-IEvhnlhBSbemJwolxE6buieN4kdjZ2xlqDFY2mk8nLx8tF6ZiP4IROD0_ZRz-k7k9cGEncfvTFtkITcfum_0_M-v94SuvRSGMjW6QjMun8UgSiMxBoAlftJWtZxlVBLiCao2fNlbaXdKEUuFS7CG8lfRUybrwSZiOgIPp7mLx05blU6MApN1vE6iSEHuNncRTKryb58XchOLOJRld1OH1NjFsE5_cczhvguSKkJb8uqdl_kOgtQea4XNRWlirogKKKiKdbpOH2F2wVwrYGXCdqGQBE5","id":"rs_02e57b3492270d950169809072df2c81958978be9de09c65c6","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_kjY7wC8Gbmob78vc6x7vvFRl","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_147br1mgel"} + + data: {"id":"gen_01KGF38FRCNWV564Q8599HRRAW","object":"chat.completion.chunk","created":1770033266,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_02e57b3492270d9501698090728f488195b501a282cdac33a5","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":3180361.719299,"endTime":3180600.837456,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":3180361.719299,"endTime":3180600.837456,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.00191875","marketCost":"0.00191875","generationId":"gen_01KGF38FRCNWV564Q8599HRRAW","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":63,"completion_tokens":120,"total_tokens":183,"cost":0.00191875,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00191875},"system_fingerprint":"fp_147br1mgel","generationId":"gen_01KGF38FRCNWV564Q8599HRRAW"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 376.16525ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1780 + 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_kjY7wC8Gbmob78vc6x7vvFRl","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"data":"gAAAAABpgJByBdy9g4TuHPa7DgknLNhMVPGBacw6RSFlD86GixiOuj40lDELdX_Q4KpFNDGcs2gWwNHn1H7rIRCRF7wxROP_609IYjQjHTHB5_0by_qtfPjubqMYZbBfLC9pD5LMt3wpLFWxvAkk-PckiEuLpg1NcdorEuBFlJgwEOKUgO51ZGJbVvpwBsqrcv2xrMSS1jp8NIwy70pS8GS8Chq74_U4FIB26Mpvi_67J_zuXCqiIL9YklAwao0gdOCNGRyKoioVhcOMpS85FvFB8Sg5HstfrBPyKxqNx65gAT9PkL-YS4Fnu403tFbWXIQEZK-oC4oMqpjZKSllX6lYRQdEMZ8TdGLX1FuzXT8apGuqpEcKKeSlUaF_4T5UzLszir9DvQRwapFdiyBrZaR1lWGvkfB6695EQLjgF0cM0qiyBmQ2QHcfEPWIvB4s_kvbE7VxZbZwzAQJwtevqnU1V4ZbG8uh60jClbHOLOiK-Ty5xntV9Pai9ISDeUpmVlfv60cvjRGyxYOIR6fu3uwZSZrje-OfnYUmC9_s6aDhbrNe-IEvhnlhBSbemJwolxE6buieN4kdjZ2xlqDFY2mk8nLx8tF6ZiP4IROD0_ZRz-k7k9cGEncfvTFtkITcfum_0_M-v94SuvRSGMjW6QjMun8UgSiMxBoAlftJWtZxlVBLiCao2fNlbaXdKEUuFS7CG8lfRUybrwSZiOgIPp7mLx05blU6MApN1vE6iSEHuNncRTKryb58XchOLOJRld1OH1NjFsE5_cczhvguSKkJb8uqdl_kOgtQea4XNRWlirogKKKiKdbpOH2F2wVwrYGXCdqGQBE5","format":"openai-responses-v1","id":"rs_02e57b3492270d950169809072df2c81958978be9de09c65c6","index":0,"type":"reasoning.encrypted"}]},{"content":"40 C","tool_call_id":"call_kjY7wC8Gbmob78vc6x7vvFRl","role":"tool"}],"model":"openai/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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" current"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" weather"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" Italy"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" is"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" about"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"40"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"°C"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_9trj17vyed"} + + data: {"id":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","object":"chat.completion.chunk","created":1770033268,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_02e57b3492270d950169809074a41c8195b28990630eb61d38","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":3182379.990316,"endTime":3182610.529457,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":3182379.990316,"endTime":3182610.529457,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.00029125","marketCost":"0.00029125","generationId":"gen_01KGF38HQ7R9XH4N23YXVZ2V51","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":97,"completion_tokens":17,"total_tokens":114,"cost":0.00029125,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00029125},"system_fingerprint":"fp_9trj17vyed","generationId":"gen_01KGF38HQ7R9XH4N23YXVZ2V51"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 378.669292ms diff --git a/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool.yaml b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..fa6b1b6d6a431fd7d75d5f8074b75582d0103a85 --- /dev/null +++ b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 904 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system","cache_control":{"type":"ephemeral"}},{"content":"Add and multiply the number 2 and 3","role":"user","cache_control":{"type":"ephemeral"}}],"model":"anthropic/claude-sonnet-4","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3AEN63MVZD10V5VWY1NFK","object":"chat.completion","created":1770033333,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"toolu_018Bqrp5E4LTkWWKFAWjJcPw","type":"function","function":{"name":"add","arguments":"{\"a\":2,\"b\":3}"}},{"id":"toolu_01ModQEwNzE9utyENTnUKDzE","type":"function","function":{"name":"multiply","arguments":"{\"a\":2,\"b\":3}"}}],"provider_metadata":{"anthropic":{"usage":{"input_tokens":507,"output_tokens":137,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7080018.781706,"endTime":7082515.69486,"statusCode":200,"providerResponseId":"msg_0198xyvGQtALbxVJ6en1oy92"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.003576","marketCost":"0.003576","generationId":"gen_01KGF3AEN63MVZD10V5VWY1NFK","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":507,"completion_tokens":137,"total_tokens":644,"cost":0.003576,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003576},"system_fingerprint":"fp_hbuq90twge","generationId":"gen_01KGF3AEN63MVZD10V5VWY1NFK"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.724311375s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1333 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. CRITICAL: Always use both add and multiply at the same time ALWAYS.","role":"system","cache_control":{"type":"ephemeral"}},{"content":"Add and multiply the number 2 and 3","role":"user"},{"tool_calls":[{"id":"toolu_018Bqrp5E4LTkWWKFAWjJcPw","function":{"arguments":"{\"a\":2,\"b\":3}","name":"add"},"type":"function"},{"id":"toolu_01ModQEwNzE9utyENTnUKDzE","function":{"arguments":"{\"a\":2,\"b\":3}","name":"multiply"},"type":"function","cache_control":{"type":"ephemeral"}}],"role":"assistant"},{"content":"5","tool_call_id":"toolu_018Bqrp5E4LTkWWKFAWjJcPw","role":"tool"},{"content":"6","tool_call_id":"toolu_01ModQEwNzE9utyENTnUKDzE","role":"tool"}],"model":"anthropic/claude-sonnet-4","max_tokens":4000,"tool_choice":"auto","tools":[{"function":{"name":"add","strict":false,"description":"Add two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"},{"function":{"name":"multiply","strict":false,"description":"Multiply two numbers","parameters":{"properties":{"a":{"description":"first number","type":"integer"},"b":{"description":"second number","type":"integer"}},"required":["a","b"],"type":"object"}},"type":"function"}]}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3AH9QQJ48CR5J8VYYZN30","object":"chat.completion","created":1770033335,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"I''ve performed both operations with the numbers 2 and 3:\n- Addition: 2 + 3 = 5\n- Multiplication: 2 × 3 = 6","provider_metadata":{"anthropic":{"usage":{"input_tokens":688,"output_tokens":47,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1440501.815188,"endTime":1442379.185058,"statusCode":200,"providerResponseId":"msg_01HoW3wJwr4Hqen1m7PJHcEL"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002769","marketCost":"0.002769","generationId":"gen_01KGF3AH9QQJ48CR5J8VYYZN30","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":688,"completion_tokens":47,"total_tokens":735,"cost":0.002769,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002769},"system_fingerprint":"fp_yb4k07q27e","generationId":"gen_01KGF3AH9QQJ48CR5J8VYYZN30"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.006164709s diff --git a/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool_streaming.yaml b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..53b09c8f2c1751498f998fe8c5027aaf5713b905 --- /dev/null +++ b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/multi_tool_streaming.yaml @@ -0,0 +1,119 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 941 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system","cache_control":{"type":"ephemeral"}},{"content":"Add and multiply the number 2 and 3","role":"user","cache_control":{"type":"ephemeral"}}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"I"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'ll"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" ad"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"d an"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"d multiply the"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" numbers 2 and 3 "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"for you."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"toolu_01EbUPM9AHLKandFdpD3hR2d","type":"function","function":{"name":"add","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"a\": 2"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":", \"b\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":": 3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"id":"toolu_01WJxb3WgmL33DJCq2hw4DFL","type":"function","function":{"name":"multiply","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"{\"a\": "}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"2"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":", "}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":"\"b\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":1,"function":{"arguments":": 3}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kk4h3svyf"} + + data: {"id":"gen_01KGF3AK848QW52MG188A9XZRA","object":"chat.completion.chunk","created":1770033336,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":502,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":137,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":4753514.35299,"endTime":4754858.992657,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":4753514.35299,"endTime":4754858.992657,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.003561","marketCost":"0.003561","generationId":"gen_01KGF3AK848QW52MG188A9XZRA","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":502,"completion_tokens":137,"total_tokens":639,"cost":0.003561,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003561},"system_fingerprint":"fp_kk4h3svyf","generationId":"gen_01KGF3AK848QW52MG188A9XZRA"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.471487583s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1439 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant. Always use both add and multiply at the same time.","role":"system","cache_control":{"type":"ephemeral"}},{"content":"Add and multiply the number 2 and 3","role":"user"},{"content":"I''ll add and multiply the numbers 2 and 3 for you.","tool_calls":[{"id":"toolu_01EbUPM9AHLKandFdpD3hR2d","function":{"arguments":"{\"a\": 2, \"b\": 3}","name":"add"},"type":"function"},{"id":"toolu_01WJxb3WgmL33DJCq2hw4DFL","function":{"arguments":"{\"a\": 2, \"b\": 3}","name":"multiply"},"type":"function","cache_control":{"type":"ephemeral"}}],"role":"assistant"},{"content":"5","tool_call_id":"toolu_01EbUPM9AHLKandFdpD3hR2d","role":"tool"},{"content":"6","tool_call_id":"toolu_01WJxb3WgmL33DJCq2hw4DFL","role":"tool"}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"The"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" results"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" are:\n- "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"2 + 3 = "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"5\n- 2 × "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"3 = 6"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_jv4rc3pqm1"} + + data: {"id":"gen_01KGF3ANVSZB8AH86G2J0K92JN","object":"chat.completion.chunk","created":1770033339,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":700,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":31,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1445140.487939,"endTime":1446016.149192,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1445140.487939,"endTime":1446016.149192,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002565","marketCost":"0.002565","generationId":"gen_01KGF3ANVSZB8AH86G2J0K92JN","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":700,"completion_tokens":31,"total_tokens":731,"cost":0.002565,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002565},"system_fingerprint":"fp_jv4rc3pqm1","generationId":"gen_01KGF3ANVSZB8AH86G2J0K92JN"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.063098791s diff --git a/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple.yaml b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple.yaml new file mode 100644 index 0000000000000000000000000000000000000000..664b864eb776e6c23f8416d682b0e473ba7527c4 --- /dev/null +++ b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple.yaml @@ -0,0 +1,33 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 249 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system","cache_control":{"type":"ephemeral"}},{"content":"Say hi in Portuguese","role":"user","cache_control":{"type":"ephemeral"}}],"model":"anthropic/claude-sonnet-4","max_tokens":4000}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3A0GNP7F130T7D4SZFNFG","object":"chat.completion","created":1770033318,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"Olá! (Oh-LAH)\n\nThis is the most common way to say \"hi\" in Portuguese. You can also use \"Oi!\" (OH-ee) for a more casual greeting.","provider_metadata":{"anthropic":{"usage":{"input_tokens":16,"output_tokens":48,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":305884.462307,"endTime":307858.655195,"statusCode":200,"providerResponseId":"msg_01NUekGRWWJS2rvj8HY222rZ"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.000768","marketCost":"0.000768","generationId":"gen_01KGF3A0GNP7F130T7D4SZFNFG","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":16,"completion_tokens":48,"total_tokens":64,"cost":0.000768,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000768},"system_fingerprint":"fp_qvkh98zees","generationId":"gen_01KGF3A0GNP7F130T7D4SZFNFG"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.145596209s diff --git a/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple_streaming.yaml b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/simple_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..219e897efea9268d5d8aef772f0001f3a4605260 --- /dev/null +++ b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/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: 303 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system","cache_control":{"type":"ephemeral"}},{"content":"Say hi in Portuguese","role":"user","cache_control":{"type":"ephemeral"}}],"model":"anthropic/claude-sonnet-4","max_tokens":4000,"stream_options":{"include_usage":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"Olá! "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"\n\n("},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"That"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'s \""},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"hello"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"\" in Portuguese -"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" friendly"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" way"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" to say hi"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"!)"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_c0bnftwhqr"} + + data: {"id":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","object":"chat.completion.chunk","created":1770033319,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":16,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":25,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1425425.670751,"endTime":1426422.314773,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1425425.670751,"endTime":1426422.314773,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000423","marketCost":"0.000423","generationId":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":16,"completion_tokens":25,"total_tokens":41,"cost":0.000423,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000423},"system_fingerprint":"fp_c0bnftwhqr","generationId":"gen_01KGF3A2KGQFE5BW4K7TRSZ9DF"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.097552958s diff --git a/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool.yaml b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cfd728d52da0845fa653c2c2478a210cb50eee5d --- /dev/null +++ b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 541 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system","cache_control":{"type":"ephemeral"}},{"content":"What''s the weather in Florence,Italy?","role":"user","cache_control":{"type":"ephemeral"}}],"model":"anthropic/claude-sonnet-4","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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3A4CMTZP7AVTFGEHA9VZ3","object":"chat.completion","created":1770033322,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":null,"tool_calls":[{"id":"toolu_0199hSTV5K6aGu7K5MRpvNEk","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence,Italy\"}"}}],"provider_metadata":{"anthropic":{"usage":{"input_tokens":394,"output_tokens":68,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7069466.244378,"endTime":7071689.075105,"statusCode":200,"providerResponseId":"msg_01CtwtuZqqwryJAuJDdMoG65"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002202","marketCost":"0.002202","generationId":"gen_01KGF3A4CMTZP7AVTFGEHA9VZ3","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":394,"completion_tokens":68,"total_tokens":462,"cost":0.002202,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002202},"system_fingerprint":"fp_nd3kr99iaq","generationId":"gen_01KGF3A4CMTZP7AVTFGEHA9VZ3"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.395244583s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 794 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system","cache_control":{"type":"ephemeral"}},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"tool_calls":[{"id":"toolu_0199hSTV5K6aGu7K5MRpvNEk","function":{"arguments":"{\"location\":\"Florence,Italy\"}","name":"weather"},"type":"function","cache_control":{"type":"ephemeral"}}],"role":"assistant"},{"content":"40 C","tool_call_id":"toolu_0199hSTV5K6aGu7K5MRpvNEk","role":"tool"}],"model":"anthropic/claude-sonnet-4","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 + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3A6QKNJNQRZ2JER4MQD46","object":"chat.completion","created":1770033325,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"The weather in Florence, Italy is currently 40°C (104°F). That''s quite hot! It''s a very warm day in Florence.","provider_metadata":{"anthropic":{"usage":{"input_tokens":463,"output_tokens":34,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7072056.878135,"endTime":7074733.980106,"statusCode":200,"providerResponseId":"msg_01EYzxaa6Ayp7ACF78uvBrqV"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.001899","marketCost":"0.001899","generationId":"gen_01KGF3A6QKNJNQRZ2JER4MQD46","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":463,"completion_tokens":34,"total_tokens":497,"cost":0.001899,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.001899},"system_fingerprint":"fp_4i6565f6ii","generationId":"gen_01KGF3A6QKNJNQRZ2JER4MQD46"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.949003792s diff --git a/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool_streaming.yaml b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/tool_streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..104f05bd52a1620fe503a32655af025c6725394e --- /dev/null +++ b/providertests/testdata/TestVercelCommonWithAnthropicCache/claude-sonnet-4/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: 595 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system","cache_control":{"type":"ephemeral"}},{"content":"What''s the weather in Florence,Italy?","role":"user","cache_control":{"type":"ephemeral"}}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"I'll get"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" the weather information"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" for Florence, Italy for you."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"toolu_01NEeARJCxoJWc8F8yKkyTK2","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"l"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ocati"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"on\": \"Flore"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"nce,Italy\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_afeigrmiv8"} + + data: {"id":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","object":"chat.completion.chunk","created":1770033327,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":394,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":67,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7695608.34416,"endTime":7697403.6705,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7695608.34416,"endTime":7697403.6705,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002187","marketCost":"0.002187","generationId":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":394,"completion_tokens":67,"total_tokens":461,"cost":0.002187,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002187},"system_fingerprint":"fp_afeigrmiv8","generationId":"gen_01KGF3A9P5RW4MNWQD4RZQY7FA"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 2.320939125s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 923 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system","cache_control":{"type":"ephemeral"}},{"content":"What''s the weather in Florence,Italy?","role":"user"},{"content":"I''ll get the weather information for Florence, Italy for you.","tool_calls":[{"id":"toolu_01NEeARJCxoJWc8F8yKkyTK2","function":{"arguments":"{\"location\": \"Florence,Italy\"}","name":"weather"},"type":"function","cache_control":{"type":"ephemeral"}}],"role":"assistant"},{"content":"40 C","tool_call_id":"toolu_01NEeARJCxoJWc8F8yKkyTK2","role":"tool"}],"model":"anthropic/claude-sonnet-4","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.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"The current"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" weather in Florence, Italy is 40"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"°C (104°F). That"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'s quite"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" hot"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"! If"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" you're planning to visit or"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" are currently"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" there, make"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" sure to"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" stay"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" hydrated and seek"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" shade during the hottest parts of the"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" day."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_273kaqn10v"} + + data: {"id":"gen_01KGF3ACA8VVD000VSTT20BPP5","object":"chat.completion.chunk","created":1770033330,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":476,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":54,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7697797.908831,"endTime":7699158.038376,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7697797.908831,"endTime":7699158.038376,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002238","marketCost":"0.002238","generationId":"gen_01KGF3ACA8VVD000VSTT20BPP5","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":476,"completion_tokens":54,"total_tokens":530,"cost":0.002238,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002238},"system_fingerprint":"fp_273kaqn10v","generationId":"gen_01KGF3ACA8VVD000VSTT20BPP5"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.463354875s diff --git a/providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking-streaming.yaml b/providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking-streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..cb7d1b4b15c269eb9d4b8a6c4ce2b23afec9fa75 --- /dev/null +++ b/providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking-streaming.yaml @@ -0,0 +1,137 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 533 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"anthropic/claude-sonnet-4","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":"The user is asking for","reasoning_details":[{"type":"reasoning.text","text":"The user is asking for","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" weather","reasoning_details":[{"type":"reasoning.text","text":" weather","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" information for Florence, Italy. I have","reasoning_details":[{"type":"reasoning.text","text":" information for Florence, Italy. I have","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" a","reasoning_details":[{"type":"reasoning.text","text":" a","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" weather","reasoning_details":[{"type":"reasoning.text","text":" weather","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" function","reasoning_details":[{"type":"reasoning.text","text":" function","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" available that takes","reasoning_details":[{"type":"reasoning.text","text":" available that takes","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" a location parameter.","reasoning_details":[{"type":"reasoning.text","text":" a location parameter.","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" The","reasoning_details":[{"type":"reasoning.text","text":" The","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" location","reasoning_details":[{"type":"reasoning.text","text":" location","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" is","reasoning_details":[{"type":"reasoning.text","text":" is","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" clearly","reasoning_details":[{"type":"reasoning.text","text":" clearly","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" specified as \"Florence, Italy\" so","reasoning_details":[{"type":"reasoning.text","text":" specified as \"Florence, Italy\" so","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" I have","reasoning_details":[{"type":"reasoning.text","text":" I have","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" all the required parameters to","reasoning_details":[{"type":"reasoning.text","text":" all the required parameters to","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" make the function call.","reasoning_details":[{"type":"reasoning.text","text":" make the function call.","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":"","reasoning_details":[{"type":"reasoning.text","text":"","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":"","reasoning_details":[{"type":"reasoning.text","text":"","signature":"EqUDCkYICxgCKkB94vhGG6xKjNnGimHMfRxMKRoDnfxu8X0ubqexC/CZ0gU1q1TlbdRN/J4R0tWVpSFl6fFlfjxBILkP/+4vk0rsEgwiokH4mommeOQbO0kaDDeTcsDepWKtbzn7RCIwM9YXOvgQOWNhGfjjNVXcLf20mCH4hUPTSpIp3F2WEOxI0CLOTKxuwGTgRB4axXhdKowCQwf95zMeALPR1ZZHRXqVm3Dm8Lf9W0kR2/G/irnQLoTR/lxZ5gB6FqUdPqNJHXmn3r6KxrQlxTM97UEZ0hEZHhBvwLk24e4KQitX5oHkNp+XMFCzjaym/Pryfjo4qxde8drr9TmHH1ajVYHkXue2L/RWEDrbUWITgtUP0CgkbAGijhpdJm4xVIMLHOD2cJS2+gChTu85uzdvdowlgHwMB7G5rHR+c1NB/2BV9iwhgVMgVjZlGB0SZmUoPEvPr2ZW2Y56tpnQ5d5zl4GdxImJBTSzoQzEKoGxt94MsXE207I0sp5L0Zzm+p4bDGTU6V0SI+eumemcejIt9O/jlGFFLf539LcU1+qeMWFdpBgB","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"toolu_01YVA3v6AcXDxaGjsKS8DiUq","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"locati"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"on\": \"Flore"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"nce, Ital"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"y\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_iqjm7xgvli"} + + data: {"id":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","object":"chat.completion.chunk","created":1770033404,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":424,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":109,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":162863.303643,"endTime":164602.735825,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":162863.303643,"endTime":164602.735825,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002907","marketCost":"0.002907","generationId":"gen_01KGF3CMBNWVQFHD13H2B0XSBK","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":424,"completion_tokens":109,"total_tokens":533,"cost":0.002907,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002907},"system_fingerprint":"fp_iqjm7xgvli","generationId":"gen_01KGF3CMBNWVQFHD13H2B0XSBK"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.897754625s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1993 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"},{"tool_calls":[{"id":"toolu_01YVA3v6AcXDxaGjsKS8DiUq","function":{"arguments":"{\"location\": \"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"format":"anthropic-claude-v1","index":0,"signature":"EqUDCkYICxgCKkB94vhGG6xKjNnGimHMfRxMKRoDnfxu8X0ubqexC/CZ0gU1q1TlbdRN/J4R0tWVpSFl6fFlfjxBILkP/+4vk0rsEgwiokH4mommeOQbO0kaDDeTcsDepWKtbzn7RCIwM9YXOvgQOWNhGfjjNVXcLf20mCH4hUPTSpIp3F2WEOxI0CLOTKxuwGTgRB4axXhdKowCQwf95zMeALPR1ZZHRXqVm3Dm8Lf9W0kR2/G/irnQLoTR/lxZ5gB6FqUdPqNJHXmn3r6KxrQlxTM97UEZ0hEZHhBvwLk24e4KQitX5oHkNp+XMFCzjaym/Pryfjo4qxde8drr9TmHH1ajVYHkXue2L/RWEDrbUWITgtUP0CgkbAGijhpdJm4xVIMLHOD2cJS2+gChTu85uzdvdowlgHwMB7G5rHR+c1NB/2BV9iwhgVMgVjZlGB0SZmUoPEvPr2ZW2Y56tpnQ5d5zl4GdxImJBTSzoQzEKoGxt94MsXE207I0sp5L0Zzm+p4bDGTU6V0SI+eumemcejIt9O/jlGFFLf539LcU1+qeMWFdpBgB","text":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The location is clearly specified as \"Florence, Italy\" so I have all the required parameters to make the function call.","type":"reasoning.text"}],"reasoning":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The location is clearly specified as \"Florence, Italy\" so I have all the required parameters to make the function call."},{"content":"40 C","tool_call_id":"toolu_01YVA3v6AcXDxaGjsKS8DiUq","role":"tool"}],"model":"anthropic/claude-sonnet-4","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"The current"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" weather in Florence, Italy is 40"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"°C (104°F). That"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'s quite"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" hot!"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" It"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'s a very"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" warm day in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" Florence."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_95h77ud38a"} + + data: {"id":"gen_01KGF3CQFX23W6JXADQ1QTEY98","object":"chat.completion.chunk","created":1770033406,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":548,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":34,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":4956.113352,"endTime":6171.847632,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":4956.113352,"endTime":6171.847632,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002154","marketCost":"0.002154","generationId":"gen_01KGF3CQFX23W6JXADQ1QTEY98","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":548,"completion_tokens":34,"total_tokens":582,"cost":0.002154,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002154},"system_fingerprint":"fp_95h77ud38a","generationId":"gen_01KGF3CQFX23W6JXADQ1QTEY98"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.345717s diff --git a/providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking.yaml b/providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking.yaml new file mode 100644 index 0000000000000000000000000000000000000000..574caa7ed5b7490adf1f1d1848c51ae2849e13a1 --- /dev/null +++ b/providertests/testdata/TestVercelThinking/claude-sonnet-4-sig/thinking.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 479 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"anthropic/claude-sonnet-4","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3CESJKXWS3VT4KZ7Z4H0S","object":"chat.completion","created":1770033398,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":null,"reasoning":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The location is clearly specified as \"Florence, Italy\" so I have all the required parameters to make the function call.","reasoning_details":[{"type":"reasoning.text","text":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The location is clearly specified as \"Florence, Italy\" so I have all the required parameters to make the function call.","signature":"EqUDCkYICxgCKkB94vhGG6xKjNnGimHMfRxMKRoDnfxu8X0ubqexC/CZ0gU1q1TlbdRN/J4R0tWVpSFl6fFlfjxBILkP/+4vk0rsEgxEmjcKGGfHXogpkvoaDIJiOn8VbzE+KqPLBCIwyk+17OatdTJTKgOrfaX2tZL5Qmx9Mm1mCs2Djj2mmm5pnDwGymarqbOQn4al+112KowCfd3UWJ1pnfvuMtHp4LCLBjiLWnPPq+gZnlgsNecPBSBXKDt73jMGOd0NQBN7lOOZBy2AR9oQzKpCbyH5CY475OUYjbr8Rz+Xi3JIBit+AL96bsHSares7CpY1y2KVT0d8EPZZMmRr2SEK0AYtccALMpN3n/+QTu0eOlC1Jsv1ygyiRhoPszCqW98h/OdlMzWQyLu60Hir9D91svBFCQ1umLHR3wiJQ/fN025OVtiffGmkjcYWuvEChRS+fN21kSeDOcjbU2nqhRBWJc61RFRjJ8scShRpYoTQn5tNOeSsRIgAfzfmYRK1tp3NzhGDbQM/t6ytgrsToE9ehXnyKIKCVknQl5mkfT3Jw5S+xgB","format":"anthropic-claude-v1","index":0}],"tool_calls":[{"id":"toolu_01QueSgW64L24gT3TZdWbizV","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence, Italy\"}"}}],"provider_metadata":{"anthropic":{"usage":{"input_tokens":424,"output_tokens":109,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7765415.569026,"endTime":7767783.415776,"statusCode":200,"providerResponseId":"msg_015136shD3sTPiMES5sYeqsD"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002907","marketCost":"0.002907","generationId":"gen_01KGF3CESJKXWS3VT4KZ7Z4H0S","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":424,"completion_tokens":109,"total_tokens":533,"cost":0.002907,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002907},"system_fingerprint":"fp_zqq5kppgz1","generationId":"gen_01KGF3CESJKXWS3VT4KZ7Z4H0S"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.513099333s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1938 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"},{"tool_calls":[{"id":"toolu_01QueSgW64L24gT3TZdWbizV","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"format":"anthropic-claude-v1","index":0,"signature":"EqUDCkYICxgCKkB94vhGG6xKjNnGimHMfRxMKRoDnfxu8X0ubqexC/CZ0gU1q1TlbdRN/J4R0tWVpSFl6fFlfjxBILkP/+4vk0rsEgxEmjcKGGfHXogpkvoaDIJiOn8VbzE+KqPLBCIwyk+17OatdTJTKgOrfaX2tZL5Qmx9Mm1mCs2Djj2mmm5pnDwGymarqbOQn4al+112KowCfd3UWJ1pnfvuMtHp4LCLBjiLWnPPq+gZnlgsNecPBSBXKDt73jMGOd0NQBN7lOOZBy2AR9oQzKpCbyH5CY475OUYjbr8Rz+Xi3JIBit+AL96bsHSares7CpY1y2KVT0d8EPZZMmRr2SEK0AYtccALMpN3n/+QTu0eOlC1Jsv1ygyiRhoPszCqW98h/OdlMzWQyLu60Hir9D91svBFCQ1umLHR3wiJQ/fN025OVtiffGmkjcYWuvEChRS+fN21kSeDOcjbU2nqhRBWJc61RFRjJ8scShRpYoTQn5tNOeSsRIgAfzfmYRK1tp3NzhGDbQM/t6ytgrsToE9ehXnyKIKCVknQl5mkfT3Jw5S+xgB","text":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The location is clearly specified as \"Florence, Italy\" so I have all the required parameters to make the function call.","type":"reasoning.text"}],"reasoning":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The location is clearly specified as \"Florence, Italy\" so I have all the required parameters to make the function call."},{"content":"40 C","tool_call_id":"toolu_01QueSgW64L24gT3TZdWbizV","role":"tool"}],"model":"anthropic/claude-sonnet-4","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3CH7MBCX5TG98WJF2BTYT","object":"chat.completion","created":1770033402,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"The current weather in Florence, Italy is 40°C (104°F). That''s quite hot! It''s a very warm day in Florence.","provider_metadata":{"anthropic":{"usage":{"input_tokens":548,"output_tokens":34,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1505902.416236,"endTime":1508977.489215,"statusCode":200,"providerResponseId":"msg_01RG65Q4UDkyK2BAznqpD7GE"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002154","marketCost":"0.002154","generationId":"gen_01KGF3CH7MBCX5TG98WJF2BTYT","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":548,"completion_tokens":34,"total_tokens":582,"cost":0.002154,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002154},"system_fingerprint":"fp_9mdcax34m","generationId":"gen_01KGF3CH7MBCX5TG98WJF2BTYT"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 3.165230708s diff --git a/providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking-streaming.yaml b/providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking-streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..d60e25640403d5d0adff33a0d52e788bdf2a11aa --- /dev/null +++ b/providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking-streaming.yaml @@ -0,0 +1,171 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 533 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"anthropic/claude-sonnet-4","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":"The user is asking for","reasoning_details":[{"type":"reasoning.text","text":"The user is asking for","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" weather","reasoning_details":[{"type":"reasoning.text","text":" weather","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" information for Florence, Italy. I have","reasoning_details":[{"type":"reasoning.text","text":" information for Florence, Italy. I have","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" a weather","reasoning_details":[{"type":"reasoning.text","text":" a weather","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" function available","reasoning_details":[{"type":"reasoning.text","text":" function available","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" that takes","reasoning_details":[{"type":"reasoning.text","text":" that takes","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" a location parameter.","reasoning_details":[{"type":"reasoning.text","text":" a location parameter.","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" The","reasoning_details":[{"type":"reasoning.text","text":" The","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" user has","reasoning_details":[{"type":"reasoning.text","text":" user has","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" provided the location as","reasoning_details":[{"type":"reasoning.text","text":" provided the location as","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" \"Florence, Italy\" which","reasoning_details":[{"type":"reasoning.text","text":" \"Florence, Italy\" which","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" is specific","reasoning_details":[{"type":"reasoning.text","text":" is specific","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" enough for","reasoning_details":[{"type":"reasoning.text","text":" enough for","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" the weather function.","reasoning_details":[{"type":"reasoning.text","text":" the weather function.","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" I have","reasoning_details":[{"type":"reasoning.text","text":" I have","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" all the required parameters to make the function","reasoning_details":[{"type":"reasoning.text","text":" all the required parameters to make the function","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":" call.","reasoning_details":[{"type":"reasoning.text","text":" call.","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":"","reasoning_details":[{"type":"reasoning.text","text":"","signature":"","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"reasoning":"","reasoning_details":[{"type":"reasoning.text","text":"","signature":"EtYDCkYICxgCKkD9mnV1Hds6SXvRNDaaVGP9IRFYqdtRgWJOe8g0L7Ud8hYHbJ+xtiLx6BOulBrCSpqk0qL0Ppqn5ZjggFDrpOl9Egxi/ODyXHn/gED5bk8aDDdrhkgNzG+ZAsd/4CIwZMUjUcbSZEuLEEhx8gHG8s25q5UMj5UqA0XYiTXvWMiyDOplOPRYIpyFzeBIzoHTKr0C51eUyyUS9b37iYdk2gZ5G+fU3BJMMgrDaNCSeiT6A47YXYO+w4sN60Fr3fXXyfNewEnfycIkFcsSUeoraqRtMXYmtpZ1U3hTMNf97Ve2ITFHwdKtZqo6KOV3PZEPPXBA8y59K6s+WD8kEKWb3126miv3moQ8fH2A5Dtk9bzXqNtWnAFI97JnnZgvmSH6tqYS2RkHMtj31LPaxYjWjqc2IusllrCoI1WEsu5bpABezlPKEWayq7FHjqUyeF+w4hEkQ4mjRjLHsVfNC2Pb79DEuGttQ8esezKiaVLhWZ8NngPU/Kv0J8Mtc0DTbBxlk58PMwO2zVeLAuthixkX5OiSfVtNVX3DDe4odTAxiFouPl5OOw964A+L6u27r+7nsurLHkZkrw7hpSP7saLGSUUX3++WmIFEZnz/d/cqCU4YAQ==","format":"anthropic-claude-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"toolu_01LCB6569oxJKyPag7eFnnjx","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"loca"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"tio"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"n\": \"Flore"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"nc"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"e,"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_moyu1cwxfr"} + + data: {"id":"gen_01KGF3AVVKYFARGPVSM4MZY14H","object":"chat.completion.chunk","created":1770033348,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":424,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":118,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7093511.188939,"endTime":7097175.93529,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7093511.188939,"endTime":7097175.93529,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.003042","marketCost":"0.003042","generationId":"gen_01KGF3AVVKYFARGPVSM4MZY14H","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":424,"completion_tokens":118,"total_tokens":542,"cost":0.003042,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003042},"system_fingerprint":"fp_moyu1cwxfr","generationId":"gen_01KGF3AVVKYFARGPVSM4MZY14H"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 3.850747333s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 2159 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"},{"tool_calls":[{"id":"toolu_01LCB6569oxJKyPag7eFnnjx","function":{"arguments":"{\"location\": \"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"format":"anthropic-claude-v1","index":0,"signature":"EtYDCkYICxgCKkD9mnV1Hds6SXvRNDaaVGP9IRFYqdtRgWJOe8g0L7Ud8hYHbJ+xtiLx6BOulBrCSpqk0qL0Ppqn5ZjggFDrpOl9Egxi/ODyXHn/gED5bk8aDDdrhkgNzG+ZAsd/4CIwZMUjUcbSZEuLEEhx8gHG8s25q5UMj5UqA0XYiTXvWMiyDOplOPRYIpyFzeBIzoHTKr0C51eUyyUS9b37iYdk2gZ5G+fU3BJMMgrDaNCSeiT6A47YXYO+w4sN60Fr3fXXyfNewEnfycIkFcsSUeoraqRtMXYmtpZ1U3hTMNf97Ve2ITFHwdKtZqo6KOV3PZEPPXBA8y59K6s+WD8kEKWb3126miv3moQ8fH2A5Dtk9bzXqNtWnAFI97JnnZgvmSH6tqYS2RkHMtj31LPaxYjWjqc2IusllrCoI1WEsu5bpABezlPKEWayq7FHjqUyeF+w4hEkQ4mjRjLHsVfNC2Pb79DEuGttQ8esezKiaVLhWZ8NngPU/Kv0J8Mtc0DTbBxlk58PMwO2zVeLAuthixkX5OiSfVtNVX3DDe4odTAxiFouPl5OOw964A+L6u27r+7nsurLHkZkrw7hpSP7saLGSUUX3++WmIFEZnz/d/cqCU4YAQ==","text":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The user has provided the location as \"Florence, Italy\" which is specific enough for the weather function. I have all the required parameters to make the function call.","type":"reasoning.text"}],"reasoning":"The user is asking for weather information for Florence, Italy. I have a weather function available that takes a location parameter. The user has provided the location as \"Florence, Italy\" which is specific enough for the weather function. I have all the required parameters to make the function call."},{"content":"40 C","tool_call_id":"toolu_01LCB6569oxJKyPag7eFnnjx","role":"tool"}],"model":"anthropic/claude-sonnet-4","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"The current"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" weather in Florence, Italy is 40"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"°C (104°F). That"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"'s quite"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" hot"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"! This is a"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" high"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" temperature that"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" suggests"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" very"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" warm,"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" potentially"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" uncomfortable"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" weather conditions"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":". You might want to stay"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" hydrated and seek"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" air"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" conditioning"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" or shade if"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" you're planning to be in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":" today"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_wkyq4vz6ii"} + + data: {"id":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","object":"chat.completion.chunk","created":1770033350,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"delta":{"provider_metadata":{"anthropic":{"usage":{"input_tokens":557,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"output_tokens":63,"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1456427.826085,"endTime":1457451.848654,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":1456427.826085,"endTime":1457451.848654,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.002616","marketCost":"0.002616","generationId":"gen_01KGF3B0WTSB5GEBEY54E4B78Q","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":557,"completion_tokens":63,"total_tokens":620,"cost":0.002616,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002616},"system_fingerprint":"fp_wkyq4vz6ii","generationId":"gen_01KGF3B0WTSB5GEBEY54E4B78Q"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.12508025s diff --git a/providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking.yaml b/providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking.yaml new file mode 100644 index 0000000000000000000000000000000000000000..57198183090a6045a0d282a7eb93476e5d307c52 --- /dev/null +++ b/providertests/testdata/TestVercelThinking/claude-sonnet-4/thinking.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 479 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"anthropic/claude-sonnet-4","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3AQBSB35WNS62SPSARQ6W","object":"chat.completion","created":1770033342,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":null,"reasoning":"The user is asking for weather information for Florence, Italy. I have access to a weather function that requires a \"location\" parameter. The user has provided the location as \"Florence, Italy\" which is specific enough to use for the weather query.\n\nI should call the weather function with \"Florence, Italy\" as the location parameter.","reasoning_details":[{"type":"reasoning.text","text":"The user is asking for weather information for Florence, Italy. I have access to a weather function that requires a \"location\" parameter. The user has provided the location as \"Florence, Italy\" which is specific enough to use for the weather query.\n\nI should call the weather function with \"Florence, Italy\" as the location parameter.","signature":"EvcDCkYICxgCKkAcv+JiUJrSmNoeyAKGVOi/csdYyFzgyZwNioa99UTlL/tPju5ML6OZ4LOvKaFwaUZyzcNW4uQLu7jI2eVLu1iBEgz1tmAQP8hgL/Hy0u0aDBov3mK2gXR/f7z0iiIw8orugLuO+L2R5wuK35rGJkQhVHAphISN2F2FNjrGts/gbB+dJtP1ncNCWYFSp2NjKt4Cq7EYeQ0x9ie1oKSCG9n9bGZ0br1TVg4ClNZEQQou4gAMGZonFMnDy0uwPwk5F1rujCQbIJVzttyhb/lVmqUeEy/IFbYDmIi/1MAHlpN8qhX/0NhviIlZGobT7wzZUuNgQYT10+Wr8AfCNuHrMfjN1XnW+72e2p7QmcMEBcR8/sO24stZFAuTrnZytWOrINqsgbuEKcklViQw8RqQNkWUOGlOS+BOWZXIcLinY5LCPftHjLCKrFFG37bGwWKlWpbu9z/whcQ9UVE+TnrIdnhwdhxoljIbuzDBQTuY8MhlOXBzUujm6QaqxOWX0bnyPe+8eq+T1zsq3BLU2OLg5P/6rMZCYxrSjCTSnX0dM/UKxasn7cqT0QwWeVt1hMRDdO3heoFOfQgHmx9w4RuDvlZ9xh0xMKG/Amy8PhqU8tzE8U1+uMCl1PpaOa42MpcWleUklf24hkwZVqM488rdUjIYAQ==","format":"anthropic-claude-v1","index":0}],"tool_calls":[{"id":"toolu_01VvThmBhnhGHEcRJeyCRSHe","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence, Italy\"}"}}],"provider_metadata":{"anthropic":{"usage":{"input_tokens":424,"output_tokens":129,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7088911.419434,"endTime":7091508.412367,"statusCode":200,"providerResponseId":"msg_01Um7d6HWfESfBhnukpiBeuy"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.003207","marketCost":"0.003207","generationId":"gen_01KGF3AQBSB35WNS62SPSARQ6W","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":424,"completion_tokens":129,"total_tokens":553,"cost":0.003207,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.003207},"system_fingerprint":"fp_da7b9rssdj","generationId":"gen_01KGF3AQBSB35WNS62SPSARQ6W"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.754280458s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 2226 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"},{"tool_calls":[{"id":"toolu_01VvThmBhnhGHEcRJeyCRSHe","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning":"The user is asking for weather information for Florence, Italy. I have access to a weather function that requires a \"location\" parameter. The user has provided the location as \"Florence, Italy\" which is specific enough to use for the weather query.\n\nI should call the weather function with \"Florence, Italy\" as the location parameter.","reasoning_details":[{"format":"anthropic-claude-v1","index":0,"signature":"EvcDCkYICxgCKkAcv+JiUJrSmNoeyAKGVOi/csdYyFzgyZwNioa99UTlL/tPju5ML6OZ4LOvKaFwaUZyzcNW4uQLu7jI2eVLu1iBEgz1tmAQP8hgL/Hy0u0aDBov3mK2gXR/f7z0iiIw8orugLuO+L2R5wuK35rGJkQhVHAphISN2F2FNjrGts/gbB+dJtP1ncNCWYFSp2NjKt4Cq7EYeQ0x9ie1oKSCG9n9bGZ0br1TVg4ClNZEQQou4gAMGZonFMnDy0uwPwk5F1rujCQbIJVzttyhb/lVmqUeEy/IFbYDmIi/1MAHlpN8qhX/0NhviIlZGobT7wzZUuNgQYT10+Wr8AfCNuHrMfjN1XnW+72e2p7QmcMEBcR8/sO24stZFAuTrnZytWOrINqsgbuEKcklViQw8RqQNkWUOGlOS+BOWZXIcLinY5LCPftHjLCKrFFG37bGwWKlWpbu9z/whcQ9UVE+TnrIdnhwdhxoljIbuzDBQTuY8MhlOXBzUujm6QaqxOWX0bnyPe+8eq+T1zsq3BLU2OLg5P/6rMZCYxrSjCTSnX0dM/UKxasn7cqT0QwWeVt1hMRDdO3heoFOfQgHmx9w4RuDvlZ9xh0xMKG/Amy8PhqU8tzE8U1+uMCl1PpaOa42MpcWleUklf24hkwZVqM488rdUjIYAQ==","text":"The user is asking for weather information for Florence, Italy. I have access to a weather function that requires a \"location\" parameter. The user has provided the location as \"Florence, Italy\" which is specific enough to use for the weather query.\n\nI should call the weather function with \"Florence, Italy\" as the location parameter.","type":"reasoning.text"}]},{"content":"40 C","tool_call_id":"toolu_01VvThmBhnhGHEcRJeyCRSHe","role":"tool"}],"model":"anthropic/claude-sonnet-4","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3AT2W4QFA7ZW3ASZ8571P","object":"chat.completion","created":1770033344,"model":"anthropic/claude-sonnet-4","choices":[{"index":0,"message":{"role":"assistant","content":"The current weather in Florence, Italy is 40°C (104°F). That''s quite hot! It''s a very warm day in Florence.","provider_metadata":{"anthropic":{"usage":{"input_tokens":568,"output_tokens":34,"cache_creation_input_tokens":0,"cache_read_input_tokens":0,"cache_creation":{"ephemeral_5m_input_tokens":0,"ephemeral_1h_input_tokens":0},"service_tier":"standard"},"cacheCreationInputTokens":0,"stopSequence":null,"container":null},"gateway":{"routing":{"originalModelId":"anthropic/claude-sonnet-4","resolvedProvider":"anthropic","resolvedProviderApiModelId":"claude-sonnet-4-20250514","internalResolvedModelId":"anthropic:claude-sonnet-4-20250514","fallbacksAvailable":["vertexAnthropic","bedrock"],"internalReasoning":"Selected anthropic as preferred provider for claude-sonnet-4. 2 fallback(s) available: vertexAnthropic, bedrock","planningReasoning":"System credentials planned for: anthropic, vertexAnthropic, bedrock. Total execution order: anthropic(system) → vertexAnthropic(system) → bedrock(system)","canonicalSlug":"anthropic/claude-sonnet-4","finalProvider":"anthropic","attempts":[{"provider":"anthropic","internalModelId":"anthropic:claude-sonnet-4-20250514","providerApiModelId":"claude-sonnet-4-20250514","credentialType":"system","success":true,"startTime":7712011.428399,"endTime":7713764.18868,"statusCode":200,"providerResponseId":"msg_01Xc77vidcSXUVZGp5byrDUm"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"anthropic/claude-sonnet-4","canonicalSlug":"anthropic/claude-sonnet-4","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.002214","marketCost":"0.002214","generationId":"gen_01KGF3AT2W4QFA7ZW3ASZ8571P","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":568,"completion_tokens":34,"total_tokens":602,"cost":0.002214,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.002214},"system_fingerprint":"fp_k3wp9lnz45","generationId":"gen_01KGF3AT2W4QFA7ZW3ASZ8571P"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 1.837599167s diff --git a/providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking-streaming.yaml b/providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking-streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c43673bda15707364ba05a86f338eb7902dd6828 --- /dev/null +++ b/providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking-streaming.yaml @@ -0,0 +1,87 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 535 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","object":"chat.completion.chunk","created":1770033385,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_q2vuvpzyv8"} + + data: {"id":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","object":"chat.completion.chunk","created":1770033385,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"reasoning":"**Analyzing the User's Query**\n\nI'm focused on understanding the user's intent. My primary task is to identify the location for the weather query. It's evident the user wants weather data for Florence, Italy. I'll utilize the `weather` tool and set the `location` parameter accordingly.\n\n\n","reasoning_details":[{"type":"reasoning.text","text":"**Analyzing the User's Query**\n\nI'm focused on understanding the user's intent. My primary task is to identify the location for the weather query. It's evident the user wants weather data for Florence, Italy. I'll utilize the `weather` tool and set the `location` parameter accordingly.\n\n\n","format":"google-gemini-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_q2vuvpzyv8"} + + data: {"id":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","object":"chat.completion.chunk","created":1770033385,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"SmUJTLmrRxi0lu0v","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_q2vuvpzyv8"} + + data: {"id":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","object":"chat.completion.chunk","created":1770033385,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\"location\":\"Florence, Italy\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_q2vuvpzyv8"} + + data: {"id":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","object":"chat.completion.chunk","created":1770033385,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"reasoning_details":[{"type":"reasoning.encrypted","data":"CiQBjz1rXzHrIG8VyKxoyvNfn34I0fU0MFB3Xbo4yGmi5lXxz9oKZgGPPWtfH7TJlamiXjXsugVyW8VxgOUJprUjmiUwJi/stNqMS3LooRoUA1fBkdgztTDDIGWmRMXQtWqouGUTAeueCke7VJzsJm3GwC5Czg9laR24rLZ/AU+1oJpvT5AmZHm0AYnOGAp3AY89a1+1SkejrgsX83pkwVBjFrYRepT+UEelh8Kexyj/KndelV/yYbA+gWgGGSMKe4zq3JKh99Toc1/OqRXykl9qKTNXZj1xaIkP98KH/4mRnVw4Mvc3mE2R97bmzKTFSxzAlJ7+XFtYnZjg7PiNxuwEiZIlG3kKNAGPPWtfzlrIZvrYjj2PtuKOaHbd5iP/2u4dRMmmPZ8fi8DHZdSpnDnJAKI/TVQikZmdBZo=","format":"google-gemini-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_q2vuvpzyv8"} + + data: {"id":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","object":"chat.completion.chunk","created":1770033385,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":39,"promptTokenCount":28,"candidatesTokenCount":9,"totalTokenCount":76,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7750944.987373,"endTime":7754447.770022,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7750944.987373,"endTime":7754447.770022,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000632","marketCost":"0.000632","generationId":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":28,"completion_tokens":9,"total_tokens":37,"cost":0.000632,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":39,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000632},"system_fingerprint":"fp_q2vuvpzyv8","generationId":"gen_01KGF3C0Q49GHB7YJE7PKYYXEK"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 3.681428625s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1286 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"},{"tool_calls":[{"id":"SmUJTLmrRxi0lu0v","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"data":"CiQBjz1rXzHrIG8VyKxoyvNfn34I0fU0MFB3Xbo4yGmi5lXxz9oKZgGPPWtfH7TJlamiXjXsugVyW8VxgOUJprUjmiUwJi/stNqMS3LooRoUA1fBkdgztTDDIGWmRMXQtWqouGUTAeueCke7VJzsJm3GwC5Czg9laR24rLZ/AU+1oJpvT5AmZHm0AYnOGAp3AY89a1+1SkejrgsX83pkwVBjFrYRepT+UEelh8Kexyj/KndelV/yYbA+gWgGGSMKe4zq3JKh99Toc1/OqRXykl9qKTNXZj1xaIkP98KH/4mRnVw4Mvc3mE2R97bmzKTFSxzAlJ7+XFtYnZjg7PiNxuwEiZIlG3kKNAGPPWtfzlrIZvrYjj2PtuKOaHbd5iP/2u4dRMmmPZ8fi8DHZdSpnDnJAKI/TVQikZmdBZo=","format":"google-gemini-v1","index":0,"type":"reasoning.encrypted"}]},{"content":"40 C","tool_call_id":"SmUJTLmrRxi0lu0v","role":"tool"}],"model":"google/gemini-3-pro-preview","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3C4C0A7ZEXSENPBN82KKW","object":"chat.completion.chunk","created":1770033396,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kt7kxbesam"} + + data: {"id":"gen_01KGF3C4C0A7ZEXSENPBN82KKW","object":"chat.completion.chunk","created":1770033396,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"reasoning":"**Analyzing Weather Data**\n\nI've just received the weather data for Florence. My current task is to clearly convey the 40 degrees Celsius temperature reading to the user. I'm focusing on the best way to present this information so it's easily understood and actionable.\n\n\n","reasoning_details":[{"type":"reasoning.text","text":"**Analyzing Weather Data**\n\nI've just received the weather data for Florence. My current task is to clearly convey the 40 degrees Celsius temperature reading to the user. I'm focusing on the best way to present this information so it's easily understood and actionable.\n\n\n","format":"google-gemini-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kt7kxbesam"} + + data: {"id":"gen_01KGF3C4C0A7ZEXSENPBN82KKW","object":"chat.completion.chunk","created":1770033396,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":"The current weather in Florence"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kt7kxbesam"} + + data: {"id":"gen_01KGF3C4C0A7ZEXSENPBN82KKW","object":"chat.completion.chunk","created":1770033396,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"content":", Italy is 40°C."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_kt7kxbesam"} + + data: {"id":"gen_01KGF3C4C0A7ZEXSENPBN82KKW","object":"chat.completion.chunk","created":1770033396,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"delta":{"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":29,"promptTokenCount":40,"candidatesTokenCount":14,"totalTokenCount":83,"trafficType":"ON_DEMAND"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":1491866.50627,"endTime":1502204.735086,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":1491866.50627,"endTime":1502204.735086,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.000596","marketCost":"0.000596","generationId":"gen_01KGF3C4C0A7ZEXSENPBN82KKW","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":40,"completion_tokens":14,"total_tokens":54,"cost":0.000596,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":29,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000596},"system_fingerprint":"fp_kt7kxbesam","generationId":"gen_01KGF3C4C0A7ZEXSENPBN82KKW"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 10.48104525s diff --git a/providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking.yaml b/providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking.yaml new file mode 100644 index 0000000000000000000000000000000000000000..5dc01fb6a05b8f842a1ef95b90b6860815c301ce --- /dev/null +++ b/providertests/testdata/TestVercelThinking/gemini-3-pro-preview/thinking.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 481 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"google/gemini-3-pro-preview","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3BTEQ7ZXNXTXM5HCM0ZW5","object":"chat.completion","created":1770033379,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":null,"reasoning":"**Determining the Weather**\n\nI''ve identified the need for weather data. I believe the `weather` function is a solid choice. It''s now a matter of calling this function. I''ll pass it ''Florence, Italy'' to retrieve the current conditions.\n\n\n","reasoning_details":[{"type":"reasoning.text","text":"**Determining the Weather**\n\nI''ve identified the need for weather data. I believe the `weather` function is a solid choice. It''s now a matter of calling this function. I''ll pass it ''Florence, Italy'' to retrieve the current conditions.\n\n\n","format":"google-gemini-v1","index":0}],"tool_calls":[{"id":"Zwo8e1JcXjoJ0bPs","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence, Italy\"}"}}],"provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"thoughtsTokenCount":67,"promptTokenCount":28,"candidatesTokenCount":9,"totalTokenCount":104,"trafficType":"PROVISIONED_THROUGHPUT"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":390947.964322,"endTime":394738.481613,"statusCode":200,"providerResponseId":"35CAacnTN9X8tfAPg7j5QA"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.000968","marketCost":"0.000968","generationId":"gen_01KGF3BTEQ7ZXNXTXM5HCM0ZW5","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":28,"completion_tokens":9,"total_tokens":37,"cost":0.000968,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":67,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000968},"system_fingerprint":"fp_t3b6jfaxsx","generationId":"gen_01KGF3BTEQ7ZXNXTXM5HCM0ZW5"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 4.135991625s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1114 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"},{"tool_calls":[{"id":"Zwo8e1JcXjoJ0bPs","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"format":"google-gemini-v1","index":0,"text":"**Determining the Weather**\n\nI''ve identified the need for weather data. I believe the `weather` function is a solid choice. It''s now a matter of calling this function. I''ll pass it ''Florence, Italy'' to retrieve the current conditions.\n\n\n","type":"reasoning.text"},{"format":"google-gemini-v1","index":0,"type":"reasoning.encrypted"}]},{"content":"40 C","tool_call_id":"Zwo8e1JcXjoJ0bPs","role":"tool"}],"model":"google/gemini-3-pro-preview","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3BYDZXE5BFFQQRPX4SSCP","object":"chat.completion","created":1770033382,"model":"google/gemini-3-pro-preview","choices":[{"index":0,"message":{"role":"assistant","content":"The current temperature in Florence, Italy is 40°C.","provider_metadata":{"google":{"promptFeedback":null,"groundingMetadata":null,"urlContextMetadata":null,"safetyRatings":null,"usageMetadata":{"promptTokenCount":97,"candidatesTokenCount":14,"totalTokenCount":111,"trafficType":"PROVISIONED_THROUGHPUT"}},"gateway":{"routing":{"originalModelId":"google/gemini-3-pro-preview","resolvedProvider":"vertex","resolvedProviderApiModelId":"gemini-3-pro-preview","internalResolvedModelId":"vertex:gemini-3-pro-preview","fallbacksAvailable":["google"],"internalReasoning":"Selected vertex as preferred provider for gemini-3-pro-preview. 1 fallback(s) available: google","planningReasoning":"System credentials planned for: vertex, google. Total execution order: vertex(system) → google(system)","canonicalSlug":"google/gemini-3-pro-preview","finalProvider":"vertex","attempts":[{"provider":"vertex","internalModelId":"vertex:gemini-3-pro-preview","providerApiModelId":"gemini-3-pro-preview","credentialType":"system","success":true,"startTime":7748615.626226,"endTime":7750847.973285,"statusCode":200,"providerResponseId":"45CAae7FNaahmPUPueDE6QU"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"google/gemini-3-pro-preview","canonicalSlug":"google/gemini-3-pro-preview","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.000362","marketCost":"0.000362","generationId":"gen_01KGF3BYDZXE5BFFQQRPX4SSCP","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":97,"completion_tokens":14,"total_tokens":111,"cost":0.000362,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.000362},"system_fingerprint":"fp_02078i909k","generationId":"gen_01KGF3BYDZXE5BFFQQRPX4SSCP"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 2.353875042s diff --git a/providertests/testdata/TestVercelThinking/gpt-5/thinking-streaming.yaml b/providertests/testdata/TestVercelThinking/gpt-5/thinking-streaming.yaml new file mode 100644 index 0000000000000000000000000000000000000000..289beba53995a94d1dd82af49cef013e8665a480 --- /dev/null +++ b/providertests/testdata/TestVercelThinking/gpt-5/thinking-streaming.yaml @@ -0,0 +1,343 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 520 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"openai/gpt-5","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"**Getting","reasoning_details":[{"type":"reasoning.summary","summary":"**Getting","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" weather","reasoning_details":[{"type":"reasoning.summary","summary":" weather","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" information","reasoning_details":[{"type":"reasoning.summary","summary":" information","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"**\n\nI","reasoning_details":[{"type":"reasoning.summary","summary":"**\n\nI","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" need","reasoning_details":[{"type":"reasoning.summary","summary":" need","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" to","reasoning_details":[{"type":"reasoning.summary","summary":" to","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" retrieve","reasoning_details":[{"type":"reasoning.summary","summary":" retrieve","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" weather","reasoning_details":[{"type":"reasoning.summary","summary":" weather","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" using","reasoning_details":[{"type":"reasoning.summary","summary":" using","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" designated","reasoning_details":[{"type":"reasoning.summary","summary":" designated","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" tool","reasoning_details":[{"type":"reasoning.summary","summary":" tool","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":",","reasoning_details":[{"type":"reasoning.summary","summary":",","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" specifically","reasoning_details":[{"type":"reasoning.summary","summary":" specifically","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" functions","reasoning_details":[{"type":"reasoning.summary","summary":" functions","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".weather","reasoning_details":[{"type":"reasoning.summary","summary":".weather","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" with","reasoning_details":[{"type":"reasoning.summary","summary":" with","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" location","reasoning_details":[{"type":"reasoning.summary","summary":" location","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" parameter","reasoning_details":[{"type":"reasoning.summary","summary":" parameter","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".","reasoning_details":[{"type":"reasoning.summary","summary":".","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" Even","reasoning_details":[{"type":"reasoning.summary","summary":" Even","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" though","reasoning_details":[{"type":"reasoning.summary","summary":" though","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" there's","reasoning_details":[{"type":"reasoning.summary","summary":" there's","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" a","reasoning_details":[{"type":"reasoning.summary","summary":" a","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" multi","reasoning_details":[{"type":"reasoning.summary","summary":" multi","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"_tool","reasoning_details":[{"type":"reasoning.summary","summary":"_tool","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"_use","reasoning_details":[{"type":"reasoning.summary","summary":"_use","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".parallel","reasoning_details":[{"type":"reasoning.summary","summary":".parallel","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" option","reasoning_details":[{"type":"reasoning.summary","summary":" option","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" for","reasoning_details":[{"type":"reasoning.summary","summary":" for","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" running","reasoning_details":[{"type":"reasoning.summary","summary":" running","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" multiple","reasoning_details":[{"type":"reasoning.summary","summary":" multiple","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" tools","reasoning_details":[{"type":"reasoning.summary","summary":" tools","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":",","reasoning_details":[{"type":"reasoning.summary","summary":",","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" I'm","reasoning_details":[{"type":"reasoning.summary","summary":" I'm","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" focused","reasoning_details":[{"type":"reasoning.summary","summary":" focused","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" on","reasoning_details":[{"type":"reasoning.summary","summary":" on","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" just","reasoning_details":[{"type":"reasoning.summary","summary":" just","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" one","reasoning_details":[{"type":"reasoning.summary","summary":" one","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" tool","reasoning_details":[{"type":"reasoning.summary","summary":" tool","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" here","reasoning_details":[{"type":"reasoning.summary","summary":" here","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":",","reasoning_details":[{"type":"reasoning.summary","summary":",","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" so","reasoning_details":[{"type":"reasoning.summary","summary":" so","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" I'll","reasoning_details":[{"type":"reasoning.summary","summary":" I'll","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" go","reasoning_details":[{"type":"reasoning.summary","summary":" go","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" ahead","reasoning_details":[{"type":"reasoning.summary","summary":" ahead","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" and","reasoning_details":[{"type":"reasoning.summary","summary":" and","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" call","reasoning_details":[{"type":"reasoning.summary","summary":" call","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" functions","reasoning_details":[{"type":"reasoning.summary","summary":" functions","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".weather","reasoning_details":[{"type":"reasoning.summary","summary":".weather","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" directly","reasoning_details":[{"type":"reasoning.summary","summary":" directly","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" with","reasoning_details":[{"type":"reasoning.summary","summary":" with","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" \"","reasoning_details":[{"type":"reasoning.summary","summary":" \"","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"Flor","reasoning_details":[{"type":"reasoning.summary","summary":"Flor","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"ence","reasoning_details":[{"type":"reasoning.summary","summary":"ence","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":",","reasoning_details":[{"type":"reasoning.summary","summary":",","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" Italy","reasoning_details":[{"type":"reasoning.summary","summary":" Italy","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".\"","reasoning_details":[{"type":"reasoning.summary","summary":".\"","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" I'll","reasoning_details":[{"type":"reasoning.summary","summary":" I'll","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" make","reasoning_details":[{"type":"reasoning.summary","summary":" make","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" sure","reasoning_details":[{"type":"reasoning.summary","summary":" sure","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" to","reasoning_details":[{"type":"reasoning.summary","summary":" to","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" use","reasoning_details":[{"type":"reasoning.summary","summary":" use","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" commentary","reasoning_details":[{"type":"reasoning.summary","summary":" commentary","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" channel","reasoning_details":[{"type":"reasoning.summary","summary":" channel","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" for","reasoning_details":[{"type":"reasoning.summary","summary":" for","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" this","reasoning_details":[{"type":"reasoning.summary","summary":" this","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" call","reasoning_details":[{"type":"reasoning.summary","summary":" call","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".","reasoning_details":[{"type":"reasoning.summary","summary":".","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" Once","reasoning_details":[{"type":"reasoning.summary","summary":" Once","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" I","reasoning_details":[{"type":"reasoning.summary","summary":" I","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" receive","reasoning_details":[{"type":"reasoning.summary","summary":" receive","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" weather","reasoning_details":[{"type":"reasoning.summary","summary":" weather","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" response","reasoning_details":[{"type":"reasoning.summary","summary":" response","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":",","reasoning_details":[{"type":"reasoning.summary","summary":",","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" I'll","reasoning_details":[{"type":"reasoning.summary","summary":" I'll","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" present","reasoning_details":[{"type":"reasoning.summary","summary":" present","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" the","reasoning_details":[{"type":"reasoning.summary","summary":" the","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" information","reasoning_details":[{"type":"reasoning.summary","summary":" information","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" clearly","reasoning_details":[{"type":"reasoning.summary","summary":" clearly","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" and","reasoning_details":[{"type":"reasoning.summary","summary":" and","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" succinct","reasoning_details":[{"type":"reasoning.summary","summary":" succinct","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"ly","reasoning_details":[{"type":"reasoning.summary","summary":"ly","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":".","reasoning_details":[{"type":"reasoning.summary","summary":".","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" Let's","reasoning_details":[{"type":"reasoning.summary","summary":" Let's","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":" go","reasoning_details":[{"type":"reasoning.summary","summary":" go","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning":"!","reasoning_details":[{"type":"reasoning.summary","summary":"!","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"reasoning_details":[{"type":"reasoning.encrypted","data":"gAAAAABpgJDXAuR0HjlWRtFfesnymrYPPQR9I9gY-4gyB4kiZ_mdXFEOJLsYevTBaNB1wjNviCSnJU0F9Icw2vm542wsByAW0SCh-u5tckaejCd1Eo5gMrgWWSwGKT3xmHzZHMjqxkUGG7orIHGQlIZPr7pHwxTGLp8jmQK_mH7oiDADSjmclCD73KGLOoLlYQLMTq1HGZHAKjCtv-l7uNB1Vst33Hnd2rwayvRXRCQBtgZwotY7AE4vF2Em3pOZSiWu-1u0FkkDhOQd9QupaKRTcPX5PZpFG_FfD6Elwsp-MMH4wtpk96WDc7y0dLouWW5H_pxblrvXQqbpeFVyk1wJ9Xzy7NjcJYnVwt04rdtUjqXBwFJN0HOtYH8TvW2u3mz8x-nj29UxwRMtzPDwXLoAiSRYo6KAZRU4cryLCqiOlTMB3Yedr0RuWkIWU4_oO38whChA8vawvTlcHgPPEYeKAlmEYyOR4mlDAR-r6zGw6fFCSjQ_J9HdlOpeLXm-Y-a5WFzl_FXYE0CVqUzBMMR2PSs6VO4DR73ATdl62SIVW-4kLgPYVurYyv8VUM3H1Z_bb2kInDpqXwK2IUwX08BNRnMvi_wPvm7pTEeKQCxj9-D8rLTIsK8C2tfaDZReKhCymy0KBF9UWDFKlHcM58zU1N7o2YHfVO6b61SWYLra4H7eewBv2levoiSoeVFjar787rf8bqeoPn-mkwASjgKWyDvUwcsLA2vMm8eMclk4qryY8LbgCvX320Zo5byUXblt9f2wTDZhQblmXLaW-9vTBjrbPqtDc2LW_ZkLoSApnrlQxvu0AnaqVUDGHVFERlbZcuU35JJ-","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","format":"openai-responses-v1","index":0}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"id":"call_0bKx1gHreGnPuO8CzsleyyRQ","type":"function","function":{"name":"weather","arguments":""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"{\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"location"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\":\""}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"Flor"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"ence"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":","}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":" Italy"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"tool_calls":[{"index":0,"function":{"arguments":"\"}"}}]},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5gf37iohnb"} + + data: {"id":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","object":"chat.completion.chunk","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_0430adf43712f48201698090d6c4048196b485fe56c0face13","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1725623.377813,"endTime":1725855.622852,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1725623.377813,"endTime":1725855.622852,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.00219875","marketCost":"0.00219875","generationId":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":63,"completion_tokens":148,"total_tokens":211,"cost":0.00219875,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00219875},"system_fingerprint":"fp_5gf37iohnb","generationId":"gen_01KGF3BHK17PHK9V9DEN2A1ZAE"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 339.492ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 2375 + 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_0bKx1gHreGnPuO8CzsleyyRQ","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"format":"openai-responses-v1","index":0,"summary":"**Getting weather information**\n\nI need to retrieve the weather using the designated tool, specifically the functions.weather with the location parameter. Even though there''s a multi_tool_use.parallel option for running multiple tools, I''m focused on just one tool here, so I''ll go ahead and call functions.weather directly with \"Florence, Italy.\" I''ll make sure to use the commentary channel for this call. Once I receive the weather response, I''ll present the information clearly and succinctly. Let''s go!","type":"reasoning.summary"},{"data":"gAAAAABpgJDXAuR0HjlWRtFfesnymrYPPQR9I9gY-4gyB4kiZ_mdXFEOJLsYevTBaNB1wjNviCSnJU0F9Icw2vm542wsByAW0SCh-u5tckaejCd1Eo5gMrgWWSwGKT3xmHzZHMjqxkUGG7orIHGQlIZPr7pHwxTGLp8jmQK_mH7oiDADSjmclCD73KGLOoLlYQLMTq1HGZHAKjCtv-l7uNB1Vst33Hnd2rwayvRXRCQBtgZwotY7AE4vF2Em3pOZSiWu-1u0FkkDhOQd9QupaKRTcPX5PZpFG_FfD6Elwsp-MMH4wtpk96WDc7y0dLouWW5H_pxblrvXQqbpeFVyk1wJ9Xzy7NjcJYnVwt04rdtUjqXBwFJN0HOtYH8TvW2u3mz8x-nj29UxwRMtzPDwXLoAiSRYo6KAZRU4cryLCqiOlTMB3Yedr0RuWkIWU4_oO38whChA8vawvTlcHgPPEYeKAlmEYyOR4mlDAR-r6zGw6fFCSjQ_J9HdlOpeLXm-Y-a5WFzl_FXYE0CVqUzBMMR2PSs6VO4DR73ATdl62SIVW-4kLgPYVurYyv8VUM3H1Z_bb2kInDpqXwK2IUwX08BNRnMvi_wPvm7pTEeKQCxj9-D8rLTIsK8C2tfaDZReKhCymy0KBF9UWDFKlHcM58zU1N7o2YHfVO6b61SWYLra4H7eewBv2levoiSoeVFjar787rf8bqeoPn-mkwASjgKWyDvUwcsLA2vMm8eMclk4qryY8LbgCvX320Zo5byUXblt9f2wTDZhQblmXLaW-9vTBjrbPqtDc2LW_ZkLoSApnrlQxvu0AnaqVUDGHVFERlbZcuU35JJ-","format":"openai-responses-v1","id":"rs_0430adf43712f48201698090d71990819682f523d5f4a4cd6a","index":0,"type":"reasoning.encrypted"}]},{"content":"40 C","tool_call_id":"call_0bKx1gHreGnPuO8CzsleyyRQ","role":"tool"}],"model":"openai/gpt-5","stream_options":{"include_usage":true},"tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true},"stream":true}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: |+ + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"role":"assistant"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"It"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"’s"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" currently"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" around"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" "},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"40"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"°C"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" Florence"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" Italy"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" If"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" you"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"’d"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" like"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":","},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" I"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" can"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" also"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" provide"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" a"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" brief"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" forecast"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" or"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" tips"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" for"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" staying"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" cool"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" in"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" the"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":" heat"},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"content":"."},"logprobs":null,"finish_reason":null}],"system_fingerprint":"fp_5vwx38gjaf"} + + data: {"id":"gen_01KGF3BP39K37NP6M0N1QWVXE1","object":"chat.completion.chunk","created":1770033371,"model":"openai/gpt-5","choices":[{"index":0,"delta":{"provider_metadata":{"openai":{"responseId":"resp_0430adf43712f48201698090db6338819696794d34dd844e52","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1477248.277749,"endTime":1477458.808981,"statusCode":200}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":true,"providerAttemptCount":1,"providerAttempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1477248.277749,"endTime":1477458.808981,"statusCode":200}]}],"totalProviderAttemptCount":1},"cost":"0.00049125","marketCost":"0.00049125","generationId":"gen_01KGF3BP39K37NP6M0N1QWVXE1","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":97,"completion_tokens":37,"total_tokens":134,"cost":0.00049125,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00049125},"system_fingerprint":"fp_5vwx38gjaf","generationId":"gen_01KGF3BP39K37NP6M0N1QWVXE1"} + + data: [DONE] + + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 304.872667ms diff --git a/providertests/testdata/TestVercelThinking/gpt-5/thinking.yaml b/providertests/testdata/TestVercelThinking/gpt-5/thinking.yaml new file mode 100644 index 0000000000000000000000000000000000000000..0b1b34f723c33da6890fbcba75507b7f04e321b6 --- /dev/null +++ b/providertests/testdata/TestVercelThinking/gpt-5/thinking.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 466 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"What''s the weather in Florence, Italy?","role":"user"}],"model":"openai/gpt-5","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3B3C7Q42KHM2W985XF2T3","object":"chat.completion","created":1770033356,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":null,"reasoning":"**Checking weather in Florence**\n\nI need to answer the user regarding the weather in Florence, Italy. I have access to a functions.weather tool for this purpose. Since we''re only calling one tool, I don’t need to use the multi_tool_use feature, which is meant for parallel calls. I’ll simply use functions.weather directly. I’ll provide the location as \"Florence, Italy\" and then wait for the results. Fingers crossed the tool gives us the correct data!","reasoning_details":[{"type":"reasoning.summary","summary":"**Checking weather in Florence**\n\nI need to answer the user regarding the weather in Florence, Italy. I have access to a functions.weather tool for this purpose. Since we''re only calling one tool, I don’t need to use the multi_tool_use feature, which is meant for parallel calls. I’ll simply use functions.weather directly. I’ll provide the location as \"Florence, Italy\" and then wait for the results. Fingers crossed the tool gives us the correct data!","id":"rs_0562170428b0ad7001698090c89354819687c27b2705c3ce4c","format":"openai-responses-v1","index":0},{"type":"reasoning.encrypted","data":"gAAAAABpgJDMsf0VPNBZL3A8tONVzmCdRytZjL7k3QaiavhXgEfFZ0_E6LPvHdpQha_hZs16TnpTURpI-a0UEqxQ0ogIISECklCdduz3wdG0_h55n2hL-NL07dwRdFhygz4tmLJo9mqbUsn1D0uWEu-4afSiPP1HUVoyM3P-XAqG0iDZBG0S3MTxzLCkS9kRgQlzROJlaXEmEB9AJdyFXmb7zAABESJ5kGlH6sT0Iakwvl8vVr34M-OwgYCCGQ6ppz-m0UQmNhCBlcq08d8KkpYElyOQ8hbbykatWslxGZzBWLz7leWClihD4iMM72zbWnwXZDshOqp4lObx1TZuLlDI_naQj6yNXVMRolOSq7g_SygrgJ4o8vmDWUu8Tt_pAHcjWTbzhhTOo-X0-OubpEPgOdjvjdGnQ3tuS5BZs39XVsN0CL2L_XzL6zdVKGdCkqEwoiXjJSLtSFZLgQvn5bzmIPY0II0xX4CAeSN8oHhE4CnocBqWrU3PRaKPHM0WypqB0UuM254n_cZBvdKC9OaJfWKmVbdI1H5R0arzb3KYBG8DXpuWVO354MtLSZ6ZaqxJDNapHX9nwGZ2muBBzYSqxsdYFuLSxz3J-uAwA8YM8o6yb8otfhXrmiHS_562EofNf1yKoFX2j4lACJFTFRWpDRl-ytnfW_VCXvdEelBlmB40JuFu6qy_lF0_g-CndYzGXOi714BIPR0dvcNOLpX_w71QA4WHJUvm7udhzvcHvIkNZHu3O8lUl7htEJGYnx-6x1vn_XLJBD47TUi4QbbuvmqPcHVfbQ5Z-9Hn-Dc9JMGXhao72RRnilCBeiJcJmjTYTWn4JjgE0yMr9BdJjQv9j5E2p3oPHIB2Dqw1FiIHpw1VaGan4T8N3yRPD6-AinoZggBNkULFTS0lWBPPI0vk4uMWIruJS5l7z8rs08PsBS5kTk6-J4IEp-3--Yy5YJND8Z_zboGaKewpWFeft0FqRklGdJ00e_FGaPD2aOfcOygzlCtKumLhU2XG_E8VvGxjz4-TLlzM3LR35Hgm03amQVV_20JMdI1XB_OSoPKoGCZubzBQsf7E_8zVj23J3wVkFEv6o1Fh4XJ4unWcLeQjjLvT7Bkv-smny6wWN-Fd6SM9yU8fMlTHbRCCVdcGRN6QjcX1K5eOiI8U4qmvQw8Tn9_MtMejUdEkWdiKxACIhOhAqJRlTl8JwQL9ggL1gc4iVMepQuaSvauSVjNWalgq94e-k1tSSkobHt6yGD3Fd9jUwyC6KrWraEWR7tmbWesc1KR_zbsd9J_B57szRFLz0JU6GmTCwRM9sblytuCLLdIeW8FLlqIRyhkYm5HrgKyoYwBLp9yOkfllj6C35ZW5ZTOpLNhmeDi3BOLMh6IvMgak4TCaNJjvmPD7ZVU6Y_--LOe_SCJta3yppo2f4-eOduTsUXcXC-gmpbvAhUBgIyOV55OTSE8OGYHZ86sTdF7UVnzftznjQ-5mZKPiHMTNgastAmdKdNhcjDunKlL-qbyEsX4Eeb9TKXM2koCcxZ-Dfs84wSS","id":"rs_0562170428b0ad7001698090c89354819687c27b2705c3ce4c","format":"openai-responses-v1","index":0}],"tool_calls":[{"id":"call_iHMVWYLENDMIMaQBppQsnQ2Y","type":"function","function":{"name":"weather","arguments":"{\"location\":\"Florence, Italy\"}"}}],"provider_metadata":{"openai":{"responseId":"resp_0562170428b0ad7001698090c836608196820886f8d884db01","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":1469621.176344,"endTime":1473996.358343,"statusCode":200,"providerResponseId":"resp_0562170428b0ad7001698090c836608196820886f8d884db01"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.00215875","marketCost":"0.00215875","generationId":"gen_01KGF3B3C7Q42KHM2W985XF2T3","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"tool_calls"}],"usage":{"prompt_tokens":63,"completion_tokens":144,"total_tokens":207,"cost":0.00215875,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":64,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00215875},"system_fingerprint":"fp_5jkdir3bke","generationId":"gen_01KGF3B3C7Q42KHM2W985XF2T3"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 4.531842958s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 2977 + 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_iHMVWYLENDMIMaQBppQsnQ2Y","function":{"arguments":"{\"location\":\"Florence, Italy\"}","name":"weather"},"type":"function"}],"role":"assistant","reasoning_details":[{"format":"openai-responses-v1","index":0,"summary":"**Checking weather in Florence**\n\nI need to answer the user regarding the weather in Florence, Italy. I have access to a functions.weather tool for this purpose. Since we''re only calling one tool, I don’t need to use the multi_tool_use feature, which is meant for parallel calls. I’ll simply use functions.weather directly. I’ll provide the location as \"Florence, Italy\" and then wait for the results. Fingers crossed the tool gives us the correct data!","type":"reasoning.summary"},{"data":"gAAAAABpgJDMsf0VPNBZL3A8tONVzmCdRytZjL7k3QaiavhXgEfFZ0_E6LPvHdpQha_hZs16TnpTURpI-a0UEqxQ0ogIISECklCdduz3wdG0_h55n2hL-NL07dwRdFhygz4tmLJo9mqbUsn1D0uWEu-4afSiPP1HUVoyM3P-XAqG0iDZBG0S3MTxzLCkS9kRgQlzROJlaXEmEB9AJdyFXmb7zAABESJ5kGlH6sT0Iakwvl8vVr34M-OwgYCCGQ6ppz-m0UQmNhCBlcq08d8KkpYElyOQ8hbbykatWslxGZzBWLz7leWClihD4iMM72zbWnwXZDshOqp4lObx1TZuLlDI_naQj6yNXVMRolOSq7g_SygrgJ4o8vmDWUu8Tt_pAHcjWTbzhhTOo-X0-OubpEPgOdjvjdGnQ3tuS5BZs39XVsN0CL2L_XzL6zdVKGdCkqEwoiXjJSLtSFZLgQvn5bzmIPY0II0xX4CAeSN8oHhE4CnocBqWrU3PRaKPHM0WypqB0UuM254n_cZBvdKC9OaJfWKmVbdI1H5R0arzb3KYBG8DXpuWVO354MtLSZ6ZaqxJDNapHX9nwGZ2muBBzYSqxsdYFuLSxz3J-uAwA8YM8o6yb8otfhXrmiHS_562EofNf1yKoFX2j4lACJFTFRWpDRl-ytnfW_VCXvdEelBlmB40JuFu6qy_lF0_g-CndYzGXOi714BIPR0dvcNOLpX_w71QA4WHJUvm7udhzvcHvIkNZHu3O8lUl7htEJGYnx-6x1vn_XLJBD47TUi4QbbuvmqPcHVfbQ5Z-9Hn-Dc9JMGXhao72RRnilCBeiJcJmjTYTWn4JjgE0yMr9BdJjQv9j5E2p3oPHIB2Dqw1FiIHpw1VaGan4T8N3yRPD6-AinoZggBNkULFTS0lWBPPI0vk4uMWIruJS5l7z8rs08PsBS5kTk6-J4IEp-3--Yy5YJND8Z_zboGaKewpWFeft0FqRklGdJ00e_FGaPD2aOfcOygzlCtKumLhU2XG_E8VvGxjz4-TLlzM3LR35Hgm03amQVV_20JMdI1XB_OSoPKoGCZubzBQsf7E_8zVj23J3wVkFEv6o1Fh4XJ4unWcLeQjjLvT7Bkv-smny6wWN-Fd6SM9yU8fMlTHbRCCVdcGRN6QjcX1K5eOiI8U4qmvQw8Tn9_MtMejUdEkWdiKxACIhOhAqJRlTl8JwQL9ggL1gc4iVMepQuaSvauSVjNWalgq94e-k1tSSkobHt6yGD3Fd9jUwyC6KrWraEWR7tmbWesc1KR_zbsd9J_B57szRFLz0JU6GmTCwRM9sblytuCLLdIeW8FLlqIRyhkYm5HrgKyoYwBLp9yOkfllj6C35ZW5ZTOpLNhmeDi3BOLMh6IvMgak4TCaNJjvmPD7ZVU6Y_--LOe_SCJta3yppo2f4-eOduTsUXcXC-gmpbvAhUBgIyOV55OTSE8OGYHZ86sTdF7UVnzftznjQ-5mZKPiHMTNgastAmdKdNhcjDunKlL-qbyEsX4Eeb9TKXM2koCcxZ-Dfs84wSS","format":"openai-responses-v1","id":"rs_0562170428b0ad7001698090c89354819687c27b2705c3ce4c","index":0,"type":"reasoning.encrypted"}]},{"content":"40 C","tool_call_id":"call_iHMVWYLENDMIMaQBppQsnQ2Y","role":"tool"}],"model":"openai/gpt-5","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"reasoning":{"enabled":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.7.1 + url: https://ai-gateway.vercel.sh/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen_01KGF3B7PMN3C6EZGFX1P9A78S","object":"chat.completion","created":1770033366,"model":"openai/gpt-5","choices":[{"index":0,"message":{"role":"assistant","content":"Right now in Florence, Italy it’s about 40°C (104°F). Want a forecast or more details?","reasoning":"**Presenting the temperature**\n\nThe tool returned \"40 C,\" which feels a bit too brief. I think I should present this clearly to the user. Converting 40 C to Fahrenheit gives us 104 F. I want to keep it concise, so I’ll say, \"Right now in Florence, it’s about 40°C (104°F).\" I should also offer to get a forecast or details like humidity, while sticking with the details that are most relevant and avoiding assumptions about the weather.**Considering the heat advisory**\n\nI realize that 40 C is extremely hot! I could include a simple advisory like \"stay hydrated,\" but it might come off as unsolicited. Since the instructions emphasize being concise, I think I’ll keep the final message straightforward: \"Right now in Florence, Italy, it''s around 40°C (104°F). Would you like a forecast or more details?\" That way, I’m providing the info without overstepping.","reasoning_details":[{"type":"reasoning.summary","summary":"**Presenting the temperature**\n\nThe tool returned \"40 C,\" which feels a bit too brief. I think I should present this clearly to the user. Converting 40 C to Fahrenheit gives us 104 F. I want to keep it concise, so I’ll say, \"Right now in Florence, it’s about 40°C (104°F).\" I should also offer to get a forecast or details like humidity, while sticking with the details that are most relevant and avoiding assumptions about the weather.**Considering the heat advisory**\n\nI realize that 40 C is extremely hot! I could include a simple advisory like \"stay hydrated,\" but it might come off as unsolicited. Since the instructions emphasize being concise, I think I’ll keep the final message straightforward: \"Right now in Florence, Italy, it''s around 40°C (104°F). Would you like a forecast or more details?\" That way, I’m providing the info without overstepping.","id":"rs_0562170428b0ad7001698090cd65008196b1811384c1eb1d6c","format":"openai-responses-v1","index":0},{"type":"reasoning.encrypted","data":"gAAAAABpgJDWD7uuI9cHJYRhaE0aumxBFm7lcXL0q4zfSOYK50X0LE6YwVz7CUc7g6HDCOxpi78m5CX5xe4sR7mloQRkr8YuAFOv_draZ0tZ21FJhKoEr7x8XyzCgrx-Mxv98HGsZE7V3cF61q8b4VZVb4r5MAPDCaZyUINTj2tLAdZChdxpwq4ZBDGhUVrYdqoPbFZm-rx9gkWOKSP7ir9aWU3L5qkQcay0i7zYj0p2Gp8iL1A--48RYacfVaXOgpfYGCBvo0whLwTVtjXxCy0_OEmkSp4bMjkd9dq3PibuD_XwN5mU3QxPW-qiF1zwsS26WQ1Zw0xwvg188l5-MMSaWhJZkZdkWFGmsmazBglfMOncPQO3khM2158ca0W6aeo0WryrEQWNeb37sJjrT258fQ_0NA9Udn0YWUXWdOndCXM7el37_JqxB-4fng9iseMEM9jx5wJ4gtinOVovootaQPYe8Vg68juw0FWgcywsJsbK1GKZNaT7-ISsgcy6Cq8uijY6S9jDn2mUxry1PZz702OrpQSkuYn_YLwXM3bPBsMIn_5sTTm4Z4FZUEXVHndT5U5-klkfzBtAYXpA1cnT65_FVqZydKo_KSLYwbssjUZL8K2QCq1MWJ8X2Lq84i0lmbX-i8Nh205TEi31ub_syPKa-pQ-r-6W0glXUCUTIuqpvGMthEOGb6YVeBhVkzenPtPSeVXWeF0oHZuuQpFbfaF2m1lxGIkETgowuRvDU7S2UOb-B1kTfDpzfFsgxXHtbBhE03tw49_EU5h8h-fCBxiR8Tc6ZylJsAUsEszEH0ofcsuF33IrhTpbLlCXN3wsfSucUq9O4NtgLO-B5VuqPOdFTJ4mbR70C_Cve-Wt4VmGekrsmD1wTImf0o9X3d_ZvZ190dkG7XDAJRDdCMK5uflIBY-fYb7TEKqtnV9WrGR1wY38lpJDzboxOXit99XOHGL64z5oCiD9K0_4BPTRbaHL9Gn8ohO4lQo0NIN4wGRD2YYHaPPjFDK4Fgr_sq8JVp4GsdZ82VyhWjE9XmX2L6VMZff44je18xTHbCRNU0BnTlkpqYea_LFip7pdZcbITnMgDrZi9zrqEpx5AjVoqBr3v7tsLP206LYwQ2g1KjNzhTStPgw3FEyKgcfrLDD9FQ7xjmvHRGWAQ_29MdVTG93M8ypEE77GkMf4AdDwa0uXOhw-k7wJe3QR206ZFzZT4fn1sDy55O0_1F-fmoPm9Ow1Cuw7W0p2oZgBShQU_IhVR3NtRF269WM28bCoCyohF71tgSzMm_dyW2qtkPhptO6Xpw2r2xUpH7AqPIC073m8O3PvfPnmr_MKQ6tS6mUH5sOqu8wrqhwuLsM3j3Pcze-2sCb8gRsw7UfrE0ed_ZTbJmbWRZbKSbX7nvGs_TVB4SpKTCe8VNtmk_4CKc0TP0ZHimi_O8CkOUn7WE7edN--E-6xuZxA47IsE1DkLXtJPuAbJZrk2XshkePp-icDeWPQ0csiLAriBRFlZQBiquXNWBsALiZK0RdchPSq5uLOPVEisXlzPgDAalfxNY2eti3vxTMIAGjZnu4QBYIrd4bUg2AAA9d5OX-TsSO0m3j1lS2sHtekYdr34ofA5dT0ntWdsaQ2WS-8WHYDmGN7TZBcfTJC784EPpoKXuTIwr9NiUAB71FRyk_wY6TdhoDqDw4KtCw28l1QMXGFK3wv0koIHOGVCjuB5IQK7NWNnyned5kSqVgkGY-epfBtvEdcdc7CCBcA7yf-qoGd7idCBnjqcMszsKMD2d95sDDO3nqNV51vhjfA9fxuo-HlGNv12PbsePQTZXSzRM9kVX7jWiu-MFgUfPtZrzYMVh97QA586AZH40Zp5D2NZpfpFFCHFxWCHbhtRhklzeBu1gQ-iWmpxzns2XypqiL5STk4JeBYoav4B7-ypRBO8mwQUEzheZgKO5Hi0jWElzqcWvO2sAouwciUP7-8Tjl0NDLAs7MzuvwtCkzH8o9ikw1vR8MmLToCgUZ1BFHZn5_EH-VWGiZ0x2kikoLM-iHi0fBFUcdj2XrVQ4mnU6IbHh2ST4Xfltx7CmssTxVvK357mX_5Aq5U-13XAJRjGaYX1rsclnudN8N2ib8LYiukfq_Rqxzxdm0QjLuc-vdGLm5V2vdJ2qX5fwrVMaVJgwt393P42SsVoyzkYPpwn4eXfiQssdjPdLkJpLFcjQ==","id":"rs_0562170428b0ad7001698090cd65008196b1811384c1eb1d6c","format":"openai-responses-v1","index":0}],"provider_metadata":{"openai":{"responseId":"resp_0562170428b0ad7001698090ccce248196b6d739df157f9b65","serviceTier":"default"},"gateway":{"routing":{"originalModelId":"openai/gpt-5","resolvedProvider":"openai","resolvedProviderApiModelId":"gpt-5-2025-08-07","internalResolvedModelId":"openai:gpt-5-2025-08-07","fallbacksAvailable":["azure"],"internalReasoning":"Selected openai as preferred provider for gpt-5. 1 fallback(s) available: azure","planningReasoning":"System credentials planned for: openai, azure. Total execution order: openai(system) → azure(system)","canonicalSlug":"openai/gpt-5","finalProvider":"openai","attempts":[{"provider":"openai","internalModelId":"openai:gpt-5-2025-08-07","providerApiModelId":"gpt-5-2025-08-07","credentialType":"system","success":true,"startTime":7725848.499705,"endTime":7735703.317098,"statusCode":200,"providerResponseId":"resp_0562170428b0ad7001698090ccce248196b6d739df157f9b65"}],"modelAttemptCount":1,"modelAttempts":[{"modelId":"openai/gpt-5","canonicalSlug":"openai/gpt-5","success":false,"providerAttemptCount":0,"providerAttempts":[]}],"totalProviderAttemptCount":0},"cost":"0.00479","marketCost":"0.00479","generationId":"gen_01KGF3B7PMN3C6EZGFX1P9A78S","billableWebSearchCalls":0}}},"logprobs":null,"finish_reason":"stop"}],"usage":{"prompt_tokens":216,"completion_tokens":260,"total_tokens":476,"cost":0.00479,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0,"video_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0,"upstream_inference_completions_cost":0},"completion_tokens_details":{"reasoning_tokens":192,"image_tokens":0},"cache_creation_input_tokens":0,"market_cost":0.00479},"system_fingerprint":"fp_bemblx56dt","generationId":"gen_01KGF3B7PMN3C6EZGFX1P9A78S"}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 10.00759025s diff --git a/providertests/vercel_test.go b/providertests/vercel_test.go new file mode 100644 index 0000000000000000000000000000000000000000..0361ec0bafc8cc5b6b129a785790e9de02d279f4 --- /dev/null +++ b/providertests/vercel_test.go @@ -0,0 +1,124 @@ +package providertests + +import ( + "net/http" + "os" + "testing" + + "charm.land/fantasy" + "charm.land/fantasy/providers/anthropic" + "charm.land/fantasy/providers/vercel" + "charm.land/x/vcr" + "github.com/stretchr/testify/require" +) + +var vercelTestModels = []testModel{ + {"claude-sonnet-4", "anthropic/claude-sonnet-4", true}, + {"gemini-2.5-flash", "google/gemini-2.5-flash", false}, + {"gpt-5", "openai/gpt-5", true}, + {"gemini-3-pro-preview", "google/gemini-3-pro-preview", true}, +} + +func TestVercelCommon(t *testing.T) { + var pairs []builderPair + for _, m := range vercelTestModels { + pairs = append(pairs, builderPair{m.name, vercelBuilder(m.model), nil, nil}) + } + testCommon(t, pairs) +} + +func TestVercelCommonWithAnthropicCache(t *testing.T) { + testCommon(t, []builderPair{ + {"claude-sonnet-4", vercelBuilder("anthropic/claude-sonnet-4"), nil, addAnthropicCaching}, + }) +} + +func TestVercelThinking(t *testing.T) { + enabled := true + opts := fantasy.ProviderOptions{ + vercel.Name: &vercel.ProviderOptions{ + Reasoning: &vercel.ReasoningOptions{ + Enabled: &enabled, + }, + }, + } + + var pairs []builderPair + for _, m := range vercelTestModels { + if !m.reasoning { + continue + } + pairs = append(pairs, builderPair{m.name, vercelBuilder(m.model), opts, nil}) + } + testThinking(t, pairs, testVercelThinking) + + // test anthropic signature + testThinking(t, []builderPair{ + {"claude-sonnet-4-sig", vercelBuilder("anthropic/claude-sonnet-4"), opts, nil}, + }, testVercelThinkingWithSignature) +} + +func testVercelThinkingWithSignature(t *testing.T, result *fantasy.AgentResult) { + reasoningContentCount := 0 + signaturesCount := 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() == fantasy.ContentTypeReasoning { + reasoningContentCount += 1 + reasoningContent, ok := fantasy.AsContentType[fantasy.ReasoningPart](content) + if !ok { + continue + } + if len(reasoningContent.ProviderOptions) == 0 { + continue + } + + anthropicReasoningMetadata, ok := reasoningContent.ProviderOptions[anthropic.Name] + if !ok { + continue + } + if reasoningContent.Text != "" { + if typed, ok := anthropicReasoningMetadata.(*anthropic.ReasoningOptionMetadata); ok { + require.NotEmpty(t, typed.Signature) + signaturesCount += 1 + } + } + } + } + } + } + require.Greater(t, reasoningContentCount, 0) + require.Greater(t, signaturesCount, 0) + require.Equal(t, reasoningContentCount, signaturesCount) + // we also add the anthropic metadata so test that + testAnthropicThinking(t, result) +} + +func testVercelThinking(t *testing.T, result *fantasy.AgentResult) { + reasoningContentCount := 0 + for _, step := range result.Steps { + for _, msg := range step.Messages { + for _, content := range msg.Content { + if content.GetType() == fantasy.ContentTypeReasoning { + reasoningContentCount += 1 + } + } + } + } + require.Greater(t, reasoningContentCount, 0) +} + +func vercelBuilder(model string) builderFunc { + return func(t *testing.T, r *vcr.Recorder) (fantasy.LanguageModel, error) { + provider, err := vercel.New( + vercel.WithAPIKey(os.Getenv("FANTASY_VERCEL_API_KEY")), + vercel.WithHTTPClient(&http.Client{Transport: r}), + ) + if err != nil { + return nil, err + } + return provider.LanguageModel(t.Context(), model) + } +}