ollie/backend/new.go

165 lines
3.5 KiB
Go

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.
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 newBackendFromConfig(name, cfg)
}
func newBackend(which string) (Backend, error) {
return newBackendFromConfig(which, loadConfig())
}
func newBackendFromConfig(which string, cfg configFile) (Backend, error) {
bc := cfg.Backends[which]
switch which {
case "ollama":
host := bc.Host
if host == "" {
host = os.Getenv("OLLAMA_HOST")
}
b, err := NewOllama(host)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
case "openai":
url := bc.URL
if url == "" {
url = os.Getenv("OLLIE_OPENAI_URL")
}
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)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
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 key == "" {
return nil, fmt.Errorf("openrouter: key required (backends.conf [openrouter] key= or OLLIE_OPENAI_KEY)")
}
b, err := NewOpenAI("openrouter", url, key)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
case "anthropic":
key := bc.Key
if key == "" {
key = os.Getenv("OLLIE_ANTHROPIC_KEY")
}
if key == "" {
return nil, fmt.Errorf("anthropic: key required (backends.conf [anthropic] key= or OLLIE_ANTHROPIC_KEY)")
}
b, err := NewAnthropic(key)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
case "copilot":
token := bc.Key
if token == "" {
token = os.Getenv("OLLIE_COPILOT_TOKEN")
}
if token == "" {
return nil, fmt.Errorf("copilot: key required (backends.conf [copilot] key= or OLLIE_COPILOT_TOKEN)")
}
b, err := NewCopilot(token)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
case "kiro", "codewhisperer":
token := bc.Key
if token == "" {
token = os.Getenv("OLLIE_KIRO_TOKEN")
}
b, err := NewCodeWhisperer(token)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
case "gemini":
key := bc.Key
if key == "" {
key = os.Getenv("OLLIE_GEMINI_KEY")
}
if key == "" {
return nil, fmt.Errorf("gemini: key required (backends.conf [gemini] key= or OLLIE_GEMINI_KEY)")
}
b, err := NewGemini(key)
if err != nil {
return nil, err
}
if bc.Model != "" {
b.SetModel(bc.Model)
}
return b, nil
default:
return nil, fmt.Errorf("unknown backend %q (supported: ollama, openai, openrouter, anthropic, copilot, kiro, gemini)", which)
}
}
// Backends returns the list of supported backend names.
func Backends() []string {
return []string{"ollama", "openai", "openrouter", "anthropic", "copilot", "kiro", "gemini"}
}