feat: sync deployed v1.0.0-rc.38-custom.42
Sync production source including routing, billing, Astra detection and public uptime. Update custom build instructions and license packaging.
This commit is contained in:
1 parent
aa6c3f50f4
commit
ceddfd3d6b
828 files changed
+122253
-13702
No files matched your search
@@ -6,11 +6,13 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/QuantumNous/new-api/relaykit/dto"
|
||||
"github.com/QuantumNous/new-api/relaykit/types"
|
||||
)
|
||||
|
||||
type GeminiRender struct {
|
||||
Config *dto.GeminiThinkingConfig
|
||||
EffectiveEffort Effort
|
||||
Diagnostics []types.ConversionDiagnostic
|
||||
}
|
||||
|
||||
type geminiThinkingKind int
|
||||
@@ -61,46 +63,85 @@ func geminiCapabilitiesFor(model string) geminiCapabilities {
|
||||
}
|
||||
}
|
||||
|
||||
// RenderGemini maps a portable intent onto the target model's thinkingConfig.
|
||||
// The capability table only maps and clamps: budgets become levels on Gemini 3,
|
||||
// efforts become budgets on Gemini 2.5, out-of-range values are clamped, and
|
||||
// models that cannot disable thinking get their lowest setting. Every such
|
||||
// coercion is reported in Diagnostics. Errors are reserved for unknown effort
|
||||
// values and numeric overflow.
|
||||
func RenderGemini(model string, intent Intent, maxOutputTokens *uint, adapterBudgetPercentage float64) (GeminiRender, error) {
|
||||
intent, err := normalizeIntent(intent)
|
||||
intent, diagnostics, err := normalizeIntent(intent)
|
||||
if err != nil {
|
||||
return GeminiRender{}, err
|
||||
}
|
||||
if intent.IsEmpty() {
|
||||
return GeminiRender{}, nil
|
||||
return GeminiRender{Diagnostics: diagnostics}, nil
|
||||
}
|
||||
|
||||
capabilities := geminiCapabilitiesFor(model)
|
||||
if capabilities.kind == geminiThinkingNotConfigurable {
|
||||
if !intent.HasStrength() && capabilities.supportsIncludeThoughts {
|
||||
return GeminiRender{Config: &dto.GeminiThinkingConfig{IncludeThoughts: intent.IncludeThoughts}, EffectiveEffort: EffortHigh}, nil
|
||||
render := GeminiRender{Diagnostics: diagnostics}
|
||||
if capabilities.supportsIncludeThoughts {
|
||||
render.EffectiveEffort = EffortHigh
|
||||
if intent.IncludeThoughts != nil {
|
||||
render.Config = &dto.GeminiThinkingConfig{IncludeThoughts: intent.IncludeThoughts}
|
||||
}
|
||||
}
|
||||
return GeminiRender{}, fmt.Errorf("model %q does not support configurable thinking", model)
|
||||
if intent.HasStrength() || (intent.IncludeThoughts != nil && !capabilities.supportsIncludeThoughts) {
|
||||
render.Diagnostics = append(render.Diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_unsupported",
|
||||
fmt.Sprintf("model %q does not support configurable thinking; the requested thinking controls were dropped", model),
|
||||
))
|
||||
}
|
||||
return render, nil
|
||||
}
|
||||
if capabilities.kind == geminiThinkingUnknown {
|
||||
// Without a capability entry there is no way to know whether the model
|
||||
// takes a budget or a level, so no strength is synthesized. Provider-
|
||||
// native controls the client sent stay untouched by the caller.
|
||||
render := GeminiRender{Diagnostics: diagnostics}
|
||||
if intent.HasStrength() {
|
||||
return GeminiRender{}, fmt.Errorf("model %q does not have a known Gemini thinking configuration", model)
|
||||
render.Diagnostics = append(render.Diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_unknown_capability",
|
||||
fmt.Sprintf("model %q has no known Gemini thinking configuration; the requested thinking strength was not applied", model),
|
||||
))
|
||||
}
|
||||
return GeminiRender{Config: &dto.GeminiThinkingConfig{IncludeThoughts: intent.IncludeThoughts}}, nil
|
||||
if intent.IncludeThoughts != nil {
|
||||
render.Config = &dto.GeminiThinkingConfig{IncludeThoughts: intent.IncludeThoughts}
|
||||
}
|
||||
return render, nil
|
||||
}
|
||||
|
||||
config := &dto.GeminiThinkingConfig{IncludeThoughts: intent.IncludeThoughts}
|
||||
if capabilities.kind == geminiThinkingBudget {
|
||||
if intent.Mode == ModeDisabled || intent.Effort == EffortNone {
|
||||
if !capabilities.supportsDisable {
|
||||
return GeminiRender{}, fmt.Errorf("%w for model %q", ErrThinkingNotDisabled, model)
|
||||
}
|
||||
budget := 0
|
||||
effort := EffortNone
|
||||
if !capabilities.supportsDisable {
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_disable_unsupported",
|
||||
fmt.Sprintf("model %q cannot disable thinking; using its minimum thinking budget %d", model, capabilities.minBudget),
|
||||
))
|
||||
budget = capabilities.minBudget
|
||||
effort = EffortFromBudget(budget)
|
||||
}
|
||||
config.ThinkingBudget = &budget
|
||||
return GeminiRender{Config: config, EffectiveEffort: EffortNone}, nil
|
||||
return GeminiRender{Config: config, EffectiveEffort: effort, Diagnostics: diagnostics}, nil
|
||||
}
|
||||
|
||||
budget := 0
|
||||
hasBudget := false
|
||||
if intent.BudgetTokens != nil {
|
||||
budget = *intent.BudgetTokens
|
||||
if intent.BudgetSource != SourceNative && budget != -1 {
|
||||
budget = clampGeminiBudget(budget, capabilities)
|
||||
if budget != -1 {
|
||||
clamped := clampGeminiBudget(budget, capabilities)
|
||||
if clamped != budget {
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_budget_clamped",
|
||||
fmt.Sprintf("thinking budget %d is outside the supported range [%d,%d] for model %q; using %d", budget, capabilities.minBudget, capabilities.maxBudget, model, clamped),
|
||||
))
|
||||
budget = clamped
|
||||
}
|
||||
}
|
||||
hasBudget = true
|
||||
} else if intent.Effort != "" {
|
||||
@@ -121,9 +162,6 @@ func RenderGemini(model string, intent Intent, maxOutputTokens *uint, adapterBud
|
||||
hasBudget = true
|
||||
}
|
||||
if hasBudget {
|
||||
if err := validateGeminiBudget(model, budget, capabilities); err != nil {
|
||||
return GeminiRender{}, err
|
||||
}
|
||||
config.ThinkingBudget = &budget
|
||||
}
|
||||
effort := intent.Effort
|
||||
@@ -132,27 +170,46 @@ func RenderGemini(model string, intent Intent, maxOutputTokens *uint, adapterBud
|
||||
} else if intent.Mode == ModeEnabled || intent.Mode == ModeAdaptive {
|
||||
effort = geminiDefaultEffort(model)
|
||||
}
|
||||
return GeminiRender{Config: config, EffectiveEffort: effort}, nil
|
||||
return GeminiRender{Config: config, EffectiveEffort: effort, Diagnostics: diagnostics}, nil
|
||||
}
|
||||
|
||||
if intent.Mode == ModeDisabled || intent.Effort == EffortNone {
|
||||
return GeminiRender{}, fmt.Errorf("%w for model %q", ErrThinkingNotDisabled, model)
|
||||
level, err := geminiLevelForEffort(model, EffortMinimal)
|
||||
if err != nil {
|
||||
return GeminiRender{}, err
|
||||
}
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_disable_unsupported",
|
||||
fmt.Sprintf("model %q cannot disable thinking; using its lowest thinking level %q", model, level),
|
||||
))
|
||||
config.ThinkingLevel = level
|
||||
return GeminiRender{Config: config, EffectiveEffort: Effort(level), Diagnostics: diagnostics}, nil
|
||||
}
|
||||
effort := intent.Effort
|
||||
if effort == "" && intent.BudgetTokens != nil {
|
||||
effort = EffortFromBudget(*intent.BudgetTokens)
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_budget_to_level",
|
||||
fmt.Sprintf("model %q uses thinkingLevel; thinking budget %d was converted to effort %q", model, *intent.BudgetTokens, effort),
|
||||
))
|
||||
}
|
||||
if effort != "" {
|
||||
level, err := geminiLevelForEffort(model, effort)
|
||||
if err != nil {
|
||||
return GeminiRender{}, err
|
||||
}
|
||||
if !strings.EqualFold(level, string(effort)) {
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_level_adjusted",
|
||||
fmt.Sprintf("model %q does not support thinking level %q; using %q", model, effort, level),
|
||||
))
|
||||
}
|
||||
config.ThinkingLevel = level
|
||||
effort = Effort(level)
|
||||
} else if intent.Mode == ModeEnabled || intent.Mode == ModeAdaptive {
|
||||
effort = geminiDefaultEffort(model)
|
||||
}
|
||||
return GeminiRender{Config: config, EffectiveEffort: effort}, nil
|
||||
return GeminiRender{Config: config, EffectiveEffort: effort, Diagnostics: diagnostics}, nil
|
||||
}
|
||||
|
||||
func geminiDefaultEffort(model string) Effort {
|
||||
@@ -176,49 +233,165 @@ func geminiDefaultEffort(model string) Effort {
|
||||
}
|
||||
}
|
||||
|
||||
func ValidateGeminiThinkingConfig(model string, config *dto.GeminiThinkingConfig) (Effort, error) {
|
||||
if config == nil {
|
||||
return "", nil
|
||||
}
|
||||
intent, err := FromGemini(&dto.GeminiChatRequest{GenerationConfig: dto.GeminiChatGenerationConfig{ThinkingConfig: config}})
|
||||
if err != nil {
|
||||
return "", err
|
||||
// NormalizeGeminiThinkingConfig rewrites a provider-native thinkingConfig in
|
||||
// place into the dialect the target model accepts: budgets become levels on
|
||||
// Gemini 3, levels become budgets on Gemini 2.5, out-of-range budgets are
|
||||
// clamped, unsupported levels move to the nearest supported one, and models
|
||||
// without configurable thinking lose the config entirely. Models missing from
|
||||
// the capability table keep their config verbatim. The returned effort is the
|
||||
// accounting label for whatever is now in the config.
|
||||
//
|
||||
// The only error is a config that sets both thinkingBudget and thinkingLevel
|
||||
// on a model whose dialect is unknown; when the dialect is known the field the
|
||||
// model does not use is dropped with a diagnostic.
|
||||
func NormalizeGeminiThinkingConfig(model string, generation *dto.GeminiChatGenerationConfig) (Effort, []types.ConversionDiagnostic, error) {
|
||||
if generation == nil || generation.ThinkingConfig == nil {
|
||||
return "", nil, nil
|
||||
}
|
||||
config := generation.ThinkingConfig
|
||||
capabilities := geminiCapabilitiesFor(model)
|
||||
if capabilities.kind == geminiThinkingNotConfigurable {
|
||||
if !intent.HasStrength() && capabilities.supportsIncludeThoughts {
|
||||
return EffortHigh, nil
|
||||
var diagnostics []types.ConversionDiagnostic
|
||||
if config.ThinkingBudget != nil && config.ThinkingLevel != "" {
|
||||
switch capabilities.kind {
|
||||
case geminiThinkingBudget:
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_budget_level_conflict",
|
||||
fmt.Sprintf("model %q uses thinkingBudget; thinkingLevel %q was dropped because both were set", model, config.ThinkingLevel),
|
||||
))
|
||||
config.ThinkingLevel = ""
|
||||
case geminiThinkingLevel:
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_budget_level_conflict",
|
||||
fmt.Sprintf("model %q uses thinkingLevel; thinkingBudget %d was dropped because both were set", model, *config.ThinkingBudget),
|
||||
))
|
||||
config.ThinkingBudget = nil
|
||||
}
|
||||
return "", fmt.Errorf("model %q does not support configurable thinking", model)
|
||||
}
|
||||
if capabilities.kind == geminiThinkingNotConfigurable {
|
||||
dropped := config.ThinkingBudget != nil || config.ThinkingLevel != "" || (config.IncludeThoughts != nil && !capabilities.supportsIncludeThoughts)
|
||||
if dropped {
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_unsupported",
|
||||
fmt.Sprintf("model %q does not support configurable thinking; the thinking configuration was dropped", model),
|
||||
))
|
||||
}
|
||||
if !capabilities.supportsIncludeThoughts || config.IncludeThoughts == nil {
|
||||
generation.ThinkingConfig = nil
|
||||
return "", diagnostics, nil
|
||||
}
|
||||
config.ThinkingBudget = nil
|
||||
config.ThinkingLevel = ""
|
||||
return EffortHigh, diagnostics, nil
|
||||
}
|
||||
|
||||
intent, intentDiagnostics, err := FromGemini(&dto.GeminiChatRequest{GenerationConfig: *generation})
|
||||
if err != nil {
|
||||
return "", diagnostics, err
|
||||
}
|
||||
diagnostics = append(diagnostics, intentDiagnostics...)
|
||||
if capabilities.kind == geminiThinkingUnknown {
|
||||
return EffectiveEffort(intent), nil
|
||||
return EffectiveEffort(intent), diagnostics, nil
|
||||
}
|
||||
|
||||
if capabilities.kind == geminiThinkingBudget {
|
||||
if config.ThinkingLevel != "" {
|
||||
return "", fmt.Errorf("Gemini 2.5 model %q requires thinkingBudget, not thinkingLevel", model)
|
||||
budget := gemini25BudgetForEffort(intent.Effort)
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_level_to_budget",
|
||||
fmt.Sprintf("model %q uses thinkingBudget; thinkingLevel %q was converted to budget %d", model, config.ThinkingLevel, budget),
|
||||
))
|
||||
config.ThinkingLevel = ""
|
||||
config.ThinkingBudget = &budget
|
||||
}
|
||||
if config.ThinkingBudget != nil {
|
||||
if err := validateGeminiBudget(model, *config.ThinkingBudget, capabilities); err != nil {
|
||||
return "", err
|
||||
if config.ThinkingBudget == nil {
|
||||
return EffectiveEffort(intent), diagnostics, nil
|
||||
}
|
||||
budget := *config.ThinkingBudget
|
||||
switch {
|
||||
case budget < -1:
|
||||
budget = -1
|
||||
case budget == 0 && !capabilities.supportsDisable:
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_disable_unsupported",
|
||||
fmt.Sprintf("model %q cannot disable thinking; using its minimum thinking budget %d", model, capabilities.minBudget),
|
||||
))
|
||||
budget = capabilities.minBudget
|
||||
case budget != 0 && budget != -1:
|
||||
clamped := clampGeminiBudget(budget, capabilities)
|
||||
if clamped != budget {
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_budget_clamped",
|
||||
fmt.Sprintf("thinking budget %d is outside the supported range [%d,%d] for model %q; using %d", budget, capabilities.minBudget, capabilities.maxBudget, model, clamped),
|
||||
))
|
||||
budget = clamped
|
||||
}
|
||||
}
|
||||
return EffectiveEffort(intent), nil
|
||||
config.ThinkingBudget = &budget
|
||||
return EffortFromBudget(budget), diagnostics, nil
|
||||
}
|
||||
|
||||
if config.ThinkingBudget != nil {
|
||||
return "", fmt.Errorf("Gemini 3 model %q requires thinkingLevel, not thinkingBudget", model)
|
||||
}
|
||||
if config.ThinkingLevel != "" {
|
||||
level, err := geminiLevelForEffort(model, intent.Effort)
|
||||
budget := *config.ThinkingBudget
|
||||
config.ThinkingBudget = nil
|
||||
if budget == 0 {
|
||||
level, err := geminiLevelForEffort(model, EffortMinimal)
|
||||
if err != nil {
|
||||
return "", diagnostics, err
|
||||
}
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_disable_unsupported",
|
||||
fmt.Sprintf("model %q cannot disable thinking; using its lowest thinking level %q", model, level),
|
||||
))
|
||||
config.ThinkingLevel = level
|
||||
return Effort(level), diagnostics, nil
|
||||
}
|
||||
level, err := geminiLevelForEffort(model, EffortFromBudget(budget))
|
||||
if err != nil {
|
||||
return "", err
|
||||
return "", diagnostics, err
|
||||
}
|
||||
if level != config.ThinkingLevel {
|
||||
return "", fmt.Errorf("thinkingLevel %q is not supported by model %q", config.ThinkingLevel, model)
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_budget_to_level",
|
||||
fmt.Sprintf("model %q uses thinkingLevel; thinkingBudget %d was converted to thinkingLevel %q", model, budget, level),
|
||||
))
|
||||
config.ThinkingLevel = level
|
||||
return Effort(level), diagnostics, nil
|
||||
}
|
||||
if config.ThinkingLevel == "" {
|
||||
return "", diagnostics, nil
|
||||
}
|
||||
if intent.Effort == EffortNone {
|
||||
level, err := geminiLevelForEffort(model, EffortMinimal)
|
||||
if err != nil {
|
||||
return "", diagnostics, err
|
||||
}
|
||||
return Effort(level), nil
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_thinking_disable_unsupported",
|
||||
fmt.Sprintf("model %q cannot disable thinking; using its lowest thinking level %q", model, level),
|
||||
))
|
||||
config.ThinkingLevel = level
|
||||
return Effort(level), diagnostics, nil
|
||||
}
|
||||
level, err := geminiLevelForEffort(model, intent.Effort)
|
||||
if err != nil {
|
||||
return "", diagnostics, err
|
||||
}
|
||||
if level != string(intent.Effort) {
|
||||
diagnostics = append(diagnostics, geminiReasoningDiagnostic(
|
||||
"gemini_level_adjusted",
|
||||
fmt.Sprintf("model %q does not support thinkingLevel %q; using %q", model, config.ThinkingLevel, level),
|
||||
))
|
||||
}
|
||||
config.ThinkingLevel = level
|
||||
return Effort(level), diagnostics, nil
|
||||
}
|
||||
|
||||
func geminiReasoningDiagnostic(code string, message string) types.ConversionDiagnostic {
|
||||
return types.ConversionDiagnostic{
|
||||
Code: code,
|
||||
Path: "generationConfig.thinkingConfig",
|
||||
Message: message,
|
||||
Severity: types.ConversionDiagnosticWarning,
|
||||
}
|
||||
return "", nil
|
||||
}
|
||||
|
||||
// ResolveGeminiDefault materializes documented family defaults when a
|
||||
@@ -347,28 +520,6 @@ func geminiLevelForEffort(model string, effort Effort) (string, error) {
|
||||
}
|
||||
}
|
||||
|
||||
func validateGeminiBudget(model string, budget int, capabilities geminiCapabilities) error {
|
||||
if budget == -1 {
|
||||
return nil
|
||||
}
|
||||
if budget == 0 {
|
||||
if capabilities.supportsDisable {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("%w for model %q", ErrThinkingNotDisabled, model)
|
||||
}
|
||||
if budget < capabilities.minBudget || budget > capabilities.maxBudget {
|
||||
return fmt.Errorf("thinking budget %d is outside the supported range [%d,%d] for model %q", budget, capabilities.minBudget, capabilities.maxBudget, model)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func clampGeminiBudget(budget int, capabilities geminiCapabilities) int {
|
||||
if budget < capabilities.minBudget {
|
||||
return capabilities.minBudget
|
||||
}
|
||||
if budget > capabilities.maxBudget {
|
||||
return capabilities.maxBudget
|
||||
}
|
||||
return budget
|
||||
return min(max(budget, capabilities.minBudget), capabilities.maxBudget)
|
||||
}
|
||||
Reference in new issue
Block a user