package executor import ( "context" "io" "net/http" "net/http/httptest" "testing" "github.com/router-for-me/CLIProxyAPI/v7/internal/config" "github.com/router-for-me/CLIProxyAPI/v7/internal/registry" cliproxyauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth" cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/executor" sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator" "github.com/tidwall/gjson") func TestOpenAICompatExecutorUsesCompatibleClaudeTranslation(t *testing.T) { var upstreamBody []byte server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { upstreamBody, _ = io.ReadAll(r.Body) w.Header().Set("Content-Type", "application/json") _, _ = w.Write([]byte(`{"id":"chatcmpl-test","object":"chat.completion","choices":[{"index":0,"message":{"role":"assistant","content":"ok"},"finish_reason":"stop"}]}`)) })) defer server.Close() executor := NewOpenAICompatExecutor("openai-compatibility", &config.Config{}) auth := &cliproxyauth.Auth{ Provider: "openai-compatibility", Attributes: map[string]string{ "base_url": server.URL, "api_key": "test-key", }, } request := cliproxyexecutor.Request{ Model: "deepseek-v4-flash", Payload: []byte(`{"model":"deepseek-v4-flash","messages":[{"role":"assistant","content":[{"type":"thinking","thinking":"prior reasoning","signature":""},{"type":"tool_use","id":"call_1","name":"Read","input":{}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"call_1","content":"ok"}]}]}`), Metadata: map[string]any{ "cliproxy.resolved_api_key_model_info": ®istry.ModelInfo{IsCompat: true}, }, } options := cliproxyexecutor.Options{ SourceFormat: sdktranslator.FormatClaude, ResponseFormat: sdktranslator.FormatOpenAI, } if _, errExecute := executor.Execute(context.Background(), auth, request, options); errExecute != nil { t.Fatalf("Execute error: %v", errExecute) } assistant := gjson.GetBytes(upstreamBody, "messages.0") if got := assistant.Get("reasoning_content").String(); got != "prior reasoning" { t.Fatalf("reasoning_content = %q, want %q; body=%s", got, "prior reasoning", upstreamBody) } if !assistant.Get("tool_calls").Exists() { t.Fatalf("tool_calls missing from upstream request: %s", upstreamBody) }}
package executor
import (
"context"
"io"
"net/http"
"net/http/httptest"
"testing"
"github.com/router-for-me/CLIProxyAPI/v7/internal/config"
"github.com/router-for-me/CLIProxyAPI/v7/internal/registry"
cliproxyauth "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/auth"
cliproxyexecutor "github.com/router-for-me/CLIProxyAPI/v7/sdk/cliproxy/executor"
sdktranslator "github.com/router-for-me/CLIProxyAPI/v7/sdk/translator"
"github.com/tidwall/gjson"
)
func TestOpenAICompatExecutorUsesCompatibleClaudeTranslation(t *testing.T) {
var upstreamBody []byte
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
upstreamBody, _ = io.ReadAll(r.Body)
w.Header().Set("Content-Type", "application/json")
_, _ = w.Write([]byte(`{"id":"chatcmpl-test","object":"chat.completion","choices":[{"index":0,"message":{"role":"assistant","content":"ok"},"finish_reason":"stop"}]}`))
}))
defer server.Close()
executor := NewOpenAICompatExecutor("openai-compatibility", &config.Config{})
auth := &cliproxyauth.Auth{
Provider: "openai-compatibility",
Attributes: map[string]string{
"base_url": server.URL,
"api_key": "test-key",
},
}
request := cliproxyexecutor.Request{
Model: "deepseek-v4-flash",
Payload: []byte(`{"model":"deepseek-v4-flash","messages":[{"role":"assistant","content":[{"type":"thinking","thinking":"prior reasoning","signature":""},{"type":"tool_use","id":"call_1","name":"Read","input":{}}]},{"role":"user","content":[{"type":"tool_result","tool_use_id":"call_1","content":"ok"}]}]}`),
Metadata: map[string]any{
"cliproxy.resolved_api_key_model_info": ®istry.ModelInfo{IsCompat: true},
},
}
options := cliproxyexecutor.Options{
SourceFormat: sdktranslator.FormatClaude,
ResponseFormat: sdktranslator.FormatOpenAI,
}
if _, errExecute := executor.Execute(context.Background(), auth, request, options); errExecute != nil {
t.Fatalf("Execute error: %v", errExecute)
}
assistant := gjson.GetBytes(upstreamBody, "messages.0")
if got := assistant.Get("reasoning_content").String(); got != "prior reasoning" {
t.Fatalf("reasoning_content = %q, want %q; body=%s", got, "prior reasoning", upstreamBody)
}
if !assistant.Get("tool_calls").Exists() {
t.Fatalf("tool_calls missing from upstream request: %s", upstreamBody)
}
}