Remove legacy backend environment configuration
This commit is contained in:
parent
16240b3e12
commit
45ff8a2864
|
|
@ -5,7 +5,6 @@ import (
|
|||
"crypto/sha256"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"ollie/cmd/olliesrv/internal/backend"
|
||||
|
|
@ -579,14 +578,11 @@ func (s *History) stripCold(ctx context.Context, b backend.Backend) (backend.Usa
|
|||
}
|
||||
|
||||
// resolveCompactionModel returns the model to use for compaction.
|
||||
// Priority: agent config > OLLIE_COMPACTION_MODEL > backends.conf compactionModel > backends.conf model > current model.
|
||||
// Priority: agent config > backends.conf compactionModel > backends.conf model > current model.
|
||||
func resolveCompactionModel(cfgModel string, b backend.Backend) string {
|
||||
if cfgModel != "" {
|
||||
return cfgModel
|
||||
}
|
||||
if env := os.Getenv("OLLIE_COMPACTION_MODEL"); env != "" {
|
||||
return env
|
||||
}
|
||||
if b != nil {
|
||||
if model := backend.CompactionModel(b.Name()); model != "" {
|
||||
return model
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ const (
|
|||
)
|
||||
|
||||
// NewGemini constructs an OpenAI-compatible backend pointed at Google AI Studio.
|
||||
// apiKey is the Google AI Studio key (OLLIE_GEMINI_KEY).
|
||||
// apiKey is the Google AI Studio key configured in backends.conf.
|
||||
// If model is empty the default model is used.
|
||||
func NewGemini(apiKey string) (*OpenAIBackend, error) {
|
||||
b, err := NewOpenAI("gemini", geminiBaseURL, apiKey)
|
||||
|
|
|
|||
|
|
@ -1448,7 +1448,6 @@ func newKiroAuthSource(apiKey string) (kiroAuthSource, error) {
|
|||
if !strings.HasPrefix(strings.ToLower(apiKey), "sqlite://") {
|
||||
return &staticKiroAuth{
|
||||
token: apiKey,
|
||||
profileARN: strings.TrimSpace(os.Getenv("OLLIE_KIRO_PROFILE_ARN")),
|
||||
}, nil
|
||||
}
|
||||
// Parse sqlite:// URI
|
||||
|
|
|
|||
|
|
@ -2,21 +2,17 @@ package backend
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
// NewWithName constructs a Backend for the given backend name.
|
||||
// If name is empty, falls back to backends.conf default, then OLLIE_BACKEND env.
|
||||
// If name is empty, it falls back to the backends.conf default.
|
||||
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 'backend' in backends.conf, OLLIE_BACKEND, or pass backend= to the session")
|
||||
return nil, fmt.Errorf("no backend specified: set 'backend' in backends.conf or pass backend= to the session")
|
||||
}
|
||||
return newBackendFromConfig(name, cfg)
|
||||
}
|
||||
|
|
@ -34,78 +30,44 @@ func newBackendFromConfig(which string, cfg configFile) (Backend, error) {
|
|||
switch which {
|
||||
case "ollama":
|
||||
host := bc.Host
|
||||
if host == "" {
|
||||
host = os.Getenv("OLLAMA_HOST")
|
||||
}
|
||||
b, err = NewOllama(host)
|
||||
|
||||
case "openai":
|
||||
url := bc.URL
|
||||
if url == "" {
|
||||
url = os.Getenv("OLLIE_OPENAI_URL")
|
||||
if bc.Key == "" {
|
||||
return nil, fmt.Errorf("openai: key required (backends.conf [openai] key=)")
|
||||
}
|
||||
key := bc.Key
|
||||
if key == "" {
|
||||
key = os.Getenv("OLLIE_OPENAI_KEY")
|
||||
}
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("openai: key required (backends.conf [openai] key= or OLLIE_OPENAI_KEY)")
|
||||
}
|
||||
b, err = NewOpenAI("openai", url, key)
|
||||
b, err = NewOpenAI("openai", bc.URL, bc.Key)
|
||||
|
||||
case "openrouter":
|
||||
url := bc.URL
|
||||
if url == "" {
|
||||
url = os.Getenv("OLLIE_OPENAI_URL")
|
||||
}
|
||||
if url == "" {
|
||||
url = "https://openrouter.ai/api"
|
||||
}
|
||||
key := bc.Key
|
||||
if key == "" {
|
||||
key = os.Getenv("OLLIE_OPENAI_KEY")
|
||||
if bc.Key == "" {
|
||||
return nil, fmt.Errorf("openrouter: key required (backends.conf [openrouter] key=)")
|
||||
}
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("openrouter: key required (backends.conf [openrouter] key= or OLLIE_OPENAI_KEY)")
|
||||
}
|
||||
b, err = NewOpenAI("openrouter", url, key)
|
||||
b, err = NewOpenAI("openrouter", url, bc.Key)
|
||||
|
||||
case "anthropic":
|
||||
key := bc.Key
|
||||
if key == "" {
|
||||
key = os.Getenv("OLLIE_ANTHROPIC_KEY")
|
||||
if bc.Key == "" {
|
||||
return nil, fmt.Errorf("anthropic: key required (backends.conf [anthropic] key=)")
|
||||
}
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("anthropic: key required (backends.conf [anthropic] key= or OLLIE_ANTHROPIC_KEY)")
|
||||
}
|
||||
b, err = NewAnthropic(key)
|
||||
b, err = NewAnthropic(bc.Key)
|
||||
|
||||
case "copilot":
|
||||
token := bc.Key
|
||||
if token == "" {
|
||||
token = os.Getenv("OLLIE_COPILOT_TOKEN")
|
||||
if bc.Key == "" {
|
||||
return nil, fmt.Errorf("copilot: key required (backends.conf [copilot] key=)")
|
||||
}
|
||||
if token == "" {
|
||||
return nil, fmt.Errorf("copilot: key required (backends.conf [copilot] key= or OLLIE_COPILOT_TOKEN)")
|
||||
}
|
||||
b, err = NewCopilot(token)
|
||||
b, err = NewCopilot(bc.Key)
|
||||
|
||||
case "kiro", "codewhisperer":
|
||||
token := bc.Key
|
||||
if token == "" {
|
||||
token = os.Getenv("OLLIE_KIRO_TOKEN")
|
||||
}
|
||||
b, err = NewKiro(token)
|
||||
b, err = NewKiro(bc.Key)
|
||||
|
||||
case "gemini":
|
||||
key := bc.Key
|
||||
if key == "" {
|
||||
key = os.Getenv("OLLIE_GEMINI_KEY")
|
||||
if bc.Key == "" {
|
||||
return nil, fmt.Errorf("gemini: key required (backends.conf [gemini] key=)")
|
||||
}
|
||||
if key == "" {
|
||||
return nil, fmt.Errorf("gemini: key required (backends.conf [gemini] key= or OLLIE_GEMINI_KEY)")
|
||||
}
|
||||
b, err = NewGemini(key)
|
||||
b, err = NewGemini(bc.Key)
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("unknown backend %q (supported: ollama, openai, openrouter, anthropic, copilot, kiro, gemini)", which)
|
||||
|
|
|
|||
|
|
@ -1,56 +1,20 @@
|
|||
package backend
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
)
|
||||
|
||||
// newFromEnv constructs a Backend from OLLIE_BACKEND env var (test helper).
|
||||
func newFromEnv() (Backend, error) {
|
||||
which := os.Getenv("OLLIE_BACKEND")
|
||||
if which == "" {
|
||||
return nil, fmt.Errorf("OLLIE_BACKEND is not set")
|
||||
}
|
||||
return newBackend(which)
|
||||
}
|
||||
|
||||
// setEnv sets env vars for a test and restores them on cleanup.
|
||||
func setEnv(t *testing.T, vars map[string]string) {
|
||||
t.Helper()
|
||||
for k, v := range vars {
|
||||
old, existed := os.LookupEnv(k)
|
||||
os.Setenv(k, v)
|
||||
if existed {
|
||||
t.Cleanup(func() { os.Setenv(k, old) })
|
||||
} else {
|
||||
t.Cleanup(func() { os.Unsetenv(k) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func clearEnv(t *testing.T, keys ...string) {
|
||||
t.Helper()
|
||||
for _, k := range keys {
|
||||
old, existed := os.LookupEnv(k)
|
||||
os.Unsetenv(k)
|
||||
if existed {
|
||||
t.Cleanup(func() { os.Setenv(k, old) })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_NoBackendErrors(t *testing.T) {
|
||||
clearEnv(t, "OLLIE_BACKEND", "OLLIE_OLLAMA_URL")
|
||||
_, err := newFromEnv()
|
||||
func TestNewWithName_NoBackendErrors(t *testing.T) {
|
||||
_, err := newBackendFromConfig("", configFile{Backends: map[string]BackendConfig{}})
|
||||
if err == nil {
|
||||
t.Fatal("expected error when OLLIE_BACKEND is unset, got nil")
|
||||
t.Fatal("expected error when backend is unset")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_Ollama(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "ollama"})
|
||||
b, err := newFromEnv()
|
||||
func TestNewBackendFromConfig_Ollama(t *testing.T) {
|
||||
b, err := newBackendFromConfig("ollama", configFile{Backends: map[string]BackendConfig{
|
||||
"ollama": {Host: "http://localhost:11434"},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -59,9 +23,10 @@ func TestNewFromEnv_Ollama(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_OpenAI(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "openai", "OLLIE_OPENAI_URL": "https://api.openai.com", "OLLIE_OPENAI_KEY": "sk-test"})
|
||||
b, err := newFromEnv()
|
||||
func TestNewBackendFromConfig_OpenAI(t *testing.T) {
|
||||
b, err := newBackendFromConfig("openai", configFile{Backends: map[string]BackendConfig{
|
||||
"openai": {URL: "https://api.openai.com", Key: "sk-test"},
|
||||
}})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
|
@ -70,71 +35,17 @@ func TestNewFromEnv_OpenAI(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_OpenRouter(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "openrouter", "OLLIE_OPENAI_URL": "https://openrouter.ai/api", "OLLIE_OPENAI_KEY": "sk-or-test"})
|
||||
b, err := newFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if b.Name() != "openrouter" {
|
||||
t.Errorf("name = %q", b.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_Anthropic(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "anthropic", "OLLIE_ANTHROPIC_KEY": "sk-ant-test"})
|
||||
b, err := newFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if b.Name() != "anthropic" {
|
||||
t.Errorf("name = %q", b.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_AnthropicMissingKey(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "anthropic"})
|
||||
clearEnv(t, "OLLIE_ANTHROPIC_KEY")
|
||||
_, err := newFromEnv()
|
||||
func TestNewBackendFromConfig_AnthropicMissingKey(t *testing.T) {
|
||||
_, err := newBackendFromConfig("anthropic", configFile{Backends: map[string]BackendConfig{
|
||||
"anthropic": {},
|
||||
}})
|
||||
if err == nil {
|
||||
t.Fatal("expected error for missing key")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_Copilot(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "copilot", "OLLIE_COPILOT_TOKEN": "tok"})
|
||||
b, err := newFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if b.Name() != "copilot" {
|
||||
t.Errorf("name = %q", b.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_CopilotMissingToken(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "copilot"})
|
||||
clearEnv(t, "OLLIE_COPILOT_TOKEN")
|
||||
_, err := newFromEnv()
|
||||
if err == nil {
|
||||
t.Fatal("expected error for missing token")
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_Kiro(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "kiro", "OLLIE_KIRO_TOKEN": "fake"})
|
||||
b, err := newFromEnv()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if b.Name() != "kiro" {
|
||||
t.Errorf("name = %q", b.Name())
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewFromEnv_Unknown(t *testing.T) {
|
||||
setEnv(t, map[string]string{"OLLIE_BACKEND": "bogus"})
|
||||
_, err := newFromEnv()
|
||||
func TestNewBackendFromConfig_Unknown(t *testing.T) {
|
||||
_, err := newBackendFromConfig("bogus", configFile{Backends: map[string]BackendConfig{}})
|
||||
if err == nil {
|
||||
t.Fatal("expected error for unknown backend")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# Model configuration for ollie agent operations.
|
||||
# Each section specifies backend→model mappings or global defaults.
|
||||
# Environment variables (OLLIE_COMPACTION_MODEL, OLLIE_COMPLETE_*) take priority.
|
||||
# Backend and compaction model settings are configured in backends.conf.
|
||||
# Agent-level config fields override everything.
|
||||
|
||||
# Compaction: cheap models per backend, used when context exceeds threshold.
|
||||
|
|
|
|||
|
|
@ -3,15 +3,8 @@
|
|||
# Lines beginning with # and blank lines are ignored.
|
||||
# Inline comments are supported: KEY=value # comment
|
||||
|
||||
# Default backend (default: ollama)
|
||||
# Supported: ollama, openai, openrouter, anthropic, copilot, kiro
|
||||
#OLLIE_BACKEND=ollama
|
||||
|
||||
# Default model name (backend-specific default if unset)
|
||||
#OLLIE_MODEL=
|
||||
|
||||
# Default agent config (default: default)
|
||||
#OLLIE_DEFAULT_AGENT=default
|
||||
# Log level (default: warn)
|
||||
#OLLIE_LOG=warn
|
||||
|
||||
# All paths follow XDG Base Directory conventions:
|
||||
# Tools: $XDG_CONFIG_HOME/ollie/tools (default: ~/.config/ollie/tools)
|
||||
|
|
@ -21,29 +14,5 @@
|
|||
# Data: $XDG_DATA_HOME/ollie (default: ~/.local/share/ollie)
|
||||
# Override XDG_CONFIG_HOME or XDG_DATA_HOME if you want non-default locations.
|
||||
|
||||
# Backend-specific settings
|
||||
|
||||
# openai / openrouter
|
||||
#OLLIE_OPENAI_URL=
|
||||
#OLLIE_OPENAI_KEY=
|
||||
|
||||
# anthropic
|
||||
#OLLIE_ANTHROPIC_KEY=
|
||||
|
||||
# copilot
|
||||
#OLLIE_COPILOT_TOKEN=
|
||||
|
||||
# kiro / codewhisperer (bearer token or sqlite:// path)
|
||||
#OLLIE_KIRO_TOKEN=
|
||||
|
||||
# u/complete: backend and model for acme code completion (required by u/complete)
|
||||
#OLLIE_COMPLETE_BACKEND=ollama
|
||||
#OLLIE_COMPLETE_MODEL=qwen3:latest
|
||||
|
||||
# cascade: planner (orchestrator) model for u/cascade script
|
||||
#OLLIE_CASCADE_PLAN_BACKEND=openrouter
|
||||
#OLLIE_CASCADE_PLAN_MODEL=deepseek/deepseek-v4-pro
|
||||
|
||||
# cascade: worker model for spawned agents
|
||||
#OLLIE_CASCADE_BACKEND=openrouter
|
||||
#OLLIE_CASCADE_MODEL=deepseek/deepseek-v4-flash
|
||||
# Backend credentials, endpoints, models, and the default backend belong in
|
||||
# ~/.config/ollie/backends.conf, not this file.
|
||||
Loading…
Reference in New Issue