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") +}