mirror of
https://github.com/router-for-me/CLIProxyAPIPlus.git
synced 2026-03-08 06:43:41 +00:00
feat(thinking): improve provider family checks and clamp unsupported levels
This commit is contained in:
@@ -53,7 +53,17 @@ func ValidateConfig(config ThinkingConfig, modelInfo *registry.ModelInfo, fromFo
|
||||
return &config, nil
|
||||
}
|
||||
|
||||
allowClampUnsupported := isBudgetBasedProvider(fromFormat) && isLevelBasedProvider(toFormat)
|
||||
// allowClampUnsupported determines whether to clamp unsupported levels instead of returning an error.
|
||||
// This applies when crossing provider families (e.g., openai→gemini, claude→gemini) and the target
|
||||
// model supports discrete levels. Same-family conversions require strict validation.
|
||||
toCapability := detectModelCapability(modelInfo)
|
||||
toHasLevelSupport := toCapability == CapabilityLevelOnly || toCapability == CapabilityHybrid
|
||||
allowClampUnsupported := toHasLevelSupport && !isSameProviderFamily(fromFormat, toFormat)
|
||||
|
||||
// strictBudget determines whether to enforce strict budget range validation.
|
||||
// This applies when: (1) config comes from request body (not suffix), (2) source format is known,
|
||||
// and (3) source and target are in the same provider family. Cross-family or suffix-based configs
|
||||
// are clamped instead of rejected to improve interoperability.
|
||||
strictBudget := !fromSuffix && fromFormat != "" && isSameProviderFamily(fromFormat, toFormat)
|
||||
budgetDerivedFromLevel := false
|
||||
|
||||
@@ -352,11 +362,21 @@ func isGeminiFamily(provider string) bool {
|
||||
}
|
||||
}
|
||||
|
||||
func isOpenAIFamily(provider string) bool {
|
||||
switch provider {
|
||||
case "openai", "openai-response", "codex":
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func isSameProviderFamily(from, to string) bool {
|
||||
if from == to {
|
||||
return true
|
||||
}
|
||||
return isGeminiFamily(from) && isGeminiFamily(to)
|
||||
return (isGeminiFamily(from) && isGeminiFamily(to)) ||
|
||||
(isOpenAIFamily(from) && isOpenAIFamily(to))
|
||||
}
|
||||
|
||||
func abs(x int) int {
|
||||
|
||||
@@ -386,15 +386,17 @@ func TestThinkingE2EMatrix_Suffix(t *testing.T) {
|
||||
includeThoughts: "true",
|
||||
expectErr: false,
|
||||
},
|
||||
// Case 30: Effort xhigh → not in low/high → error
|
||||
// Case 30: Effort xhigh → clamped to high
|
||||
{
|
||||
name: "30",
|
||||
from: "openai",
|
||||
to: "gemini",
|
||||
model: "gemini-mixed-model(xhigh)",
|
||||
inputJSON: `{"model":"gemini-mixed-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`,
|
||||
expectField: "",
|
||||
expectErr: true,
|
||||
name: "30",
|
||||
from: "openai",
|
||||
to: "gemini",
|
||||
model: "gemini-mixed-model(xhigh)",
|
||||
inputJSON: `{"model":"gemini-mixed-model(xhigh)","messages":[{"role":"user","content":"hi"}]}`,
|
||||
expectField: "generationConfig.thinkingConfig.thinkingLevel",
|
||||
expectValue: "high",
|
||||
includeThoughts: "true",
|
||||
expectErr: false,
|
||||
},
|
||||
// Case 31: Effort none → clamped to low (min supported) → includeThoughts=false
|
||||
{
|
||||
@@ -1668,15 +1670,17 @@ func TestThinkingE2EMatrix_Body(t *testing.T) {
|
||||
includeThoughts: "true",
|
||||
expectErr: false,
|
||||
},
|
||||
// Case 30: reasoning_effort=xhigh → error (not in low/high)
|
||||
// Case 30: reasoning_effort=xhigh → clamped to high
|
||||
{
|
||||
name: "30",
|
||||
from: "openai",
|
||||
to: "gemini",
|
||||
model: "gemini-mixed-model",
|
||||
inputJSON: `{"model":"gemini-mixed-model","messages":[{"role":"user","content":"hi"}],"reasoning_effort":"xhigh"}`,
|
||||
expectField: "",
|
||||
expectErr: true,
|
||||
name: "30",
|
||||
from: "openai",
|
||||
to: "gemini",
|
||||
model: "gemini-mixed-model",
|
||||
inputJSON: `{"model":"gemini-mixed-model","messages":[{"role":"user","content":"hi"}],"reasoning_effort":"xhigh"}`,
|
||||
expectField: "generationConfig.thinkingConfig.thinkingLevel",
|
||||
expectValue: "high",
|
||||
includeThoughts: "true",
|
||||
expectErr: false,
|
||||
},
|
||||
// Case 31: reasoning_effort=none → clamped to low → includeThoughts=false
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user