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:
parent
c9df895445
commit
d596c31606
|
|
@ -17,10 +17,13 @@ type BackendConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
// configFile is the parsed contents of backends.conf: section name → key/value pairs.
|
// 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.
|
// 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 {
|
func loadConfig() configFile {
|
||||||
return parseConfigFile(paths.CfgDir() + "/backends.conf")
|
return parseConfigFile(paths.CfgDir() + "/backends.conf")
|
||||||
}
|
}
|
||||||
|
|
@ -28,6 +31,8 @@ func loadConfig() configFile {
|
||||||
// parseConfigFile parses an INI-style config file.
|
// parseConfigFile parses an INI-style config file.
|
||||||
// Format:
|
// Format:
|
||||||
//
|
//
|
||||||
|
// backend = openrouter (top-level: default backend selection)
|
||||||
|
//
|
||||||
// [section]
|
// [section]
|
||||||
// key = value
|
// key = value
|
||||||
//
|
//
|
||||||
|
|
@ -35,11 +40,11 @@ func loadConfig() configFile {
|
||||||
func parseConfigFile(path string) configFile {
|
func parseConfigFile(path string) configFile {
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return configFile{}
|
return configFile{Backends: map[string]BackendConfig{}}
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
cfg := configFile{}
|
cfg := configFile{Backends: map[string]BackendConfig{}}
|
||||||
section := ""
|
section := ""
|
||||||
|
|
||||||
sc := bufio.NewScanner(f)
|
sc := bufio.NewScanner(f)
|
||||||
|
|
@ -51,15 +56,12 @@ func parseConfigFile(path string) configFile {
|
||||||
// Section header.
|
// Section header.
|
||||||
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
if strings.HasPrefix(line, "[") && strings.HasSuffix(line, "]") {
|
||||||
section = strings.TrimSpace(line[1 : len(line)-1])
|
section = strings.TrimSpace(line[1 : len(line)-1])
|
||||||
if _, ok := cfg[section]; !ok {
|
if _, ok := cfg.Backends[section]; !ok {
|
||||||
cfg[section] = BackendConfig{}
|
cfg.Backends[section] = BackendConfig{}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// Key = value.
|
// Key = value.
|
||||||
if section == "" {
|
|
||||||
continue // ignore keys before first section
|
|
||||||
}
|
|
||||||
k, v, ok := strings.Cut(line, "=")
|
k, v, ok := strings.Cut(line, "=")
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
|
|
@ -71,7 +73,15 @@ func parseConfigFile(path string) configFile {
|
||||||
v = v[1 : len(v)-1]
|
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 {
|
switch k {
|
||||||
case "key":
|
case "key":
|
||||||
bc.Key = v
|
bc.Key = v
|
||||||
|
|
@ -82,7 +92,7 @@ func parseConfigFile(path string) configFile {
|
||||||
case "host":
|
case "host":
|
||||||
bc.Host = v
|
bc.Host = v
|
||||||
}
|
}
|
||||||
cfg[section] = bc
|
cfg.Backends[section] = bc
|
||||||
}
|
}
|
||||||
return cfg
|
return cfg
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,20 +6,27 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// NewWithName constructs a Backend for the given backend name.
|
// 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) {
|
func NewWithName(name string) (Backend, error) {
|
||||||
|
cfg := loadConfig()
|
||||||
|
if name == "" {
|
||||||
|
name = cfg.Default
|
||||||
|
}
|
||||||
if name == "" {
|
if name == "" {
|
||||||
name = os.Getenv("OLLIE_BACKEND")
|
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) {
|
func newBackend(which string) (Backend, error) {
|
||||||
cfg := loadConfig()
|
return newBackendFromConfig(which, loadConfig())
|
||||||
bc := cfg[which]
|
}
|
||||||
|
|
||||||
|
func newBackendFromConfig(which string, cfg configFile) (Backend, error) {
|
||||||
|
bc := cfg.Backends[which]
|
||||||
|
|
||||||
switch which {
|
switch which {
|
||||||
case "ollama":
|
case "ollama":
|
||||||
|
|
|
||||||
|
|
@ -1,13 +1,18 @@
|
||||||
# Ollie backend configuration.
|
# Ollie backend configuration.
|
||||||
# Each section configures a backend. The session selects which backend to use
|
# 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
|
# key = API key or token
|
||||||
# url = base URL override (optional; each backend has a sensible default)
|
# url = base URL override (optional; each backend has a sensible default)
|
||||||
# model = default model (optional; overridden by session model= parameter)
|
# model = default model (optional; overridden by session model= parameter)
|
||||||
# host = host address (ollama only)
|
# host = host address (ollama only)
|
||||||
|
|
||||||
|
backend = openrouter
|
||||||
|
|
||||||
[openrouter]
|
[openrouter]
|
||||||
# key = sk-or-v1-...
|
# key = sk-or-v1-...
|
||||||
# model = qwen/qwen3-235b-a22b
|
# model = qwen/qwen3-235b-a22b
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue