From a7b436dad5fcc37b04ec769f4429966c4282a489 Mon Sep 17 00:00:00 2001 From: kujtimiihoxha Date: Mon, 22 Sep 2025 13:11:16 +0200 Subject: [PATCH] chore: openrouter initial extra hooks --- openai/language_model.go | 175 +++++++-------- openai/language_model_hooks.go | 110 +++++++++- openrouter/language_model_hooks.go | 205 +++++++++++++++++- openrouter/openrouter.go | 9 +- openrouter/provider_options.go | 41 +++- providertests/builders_test.go | 19 ++ providertests/provider_test.go | 81 ++++++- .../TestSimple/openrouter-kimi-k2.yaml | 33 +++ .../TestStream/openrouter-kimi-k2.yaml | 32 +++ .../anthropic-claude-sonnet.yaml | 61 ++++++ .../google-gemini-2.5-flash.yaml | 63 ++++++ .../google-gemini-2.5-pro.yaml | 63 ++++++ .../openai-gpt-4o-mini.yaml | 61 ++++++ .../openai-gpt-4o.yaml | 61 ++++++ .../openrouter-kimi-k2.yaml | 61 ++++++ .../openrouter-kimi-k2.yaml | 90 ++++++++ .../TestThinking/openrouter-glm-4.5.yaml | 63 ++++++ .../openrouter-glm-4.5.yaml | 61 ++++++ .../testdata/TestTool/openrouter-kimi-k2.yaml | 63 ++++++ providertests/thinking_test.go | 22 +- 20 files changed, 1274 insertions(+), 100 deletions(-) create mode 100644 providertests/testdata/TestSimple/openrouter-kimi-k2.yaml create mode 100644 providertests/testdata/TestStream/openrouter-kimi-k2.yaml create mode 100644 providertests/testdata/TestStreamWithMultipleTools/anthropic-claude-sonnet.yaml create mode 100644 providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-flash.yaml create mode 100644 providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-pro.yaml create mode 100644 providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o-mini.yaml create mode 100644 providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o.yaml create mode 100644 providertests/testdata/TestStreamWithMultipleTools/openrouter-kimi-k2.yaml create mode 100644 providertests/testdata/TestStreamWithTools/openrouter-kimi-k2.yaml create mode 100644 providertests/testdata/TestThinking/openrouter-glm-4.5.yaml create mode 100644 providertests/testdata/TestThinkingStreaming/openrouter-glm-4.5.yaml create mode 100644 providertests/testdata/TestTool/openrouter-kimi-k2.yaml diff --git a/openai/language_model.go b/openai/language_model.go index ffc8b7a7b5629bc2810af7cf75508a3d5ed4f24e..303c55deb9ba7f413e050a6bcd880e8d46a376d6 100644 --- a/openai/language_model.go +++ b/openai/language_model.go @@ -18,26 +18,66 @@ import ( ) type languageModel struct { - provider string - modelID string - client openai.Client - prepareCallFunc PrepareLanguageModelCallFunc + provider string + modelID string + client openai.Client + prepareCallFunc LanguageModelPrepareCallFunc + mapFinishReasonFunc LanguageModelMapFinishReasonFunc + extraContentFunc LanguageModelExtraContentFunc + usageFunc LanguageModelUsageFunc + streamUsageFunc LanguageModelStreamUsageFunc + streamExtraFunc LanguageModelStreamExtraFunc + streamProviderMetadataFunc LanguageModelStreamProviderMetadataFunc } type LanguageModelOption = func(*languageModel) -func WithPrepareLanguageModelCallFunc(fn PrepareLanguageModelCallFunc) LanguageModelOption { +func WithLanguageModelPrepareCallFunc(fn LanguageModelPrepareCallFunc) LanguageModelOption { return func(l *languageModel) { l.prepareCallFunc = fn } } +func WithLanguageModelMapFinishReasonFunc(fn LanguageModelMapFinishReasonFunc) LanguageModelOption { + return func(l *languageModel) { + l.mapFinishReasonFunc = fn + } +} + +func WithLanguageModelExtraContentFunc(fn LanguageModelExtraContentFunc) LanguageModelOption { + return func(l *languageModel) { + l.extraContentFunc = fn + } +} + +func WithLanguageModelStreamExtraFunc(fn LanguageModelStreamExtraFunc) LanguageModelOption { + return func(l *languageModel) { + l.streamExtraFunc = fn + } +} + +func WithLanguageModelUsageFunc(fn LanguageModelUsageFunc) LanguageModelOption { + return func(l *languageModel) { + l.usageFunc = fn + } +} + +func WithLanguageModelStreamUsageFunc(fn LanguageModelStreamUsageFunc) LanguageModelOption { + return func(l *languageModel) { + l.streamUsageFunc = fn + } +} + func newLanguageModel(modelID string, provider string, client openai.Client, opts ...LanguageModelOption) languageModel { model := languageModel{ - modelID: modelID, - provider: provider, - client: client, - prepareCallFunc: defaultPrepareLanguageModelCall, + modelID: modelID, + provider: provider, + client: client, + prepareCallFunc: defaultPrepareLanguageModelCall, + mapFinishReasonFunc: defaultMapFinishReason, + usageFunc: defaultUsage, + streamUsageFunc: defaultStreamUsage, + streamProviderMetadataFunc: defaultStreamProviderMetadataFunc, } for _, o := range opts { @@ -215,7 +255,10 @@ func (o languageModel) Generate(ctx context.Context, call ai.Call) (*ai.Response Text: text, }) } - + if o.extraContentFunc != nil { + extraContent := o.extraContentFunc(choice) + content = append(content, extraContent...) + } for _, tc := range choice.Message.ToolCalls { toolCallID := tc.ID if toolCallID == "" { @@ -240,36 +283,12 @@ func (o languageModel) Generate(ctx context.Context, call ai.Call) (*ai.Response } } - completionTokenDetails := response.Usage.CompletionTokensDetails - promptTokenDetails := response.Usage.PromptTokensDetails - - // Build provider metadata - providerMetadata := &ProviderMetadata{} - // Add logprobs if available - if len(choice.Logprobs.Content) > 0 { - providerMetadata.Logprobs = choice.Logprobs.Content - } - - // Add prediction tokens if available - if completionTokenDetails.AcceptedPredictionTokens > 0 || completionTokenDetails.RejectedPredictionTokens > 0 { - if completionTokenDetails.AcceptedPredictionTokens > 0 { - providerMetadata.AcceptedPredictionTokens = completionTokenDetails.AcceptedPredictionTokens - } - if completionTokenDetails.RejectedPredictionTokens > 0 { - providerMetadata.RejectedPredictionTokens = completionTokenDetails.RejectedPredictionTokens - } - } + usage, providerMetadata := o.usageFunc(*response) return &ai.Response{ - Content: content, - Usage: ai.Usage{ - InputTokens: response.Usage.PromptTokens, - OutputTokens: response.Usage.CompletionTokens, - TotalTokens: response.Usage.TotalTokens, - ReasoningTokens: completionTokenDetails.ReasoningTokens, - CacheReadTokens: promptTokenDetails.CachedTokens, - }, - FinishReason: mapOpenAiFinishReason(choice.FinishReason), + Content: content, + Usage: usage, + FinishReason: defaultMapFinishReason(choice), ProviderMetadata: ai.ProviderMetadata{ Name: providerMetadata, }, @@ -293,8 +312,11 @@ func (o languageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamRespo toolCalls := make(map[int64]streamToolCall) // Build provider metadata for streaming - streamProviderMetadata := &ProviderMetadata{} + providerMetadata := ai.ProviderMetadata{ + Name: &ProviderMetadata{}, + } acc := openai.ChatCompletionAccumulator{} + extraContext := make(map[string]any) var usage ai.Usage return func(yield func(ai.StreamPart) bool) { if len(warnings) > 0 { @@ -308,28 +330,7 @@ func (o languageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamRespo for stream.Next() { chunk := stream.Current() acc.AddChunk(chunk) - if chunk.Usage.TotalTokens > 0 { - // we do this here because the acc does not add prompt details - completionTokenDetails := chunk.Usage.CompletionTokensDetails - promptTokenDetails := chunk.Usage.PromptTokensDetails - usage = ai.Usage{ - InputTokens: chunk.Usage.PromptTokens, - OutputTokens: chunk.Usage.CompletionTokens, - TotalTokens: chunk.Usage.TotalTokens, - ReasoningTokens: completionTokenDetails.ReasoningTokens, - CacheReadTokens: promptTokenDetails.CachedTokens, - } - - // Add prediction tokens if available - if completionTokenDetails.AcceptedPredictionTokens > 0 || completionTokenDetails.RejectedPredictionTokens > 0 { - if completionTokenDetails.AcceptedPredictionTokens > 0 { - streamProviderMetadata.AcceptedPredictionTokens = completionTokenDetails.AcceptedPredictionTokens - } - if completionTokenDetails.RejectedPredictionTokens > 0 { - streamProviderMetadata.RejectedPredictionTokens = completionTokenDetails.RejectedPredictionTokens - } - } - } + usage, providerMetadata = o.streamUsageFunc(chunk, extraContext, providerMetadata) if len(chunk.Choices) == 0 { continue } @@ -464,6 +465,14 @@ func (o languageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamRespo } } } + + if o.streamExtraFunc != nil { + updatedContext, shouldContinue := o.streamExtraFunc(chunk, yield, extraContext) + if !shouldContinue { + return + } + extraContext = updatedContext + } } // Check for annotations in the delta's raw JSON @@ -498,14 +507,13 @@ func (o languageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamRespo } } - // Add logprobs if available - if len(acc.Choices) > 0 && len(acc.Choices[0].Logprobs.Content) > 0 { - streamProviderMetadata.Logprobs = acc.Choices[0].Logprobs.Content - } - - // Handle annotations/citations from accumulated response if len(acc.Choices) > 0 { - for _, annotation := range acc.Choices[0].Message.Annotations { + choice := acc.Choices[0] + // Add logprobs if available + providerMetadata = o.streamProviderMetadataFunc(choice, providerMetadata) + + // Handle annotations/citations from accumulated response + for _, annotation := range choice.Message.Annotations { if annotation.Type == "url_citation" { if !yield(ai.StreamPart{ Type: ai.StreamPartTypeSource, @@ -519,15 +527,15 @@ func (o languageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamRespo } } } - - finishReason := mapOpenAiFinishReason(acc.Choices[0].FinishReason) + finishReason := ai.FinishReasonUnknown + if len(acc.Choices) > 0 { + finishReason = o.mapFinishReasonFunc(acc.Choices[0]) + } yield(ai.StreamPart{ - Type: ai.StreamPartTypeFinish, - Usage: usage, - FinishReason: finishReason, - ProviderMetadata: ai.ProviderMetadata{ - Name: streamProviderMetadata, - }, + Type: ai.StreamPartTypeFinish, + Usage: usage, + FinishReason: finishReason, + ProviderMetadata: providerMetadata, }) return } else { @@ -540,21 +548,6 @@ func (o languageModel) Stream(ctx context.Context, call ai.Call) (ai.StreamRespo }, nil } -func mapOpenAiFinishReason(finishReason string) ai.FinishReason { - switch finishReason { - case "stop": - return ai.FinishReasonStop - case "length": - return ai.FinishReasonLength - case "content_filter": - return ai.FinishReasonContentFilter - case "function_call", "tool_calls": - return ai.FinishReasonToolCalls - default: - return ai.FinishReasonUnknown - } -} - func isReasoningModel(modelID string) bool { return strings.HasPrefix(modelID, "o") || strings.HasPrefix(modelID, "gpt-5") || strings.HasPrefix(modelID, "gpt-5-chat") } diff --git a/openai/language_model_hooks.go b/openai/language_model_hooks.go index 537c88f6e2af8ae9082e0aae0339866e60521b2c..6b44d4caa29a35520c1486b73e7cd6c3252d3e02 100644 --- a/openai/language_model_hooks.go +++ b/openai/language_model_hooks.go @@ -9,7 +9,15 @@ import ( "github.com/openai/openai-go/v2/shared" ) -type PrepareLanguageModelCallFunc = func(model ai.LanguageModel, params *openai.ChatCompletionNewParams, call ai.Call) ([]ai.CallWarning, error) +type ( + LanguageModelPrepareCallFunc = func(model ai.LanguageModel, params *openai.ChatCompletionNewParams, call ai.Call) ([]ai.CallWarning, error) + LanguageModelMapFinishReasonFunc = func(choice openai.ChatCompletionChoice) ai.FinishReason + LanguageModelUsageFunc = func(choice openai.ChatCompletion) (ai.Usage, ai.ProviderOptionsData) + LanguageModelExtraContentFunc = func(choice openai.ChatCompletionChoice) []ai.Content + LanguageModelStreamExtraFunc = func(chunk openai.ChatCompletionChunk, yield func(ai.StreamPart) bool, ctx map[string]any) (map[string]any, bool) + LanguageModelStreamUsageFunc = func(chunk openai.ChatCompletionChunk, ctx map[string]any, metadata ai.ProviderMetadata) (ai.Usage, ai.ProviderMetadata) + LanguageModelStreamProviderMetadataFunc = func(choice openai.ChatCompletionChoice, metadata ai.ProviderMetadata) ai.ProviderMetadata +) func defaultPrepareLanguageModelCall(model ai.LanguageModel, params *openai.ChatCompletionNewParams, call ai.Call) ([]ai.CallWarning, error) { if call.ProviderOptions == nil { @@ -147,3 +155,103 @@ func defaultPrepareLanguageModelCall(model ai.LanguageModel, params *openai.Chat } return warnings, nil } + +func defaultMapFinishReason(choice openai.ChatCompletionChoice) ai.FinishReason { + finishReason := choice.FinishReason + switch finishReason { + case "stop": + return ai.FinishReasonStop + case "length": + return ai.FinishReasonLength + case "content_filter": + return ai.FinishReasonContentFilter + case "function_call", "tool_calls": + return ai.FinishReasonToolCalls + default: + return ai.FinishReasonUnknown + } +} + +func defaultUsage(response openai.ChatCompletion) (ai.Usage, ai.ProviderOptionsData) { + if len(response.Choices) == 0 { + return ai.Usage{}, nil + } + choice := response.Choices[0] + completionTokenDetails := response.Usage.CompletionTokensDetails + promptTokenDetails := response.Usage.PromptTokensDetails + + // Build provider metadata + providerMetadata := &ProviderMetadata{} + // Add logprobs if available + if len(choice.Logprobs.Content) > 0 { + providerMetadata.Logprobs = choice.Logprobs.Content + } + + // Add prediction tokens if available + if completionTokenDetails.AcceptedPredictionTokens > 0 || completionTokenDetails.RejectedPredictionTokens > 0 { + if completionTokenDetails.AcceptedPredictionTokens > 0 { + providerMetadata.AcceptedPredictionTokens = completionTokenDetails.AcceptedPredictionTokens + } + if completionTokenDetails.RejectedPredictionTokens > 0 { + providerMetadata.RejectedPredictionTokens = completionTokenDetails.RejectedPredictionTokens + } + } + return ai.Usage{ + InputTokens: response.Usage.PromptTokens, + OutputTokens: response.Usage.CompletionTokens, + TotalTokens: response.Usage.TotalTokens, + ReasoningTokens: completionTokenDetails.ReasoningTokens, + CacheReadTokens: promptTokenDetails.CachedTokens, + }, providerMetadata +} + +func defaultStreamUsage(chunk openai.ChatCompletionChunk, ctx map[string]any, metadata ai.ProviderMetadata) (ai.Usage, ai.ProviderMetadata) { + if chunk.Usage.TotalTokens == 0 { + return ai.Usage{}, nil + } + streamProviderMetadata := &ProviderMetadata{} + if metadata != nil { + if providerMetadata, ok := metadata[Name]; ok { + converted, ok := providerMetadata.(*ProviderMetadata) + if ok { + streamProviderMetadata = converted + } + } + } + // we do this here because the acc does not add prompt details + completionTokenDetails := chunk.Usage.CompletionTokensDetails + promptTokenDetails := chunk.Usage.PromptTokensDetails + usage := ai.Usage{ + InputTokens: chunk.Usage.PromptTokens, + OutputTokens: chunk.Usage.CompletionTokens, + TotalTokens: chunk.Usage.TotalTokens, + ReasoningTokens: completionTokenDetails.ReasoningTokens, + CacheReadTokens: promptTokenDetails.CachedTokens, + } + + // Add prediction tokens if available + if completionTokenDetails.AcceptedPredictionTokens > 0 || completionTokenDetails.RejectedPredictionTokens > 0 { + if completionTokenDetails.AcceptedPredictionTokens > 0 { + streamProviderMetadata.AcceptedPredictionTokens = completionTokenDetails.AcceptedPredictionTokens + } + if completionTokenDetails.RejectedPredictionTokens > 0 { + streamProviderMetadata.RejectedPredictionTokens = completionTokenDetails.RejectedPredictionTokens + } + } + + return usage, ai.ProviderMetadata{ + Name: streamProviderMetadata, + } +} + +func defaultStreamProviderMetadataFunc(choice openai.ChatCompletionChoice, metadata ai.ProviderMetadata) ai.ProviderMetadata { + streamProviderMetadata, ok := metadata[Name] + if !ok { + streamProviderMetadata = &ProviderMetadata{} + } + if converted, ok := streamProviderMetadata.(*ProviderMetadata); ok { + converted.Logprobs = choice.Logprobs.Content + metadata[Name] = converted + } + return metadata +} diff --git a/openrouter/language_model_hooks.go b/openrouter/language_model_hooks.go index ac8640591066b159505852664c6ec7ea2d04c42f..3fea2e0cc27bcf1d7922a02bde0c43bbbc087b6d 100644 --- a/openrouter/language_model_hooks.go +++ b/openrouter/language_model_hooks.go @@ -1,6 +1,8 @@ package openrouter import ( + "encoding/json" + "fmt" "maps" "github.com/charmbracelet/fantasy/ai" @@ -8,7 +10,9 @@ import ( "github.com/openai/openai-go/v2/packages/param" ) -func prepareLanguageModelCall(model ai.LanguageModel, params *openaisdk.ChatCompletionNewParams, call ai.Call) ([]ai.CallWarning, error) { +const reasoningStartedCtx = "reasoning_started" + +func languagePrepareModelCall(model ai.LanguageModel, params *openaisdk.ChatCompletionNewParams, call ai.Call) ([]ai.CallWarning, error) { providerOptions := &ProviderOptions{} if v, ok := call.ProviderOptions[Name]; ok { providerOptions, ok = v.(*ProviderOptions) @@ -39,6 +43,10 @@ func prepareLanguageModelCall(model ai.LanguageModel, params *openaisdk.ChatComp extraFields["usage"] = map[string]any{ "include": *providerOptions.IncludeUsage, } + } else { // default include usage + extraFields["usage"] = map[string]any{ + "include": true, + } } if providerOptions.LogitBias != nil { params.LogitBias = providerOptions.LogitBias @@ -57,3 +65,198 @@ func prepareLanguageModelCall(model ai.LanguageModel, params *openaisdk.ChatComp params.SetExtraFields(extraFields) return nil, nil } + +func languageModelMapFinishReason(choice openaisdk.ChatCompletionChoice) ai.FinishReason { + finishReason := choice.FinishReason + switch finishReason { + case "stop": + return ai.FinishReasonStop + case "length": + return ai.FinishReasonLength + case "content_filter": + return ai.FinishReasonContentFilter + case "function_call", "tool_calls": + return ai.FinishReasonToolCalls + default: + // for streaming responses the openai accumulator is not working as expected with some provider + // therefore it is sending no finish reason so we need to manually handle it + if len(choice.Message.ToolCalls) > 0 { + return ai.FinishReasonToolCalls + } else if finishReason == "" { + return ai.FinishReasonStop + } + return ai.FinishReasonUnknown + } +} + +func languageModelExtraContent(choice openaisdk.ChatCompletionChoice) []ai.Content { + var content []ai.Content + reasoningData := ReasoningData{} + err := json.Unmarshal([]byte(choice.Message.RawJSON()), &reasoningData) + if err != nil { + return content + } + for _, detail := range reasoningData.ReasoningDetails { + switch detail.Type { + case "reasoning.text": + content = append(content, ai.ReasoningContent{ + Text: detail.Text, + }) + case "reasoning.summary": + content = append(content, ai.ReasoningContent{ + Text: detail.Summary, + }) + case "reasoning.encrypted": + content = append(content, ai.ReasoningContent{ + Text: "[REDACTED]", + }) + } + } + return content +} + +func extractReasoningContext(ctx map[string]any) bool { + reasoningStarted, ok := ctx[reasoningStartedCtx] + if !ok { + return false + } + b, ok := reasoningStarted.(bool) + if !ok { + return false + } + return b +} + +func languageModelStreamExtra(chunk openaisdk.ChatCompletionChunk, yield func(ai.StreamPart) bool, ctx map[string]any) (map[string]any, bool) { + if len(chunk.Choices) == 0 { + return ctx, true + } + + reasoningStarted := extractReasoningContext(ctx) + + for inx, choice := range chunk.Choices { + reasoningData := ReasoningData{} + err := json.Unmarshal([]byte(choice.Delta.RawJSON()), &reasoningData) + if err != nil { + yield(ai.StreamPart{ + Type: ai.StreamPartTypeError, + Error: ai.NewAIError("Unexpected", "error unmarshalling delta", err), + }) + return ctx, false + } + + emitEvent := func(reasoningContent string) bool { + if !reasoningStarted { + shouldContinue := yield(ai.StreamPart{ + Type: ai.StreamPartTypeReasoningStart, + ID: fmt.Sprintf("%d", inx), + }) + if !shouldContinue { + return false + } + } + + return yield(ai.StreamPart{ + Type: ai.StreamPartTypeReasoningDelta, + ID: fmt.Sprintf("%d", inx), + Delta: reasoningContent, + }) + } + if len(reasoningData.ReasoningDetails) > 0 { + for _, detail := range reasoningData.ReasoningDetails { + if !reasoningStarted { + ctx[reasoningStartedCtx] = true + } + switch detail.Type { + case "reasoning.text": + return ctx, emitEvent(detail.Text) + case "reasoning.summary": + return ctx, emitEvent(detail.Summary) + case "reasoning.encrypted": + return ctx, emitEvent("[REDACTED]") + } + } + } else if reasoningData.Reasoning != "" { + return ctx, emitEvent(reasoningData.Reasoning) + } + if reasoningStarted && (choice.Delta.Content != "" || len(choice.Delta.ToolCalls) > 0) { + ctx[reasoningStartedCtx] = false + return ctx, yield(ai.StreamPart{ + Type: ai.StreamPartTypeReasoningEnd, + ID: fmt.Sprintf("%d", inx), + }) + } + } + return ctx, true +} + +func languageModelUsage(response openaisdk.ChatCompletion) (ai.Usage, ai.ProviderOptionsData) { + if len(response.Choices) == 0 { + return ai.Usage{}, nil + } + openrouterUsage := UsageAccounting{} + usage := response.Usage + + _ = json.Unmarshal([]byte(usage.RawJSON()), &openrouterUsage) + + completionTokenDetails := usage.CompletionTokensDetails + promptTokenDetails := usage.PromptTokensDetails + + var provider string + if p, ok := response.JSON.ExtraFields["provider"]; ok { + provider = p.Raw() + } + + // Build provider metadata + providerMetadata := &ProviderMetadata{ + Provider: provider, + Usage: openrouterUsage, + } + + return ai.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 ai.ProviderMetadata) (ai.Usage, ai.ProviderMetadata) { + usage := chunk.Usage + if usage.TotalTokens == 0 { + return ai.Usage{}, nil + } + + streamProviderMetadata := &ProviderMetadata{} + if metadata != nil { + if providerMetadata, ok := metadata[Name]; ok { + converted, ok := providerMetadata.(*ProviderMetadata) + if ok { + streamProviderMetadata = converted + } + } + } + openrouterUsage := UsageAccounting{} + _ = json.Unmarshal([]byte(usage.RawJSON()), &openrouterUsage) + streamProviderMetadata.Usage = openrouterUsage + + if p, ok := chunk.JSON.ExtraFields["provider"]; ok { + streamProviderMetadata.Provider = p.Raw() + } + + // we do this here because the acc does not add prompt details + completionTokenDetails := usage.CompletionTokensDetails + promptTokenDetails := usage.PromptTokensDetails + aiUsage := ai.Usage{ + InputTokens: usage.PromptTokens, + OutputTokens: usage.CompletionTokens, + TotalTokens: usage.TotalTokens, + ReasoningTokens: completionTokenDetails.ReasoningTokens, + CacheReadTokens: promptTokenDetails.CachedTokens, + } + + return aiUsage, ai.ProviderMetadata{ + Name: streamProviderMetadata, + } +} diff --git a/openrouter/openrouter.go b/openrouter/openrouter.go index 4e7cee3e53af047db4e85ef2d2d1fc04c9ae324e..40c140439cf454a98569d161c76de7b461b19725 100644 --- a/openrouter/openrouter.go +++ b/openrouter/openrouter.go @@ -14,6 +14,7 @@ type options struct { const ( DefaultURL = "https://openrouter.ai/api/v1" + Name = "openrouter" ) type Option = func(*options) @@ -21,9 +22,15 @@ type Option = func(*options) func New(opts ...Option) ai.Provider { providerOptions := options{ openaiOptions: []openai.Option{ + openai.WithName(Name), openai.WithBaseURL(DefaultURL), openai.WithLanguageModelOptions( - openai.WithPrepareLanguageModelCallFunc(prepareLanguageModelCall), + openai.WithLanguageModelPrepareCallFunc(languagePrepareModelCall), + openai.WithLanguageModelUsageFunc(languageModelUsage), + openai.WithLanguageModelStreamUsageFunc(languageModelStreamUsage), + openai.WithLanguageModelStreamExtraFunc(languageModelStreamExtra), + openai.WithLanguageModelExtraContentFunc(languageModelExtraContent), + openai.WithLanguageModelMapFinishReasonFunc(languageModelMapFinishReason), ), }, } diff --git a/openrouter/provider_options.go b/openrouter/provider_options.go index c3b5c4b54efc7165ac6440a661602c951edcf3c6..add85ef43b5d5413594a484b68d8aed2995b7698 100644 --- a/openrouter/provider_options.go +++ b/openrouter/provider_options.go @@ -4,8 +4,6 @@ import ( "github.com/charmbracelet/fantasy/ai" ) -const Name = "openrouter" - type ReasoningEffort string const ( @@ -14,7 +12,34 @@ const ( ReasoningEffortHigh ReasoningEffort = "high" ) -type ProviderMetadata struct{} +type PromptTokensDetails struct { + CachedTokens int64 +} + +type CompletionTokensDetails struct { + ReasoningTokens int64 +} + +type CostDetails struct { + UpstreamInferenceCost float64 `json:"upstream_inference_cost"` + UpstreamInferencePromptCost float64 `json:"upstream_inference_prompt_cost"` + UpstreamInferenceCompletionsCost float64 `json:"upstream_inference_completions_cost"` +} + +type UsageAccounting struct { + PromptTokens int64 `json:"prompt_tokens"` + PromptTokensDetails PromptTokensDetails `json:"prompt_tokens_details"` + CompletionTokens int64 `json:"completion_tokens"` + CompletionTokensDetails CompletionTokensDetails `json:"completion_tokens_details"` + TotalTokens int64 `json:"total_tokens"` + Cost float64 `json:"cost"` + CostDetails CostDetails `json:"cost_details"` +} + +type ProviderMetadata struct { + Provider string `json:"provider"` + Usage UsageAccounting `json:"usage"` +} func (*ProviderMetadata) Options() {} @@ -70,6 +95,16 @@ type ProviderOptions struct { func (*ProviderOptions) Options() {} +type ReasoningDetail struct { + Type string `json:"type"` + Text string `json:"text"` + Summary string `json:"summary"` +} +type ReasoningData struct { + Reasoning string `json:"reasoning"` + ReasoningDetails []ReasoningDetail `json:"reasoning_details"` +} + func ReasoningEffortOption(e ReasoningEffort) *ReasoningEffort { return &e } diff --git a/providertests/builders_test.go b/providertests/builders_test.go index c7e5add7335e65617ee7ae92a77e96e8633f7714..1460fd4f27335451ed4ebc21abaa3a7b45e3cb58 100644 --- a/providertests/builders_test.go +++ b/providertests/builders_test.go @@ -9,6 +9,7 @@ import ( "github.com/charmbracelet/fantasy/anthropic" "github.com/charmbracelet/fantasy/google" "github.com/charmbracelet/fantasy/openai" + "github.com/charmbracelet/fantasy/openrouter" "gopkg.in/dnaeon/go-vcr.v4/pkg/recorder" ) @@ -25,12 +26,14 @@ var languageModelBuilders = []builderPair{ {"anthropic-claude-sonnet", builderAnthropicClaudeSonnet4}, {"google-gemini-2.5-flash", builderGoogleGemini25Flash}, {"google-gemini-2.5-pro", builderGoogleGemini25Pro}, + {"openrouter-kimi-k2", builderOpenrouterKimiK2}, } var thinkingLanguageModelBuilders = []builderPair{ {"openai-gpt-5", builderOpenaiGpt5}, {"anthropic-claude-sonnet", builderAnthropicClaudeSonnet4}, {"google-gemini-2.5-pro", builderGoogleGemini25Pro}, + {"openrouter-glm-4.5", builderOpenrouterGLM45}, } func builderOpenaiGpt4o(r *recorder.Recorder) (ai.LanguageModel, error) { @@ -80,3 +83,19 @@ func builderGoogleGemini25Pro(r *recorder.Recorder) (ai.LanguageModel, error) { ) return provider.LanguageModel("gemini-2.5-pro") } + +func builderOpenrouterKimiK2(r *recorder.Recorder) (ai.LanguageModel, error) { + provider := openrouter.New( + openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")), + openrouter.WithHTTPClient(&http.Client{Transport: r}), + ) + return provider.LanguageModel("moonshotai/kimi-k2-0905") +} + +func builderOpenrouterGLM45(r *recorder.Recorder) (ai.LanguageModel, error) { + provider := openrouter.New( + openrouter.WithAPIKey(os.Getenv("OPENROUTER_API_KEY")), + openrouter.WithHTTPClient(&http.Client{Transport: r}), + ) + return provider.LanguageModel("z-ai/glm-4.5") +} diff --git a/providertests/provider_test.go b/providertests/provider_test.go index acc30e78d7b9e0823cfc45f4e95174b27482df7f..714632c6b19e644c27c80365ec395c22a2ee73ba 100644 --- a/providertests/provider_test.go +++ b/providertests/provider_test.go @@ -10,6 +10,7 @@ import ( "github.com/charmbracelet/fantasy/anthropic" "github.com/charmbracelet/fantasy/google" "github.com/charmbracelet/fantasy/openai" + "github.com/charmbracelet/fantasy/openrouter" _ "github.com/joho/godotenv/autoload" "github.com/stretchr/testify/require" ) @@ -119,6 +120,11 @@ func TestThinking(t *testing.T) { "openai": &openai.ProviderOptions{ ReasoningEffort: openai.ReasoningEffortOption(openai.ReasoningEffortMedium), }, + "openrouter": &openrouter.ProviderOptions{ + Reasoning: &openrouter.ReasoningOptions{ + Effort: openrouter.ReasoningEffortOption(openrouter.ReasoningEffortHigh), + }, + }, }, }) require.NoError(t, err, "failed to generate") @@ -128,7 +134,7 @@ func TestThinking(t *testing.T) { got := result.Response.Content.Text() require.True(t, strings.Contains(got, want1) && strings.Contains(got, want2), "unexpected response: got %q, want %q %q", got, want1, want2) - testThinkingSteps(t, languageModel.Provider(), result.Steps) + testThinking(t, languageModel.Provider(), result.Steps) }) } } @@ -184,7 +190,7 @@ func TestThinkingStreaming(t *testing.T) { got := result.Response.Content.Text() require.True(t, strings.Contains(got, want1) && strings.Contains(got, want2), "unexpected response: got %q, want %q %q", got, want1, want2) - testThinkingSteps(t, languageModel.Provider(), result.Steps) + testThinking(t, languageModel.Provider(), result.Steps) }) } } @@ -299,3 +305,74 @@ func TestStreamWithTools(t *testing.T) { }) } } + +func TestStreamWithMultipleTools(t *testing.T) { + for _, pair := range languageModelBuilders { + t.Run(pair.name, func(t *testing.T) { + r := newRecorder(t) + + languageModel, err := pair.builder(r) + require.NoError(t, err, "failed to build language model") + + type CalculatorInput struct { + A int `json:"a" description:"first number"` + B int `json:"b" description:"second number"` + } + + addTool := ai.NewAgentTool( + "add", + "Add two numbers", + func(ctx context.Context, input CalculatorInput, _ ai.ToolCall) (ai.ToolResponse, error) { + result := input.A + input.B + return ai.NewTextResponse(strings.TrimSpace(strconv.Itoa(result))), nil + }, + ) + multiplyTool := ai.NewAgentTool( + "multiply", + "Multiply two numbers", + func(ctx context.Context, input CalculatorInput, _ ai.ToolCall) (ai.ToolResponse, error) { + result := input.A * input.B + return ai.NewTextResponse(strings.TrimSpace(strconv.Itoa(result))), nil + }, + ) + + agent := ai.NewAgent( + languageModel, + ai.WithSystemPrompt("You are a helpful assistant. Always use both add and multiply at the same time."), + ai.WithTools(addTool), + ai.WithTools(multiplyTool), + ) + + toolCallCount := 0 + toolResultCount := 0 + var collectedText strings.Builder + + streamCall := ai.AgentStreamCall{ + Prompt: "Add and multiply the number 2 and 3", + OnTextDelta: func(id, text string) error { + collectedText.WriteString(text) + return nil + }, + OnToolCall: func(toolCall ai.ToolCallContent) error { + toolCallCount++ + return nil + }, + OnToolResult: func(result ai.ToolResultContent) error { + toolResultCount++ + return nil + }, + } + + result, err := agent.Stream(t.Context(), streamCall) + require.NoError(t, err, "failed to stream") + require.Equal(t, len(result.Steps), 2, "expected all tool calls in step 1") + finalText := result.Response.Content.Text() + require.Contains(t, finalText, "5", "expected response to contain '5', got: %q", finalText) + require.Contains(t, finalText, "6", "expected response to contain '5', got: %q", finalText) + + require.Greater(t, toolCallCount, 0, "expected at least one tool call") + + require.Greater(t, toolResultCount, 0, "expected at least one tool result") + }) + } +} diff --git a/providertests/testdata/TestSimple/openrouter-kimi-k2.yaml b/providertests/testdata/TestSimple/openrouter-kimi-k2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..f4cb92cea21d802469d2ddec3dbc691a336cfbeb --- /dev/null +++ b/providertests/testdata/TestSimple/openrouter-kimi-k2.yaml @@ -0,0 +1,33 @@ +--- +version: 2 +interactions: + - id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 180 + host: "" + body: '{"messages":[{"content":"You are a helpful assistant","role":"system"},{"content":"Say hi in Portuguese","role":"user"}],"model":"moonshotai/kimi-k2-0905","usage":{"include":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen-1758536663-isAYACl4o5P2svHApNjR","provider":"DeepInfra","model":"moonshotai/kimi-k2-0905","object":"chat.completion","created":1758536663,"choices":[{"logprobs":null,"finish_reason":"stop","native_finish_reason":"stop","index":0,"message":{"role":"assistant","content":"Olá!","refusal":null,"reasoning":null}}],"usage":{"prompt_tokens":20,"completion_tokens":3,"total_tokens":23,"cost":0.000016,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.00001,"upstream_inference_completions_cost":0.000006},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 937.162041ms diff --git a/providertests/testdata/TestStream/openrouter-kimi-k2.yaml b/providertests/testdata/TestStream/openrouter-kimi-k2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..825246a0b1f762710dee1c4f61a913d5731b95ee --- /dev/null +++ b/providertests/testdata/TestStream/openrouter-kimi-k2.yaml @@ -0,0 +1,32 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 242 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant\",\"role\":\"system\"},{\"content\":\"Count from 1 to 3 in Spanish\",\"role\":\"user\"}],\"model\":\"moonshotai/kimi-k2-0905\",\"stream_options\":{\"include_usage\":true},\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"Un\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"o\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\",\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" dos\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\",\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" tres\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\".\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"stop\",\"logprobs\":null}],\"system_fingerprint\":\"\"}\n\ndata: {\"id\":\"gen-1758536685-uqiifVIp9XhYrjFSvssK\",\"provider\":\"SiliconFlow\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536685,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":26,\"completion_tokens\":7,\"total_tokens\":33,\"cost\":0.00003111,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.00001508,\"upstream_inference_completions_cost\":0.00001603},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.936039959s diff --git a/providertests/testdata/TestStreamWithMultipleTools/anthropic-claude-sonnet.yaml b/providertests/testdata/TestStreamWithMultipleTools/anthropic-claude-sonnet.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c4d587900cdabca2d021e3827de88f9086a97303 --- /dev/null +++ b/providertests/testdata/TestStreamWithMultipleTools/anthropic-claude-sonnet.yaml @@ -0,0 +1,61 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 812 + host: "" + body: "{\"max_tokens\":4096,\"messages\":[{\"content\":[{\"text\":\"Add and multiply the number 2 and 3\",\"type\":\"text\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-20250514\",\"system\":[{\"text\":\"You are a helpful assistant. Always use both add and multiply at the same time.\",\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"},\"name\":\"add\",\"description\":\"Add two numbers\"},{\"input_schema\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"},\"name\":\"multiply\",\"description\":\"Multiply two numbers\"}],\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - Anthropic/Go 1.10.0 + url: https://api.anthropic.com/v1/messages + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01PUw9RoW7BhRqa5rFEW1Y4c\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"claude-sonnet-4-20250514\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"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\":4,\"service_tier\":\"standard\"}} }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"I'll add an\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"d multiply 2 and 3 \"} }\n\nevent: ping\ndata: {\"type\": \"ping\"}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"for you.\"} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0 }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":1,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01MBZvm8gNZSTuJCkVy49PiF\",\"name\":\"add\",\"input\":{}} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"a\\\"\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\": 2\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":1,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\", \\\"b\\\": 3}\"} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":1 }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":2,\"content_block\":{\"type\":\"tool_use\",\"id\":\"toolu_01G7Ju4HLQV7pfMc5KTwztJ3\",\"name\":\"multiply\",\"input\":{}} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\"{\\\"a\\\":\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\" 2\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":2,\"delta\":{\"type\":\"input_json_delta\",\"partial_json\":\", \\\"b\\\": 3}\"} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":2 }\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"tool_use\",\"stop_sequence\":null},\"usage\":{\"input_tokens\":502,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":135} }\n\nevent: message_stop\ndata: {\"type\":\"message_stop\" }\n\n" + headers: + Content-Type: + - text/event-stream; charset=utf-8 + status: 200 OK + code: 200 + duration: 925.170625ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1346 + host: "" + body: "{\"max_tokens\":4096,\"messages\":[{\"content\":[{\"text\":\"Add and multiply the number 2 and 3\",\"type\":\"text\"}],\"role\":\"user\"},{\"content\":[{\"text\":\"I'll add and multiply 2 and 3 for you.\",\"type\":\"text\"},{\"id\":\"toolu_01MBZvm8gNZSTuJCkVy49PiF\",\"input\":{\"a\":2,\"b\":3},\"name\":\"add\",\"type\":\"tool_use\"},{\"id\":\"toolu_01G7Ju4HLQV7pfMc5KTwztJ3\",\"input\":{\"a\":2,\"b\":3},\"name\":\"multiply\",\"type\":\"tool_use\"}],\"role\":\"assistant\"},{\"content\":[{\"tool_use_id\":\"toolu_01MBZvm8gNZSTuJCkVy49PiF\",\"content\":[{\"text\":\"5\",\"type\":\"text\"}],\"type\":\"tool_result\"},{\"tool_use_id\":\"toolu_01G7Ju4HLQV7pfMc5KTwztJ3\",\"content\":[{\"text\":\"6\",\"type\":\"text\"}],\"type\":\"tool_result\"}],\"role\":\"user\"}],\"model\":\"claude-sonnet-4-20250514\",\"system\":[{\"text\":\"You are a helpful assistant. Always use both add and multiply at the same time.\",\"type\":\"text\"}],\"tool_choice\":{\"disable_parallel_tool_use\":false,\"type\":\"auto\"},\"tools\":[{\"input_schema\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"},\"name\":\"add\",\"description\":\"Add two numbers\"},{\"input_schema\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"},\"name\":\"multiply\",\"description\":\"Multiply two numbers\"}],\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - Anthropic/Go 1.10.0 + url: https://api.anthropic.com/v1/messages + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "event: message_start\ndata: {\"type\":\"message_start\",\"message\":{\"id\":\"msg_01MjN2ypP8MpRWywCioDtA38\",\"type\":\"message\",\"role\":\"assistant\",\"model\":\"claude-sonnet-4-20250514\",\"content\":[],\"stop_reason\":null,\"stop_sequence\":null,\"usage\":{\"input_tokens\":698,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"cache_creation\":{\"ephemeral_5m_input_tokens\":0,\"ephemeral_1h_input_tokens\":0},\"output_tokens\":1,\"service_tier\":\"standard\"}} }\n\nevent: content_block_start\ndata: {\"type\":\"content_block_start\",\"index\":0,\"content_block\":{\"type\":\"text\",\"text\":\"\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"The\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" results are:\\n- Adding\"} }\n\nevent: ping\ndata: {\"type\": \"ping\"}\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\" 2 and 3: **\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"5**\\n- Multiplying \"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"2 and 3: **6\"} }\n\nevent: content_block_delta\ndata: {\"type\":\"content_block_delta\",\"index\":0,\"delta\":{\"type\":\"text_delta\",\"text\":\"**\"} }\n\nevent: content_block_stop\ndata: {\"type\":\"content_block_stop\",\"index\":0 }\n\nevent: message_delta\ndata: {\"type\":\"message_delta\",\"delta\":{\"stop_reason\":\"end_turn\",\"stop_sequence\":null},\"usage\":{\"input_tokens\":698,\"cache_creation_input_tokens\":0,\"cache_read_input_tokens\":0,\"output_tokens\":35} }\n\nevent: message_stop\ndata: {\"type\":\"message_stop\" }\n\n" + headers: + Content-Type: + - text/event-stream; charset=utf-8 + status: 200 OK + code: 200 + duration: 1.137101375s diff --git a/providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-flash.yaml b/providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-flash.yaml new file mode 100644 index 0000000000000000000000000000000000000000..8eb86a7d35903b405c33182048168064f4f459d9 --- /dev/null +++ b/providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-flash.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 787 + host: generativelanguage.googleapis.com + body: "{\"contents\":[{\"parts\":[{\"text\":\"Add and multiply the number 2 and 3\"}],\"role\":\"user\"}],\"generationConfig\":{},\"systemInstruction\":{\"parts\":[{\"text\":\"You are a helpful assistant. Always use both add and multiply at the same time.\"}],\"role\":\"user\"},\"toolConfig\":{\"functionCallingConfig\":{\"mode\":\"AUTO\"}},\"tools\":[{\"functionDeclarations\":[{\"description\":\"Add two numbers\",\"name\":\"add\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}},{\"description\":\"Multiply two numbers\",\"name\":\"multiply\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}}]}]}\n" + form: + alt: + - sse + headers: + Content-Type: + - application/json + User-Agent: + - google-genai-sdk/1.23.0 gl-go/go1.25.1 + url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"add\",\"args\": {\"a\": 2,\"b\": 3}},\"thoughtSignature\": \"CikB0e2Kb9Cbo981mR8v4MhGuu8kkazE7e5W2Yaehwjb6iqXgIQTnlkiEQptAdHtim/2wYeqmL8JTZVWRWzYrj1Yh72I2/C1joGgI7SMVWgEv1EcSoryWwxuWg8XnVTwE8etvpuv42AzaAjwdyTHeRpMZRFTwCsbs72ZcfZaNp5fGcdsULLk8ofUEgdjv3traQpoVe6f8gwCqgpnAdHtim8gitawv43Dk2C2hFdN2eoi7yDLD4TzcSJlI30wo3U2t3dO08m4RSdj9n8cItxy0Xgr2oMrYlx0gxObVepGmwdc0JVLiruE9sWE8FC/Jr4nq9avS6jXag4yzb1cmWSb9jqdmA==\"},{\"functionCall\": {\"name\": \"multiply\",\"args\": {\"a\": 2,\"b\": 3}}}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 121,\"candidatesTokenCount\": 36,\"totalTokenCount\": 195,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 121}],\"thoughtsTokenCount\": 38},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"Cy7RaKyyIPGO28oPouv7mAg\"}\r\n\r\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 974.596292ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1134 + host: generativelanguage.googleapis.com + body: "{\"contents\":[{\"parts\":[{\"text\":\"Add and multiply the number 2 and 3\"}],\"role\":\"user\"},{\"parts\":[{\"functionCall\":{\"args\":{\"a\":2,\"b\":3},\"id\":\"add\",\"name\":\"add\"}},{\"functionCall\":{\"args\":{\"a\":2,\"b\":3},\"id\":\"multiply\",\"name\":\"multiply\"}}],\"role\":\"model\"},{\"parts\":[{\"functionResponse\":{\"id\":\"add\",\"name\":\"add\",\"response\":{\"result\":\"5\"}}},{\"functionResponse\":{\"id\":\"multiply\",\"name\":\"multiply\",\"response\":{\"result\":\"6\"}}}],\"role\":\"user\"}],\"generationConfig\":{},\"systemInstruction\":{\"parts\":[{\"text\":\"You are a helpful assistant. Always use both add and multiply at the same time.\"}],\"role\":\"user\"},\"toolConfig\":{\"functionCallingConfig\":{\"mode\":\"AUTO\"}},\"tools\":[{\"functionDeclarations\":[{\"description\":\"Add two numbers\",\"name\":\"add\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}},{\"description\":\"Multiply two numbers\",\"name\":\"multiply\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}}]}]}\n" + form: + alt: + - sse + headers: + Content-Type: + - application/json + User-Agent: + - google-genai-sdk/1.23.0 gl-go/go1.25.1 + url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-flash:streamGenerateContent?alt=sse + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"The\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 181,\"candidatesTokenCount\": 1,\"totalTokenCount\": 182,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 181}]},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"DC7RaMP8CduFxN8P18bViQQ\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \" sum of 2 and 3 is 5. The product of 2\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 181,\"candidatesTokenCount\": 17,\"totalTokenCount\": 198,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 181}]},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"DC7RaMP8CduFxN8P18bViQQ\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \" and 3 is 6.\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 181,\"candidatesTokenCount\": 24,\"totalTokenCount\": 205,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 181}]},\"modelVersion\": \"gemini-2.5-flash\",\"responseId\": \"DC7RaMP8CduFxN8P18bViQQ\"}\r\n\r\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 227.840791ms diff --git a/providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-pro.yaml b/providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-pro.yaml new file mode 100644 index 0000000000000000000000000000000000000000..7a68832dc3be60be38ef8faed3869c8c3e503435 --- /dev/null +++ b/providertests/testdata/TestStreamWithMultipleTools/google-gemini-2.5-pro.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 787 + host: generativelanguage.googleapis.com + body: "{\"contents\":[{\"parts\":[{\"text\":\"Add and multiply the number 2 and 3\"}],\"role\":\"user\"}],\"generationConfig\":{},\"systemInstruction\":{\"parts\":[{\"text\":\"You are a helpful assistant. Always use both add and multiply at the same time.\"}],\"role\":\"user\"},\"toolConfig\":{\"functionCallingConfig\":{\"mode\":\"AUTO\"}},\"tools\":[{\"functionDeclarations\":[{\"description\":\"Add two numbers\",\"name\":\"add\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}},{\"description\":\"Multiply two numbers\",\"name\":\"multiply\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}}]}]}\n" + form: + alt: + - sse + headers: + Content-Type: + - application/json + User-Agent: + - google-genai-sdk/1.23.0 gl-go/go1.25.1 + url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"add\",\"args\": {\"a\": 2,\"b\": 3}},\"thoughtSignature\": \"CiQB0e2KbyaGJkeLUxOKi+YLCbUz74UFuKTOG65mtgrcWQjsRhwKXgHR7Ypv5LPPqD0JFSBqau+IKrPMP3S0EbzrijJDrfF9JqrQs+ZJ8NjV+7viPuSK1or4jGrFZs2E/t8uzQqOtMxbAzKwU84C+LgMK3HqEAmrvCHN+HJlifBwLmSvHfEKkQEB0e2Kb6mw006U33MakwJZtMmdk/PV2iY2BuGcIvmUgTH1zL1WK+JqUQq4mTboxXNq/rJQf+zdv5sg1vtKefj/7ytmblNF/v3YxEQ7ujbJof2gHj0DJCLVn8ag7GVyTnlI7kehbKjrgFgfPo1w84Q0WYbXvPjsQhj/RrBOjYM1NlJ4NA78TGoDBMHWY3rkOIklCpYBAdHtim9Ge7yE8vCr2vWHsIoRLSVtm+SWsHNAaw7yiNfdi8jZtV8l06cE1NtrN+4MuborbIFNb6Xju1IZAa/EfB/kXlWKTwGrYNe7nX8pcTeH/iPOYKtnMa1W5/HK8bCEpw2YA5oWwGYWeSkgXHigCwV+ARkaI+LPZ6cTeZBncGuSWNXrQMMNwojq5jZ/nfNWHYyckmOoCokBAdHtim8aNfukVbH0ELr/9umaE01hY7Zlw59lyidmgcfBvvAUkqw1DMXtUqw7glI1GfAjTY4mX1LmK61NtGKSz4jxI6C5FKokaUCLccIRTekW1EKNcrbFdgjLCFjt8wVtaQZn1YHNPk96cy/CpZdMYpTat0jc9rMZ8M7IxHAV/XovkwgU+8Ptn7YKaAHR7YpvWrEgQUWE/Qgv3ZnIf0D4Q1PAX7Iql8BKIMsOdtaU2g6eDHXLXu635q0KNEgW106QibeiBKVUqvDR+hMg2vmyWW5dOBO9mDsGGXtk3W+ikQ1zAM6K3AjakAtY3IkrjTKiHC1ACnAB0e2Kb0PeC541hQ/bZsK28NY09MMgWzNl7pUGmmwfuoSKHkYlU1LRIsWzAAHZpt9n/MsIrqxnFh8oTEivc8lTIyPh12nHrz99yZv9hQLd2TyPYgF05zPkDtyp/Up63N29TlBnkEdrBj5zigMqBk41CmMB0e2Kb9X4vKO1TUZ/tMgNX/Xyjqk/v9VWsT1nEYtlPoL7yjkcliBQWQrNlqrvA5xumTBVBoT4fiZi0QQDH5RouBQJvtH2mueudZq06xxoLkOjPLClNufWAsHnkKy3tMuCldsKZQHR7Ypvr4RXX++UhiK+cFjNrf3xRG2SOxpx7eopQRRXrz4iMrqzEojTOkRlto/GYGPGAnShqRyw3VmJ/BWazwf91EXmcnavdmXaSJ7Yog6A9D+hKG5YyZSW1p8WpqQh0vCVk7jwCpgBAdHtim/27LCCUWVCGPMSfLTwFbKacnQvI6bG2mGpST9tpq6EVP2MMx/9NbTnz6G9iVzIezaE6QmokFnZt/Jk3Coyp7o70GiTnuPQp8dI31SezAaPh+KDyO0cNEyD0yOuJ5y32YfZYQy/EZSmrDhk68KiJFdanlMD4lueWpJmav8SLw/dAJpkT8swEsKXbA7iOArEp5Sw8icKVQHR7YpvCy2/5mdSW+seg8kjX/Ttw2jJz8RtZxadlNqG+qVbm1MSsgsGfPY+zDgIWMU3QcVfTFPWB4DRYwVhzGNEzSv+FDTdh4ue9lZFjLztOks11PcKgQEB0e2Kb6czsOAGBOYINL5bfJswhmg3cQUE2JHOS1gaTjNOzjmistBOqQ4MOBoVousfZJn6LBJiYFqivum+LGT9zy5yYzN4/qwS3Oo611PJBdX1mtAKvQUI+nqMvqsvyDu7+Wuo3AEQ2eLxowzqbFLhiveIwgKscChYMBDuKr1MMto=\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 121,\"candidatesTokenCount\": 18,\"totalTokenCount\": 413,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 121}],\"thoughtsTokenCount\": 274},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"Di7RaLaMNs-o28oPmY2ZwQU\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"functionCall\": {\"name\": \"multiply\",\"args\": {\"b\": 3,\"a\": 2}}}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 121,\"candidatesTokenCount\": 36,\"totalTokenCount\": 431,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 121}],\"thoughtsTokenCount\": 274},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"Di7RaLaMNs-o28oPmY2ZwQU\"}\r\n\r\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 4.7870815s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1134 + host: generativelanguage.googleapis.com + body: "{\"contents\":[{\"parts\":[{\"text\":\"Add and multiply the number 2 and 3\"}],\"role\":\"user\"},{\"parts\":[{\"functionCall\":{\"args\":{\"a\":2,\"b\":3},\"id\":\"add\",\"name\":\"add\"}},{\"functionCall\":{\"args\":{\"a\":2,\"b\":3},\"id\":\"multiply\",\"name\":\"multiply\"}}],\"role\":\"model\"},{\"parts\":[{\"functionResponse\":{\"id\":\"add\",\"name\":\"add\",\"response\":{\"result\":\"5\"}}},{\"functionResponse\":{\"id\":\"multiply\",\"name\":\"multiply\",\"response\":{\"result\":\"6\"}}}],\"role\":\"user\"}],\"generationConfig\":{},\"systemInstruction\":{\"parts\":[{\"text\":\"You are a helpful assistant. Always use both add and multiply at the same time.\"}],\"role\":\"user\"},\"toolConfig\":{\"functionCallingConfig\":{\"mode\":\"AUTO\"}},\"tools\":[{\"functionDeclarations\":[{\"description\":\"Add two numbers\",\"name\":\"add\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}},{\"description\":\"Multiply two numbers\",\"name\":\"multiply\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"INTEGER\"},\"b\":{\"description\":\"second number\",\"type\":\"INTEGER\"}},\"required\":[\"a\",\"b\"],\"type\":\"OBJECT\"}}]}]}\n" + form: + alt: + - sse + headers: + Content-Type: + - application/json + User-Agent: + - google-genai-sdk/1.23.0 gl-go/go1.25.1 + url: https://generativelanguage.googleapis.com/v1beta/models/gemini-2.5-pro:streamGenerateContent?alt=sse + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \"OK. The\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 181,\"candidatesTokenCount\": 3,\"totalTokenCount\": 184,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 181}]},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"FS7RaKXmIYqdvdIPg6LW2Q8\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \" sum of 2 and 3 is 5. The product of 2 and 3\"}],\"role\": \"model\"},\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 181,\"candidatesTokenCount\": 22,\"totalTokenCount\": 203,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 181}]},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"FS7RaKXmIYqdvdIPg6LW2Q8\"}\r\n\r\ndata: {\"candidates\": [{\"content\": {\"parts\": [{\"text\": \" is 6.\\n\"}],\"role\": \"model\"},\"finishReason\": \"STOP\",\"index\": 0}],\"usageMetadata\": {\"promptTokenCount\": 181,\"candidatesTokenCount\": 26,\"totalTokenCount\": 207,\"promptTokensDetails\": [{\"modality\": \"TEXT\",\"tokenCount\": 181}]},\"modelVersion\": \"gemini-2.5-pro\",\"responseId\": \"FS7RaKXmIYqdvdIPg6LW2Q8\"}\r\n\r\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 4.316570792s diff --git a/providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o-mini.yaml b/providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o-mini.yaml new file mode 100644 index 0000000000000000000000000000000000000000..990282903f9154502cd8f61146be757a6e284b69 --- /dev/null +++ b/providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o-mini.yaml @@ -0,0 +1,61 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 835 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant. Always use both add and multiply at the same time.\",\"role\":\"system\"},{\"content\":\"Add and multiply the number 2 and 3\",\"role\":\"user\"}],\"model\":\"gpt-4o-mini\",\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"add\",\"strict\":false,\"description\":\"Add two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiply\",\"strict\":false,\"description\":\"Multiply two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://api.openai.com/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"aa72v6\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"id\":\"call_AllxF2QWi0Tce38DKSdo8brT\",\"type\":\"function\",\"function\":{\"name\":\"add\",\"arguments\":\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"FakOnIdqvDRfm\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"a\\\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"RkovdZUnx1u\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\": 2, \"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"NsClYeAAzdtY\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"b\\\": 3\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"jsaZAq3C7\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"}\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"id\":\"call_W9zsGJWgk7F9x7M6E0v6FpyF\",\"type\":\"function\",\"function\":{\"name\":\"multiply\",\"arguments\":\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"TEWXsouM\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"{\\\"a\\\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"vXKmg4BNNJJ\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\": 2, \"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"2PXGEOdDuPBX\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"\\\"b\\\": 3\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"d9aDQUpVf\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"}\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"tool_calls\"}],\"usage\":null,\"obfuscation\":\"X2i3i29n3O4W9IS\"}\n\ndata: {\"id\":\"chatcmpl-CIYfO2YDNu3fisNPN7DOLBu1qP4ul\",\"object\":\"chat.completion.chunk\",\"created\":1758539198,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[],\"usage\":{\"prompt_tokens\":106,\"completion_tokens\":50,\"total_tokens\":156,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"wG0WXE1D\"}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream; charset=utf-8 + status: 200 OK + code: 200 + duration: 2.792789959s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1266 + 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_AllxF2QWi0Tce38DKSdo8brT\",\"function\":{\"arguments\":\"{\\\"a\\\": 2, \\\"b\\\": 3}\",\"name\":\"add\"},\"type\":\"function\"},{\"id\":\"call_W9zsGJWgk7F9x7M6E0v6FpyF\",\"function\":{\"arguments\":\"{\\\"a\\\": 2, \\\"b\\\": 3}\",\"name\":\"multiply\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"5\",\"tool_call_id\":\"call_AllxF2QWi0Tce38DKSdo8brT\",\"role\":\"tool\"},{\"content\":\"6\",\"tool_call_id\":\"call_W9zsGJWgk7F9x7M6E0v6FpyF\",\"role\":\"tool\"}],\"model\":\"gpt-4o-mini\",\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"add\",\"strict\":false,\"description\":\"Add two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiply\",\"strict\":false,\"description\":\"Multiply two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://api.openai.com/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"LpXFAjoW1\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"The\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"5unPoH2g\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" sum\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"ZVT4FK8\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" of\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"THp8TaYG\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"5dGZuwSiBy\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"2\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"B00dCJSOqC\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"9JHeCjZ\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"qLOsHITog6\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"3\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"vjJFX73IrR\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"8ckW2zLl\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"d89PZocndQ\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"5\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"YshqHR4mut\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\",\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"1BhpFb6IU7\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"61QA0re\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" the\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"C6dswtG\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" product\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"oCs\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" of\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"GPryvzOA\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"GBFgHFU12k\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"2\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"HfJbC2MozL\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"21K8iXz\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"J8T4Pc31xT\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"3\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"KFKLwPg06L\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"6SQiypmk\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"VdWZgyqxlN\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"6\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"qh7my8erhh\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\".\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"EdnL0n1syy\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"stop\"}],\"usage\":null,\"obfuscation\":\"qm3FK\"}\n\ndata: {\"id\":\"chatcmpl-CIYfQnc4yCde1WOeJ9o7ThTkLuPiY\",\"object\":\"chat.completion.chunk\",\"created\":1758539200,\"model\":\"gpt-4o-mini-2024-07-18\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_560af6e559\",\"choices\":[],\"usage\":{\"prompt_tokens\":172,\"completion_tokens\":26,\"total_tokens\":198,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"NKBLSjTg\"}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream; charset=utf-8 + status: 200 OK + code: 200 + duration: 1.05307025s diff --git a/providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o.yaml b/providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o.yaml new file mode 100644 index 0000000000000000000000000000000000000000..e937f1463f616b3c0994e9d4305f35bae70300ed --- /dev/null +++ b/providertests/testdata/TestStreamWithMultipleTools/openai-gpt-4o.yaml @@ -0,0 +1,61 @@ +--- +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. Always use both add and multiply at the same time.\",\"role\":\"system\"},{\"content\":\"Add and multiply the number 2 and 3\",\"role\":\"user\"}],\"model\":\"gpt-4o\",\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"add\",\"strict\":false,\"description\":\"Add two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiply\",\"strict\":false,\"description\":\"Multiply two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://api.openai.com/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"ml8zhwYvriy\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"id\":\"call_c9ycbTtTLCKR4214Fv4yvbcO\",\"type\":\"function\",\"function\":{\"name\":\"add\",\"arguments\":\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"4Z\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"a\\\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\": 2, \"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"e\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"b\\\": 3\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"5e7srrTAkj7qW1\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"}\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"XH6sN\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"id\":\"call_CIlNthDS1SkYh3ep4iHDeu4Z\",\"type\":\"function\",\"function\":{\"name\":\"multiply\",\"arguments\":\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"n8BLeLWCiVijG\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"{\\\"a\\\"\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\": 2, \"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"e\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"\\\"b\\\": 3\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"3PBAGUvFgBPJ6m\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"usage\":null,\"choices\":[{\"index\":0,\"delta\":{\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"}\"}}]},\"logprobs\":null,\"finish_reason\":null}],\"obfuscation\":\"gsg2x\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"tool_calls\"}],\"usage\":null,\"obfuscation\":\"SYOQ\"}\n\ndata: {\"id\":\"chatcmpl-CIYfKFiz4LEais1lpygdWyr6fXzrM\",\"object\":\"chat.completion.chunk\",\"created\":1758539194,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[],\"usage\":{\"prompt_tokens\":106,\"completion_tokens\":50,\"total_tokens\":156,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"wTICV91saAoPW\"}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream; charset=utf-8 + status: 200 OK + code: 200 + duration: 1.897076542s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1261 + 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_c9ycbTtTLCKR4214Fv4yvbcO\",\"function\":{\"arguments\":\"{\\\"a\\\": 2, \\\"b\\\": 3}\",\"name\":\"add\"},\"type\":\"function\"},{\"id\":\"call_CIlNthDS1SkYh3ep4iHDeu4Z\",\"function\":{\"arguments\":\"{\\\"a\\\": 2, \\\"b\\\": 3}\",\"name\":\"multiply\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"5\",\"tool_call_id\":\"call_c9ycbTtTLCKR4214Fv4yvbcO\",\"role\":\"tool\"},{\"content\":\"6\",\"tool_call_id\":\"call_CIlNthDS1SkYh3ep4iHDeu4Z\",\"role\":\"tool\"}],\"model\":\"gpt-4o\",\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"add\",\"strict\":false,\"description\":\"Add two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiply\",\"strict\":false,\"description\":\"Multiply two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"}],\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://api.openai.com/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"refusal\":null},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"3g2hGn6D34kt2y\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"The\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"0Z3VR0erkUhmq\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" result\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"0x8NdBh0i\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" of\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"WbZyfzk1KTgFS\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" adding\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"1f7IlODXu\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"WihERktKgNeuqLs\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"2\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"MVVMviEnq7qEQET\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"mLf5Zd9pWVtM\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"rg3gY0s7GhYr2MG\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"3\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"jBJfCcnENbpRybt\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"dHItIK1s6Ejre\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"0pz9YyyHoQVDsM6\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"5\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"DyKcIysIdChycXR\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\",\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"KHDdQ8bss7RqEiE\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"n6q3twKLSRZ7\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" the\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"LlHxE2vHnWEv\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" result\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"RomUQeGLW\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" of\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"bAfSH7N7YerEq\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" multiplying\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"2800\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"if3X82l0Y7Ui1jn\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"2\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"HT4wshBEhjRTDJ6\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" and\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"rGzuNfqg4d1t\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"LbslVSrgCXRJta8\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"3\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"trdZhyDZP9RIBRh\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" is\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"lIEPqyBOnoBUY\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\" \"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"5OIHswd8zK8TI90\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\"6\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"yqubPfg2gsLOYLp\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{\"content\":\".\"},\"logprobs\":null,\"finish_reason\":null}],\"usage\":null,\"obfuscation\":\"DbwzUBOSobogSmv\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[{\"index\":0,\"delta\":{},\"logprobs\":null,\"finish_reason\":\"stop\"}],\"usage\":null,\"obfuscation\":\"zLJnDuuUzT\"}\n\ndata: {\"id\":\"chatcmpl-CIYfMcNCnjwH8CTVFp8exAYZ3aFuG\",\"object\":\"chat.completion.chunk\",\"created\":1758539196,\"model\":\"gpt-4o-2024-08-06\",\"service_tier\":\"default\",\"system_fingerprint\":\"fp_f33640a400\",\"choices\":[],\"usage\":{\"prompt_tokens\":172,\"completion_tokens\":28,\"total_tokens\":200,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"audio_tokens\":0,\"accepted_prediction_tokens\":0,\"rejected_prediction_tokens\":0}},\"obfuscation\":\"8aKUzHDU7u7QC\"}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream; charset=utf-8 + status: 200 OK + code: 200 + duration: 1.279416208s diff --git a/providertests/testdata/TestStreamWithMultipleTools/openrouter-kimi-k2.yaml b/providertests/testdata/TestStreamWithMultipleTools/openrouter-kimi-k2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..4d8e5afff065d64d76ef6162989e9ef637a0e51b --- /dev/null +++ b/providertests/testdata/TestStreamWithMultipleTools/openrouter-kimi-k2.yaml @@ -0,0 +1,61 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 872 + 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\":\"moonshotai/kimi-k2-0905\",\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"add\",\"strict\":false,\"description\":\"Add two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiply\",\"strict\":false,\"description\":\"Multiply two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"I'll\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" perform\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" both\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" operations\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" with\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" the\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" numbers\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"2\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" and\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"3\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\".\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"call_o1p1wrhufp6epnj7d8ku3n7b\",\"type\":\"function\",\"function\":{\"name\":\"add\",\"arguments\":\"\"}}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"a\\\":2,\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\"b\\\":3}\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":1,\"id\":\"call_2p8ey5itezput2hlazmx9esq\",\"type\":\"function\",\"function\":{\"name\":\"multiply\",\"arguments\":\"\"}}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"{\\\"a\\\":2,\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":1,\"function\":{\"arguments\":\"\\\"b\\\":3}\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"tool_calls\",\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539206-imjPEWEpXTKCNbw94ywy\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539206,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":218,\"completion_tokens\":54,\"total_tokens\":272,\"cost\":0.00038,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.000218,\"upstream_inference_completions_cost\":0.000162},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 2.540430708s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 1364 + 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 perform both operations with the numbers 2 and 3.\",\"tool_calls\":[{\"id\":\"call_o1p1wrhufp6epnj7d8ku3n7b\",\"function\":{\"arguments\":\"{\\\"a\\\":2,\\\"b\\\":3}\",\"name\":\"add\"},\"type\":\"function\"},{\"id\":\"call_2p8ey5itezput2hlazmx9esq\",\"function\":{\"arguments\":\"{\\\"a\\\":2,\\\"b\\\":3}\",\"name\":\"multiply\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"5\",\"tool_call_id\":\"call_o1p1wrhufp6epnj7d8ku3n7b\",\"role\":\"tool\"},{\"content\":\"6\",\"tool_call_id\":\"call_2p8ey5itezput2hlazmx9esq\",\"role\":\"tool\"}],\"model\":\"moonshotai/kimi-k2-0905\",\"stream_options\":{\"include_usage\":true},\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"add\",\"strict\":false,\"description\":\"Add two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"},{\"function\":{\"name\":\"multiply\",\"strict\":false,\"description\":\"Multiply two numbers\",\"parameters\":{\"properties\":{\"a\":{\"description\":\"first number\",\"type\":\"integer\"},\"b\":{\"description\":\"second number\",\"type\":\"integer\"}},\"required\":[\"a\",\"b\"],\"type\":\"object\"}},\"type\":\"function\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"The\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" results\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" are\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\":\\n\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"-\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" Addition\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\":\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"2\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" +\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"3\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" =\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"5\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \\n\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"-\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" Multi\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"plication\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\":\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"2\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" ×\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"3\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" =\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"6\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"stop\",\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758539210-2a8JjOltIpd8OEhwS0bf\",\"provider\":\"Together\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758539210,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":399,\"completion_tokens\":29,\"total_tokens\":428,\"cost\":0.000486,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.000399,\"upstream_inference_completions_cost\":0.000087},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.629816208s diff --git a/providertests/testdata/TestStreamWithTools/openrouter-kimi-k2.yaml b/providertests/testdata/TestStreamWithTools/openrouter-kimi-k2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..3ce2d06ac370ec6482425512febc5ecb4fb18076 --- /dev/null +++ b/providertests/testdata/TestStreamWithTools/openrouter-kimi-k2.yaml @@ -0,0 +1,90 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 569 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant. Use the add tool to perform calculations.\",\"role\":\"system\"},{\"content\":\"What is 15 + 27?\",\"role\":\"user\"}],\"model\":\"moonshotai/kimi-k2-0905\",\"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\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"I'll\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" use\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" the\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" add\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" tool\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" to\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" calculate\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"15\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" +\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"27\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" for\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" you\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\".\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"id\":\"add:0\",\"type\":\"function\",\"function\":{\"name\":\"add\",\"arguments\":\"\"}}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"{\\\"\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"a\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\":\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\" \"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"15\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\",\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\" \\\"\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"b\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"\\\":\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\" \"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"27\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"index\":0,\"function\":{\"arguments\":\"}\"},\"type\":\"function\"}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"tool_calls\",\"logprobs\":null}],\"system_fingerprint\":\"fpv0_ec889fbb\"}\n\ndata: {\"id\":\"gen-1758536687-GEdmyOeqMtsBHOOX9yf0\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536687,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":95,\"completion_tokens\":36,\"total_tokens\":131,\"cost\":0.000294,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.000114,\"upstream_inference_completions_cost\":0.00018},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.329810959s +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 819 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant. Use the add tool to perform calculations.\",\"role\":\"system\"},{\"content\":\"What is 15 + 27?\",\"role\":\"user\"},{\"content\":\"I'll use the add tool to calculate 15 + 27 for you.\",\"tool_calls\":[{\"id\":\"add:0\",\"function\":{\"arguments\":\"{\\\"a\\\": 15, \\\"b\\\": 27}\",\"name\":\"add\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"42\",\"tool_call_id\":\"add:0\",\"role\":\"tool\"}],\"model\":\"moonshotai/kimi-k2-0905\",\"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\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "{\"error\":{\"message\":\"Provider returned error\",\"code\":429,\"metadata\":{\"raw\":\"moonshotai/kimi-k2-0905 is temporarily rate-limited upstream. Please retry shortly, or add your own key to accumulate your rate limits: https://openrouter.ai/settings/integrations\",\"provider_name\":\"GMICloud\"}},\"user_id\":\"user_2zMGmKqlf4zmAvL9snVImB1Z1ZQ\"}" + headers: + Content-Type: + - application/json + status: 429 Too Many Requests + code: 429 + duration: 1.30477125s +- id: 2 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 819 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant. Use the add tool to perform calculations.\",\"role\":\"system\"},{\"content\":\"What is 15 + 27?\",\"role\":\"user\"},{\"content\":\"I'll use the add tool to calculate 15 + 27 for you.\",\"tool_calls\":[{\"id\":\"add:0\",\"function\":{\"arguments\":\"{\\\"a\\\": 15, \\\"b\\\": 27}\",\"name\":\"add\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"42\",\"tool_call_id\":\"add:0\",\"role\":\"tool\"}],\"model\":\"moonshotai/kimi-k2-0905\",\"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\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"15\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" +\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"27\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" =\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"42\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":\"stop\",\"native_finish_reason\":\"stop\",\"logprobs\":null}],\"system_fingerprint\":\"fpv0_f0f625a1\"}\n\ndata: {\"id\":\"gen-1758536691-22vujk3K5zhcbawSIEiY\",\"provider\":\"Novita\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion.chunk\",\"created\":1758536691,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":148,\"completion_tokens\":8,\"total_tokens\":156,\"cost\":0.0001088,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.0000888,\"upstream_inference_completions_cost\":0.00002},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 1.578136708s diff --git a/providertests/testdata/TestThinking/openrouter-glm-4.5.yaml b/providertests/testdata/TestThinking/openrouter-glm-4.5.yaml new file mode 100644 index 0000000000000000000000000000000000000000..c26da2ef9c2224d062b371c41ddbb8de805570ef --- /dev/null +++ b/providertests/testdata/TestThinking/openrouter-glm-4.5.yaml @@ -0,0 +1,63 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 492 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What's the weather in Florence, Italy?\",\"role\":\"user\"}],\"model\":\"z-ai/glm-4.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\":{\"effort\":\"high\"},\"usage\":{\"include\":true}}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: "\n \n\n \n\n \n\n \n{\"id\":\"gen-1758536669-kDbFFtgS3dhGI6ZUw7ol\",\"provider\":\"GMICloud\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion\",\"created\":1758536669,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"tool_calls\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"\\nI'll get the weather information for Florence, Italy for you.\\n\",\"refusal\":null,\"reasoning\":\"\\nThe 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 \\\"Florence, Italy\\\" as the location, so I have all the required parameters to make the function call.\",\"tool_calls\":[{\"id\":\"call_c6a0fd78f7464050b77daa19\",\"index\":0,\"type\":\"function\",\"function\":{\"name\":\"weather\",\"arguments\":\"{\\\"location\\\": \\\"Florence, Italy\\\"}\"}}],\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"\\nThe 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 \\\"Florence, Italy\\\" as the location, so I have all the required parameters to make the function call.\",\"format\":\"unknown\",\"index\":0}]}}],\"usage\":{\"prompt_tokens\":178,\"completion_tokens\":87,\"total_tokens\":265,\"cost\":0.0002982,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.0001068,\"upstream_inference_completions_cost\":0.0001914},\"completion_tokens_details\":{\"reasoning_tokens\":66,\"image_tokens\":0}}}" + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 554.67ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 823 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What's the weather in Florence, Italy?\",\"role\":\"user\"},{\"content\":\"\\nI'll get the weather information for Florence, Italy for you.\\n\",\"tool_calls\":[{\"id\":\"call_c6a0fd78f7464050b77daa19\",\"function\":{\"arguments\":\"{\\\"location\\\": \\\"Florence, Italy\\\"}\",\"name\":\"weather\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"40 C\",\"tool_call_id\":\"call_c6a0fd78f7464050b77daa19\",\"role\":\"tool\"}],\"model\":\"z-ai/glm-4.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\":{\"effort\":\"high\"},\"usage\":{\"include\":true}}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: "\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n\n \n{\"id\":\"gen-1758536671-EDr8hEIURKuI1cJJleMd\",\"provider\":\"Novita\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion\",\"created\":1758536671,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"stop\",\"native_finish_reason\":\"stop\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"\\n\\nThe current weather in Florence, Italy is 40°C (104°F). That's quite hot - be sure to stay hydrated and seek shade if you're visiting!\",\"refusal\":null,\"reasoning\":\"The weather function returned \\\"40 C\\\" for Florence, Italy. This indicates that the current temperature in Florence, Italy is 40 degrees Celsius. This is quite warm/hot weather. I should provide this information to the user in a helpful way.\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"The weather function returned \\\"40 C\\\" for Florence, Italy. This indicates that the current temperature in Florence, Italy is 40 degrees Celsius. This is quite warm/hot weather. I should provide this information to the user in a helpful way.\",\"format\":\"unknown\",\"index\":0}]}}],\"system_fingerprint\":\"\",\"usage\":{\"prompt_tokens\":220,\"completion_tokens\":88,\"total_tokens\":308,\"cost\":0.0003256,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":43,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.000132,\"upstream_inference_completions_cost\":0.0001936},\"completion_tokens_details\":{\"reasoning_tokens\":60,\"image_tokens\":0}}}" + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 1.785684708s diff --git a/providertests/testdata/TestThinkingStreaming/openrouter-glm-4.5.yaml b/providertests/testdata/TestThinkingStreaming/openrouter-glm-4.5.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2465d391b6822df94a56d4d9ebb3e3969ca70d4e --- /dev/null +++ b/providertests/testdata/TestThinkingStreaming/openrouter-glm-4.5.yaml @@ -0,0 +1,61 @@ +--- +version: 2 +interactions: +- id: 0 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 516 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What's the weather in Florence, Italy?\",\"role\":\"user\"}],\"model\":\"z-ai/glm-4.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\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\\n\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"The\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"The\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" user\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" user\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" is\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" is\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" asking\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" asking\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" for\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" for\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" the\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" the\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" weather\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" weather\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" in\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" in\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" Florence\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" Florence\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\",\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\",\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" Italy\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" Italy\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" I\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" I\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" have\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" have\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" access\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" access\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" to\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" to\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" a\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" a\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" weather\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" weather\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" function\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" function\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" that\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" that\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" takes\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" takes\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" a\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" a\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" location\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" location\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" parameter\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" parameter\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" The\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" The\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" user\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" user\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" has\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" has\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" specified\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" specified\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" \\\"\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" \\\"\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"Flo\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"Flo\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"rence\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"rence\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\",\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\",\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" Italy\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" Italy\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"\\\"\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"\\\"\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" as\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" as\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" the\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" the\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" location\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" location\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" I\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" I\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" should\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" should\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" call\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" call\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" the\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" the\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" weather\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" weather\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" function\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" function\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" with\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" with\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" this\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" this\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" exact\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" exact\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" location\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" location\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\\n\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":null,\"tool_calls\":[{\"id\":\"chatcmpl-tool-61cc1c29b8e048c9b98c1defbb7117d2\",\"type\":\"function\",\"index\":0,\"function\":{\"name\":\"weather\",\"arguments\":\"{\\\"location\\\": \\\"Florence, Italy\\\"}\"}}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"tool_calls\",\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536678-FfvjBGpaoGzh1AiCxQuh\",\"provider\":\"WandB\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536678,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":187,\"completion_tokens\":70,\"total_tokens\":257,\"cost\":0.00024285,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":32,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.00010285,\"upstream_inference_completions_cost\":0.00014},\"completion_tokens_details\":{\"reasoning_tokens\":61,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 405.284125ms +- id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 820 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What's the weather in Florence, Italy?\",\"role\":\"user\"},{\"content\":\"\\n\\n\",\"tool_calls\":[{\"id\":\"chatcmpl-tool-61cc1c29b8e048c9b98c1defbb7117d2\",\"function\":{\"arguments\":\"{\\\"location\\\": \\\"Florence, Italy\\\"}\",\"name\":\"weather\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"40 C\",\"tool_call_id\":\"chatcmpl-tool-61cc1c29b8e048c9b98c1defbb7117d2\",\"role\":\"tool\"}],\"model\":\"z-ai/glm-4.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\"}],\"usage\":{\"include\":true},\"stream\":true}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + body: "data: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\\n\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"The\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"The\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" weather\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" weather\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" function\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" function\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" returned\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" returned\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" \\\"\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" \\\"\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"40\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"40\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" C\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" C\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"\\\"\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"\\\"\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" for\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" for\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" Florence\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" Florence\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\",\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\",\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" Italy\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" Italy\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" This\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" This\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" indicates\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" indicates\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" the\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" the\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" current\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" current\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" temperature\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" temperature\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" is\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" is\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" \",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" \",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\"40\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\"40\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" degrees\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" degrees\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" Celsius\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" Celsius\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\",\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\",\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" which\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" which\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" is\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" is\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" quite\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" quite\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" hot\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" hot\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" -\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" -\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" summer\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" summer\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" weather\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" weather\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" conditions\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" conditions\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" I\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" I\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" should\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" should\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" provide\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" provide\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" this\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" this\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" information\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" information\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" to\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" to\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" the\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" the\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" user\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" user\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" in\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" in\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" a\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" a\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" clear\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" clear\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" and\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" and\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" helpful\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" helpful\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\" way\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\" way\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":\".\",\"reasoning_details\":[{\"type\":\"reasoning.text\",\"text\":\".\",\"format\":\"unknown\",\"index\":0}]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\\n\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"The\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" current\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" weather\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" in\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" Florence\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\",\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" Italy\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" is\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" \",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"40\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"°C\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\".\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" That\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"'s\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" quite\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" warm\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" -\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" typical\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" summer\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" weather\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" for\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\" Florence\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"!\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\",\"reasoning\":null,\"reasoning_details\":[]},\"finish_reason\":\"stop\",\"native_finish_reason\":\"stop\",\"logprobs\":null}]}\n\ndata: {\"id\":\"gen-1758536680-9FbpzAyhRyIN0W0bUDnx\",\"provider\":\"Z.AI\",\"model\":\"z-ai/glm-4.5\",\"object\":\"chat.completion.chunk\",\"created\":1758536680,\"choices\":[{\"index\":0,\"delta\":{\"role\":\"assistant\",\"content\":\"\"},\"finish_reason\":null,\"native_finish_reason\":null,\"logprobs\":null}],\"usage\":{\"prompt_tokens\":207,\"completion_tokens\":76,\"total_tokens\":283,\"cost\":0.00027033,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":43,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.00010313,\"upstream_inference_completions_cost\":0.0001672},\"completion_tokens_details\":{\"reasoning_tokens\":61,\"image_tokens\":0}}}\n\ndata: [DONE]\n\n" + headers: + Content-Type: + - text/event-stream + status: 200 OK + code: 200 + duration: 3.121796917s diff --git a/providertests/testdata/TestTool/openrouter-kimi-k2.yaml b/providertests/testdata/TestTool/openrouter-kimi-k2.yaml new file mode 100644 index 0000000000000000000000000000000000000000..2f9465a7a352b1a26d1720b3a059b116b256180a --- /dev/null +++ b/providertests/testdata/TestTool/openrouter-kimi-k2.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?","role":"user"}],"model":"moonshotai/kimi-k2-0905","tool_choice":"auto","tools":[{"function":{"name":"weather","strict":false,"description":"Get weather information for a location","parameters":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"}},"type":"function"}],"usage":{"include":true}}' + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: "\n \n\n \n\n \n\n \n\n \n\n \n{\"id\":\"gen-1758536664-UaCYJMs4TUDzzENXVnwe\",\"provider\":\"Moonshot AI\",\"model\":\"moonshotai/kimi-k2-0905\",\"object\":\"chat.completion\",\"created\":1758536664,\"choices\":[{\"logprobs\":null,\"finish_reason\":\"tool_calls\",\"native_finish_reason\":\"tool_calls\",\"index\":0,\"message\":{\"role\":\"assistant\",\"content\":\"I'll check the weather in Florence for you.\",\"refusal\":null,\"reasoning\":null,\"tool_calls\":[{\"index\":0,\"id\":\"weather:0\",\"type\":\"function\",\"function\":{\"name\":\"weather\",\"arguments\":\"{\\\"location\\\": \\\"Florence\\\"}\"}}]}}],\"system_fingerprint\":\"fpv0_f0f625a1\",\"usage\":{\"prompt_tokens\":74,\"completion_tokens\":27,\"total_tokens\":101,\"cost\":0.0001119,\"is_byok\":false,\"prompt_tokens_details\":{\"cached_tokens\":0,\"audio_tokens\":0},\"cost_details\":{\"upstream_inference_cost\":null,\"upstream_inference_prompt_cost\":0.0000444,\"upstream_inference_completions_cost\":0.0000675},\"completion_tokens_details\":{\"reasoning_tokens\":0,\"image_tokens\":0}}}" + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 1.69516625s + - id: 1 + request: + proto: HTTP/1.1 + proto_major: 1 + proto_minor: 1 + content_length: 728 + host: "" + body: "{\"messages\":[{\"content\":\"You are a helpful assistant\",\"role\":\"system\"},{\"content\":\"What's the weather in Florence?\",\"role\":\"user\"},{\"content\":\"I'll check the weather in Florence for you.\",\"tool_calls\":[{\"id\":\"weather:0\",\"function\":{\"arguments\":\"{\\\"location\\\": \\\"Florence\\\"}\",\"name\":\"weather\"},\"type\":\"function\"}],\"role\":\"assistant\"},{\"content\":\"40 C\",\"tool_call_id\":\"weather:0\",\"role\":\"tool\"}],\"model\":\"moonshotai/kimi-k2-0905\",\"tool_choice\":\"auto\",\"tools\":[{\"function\":{\"name\":\"weather\",\"strict\":false,\"description\":\"Get weather information for a location\",\"parameters\":{\"properties\":{\"location\":{\"description\":\"the city\",\"type\":\"string\"}},\"required\":[\"location\"],\"type\":\"object\"}},\"type\":\"function\"}],\"usage\":{\"include\":true}}" + headers: + Accept: + - application/json + Content-Type: + - application/json + User-Agent: + - OpenAI/Go 2.3.0 + url: https://openrouter.ai/api/v1/chat/completions + method: POST + response: + proto: HTTP/2.0 + proto_major: 2 + proto_minor: 0 + content_length: -1 + uncompressed: true + body: '{"id":"gen-1758536667-pQdDoWxSJHoNqbKNl5gW","provider":"Novita","model":"moonshotai/kimi-k2-0905","object":"chat.completion","created":1758536667,"choices":[{"logprobs":null,"finish_reason":"stop","native_finish_reason":"stop","index":0,"message":{"role":"assistant","content":"The weather in Florence is currently 40°C (104°F). It`s quite hot there!","refusal":null,"reasoning":null}}],"system_fingerprint":"fpv0_f0f625a1","usage":{"prompt_tokens":120,"completion_tokens":19,"total_tokens":139,"cost":0.0001195,"is_byok":false,"prompt_tokens_details":{"cached_tokens":0,"audio_tokens":0},"cost_details":{"upstream_inference_cost":null,"upstream_inference_prompt_cost":0.000072,"upstream_inference_completions_cost":0.0000475},"completion_tokens_details":{"reasoning_tokens":0,"image_tokens":0}}}' + headers: + Content-Type: + - application/json + status: 200 OK + code: 200 + duration: 1.608302625s diff --git a/providertests/thinking_test.go b/providertests/thinking_test.go index e4a9363be4937f3e3ed80468a3527a6c54016e13..8b9c8f4824c781596d4f6ccdbad929bbd51ec309 100644 --- a/providertests/thinking_test.go +++ b/providertests/thinking_test.go @@ -1,20 +1,24 @@ package providertests import ( + "fmt" "testing" "github.com/charmbracelet/fantasy/ai" "github.com/charmbracelet/fantasy/anthropic" "github.com/charmbracelet/fantasy/google" + "github.com/charmbracelet/fantasy/openrouter" "github.com/stretchr/testify/require" ) -func testThinkingSteps(t *testing.T, providerName string, steps []ai.StepResult) { +func testThinking(t *testing.T, providerName string, steps []ai.StepResult) { switch providerName { case anthropic.Name: testAnthropicThinking(t, steps) case google.Name: testGoogleThinking(t, steps) + case openrouter.Name: + testOpenrouterThinking(t, steps) } } @@ -33,6 +37,22 @@ func testGoogleThinking(t *testing.T, steps []ai.StepResult) { require.Greater(t, reasoningContentCount, 0) } +func testOpenrouterThinking(t *testing.T, steps []ai.StepResult) { + reasoningContentCount := 0 + // Test if we got the signature + for _, step := range steps { + for _, msg := range step.Messages { + for _, content := range msg.Content { + if content.GetType() == ai.ContentTypeReasoning { + reasoningContentCount += 1 + } + } + } + } + fmt.Println(reasoningContentCount) + require.Greater(t, reasoningContentCount, 0) +} + func testAnthropicThinking(t *testing.T, steps []ai.StepResult) { reasoningContentCount := 0 signaturesCount := 0