Add projects
This commit is contained in:
parent
2d3a9ad623
commit
8b607dd700
1802 changed files with 503346 additions and 2 deletions
258
backend/sdk/translator/registry_summary_test.go
Normal file
258
backend/sdk/translator/registry_summary_test.go
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
package translator
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"testing"
|
||||
|
||||
"github.com/tidwall/gjson"
|
||||
"github.com/tidwall/sjson"
|
||||
)
|
||||
|
||||
func TestRegistryTranslateRequestAppliesSummaryIntent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
from Format
|
||||
to Format
|
||||
input string
|
||||
translated string
|
||||
path string
|
||||
want string
|
||||
wantExists bool
|
||||
}{
|
||||
{
|
||||
name: "chat effort enables Claude summary",
|
||||
from: FormatOpenAI,
|
||||
to: FormatClaude,
|
||||
input: `{"reasoning_effort":"high"}`,
|
||||
translated: `{"thinking":{"type":"adaptive"}}`,
|
||||
path: "thinking.display",
|
||||
want: "summarized",
|
||||
wantExists: true,
|
||||
},
|
||||
{
|
||||
name: "responses effort alone leaves Claude display absent",
|
||||
from: FormatOpenAIResponse,
|
||||
to: FormatClaude,
|
||||
input: `{"reasoning":{"effort":"high"}}`,
|
||||
translated: `{"thinking":{"type":"adaptive"}}`,
|
||||
path: "thinking.display",
|
||||
},
|
||||
{
|
||||
name: "responses summary enables Claude summary",
|
||||
from: FormatOpenAIResponse,
|
||||
to: FormatClaude,
|
||||
input: `{"reasoning":{"effort":"high","summary":"auto"}}`,
|
||||
translated: `{"thinking":{"type":"adaptive"}}`,
|
||||
path: "thinking.display",
|
||||
want: "summarized",
|
||||
wantExists: true,
|
||||
},
|
||||
{
|
||||
name: "responses null summary disables Gemini summaries",
|
||||
from: FormatOpenAIResponse,
|
||||
to: FormatGemini,
|
||||
input: `{"reasoning":{"effort":"high","summary":null}}`,
|
||||
translated: `{"generationConfig":{"thinkingConfig":{"thinkingLevel":"high"}}}`,
|
||||
path: "generationConfig.thinkingConfig.includeThoughts",
|
||||
want: "false",
|
||||
wantExists: true,
|
||||
},
|
||||
{
|
||||
name: "Google Chat extension overrides effort",
|
||||
from: FormatOpenAI,
|
||||
to: FormatGemini,
|
||||
input: `{"reasoning_effort":"high","extra_body":{"google":{"thinking_config":{"include_thoughts":false}}}}`,
|
||||
translated: `{"generationConfig":{"thinkingConfig":{"thinkingLevel":"high","includeThoughts":true}}}`,
|
||||
path: "generationConfig.thinkingConfig.includeThoughts",
|
||||
want: "false",
|
||||
wantExists: true,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
registry.Register(test.from, test.to, func(_ string, _ []byte, _ bool) []byte {
|
||||
return []byte(test.translated)
|
||||
}, ResponseTransform{})
|
||||
out := registry.TranslateRequest(test.from, test.to, "model", []byte(test.input), false)
|
||||
result := gjson.GetBytes(out, test.path)
|
||||
if result.Exists() != test.wantExists {
|
||||
t.Fatalf("%s exists = %v, want %v; body=%s", test.path, result.Exists(), test.wantExists, out)
|
||||
}
|
||||
if test.wantExists && result.String() != test.want {
|
||||
t.Fatalf("%s = %q, want %q; body=%s", test.path, result.String(), test.want, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestActivatesClaudeForEnabledSummary(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
registry.Register(FormatOpenAIResponse, FormatClaude, func(_ string, _ []byte, _ bool) []byte {
|
||||
return []byte(`{"model":"claude-opus-5","max_tokens":32000}`)
|
||||
}, ResponseTransform{})
|
||||
out := registry.TranslateRequest(
|
||||
FormatOpenAIResponse,
|
||||
FormatClaude,
|
||||
"claude-opus-5",
|
||||
[]byte(`{"reasoning":{"summary":"auto"},"input":"hi"}`),
|
||||
false,
|
||||
)
|
||||
if got := gjson.GetBytes(out, "thinking.type").String(); got != "adaptive" {
|
||||
t.Fatalf("thinking.type = %q, want adaptive; body=%s", got, out)
|
||||
}
|
||||
if got := gjson.GetBytes(out, "thinking.display").String(); got != "summarized" {
|
||||
t.Fatalf("thinking.display = %q, want summarized; body=%s", got, out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestDoesNotActivateClaudeForDisabledSummary(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
registry.Register(FormatOpenAIResponse, FormatClaude, func(_ string, _ []byte, _ bool) []byte {
|
||||
return []byte(`{"model":"claude-opus-5","max_tokens":32000}`)
|
||||
}, ResponseTransform{})
|
||||
out := registry.TranslateRequest(
|
||||
FormatOpenAIResponse,
|
||||
FormatClaude,
|
||||
"claude-opus-5",
|
||||
[]byte(`{"reasoning":{"summary":null},"input":"hi"}`),
|
||||
false,
|
||||
)
|
||||
if gjson.GetBytes(out, "thinking").Exists() {
|
||||
t.Fatalf("disabled summary activated Claude thinking: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestPreservesNativeClaudeMissingDisplay(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
body := []byte(`{"model":"claude-opus-5","thinking":{"type":"adaptive"}}`)
|
||||
out := registry.TranslateRequest(FormatClaude, FormatClaude, "claude-opus-5", body, true)
|
||||
if gjson.GetBytes(out, "thinking.display").Exists() {
|
||||
t.Fatalf("native Claude request without display gained one: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestDoesNotMixSummaryIntoFallback(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
body := []byte(`{"model":"gemini-3.6-flash","reasoning":{"summary":"auto"},"input":"hi"}`)
|
||||
out := registry.TranslateRequest(FormatOpenAIResponse, FormatGemini, "gemini-3.6-flash", body, false)
|
||||
if !bytes.Equal(out, body) {
|
||||
t.Fatalf("missing translator changed fallback body: got %s, want %s", out, body)
|
||||
}
|
||||
if gjson.GetBytes(out, "generationConfig").Exists() {
|
||||
t.Fatalf("missing translator mixed Gemini fields into Responses body: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestPluginMissDoesNotMixSummary(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
hooks := &fakePluginHooks{requestTranslateOK: false}
|
||||
registry.SetPluginHooks(hooks)
|
||||
body := []byte(`{"model":"gemini-3.6-flash","reasoning":{"summary":"auto"},"input":"hi"}`)
|
||||
out := registry.TranslateRequest(FormatOpenAIResponse, FormatGemini, "gemini-3.6-flash", body, false)
|
||||
if !bytes.Equal(out, body) {
|
||||
t.Fatalf("plugin translation miss changed fallback body: got %s, want %s", out, body)
|
||||
}
|
||||
if gjson.GetBytes(out, "generationConfig").Exists() {
|
||||
t.Fatalf("plugin translation miss mixed Gemini fields into Responses body: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestAppliesSummaryAfterPluginTranslation(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
hooks := &fakePluginHooks{
|
||||
requestTranslateBody: []byte(`{"generationConfig":{"thinkingConfig":{"thinkingLevel":"high"}}}`),
|
||||
requestTranslateOK: true,
|
||||
}
|
||||
registry.SetPluginHooks(hooks)
|
||||
out := registry.TranslateRequest(
|
||||
FormatOpenAIResponse,
|
||||
FormatGemini,
|
||||
"gemini-3.6-flash",
|
||||
[]byte(`{"reasoning":{"summary":"auto"},"input":"hi"}`),
|
||||
false,
|
||||
)
|
||||
if !gjson.GetBytes(out, "generationConfig.thinkingConfig.includeThoughts").Bool() {
|
||||
t.Fatalf("plugin-translated request lost canonical summary: %s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestPluginNormalizerOwnsSourceSummaryIntent(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
normalize func([]byte) []byte
|
||||
wantExists bool
|
||||
want bool
|
||||
}{
|
||||
{
|
||||
name: "removed summary remains absent",
|
||||
normalize: func(body []byte) []byte {
|
||||
out, _ := sjson.DeleteBytes(body, "reasoning.summary")
|
||||
return out
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "disabled summary replaces enabled intent",
|
||||
normalize: func(body []byte) []byte {
|
||||
out, _ := sjson.SetBytes(body, "reasoning.summary", nil)
|
||||
return out
|
||||
},
|
||||
wantExists: true,
|
||||
want: false,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
t.Run(test.name, func(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
hooks := &fakePluginHooks{
|
||||
normalizeRequest: test.normalize,
|
||||
requestTranslateBody: []byte(`{"generationConfig":{"thinkingConfig":{"thinkingLevel":"high"}}}`),
|
||||
requestTranslateOK: true,
|
||||
}
|
||||
registry.SetPluginHooks(hooks)
|
||||
|
||||
out := registry.TranslateRequest(
|
||||
FormatOpenAIResponse,
|
||||
FormatGemini,
|
||||
"gemini-3.6-flash",
|
||||
[]byte(`{"reasoning":{"summary":"auto"},"input":"hi"}`),
|
||||
false,
|
||||
)
|
||||
result := gjson.GetBytes(out, "generationConfig.thinkingConfig.includeThoughts")
|
||||
if result.Exists() != test.wantExists {
|
||||
t.Fatalf("includeThoughts exists = %v, want %v; body=%s", result.Exists(), test.wantExists, out)
|
||||
}
|
||||
if test.wantExists && result.Bool() != test.want {
|
||||
t.Fatalf("includeThoughts = %v, want %v; body=%s", result.Bool(), test.want, out)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestRegistryTranslateRequestNormalizerOwnsFinalSummaryField(t *testing.T) {
|
||||
registry := NewRegistry()
|
||||
registry.Register(FormatOpenAIResponse, FormatGemini, func(_ string, _ []byte, _ bool) []byte {
|
||||
return []byte(`{"generationConfig":{"thinkingConfig":{"thinkingLevel":"high"}}}`)
|
||||
}, ResponseTransform{})
|
||||
hooks := &fakePluginHooks{normalizeRequest: func(body []byte) []byte {
|
||||
if !gjson.GetBytes(body, "generationConfig.thinkingConfig.includeThoughts").Bool() {
|
||||
t.Fatalf("normalizer did not receive canonical enabled summary: %s", body)
|
||||
}
|
||||
out, _ := sjson.DeleteBytes(body, "generationConfig.thinkingConfig.includeThoughts")
|
||||
return out
|
||||
}}
|
||||
registry.SetPluginHooks(hooks)
|
||||
|
||||
out := registry.TranslateRequest(
|
||||
FormatOpenAIResponse,
|
||||
FormatGemini,
|
||||
"gemini-3.6-flash",
|
||||
[]byte(`{"reasoning":{"effort":"high","summary":"auto"},"input":"hi"}`),
|
||||
false,
|
||||
)
|
||||
if gjson.GetBytes(out, "generationConfig.thinkingConfig.includeThoughts").Exists() {
|
||||
t.Fatalf("summary post-processing overrode request normalizer: %s", out)
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue