MCPcopy Create free account
hub / github.com/chainreactors/EvilProxy / ValidateConfig

Function ValidateConfig

internal/thinking/validate.go:38–165  ·  view source on GitHub ↗

ValidateConfig validates a thinking configuration against model capabilities. This function performs comprehensive validation: - Checks if the model supports thinking - Auto-converts between Budget and Level formats based on model capability - Validates that requested level is in the model's suppor

(config ThinkingConfig, modelInfo *registry.ModelInfo, fromFormat, toFormat string, fromSuffix bool)

Source from the content-addressed store, hash-verified

36// - Level-only model + Budget config → Budget converted to Level
37// - Hybrid model → preserve original format
38func ValidateConfig(config ThinkingConfig, modelInfo *registry.ModelInfo, fromFormat, toFormat string, fromSuffix bool) (*ThinkingConfig, error) {
39 fromFormat, toFormat = strings.ToLower(strings.TrimSpace(fromFormat)), strings.ToLower(strings.TrimSpace(toFormat))
40 model := "unknown"
41 support := (*registry.ThinkingSupport)(nil)
42 if modelInfo != nil {
43 if modelInfo.ID != "" {
44 model = modelInfo.ID
45 }
46 support = modelInfo.Thinking
47 }
48
49 if support == nil {
50 if config.Mode != ModeNone {
51 return nil, NewThinkingErrorWithModel(ErrThinkingNotSupported, "thinking not supported for this model", model)
52 }
53 return &config, nil
54 }
55
56 // allowClampUnsupported determines whether to clamp unsupported levels instead of returning an error.
57 // This applies when crossing provider families (e.g., openai→gemini, claude→gemini) and the target
58 // model supports discrete levels. Same-family conversions require strict validation.
59 toCapability := detectModelCapability(modelInfo)
60 toHasLevelSupport := toCapability == CapabilityLevelOnly || toCapability == CapabilityHybrid
61 allowClampUnsupported := toHasLevelSupport && !isSameProviderFamily(fromFormat, toFormat)
62
63 // strictBudget determines whether to enforce strict budget range validation.
64 // This applies when: (1) config comes from request body (not suffix), (2) source format is known,
65 // and (3) source and target are in the same provider family. Cross-family or suffix-based configs
66 // are clamped instead of rejected to improve interoperability.
67 strictBudget := !fromSuffix && fromFormat != "" && isSameProviderFamily(fromFormat, toFormat)
68 budgetDerivedFromLevel := false
69
70 capability := detectModelCapability(modelInfo)
71 switch capability {
72 case CapabilityBudgetOnly:
73 if config.Mode == ModeLevel {
74 if config.Level == LevelAuto {
75 break
76 }
77 budget, ok := ConvertLevelToBudget(string(config.Level))
78 if !ok {
79 return nil, NewThinkingError(ErrUnknownLevel, fmt.Sprintf("unknown level: %s", config.Level))
80 }
81 config.Mode = ModeBudget
82 config.Budget = budget
83 config.Level = ""
84 budgetDerivedFromLevel = true
85 }
86 case CapabilityLevelOnly:
87 if config.Mode == ModeBudget {
88 level, ok := ConvertBudgetToLevel(config.Budget)
89 if !ok {
90 return nil, NewThinkingError(ErrUnknownLevel, fmt.Sprintf("budget %d cannot be converted to a valid level", config.Budget))
91 }
92 // When converting Budget -> Level for level-only models, clamp the derived standard level
93 // to the nearest supported level. Special values (none/auto) are preserved.
94 config.Mode = ModeLevel
95 config.Level = clampLevel(ThinkingLevel(level), modelInfo, toFormat)

Callers 1

ApplyThinkingFunction · 0.85

Calls 12

detectModelCapabilityFunction · 0.85
isSameProviderFamilyFunction · 0.85
ConvertLevelToBudgetFunction · 0.85
NewThinkingErrorFunction · 0.85
ConvertBudgetToLevelFunction · 0.85
clampLevelFunction · 0.85
ThinkingLevelTypeAlias · 0.85
isLevelSupportedFunction · 0.85
normalizeLevelsFunction · 0.85
convertAutoToMidRangeFunction · 0.85
clampBudgetFunction · 0.85

Tested by

no test coverage detected