@@ -485,6 +485,7 @@ func (s *Session) SetModel(prov, model string) error {
485485 })
486486
487487 s .reclampThinking ()
488+ s .updateContextFromRegistry (prov , model )
488489
489490 return nil
490491}
@@ -500,115 +501,6 @@ func (s *Session) providerType(prov string) (string, error) {
500501 return config .ResolveProviderType (prov , "" )
501502}
502503
503- func (s * Session ) ResolveAndSetModel (pattern string ) (resolved string , err error ) {
504- defer func () {
505- if err == nil {
506- prov , model := s .Provider (), s .ModelName ()
507- if e := config .PatchGlobalSettings (config.Settings {
508- Provider : & prov ,
509- Model : & model ,
510- }); e != nil {
511- fmt .Fprintf (os .Stderr , "warning: persist model setting: %v\n " , e )
512- }
513- }
514- }()
515-
516- // Extract :thinking suffix (e.g. "model:high").
517- thinkingLevel := agentcore .ThinkingLevel ("" )
518- if idx := strings .LastIndex (pattern , ":" ); idx > 0 {
519- suffix := pattern [idx + 1 :]
520- if provider .IsValidThinkingLevel (suffix ) {
521- thinkingLevel = agentcore .ThinkingLevel (suffix )
522- pattern = pattern [:idx ]
523- }
524- }
525-
526- // Snapshot configured providers.
527- s .mu .Lock ()
528- provSnapshot := make (map [string ]config.ProviderConfig , len (s .providers ))
529- maps .Copy (provSnapshot , s .providers )
530- s .mu .Unlock ()
531-
532- // Explicit provider/model or provider:model.
533- // Only split when the left side is a configured provider key so that
534- // model IDs containing slashes (e.g. OpenRouter's "openai/gpt-5") still
535- // work as explicit model IDs under the chosen provider.
536- if prov , model , ok := splitExplicitModelPattern (pattern , provSnapshot ); ok {
537- if err := s .SetModel (prov , model ); err != nil {
538- return "" , err
539- }
540- s .updateContextFromRegistry (prov , model )
541- if thinkingLevel != "" {
542- s .SetThinkingLevel (thinkingLevel )
543- }
544- return explicitModelID (prov , model ), nil
545- }
546-
547- // Search across all configured providers' models lists.
548- type match struct {
549- provider string
550- model string
551- }
552- var matches []match
553- for provName , pc := range provSnapshot {
554- for _ , m := range pc .Models {
555- if strings .EqualFold (m , pattern ) {
556- matches = append (matches , match {provider : provName , model : m })
557- }
558- }
559- }
560- if len (matches ) == 1 {
561- m := matches [0 ]
562- if err := s .SetModel (m .provider , m .model ); err != nil {
563- return "" , err
564- }
565- s .updateContextFromRegistry (m .provider , m .model )
566- if thinkingLevel != "" {
567- s .SetThinkingLevel (thinkingLevel )
568- }
569- return m .model , nil
570- }
571- if len (matches ) > 1 {
572- provs := make ([]string , len (matches ))
573- for i , m := range matches {
574- provs [i ] = config .FormatModelID (m .provider , m .model )
575- }
576- return "" , fmt .Errorf ("model %q is ambiguous, found in: %s; use provider/model format" , pattern , strings .Join (provs , ", " ))
577- }
578-
579- // Fallback: try current provider with the pattern as model name.
580- curProv := s .Provider ()
581- if err := s .SetModel (curProv , pattern ); err != nil {
582- return "" , fmt .Errorf ("model %q not found in any configured provider" , pattern )
583- }
584- s .updateContextFromRegistry (curProv , pattern )
585- if thinkingLevel != "" {
586- s .SetThinkingLevel (thinkingLevel )
587- }
588- return pattern , nil
589- }
590-
591- func splitExplicitModelPattern (pattern string , providers map [string ]config.ProviderConfig ) (providerKey , model string , ok bool ) {
592- if prov , model , ok := strings .Cut (pattern , "/" ); ok {
593- if _ , exists := providers [prov ]; exists && model != "" {
594- return prov , model , true
595- }
596- }
597- if prov , model , ok := strings .Cut (pattern , ":" ); ok {
598- if _ , exists := providers [prov ]; exists && model != "" {
599- return prov , model , true
600- }
601- }
602- return "" , "" , false
603- }
604-
605- func explicitModelID (providerKey , model string ) string {
606- if providerKey == "" {
607- return model
608- }
609- return providerKey + "/" + model
610- }
611-
612504// updateContextFromRegistry updates context window from registry metadata if available.
613505// It tries provider-qualified lookup first (e.g. "anthropic/claude-sonnet-4-5"),
614506// then falls back to bare modelID for custom providers not in the registry.
@@ -633,13 +525,23 @@ func (s *Session) updateContextFromRegistry(providerKey, modelID string) {
633525}
634526
635527func (s * Session ) applyContextWindow (window int ) {
528+ // Re-apply user-configured compaction caps to the new model window so that
529+ // mid-session model switches honor compact_window / compact_ratio.
530+ if cap := s .settings .CompactWindow ; cap > 0 && cap < window {
531+ window = cap
532+ }
533+ reserve := 0
534+ if r := s .settings .CompactRatio ; r > 0 && r < 1 {
535+ reserve = window - int (float64 (window )* r )
536+ }
636537 s .agent .SetContextWindow (window )
637538 s .mu .Lock ()
638539 s .settings .ContextWindow = window
639540 cm := s .contextManager
640541 s .mu .Unlock ()
641542 if engine , ok := cm .(* agentctx.ContextEngine ); ok {
642543 engine .SetContextWindow (window )
544+ engine .SetReserveTokens (reserve )
643545 }
644546}
645547
0 commit comments