backend: move default backend selection to backends.conf

backends.conf now supports a top-level 'backend = name' line that
selects the default backend for new sessions. Lookup order:

  1. backends.conf 'backend = ...'
  2. OLLIE_BACKEND env var (fallback)
  3. session-level backend= parameter (override)

No env file needed for backend/model config anymore.
This commit is contained in:
Ollie Agent 2026-08-08 22:57:37 +02:00
parent c9df895445
commit d596c31606
3 changed files with 42 additions and 20 deletions

View File

@ -17,10 +17,13 @@ type BackendConfig struct {
}
// configFile is the parsed contents of backends.conf: section name → key/value pairs.
type configFile map[string]BackendConfig
type configFile struct {
Default string // top-level "backend = ..." selects the default
Backends map[string]BackendConfig
}
// loadConfig reads ~/.config/ollie/backends.conf.
// Returns an empty map (not nil) if the file doesn't exist or is unreadable.
// Returns zero value if the file doesn't exist or is unreadable.
func loadConfig() configFile {
return parseConfigFile(paths.CfgDir() + "/backends.conf")
}
@ -28,6 +31,8 @@ func loadConfig() configFile {
// parseConfigFile parses an INI-style config file.
// Format:
//
// backend = openrouter (top-level: default backend selection)
//
// [section]
// key = value
//
@ -35,11 +40,11 @@ func loadConfig() configFile {
func parseConfigFile(path string) configFile {
f, err := os.Open(path)
if err != nil {
return configFile{}
return configFile{Backends: map[string]BackendConfig{}}
}
defer f.Close()
cfg := configFile{}
cfg := configFile{Backends: map[string]BackendConfig{}}
section := ""
sc := bufio.NewScanner(f)
@ -51,15 +56,12 @@ func parseConfigFile(path string) configFile {
// Section header.
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
section = strings.TrimSpace(line[1 : len(line)-1])
if _, ok := cfg[section]; !ok {
cfg[section] = BackendConfig{}
if _, ok := cfg.Backends[section]; !ok {
cfg.Backends[section] = BackendConfig{}
}
continue
}
// Key = value.
if section == "" {
continue // ignore keys before first section
}
k, v, ok := strings.Cut(line, "=")
if !ok {
continue
@ -71,7 +73,15 @@ func parseConfigFile(path string) configFile {
v = v[1 : len(v)-1]
}
bc := cfg[section]
// Top-level keys (before any section).
if section == "" {
if k == "backend" {
cfg.Default = v
}
continue
}
bc := cfg.Backends[section]
switch k {
case "key":
bc.Key = v
@ -82,7 +92,7 @@ func parseConfigFile(path string) configFile {
case "host":
bc.Host = v
}
cfg[section] = bc
cfg.Backends[section] = bc
}
return cfg
}

View File

@ -6,20 +6,27 @@ import (
)
// NewWithName constructs a Backend for the given backend name.
// If name is empty, falls back to OLLIE_BACKEND; errors if neither is set.
// If name is empty, falls back to backends.conf default, then OLLIE_BACKEND env.
func NewWithName(name string) (Backend, error) {
cfg := loadConfig()
if name == "" {
name = cfg.Default
}
if name == "" {
name = os.Getenv("OLLIE_BACKEND")
if name == "" {
return nil, fmt.Errorf("no backend specified: set OLLIE_BACKEND or pass backend= to the session")
}
}
return newBackend(name)
if name == "" {
return nil, fmt.Errorf("no backend specified: set 'backend' in backends.conf, OLLIE_BACKEND, or pass backend= to the session")
}
return newBackendFromConfig(name, cfg)
}
func newBackend(which string) (Backend, error) {
cfg := loadConfig()
bc := cfg[which]
return newBackendFromConfig(which, loadConfig())
}
func newBackendFromConfig(which string, cfg configFile) (Backend, error) {
bc := cfg.Backends[which]
switch which {
case "ollama":

View File

@ -1,13 +1,18 @@
# Ollie backend configuration.
# Each section configures a backend. The session selects which backend to use
# via OLLIE_BACKEND env var or backend= parameter.
# via the top-level 'backend' setting or backend= parameter.
#
# Fields:
# Top-level:
# backend = name (default backend for new sessions)
#
# Per-backend fields:
# key = API key or token
# url = base URL override (optional; each backend has a sensible default)
# model = default model (optional; overridden by session model= parameter)
# host = host address (ollama only)
backend = openrouter
[openrouter]
# key = sk-or-v1-...
# model = qwen/qwen3-235b-a22b