Skip to content

Commit 4f6b1ab

Browse files
committed
Reject unknown thinking_budget effort levels at parse time
Previously, a typo like 'thinking_budget: adaptative' was silently accepted but no provider recognized it, so thinking was never enabled. Now the YAML and JSON unmarshalers validate the effort string against the set of accepted values (none, minimal, low, medium, high, max, adaptive) and return a clear error on unrecognized input. Assisted-By: docker-agent
1 parent 4dd843d commit 4f6b1ab

2 files changed

Lines changed: 47 additions & 0 deletions

File tree

pkg/config/latest/types.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -683,6 +683,20 @@ type ThinkingBudget struct {
683683
Tokens int `json:"tokens,omitempty"`
684684
}
685685

686+
// validThinkingEfforts lists all accepted string values for thinking_budget.
687+
const validThinkingEfforts = "none, minimal, low, medium, high, max, adaptive"
688+
689+
// isValidThinkingEffort reports whether s (case-insensitive, trimmed) is a
690+
// recognised thinking_budget effort level.
691+
func isValidThinkingEffort(s string) bool {
692+
switch strings.ToLower(strings.TrimSpace(s)) {
693+
case "none", "minimal", "low", "medium", "high", "max", "adaptive":
694+
return true
695+
default:
696+
return false
697+
}
698+
}
699+
686700
func (t *ThinkingBudget) UnmarshalYAML(unmarshal func(any) error) error {
687701
// Try integer tokens first
688702
var n int
@@ -694,6 +708,9 @@ func (t *ThinkingBudget) UnmarshalYAML(unmarshal func(any) error) error {
694708
// Try string level
695709
var s string
696710
if err := unmarshal(&s); err == nil {
711+
if !isValidThinkingEffort(s) {
712+
return fmt.Errorf("invalid thinking_budget effort %q: must be one of %s", s, validThinkingEfforts)
713+
}
697714
*t = ThinkingBudget{Effort: s}
698715
return nil
699716
}
@@ -793,6 +810,9 @@ func (t *ThinkingBudget) UnmarshalJSON(data []byte) error {
793810
// Try string level
794811
var s string
795812
if err := json.Unmarshal(data, &s); err == nil {
813+
if !isValidThinkingEffort(s) {
814+
return fmt.Errorf("invalid thinking_budget effort %q: must be one of %s", s, validThinkingEfforts)
815+
}
796816
*t = ThinkingBudget{Effort: s}
797817
return nil
798818
}

pkg/config/latest/types_test.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package latest
22

33
import (
4+
"encoding/json"
45
"testing"
56

67
"github.com/goccy/go-yaml"
@@ -144,6 +145,32 @@ func TestThinkingBudget_IsDisabled(t *testing.T) {
144145
}
145146
}
146147

148+
func TestThinkingBudget_UnmarshalYAML_InvalidEffort(t *testing.T) {
149+
t.Parallel()
150+
151+
input := []byte(`thinking_budget: adaptative`)
152+
var config struct {
153+
ThinkingBudget *ThinkingBudget `yaml:"thinking_budget"`
154+
}
155+
156+
err := yaml.Unmarshal(input, &config)
157+
require.Error(t, err)
158+
require.Contains(t, err.Error(), `invalid thinking_budget effort "adaptative"`)
159+
}
160+
161+
func TestThinkingBudget_UnmarshalJSON_InvalidEffort(t *testing.T) {
162+
t.Parallel()
163+
164+
data := []byte(`{"thinking_budget": "adaptative"}`)
165+
var config struct {
166+
ThinkingBudget *ThinkingBudget `json:"thinking_budget"`
167+
}
168+
169+
err := json.Unmarshal(data, &config)
170+
require.Error(t, err)
171+
require.Contains(t, err.Error(), `invalid thinking_budget effort "adaptative"`)
172+
}
173+
147174
func TestThinkingBudget_IsAdaptive(t *testing.T) {
148175
t.Parallel()
149176

0 commit comments

Comments
 (0)