package backend import ( "fmt" ) // NewWithName constructs a Backend for the given backend name. // 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 == "" { return nil, fmt.Errorf("no backend specified: set 'backend' in backends.conf 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] var b Backend var err error switch which { case "ollama": host := bc.Host b, err = NewOllama(host) case "openai": if bc.Key == "" { return nil, fmt.Errorf("openai: key required (backends.conf [openai] key=)") } b, err = NewOpenAI("openai", bc.URL, bc.Key) case "openrouter": url := bc.URL if url == "" { url = "https://openrouter.ai/api" } if bc.Key == "" { return nil, fmt.Errorf("openrouter: key required (backends.conf [openrouter] key=)") } b, err = NewOpenAI("openrouter", url, bc.Key) case "anthropic": if bc.Key == "" { return nil, fmt.Errorf("anthropic: key required (backends.conf [anthropic] key=)") } b, err = NewAnthropic(bc.Key) case "copilot": if bc.Key == "" { return nil, fmt.Errorf("copilot: key required (backends.conf [copilot] key=)") } b, err = NewCopilot(bc.Key) case "kiro", "codewhisperer": b, err = NewKiro(bc.Key) case "gemini": if bc.Key == "" { return nil, fmt.Errorf("gemini: key required (backends.conf [gemini] key=)") } b, err = NewGemini(bc.Key) default: return nil, fmt.Errorf("unknown backend %q (supported: ollama, openai, openrouter, anthropic, copilot, kiro, gemini)", which) } if err != nil { return nil, err } if bc.Model != "" { b.SetModel(bc.Model) } return b, nil } // Backends returns the list of supported backend names. func Backends() []string { return []string{"ollama", "openai", "openrouter", "anthropic", "copilot", "kiro", "gemini"} }