@@ -11,6 +11,7 @@ import (
1111 "io"
1212 "maps"
1313 "math"
14+ "strconv"
1415 "strings"
1516
1617 "charm.land/fantasy"
@@ -38,6 +39,51 @@ func betaRequestOptions(flags []string) []option.RequestOption {
3839 return opts
3940}
4041
42+ func thinkingDisplay (providerOptions * ProviderOptions , modelID string ) (ThinkingDisplay , bool ) {
43+ if providerOptions != nil && providerOptions .ThinkingDisplay != nil && * providerOptions .ThinkingDisplay != "" {
44+ return * providerOptions .ThinkingDisplay , true
45+ }
46+ if defaultsToOmittedThinkingDisplay (modelID ) {
47+ return ThinkingDisplaySummarized , true
48+ }
49+ return "" , false
50+ }
51+
52+ func defaultsToAdaptiveThinking (model string ) bool {
53+ model = strings .ToLower (strings .TrimSpace (model ))
54+ return strings .Contains (model , "claude-mythos-preview" )
55+ }
56+
57+ func requiresAdaptiveThinking (model string ) bool {
58+ return defaultsToAdaptiveThinking (model ) || defaultsToOmittedOpusThinkingDisplay (model )
59+ }
60+
61+ func setThinkingDisplay (param interface { SetExtraFields (map [string ]any ) }, display ThinkingDisplay ) {
62+ param .SetExtraFields (map [string ]any {"display" : string (display )})
63+ }
64+
65+ func defaultsToOmittedThinkingDisplay (model string ) bool {
66+ model = strings .ToLower (strings .TrimSpace (model ))
67+ return defaultsToAdaptiveThinking (model ) || defaultsToOmittedOpusThinkingDisplay (model )
68+ }
69+
70+ func defaultsToOmittedOpusThinkingDisplay (model string ) bool {
71+ _ , suffix , ok := strings .Cut (model , "claude-opus-4-" )
72+ if ! ok {
73+ return false
74+ }
75+
76+ versionEnd := 0
77+ for versionEnd < len (suffix ) && suffix [versionEnd ] >= '0' && suffix [versionEnd ] <= '9' {
78+ versionEnd ++
79+ }
80+ if versionEnd == 0 || versionEnd > 2 {
81+ return false
82+ }
83+ minor , err := strconv .Atoi (suffix [:versionEnd ])
84+ return err == nil && minor >= 7
85+ }
86+
4187// buildRequestOptions constructs the common request options shared
4288// by Generate and Stream: user-agent, raw tool injection, and any
4389// beta API flags.
@@ -335,12 +381,26 @@ func (a languageModel) prepareParams(call fantasy.Call) (
335381 Effort : anthropic .OutputConfigEffort (effort ),
336382 }
337383 adaptive := anthropic .NewThinkingConfigAdaptiveParam ()
384+ if display , ok := thinkingDisplay (providerOptions , a .modelID ); ok {
385+ setThinkingDisplay (& adaptive , display )
386+ }
338387 params .Thinking .OfAdaptive = & adaptive
339388 case providerOptions .Thinking != nil :
340389 if providerOptions .Thinking .BudgetTokens == 0 {
341390 return nil , nil , nil , nil , & fantasy.Error {Title : "no budget" , Message : "thinking requires budget" }
342391 }
343- params .Thinking = anthropic .ThinkingConfigParamOfEnabled (providerOptions .Thinking .BudgetTokens )
392+ if requiresAdaptiveThinking (a .modelID ) {
393+ adaptive := anthropic .NewThinkingConfigAdaptiveParam ()
394+ if display , ok := thinkingDisplay (providerOptions , a .modelID ); ok {
395+ setThinkingDisplay (& adaptive , display )
396+ }
397+ params .Thinking .OfAdaptive = & adaptive
398+ } else {
399+ params .Thinking = anthropic .ThinkingConfigParamOfEnabled (providerOptions .Thinking .BudgetTokens )
400+ if display , ok := thinkingDisplay (providerOptions , a .modelID ); ok {
401+ setThinkingDisplay (params .Thinking .OfEnabled , display )
402+ }
403+ }
344404 if call .Temperature != nil {
345405 params .Temperature = param.Opt [float64 ]{}
346406 warnings = append (warnings , fantasy.CallWarning {
@@ -365,6 +425,12 @@ func (a languageModel) prepareParams(call fantasy.Call) (
365425 Details : "TopK is not supported when thinking is enabled" ,
366426 })
367427 }
428+ case defaultsToAdaptiveThinking (a .modelID ):
429+ adaptive := anthropic .NewThinkingConfigAdaptiveParam ()
430+ if display , ok := thinkingDisplay (providerOptions , a .modelID ); ok {
431+ setThinkingDisplay (& adaptive , display )
432+ }
433+ params .Thinking .OfAdaptive = & adaptive
368434 }
369435
370436 if len (call .Tools ) > 0 {
0 commit comments