From 1eacb4f42dba7dd7d73c7bdbffa01790e34f2270 Mon Sep 17 00:00:00 2001 From: Levi Neely <141506390+lneely@users.noreply.github.com> Date: Fri, 7 Aug 2026 07:24:40 +0200 Subject: [PATCH] agent: replace hardcoded model maps with models.yaml config - Remove defaultCompactionModels map from compaction.go - Add agent/models.go: load ~/.config/ollie/models.yaml for all backend/model settings - Completion (Complete()) falls back to models.yaml completion section when env vars unset - Compaction falls back to models.yaml compaction section per-backend - Priority chain: agent config > OLLIE_*_MODEL env > models.yaml > session model --- agent/compaction.go | 17 ++++++----------- agent/complete.go | 11 ++++++++++- agent/models.go | 41 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 12 deletions(-) create mode 100644 agent/models.go diff --git a/agent/compaction.go b/agent/compaction.go index 06a8654..7149e88 100644 --- a/agent/compaction.go +++ b/agent/compaction.go @@ -2,21 +2,13 @@ package agent import "os" -// defaultCompactionModels maps backend names to cheap models suitable for compaction. -var defaultCompactionModels = map[string]string{ - "anthropic": "claude-3-5-haiku-latest", - "openai": "gpt-4o-mini", - "openrouter": "deepseek-v4-flash", - "gemini": "gemini-2.0-flash", -} - -// backendNamer is the subset of backend.Backend needed for compaction model resolution. +// backendNamer is the subset of backend.Backend needed for model resolution. type backendNamer interface { Name() string } // resolveCompactionModel returns the model to use for compaction. -// Priority: agent config > OLLIE_COMPACTION_MODEL env > per-backend default. +// Priority: agent config > OLLIE_COMPACTION_MODEL env > per-backend default from models.yaml > session's current model. // Returns "" if no override is configured (use the session's current model). func resolveCompactionModel(cfgModel string, b backendNamer) string { if cfgModel != "" { @@ -25,8 +17,11 @@ func resolveCompactionModel(cfgModel string, b backendNamer) string { if env := os.Getenv("OLLIE_COMPACTION_MODEL"); env != "" { return env } + cfg := loadModelsConfig() if b != nil { - return defaultCompactionModels[b.Name()] + if m, ok := cfg.Compaction[b.Name()]; ok { + return m + } } return "" } diff --git a/agent/complete.go b/agent/complete.go index 3199ece..b79e636 100644 --- a/agent/complete.go +++ b/agent/complete.go @@ -24,7 +24,16 @@ func Complete(cwd, filePath, prefix, suffix, extraContext string) (string, error model := os.Getenv("OLLIE_COMPLETE_MODEL") backendName := os.Getenv("OLLIE_COMPLETE_BACKEND") if model == "" || backendName == "" { - return "", fmt.Errorf("OLLIE_COMPLETE_MODEL and OLLIE_COMPLETE_BACKEND must be set") + cfg := loadModelsConfig() + if model == "" && cfg.Completion.Model != "" { + model = cfg.Completion.Model + } + if backendName == "" && cfg.Completion.Backend != "" { + backendName = cfg.Completion.Backend + } + } + if model == "" || backendName == "" { + return "", fmt.Errorf("OLLIE_COMPLETE_MODEL and OLLIE_COMPLETE_BACKEND must be set (or configured in models.yaml)") } const prefixMax = 12000 diff --git a/agent/models.go b/agent/models.go new file mode 100644 index 0000000..148059a --- /dev/null +++ b/agent/models.go @@ -0,0 +1,41 @@ +package agent + +import ( + "os" + "path/filepath" + + "gopkg.in/yaml.v3" +) + +// modelsConfig holds the parsed contents of ~/.config/ollie/models.yaml. +type modelsConfig struct { + Compaction map[string]string `yaml:"compaction"` + Completion struct { + Model string `yaml:"model"` + Backend string `yaml:"backend"` + } `yaml:"completion"` +} + +// loadModelsConfig reads and parses the models config file. +// Returns zero value if the file doesn't exist or is invalid. +func loadModelsConfig() modelsConfig { + path := filepath.Join(cfgDir(), "models.yaml") + data, err := os.ReadFile(path) + if err != nil { + return modelsConfig{} + } + var cfg modelsConfig + if err := yaml.Unmarshal(data, &cfg); err != nil { + return modelsConfig{} + } + return cfg +} + +// cfgDir returns the ollie config directory, respecting XDG_CONFIG_HOME. +func cfgDir() string { + if xdg := os.Getenv("XDG_CONFIG_HOME"); xdg != "" { + return filepath.Join(xdg, "ollie") + } + home, _ := os.UserHomeDir() + return filepath.Join(home, ".config", "ollie") +}