feat: support provider-level compaction_model default - #3785
Conversation
Resolution priority is now agent > model > provider, which also flips the previous model-over-agent precedence. Assisted-By: Claude
…d env preflight Extract precedence logic into config.EffectiveCompactionModelRef; wire it into first_available reachability and credential preflight so a compaction model named only at the provider level is never silently skipped. Assisted-By: Claude
docker-agent
left a comment
There was a problem hiding this comment.
Assessment: 🟡 NEEDS ATTENTION
This PR centralizes compaction-model resolution into EffectiveCompactionModelRef and the new priority order (agent > model > provider) is correctly implemented and documented. One gap was found in the new provider-level lookup path.
| for name := range strings.SplitSeq(a.Model, ",") { | ||
| modelCfg, ok := cfg.Models[name] | ||
| if !ok { | ||
| continue | ||
| } | ||
| if providerCfg, ok := cfg.Providers[modelCfg.Provider]; ok && providerCfg.CompactionModel != "" { | ||
| return providerCfg.CompactionModel | ||
| } | ||
| } | ||
| return "" |
There was a problem hiding this comment.
[medium] Provider-level compaction_model is never applied when agent.Model is an inline provider/model spec
The second loop in EffectiveCompactionModelRef tries to resolve the provider-level default by looking up each model name in cfg.Models and then finding its .Provider. When agent.Model is an inline spec such as "openai/gpt-4o" (not a named entry in cfg.Models), the !ok guard causes the loop to continue, so cfg.Providers["openai"].CompactionModel is never consulted.
The provider can be extracted from inline specs with the already-available latest.ParseModelRef, which is exactly what gatherEnvVarsForCompactionModel does for the compaction ref itself (gather.go). Applying the same pattern here closes the gap:
| for name := range strings.SplitSeq(a.Model, ",") { | |
| modelCfg, ok := cfg.Models[name] | |
| if !ok { | |
| continue | |
| } | |
| if providerCfg, ok := cfg.Providers[modelCfg.Provider]; ok && providerCfg.CompactionModel != "" { | |
| return providerCfg.CompactionModel | |
| } | |
| } | |
| return "" | |
| for name := range strings.SplitSeq(a.Model, ",") { | |
| var provider string | |
| if modelCfg, ok := cfg.Models[name]; ok { | |
| provider = modelCfg.Provider | |
| } else if parsed, err := latest.ParseModelRef(strings.TrimSpace(name)); err == nil { | |
| provider = parsed.Provider | |
| } | |
| if provider != "" { | |
| if providerCfg, ok := cfg.Providers[provider]; ok && providerCfg.CompactionModel != "" { | |
| return providerCfg.CompactionModel | |
| } | |
| } | |
| } | |
| return "" |
Without this fix, a user who sets compaction_model at the provider level and uses an inline model reference (e.g. model: openai/gpt-4o) will silently get no compaction model, contrary to what the ProviderConfig.CompactionModel doc comment promises ("agents whose model uses this provider").
| Confidence | Score |
|---|---|
| 🟡 moderate | 67/100 |
When multiple agents share the same provider, each one previously had to repeat its
compaction_model— there was no way to express a default at the provider level. This change adds acompaction_modelfield to provider definitions so the default can live in one place.Resolution now follows a clear priority: an agent-level
compaction_modelwins, then a model-level one, then the provider-level default. Note that this intentionally flips the previous precedence where model-level beat agent-level. The logic is centralized inconfig.EffectiveCompactionModelRef(pkg/config/compaction.go), which is now the single source of truth consumed by the team loader,first_availablereachability checks, and the credential preflight.Two other gaps are closed at the same time:
first_availableselectors that are only referenced through acompaction_model(at any level) are now resolved at load time, and the credential preflight includes the effective compaction model's env vars so a missing API key surfaces in the consolidated preflight error rather than silently at runtime.agent-schema.json,examples/compaction_model.yaml, and the docs for agents, models, the compaction guide, and custom providers are all updated to reflect the new field.