feat: add LLM provider settings to web UI with encrypted API key storage
Add full LLM configuration section to the setup page with provider dropdown, model/API key fields for cloud providers (Anthropic, OpenAI, Gemini), and endpoint/model fields for Ollama. API keys are encrypted with AES-256-GCM and stored in the database.
This commit is contained in:
@@ -88,32 +88,58 @@ func getActiveProfile() (*store.Profile, error) {
|
||||
return &profiles[0], nil
|
||||
}
|
||||
|
||||
// getLLMProvider creates an LLM provider based on config.
|
||||
// getLLMProvider creates an LLM provider from DB settings, with env var / config fallback.
|
||||
func getLLMProvider() llm.Provider {
|
||||
switch cfg.LLM.Provider {
|
||||
// Determine provider: --llm flag > DB settings > config.yaml
|
||||
provider := cfg.LLM.Provider
|
||||
model := cfg.LLM.Model
|
||||
endpoint := cfg.LLM.Endpoint
|
||||
var dbKey string
|
||||
|
||||
if db != nil {
|
||||
if ls, err := db.GetLLMSettings(); err == nil && ls.Provider != "" {
|
||||
if llmFlag == "" { // only use DB provider when no CLI flag override
|
||||
provider = ls.Provider
|
||||
}
|
||||
model = ls.Model
|
||||
endpoint = ls.Endpoint
|
||||
if key, err := config.Decrypt(ls.APIKeyEnc); err == nil {
|
||||
dbKey = key
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
envKey := func(envVar string) string {
|
||||
if dbKey != "" {
|
||||
return dbKey
|
||||
}
|
||||
return os.Getenv(envVar)
|
||||
}
|
||||
|
||||
switch provider {
|
||||
case "anthropic":
|
||||
key := os.Getenv("ANTHROPIC_API_KEY")
|
||||
key := envKey("ANTHROPIC_API_KEY")
|
||||
if key == "" {
|
||||
fmt.Fprintln(os.Stderr, "Warning: ANTHROPIC_API_KEY not set, LLM features disabled")
|
||||
fmt.Fprintln(os.Stderr, "Warning: no Anthropic API key configured, LLM features disabled")
|
||||
return llm.NewNoop()
|
||||
}
|
||||
return llm.NewAnthropic(key, cfg.LLM.Model, nil)
|
||||
return llm.NewAnthropic(key, model, nil)
|
||||
case "openai":
|
||||
key := os.Getenv("OPENAI_API_KEY")
|
||||
key := envKey("OPENAI_API_KEY")
|
||||
if key == "" {
|
||||
fmt.Fprintln(os.Stderr, "Warning: OPENAI_API_KEY not set, LLM features disabled")
|
||||
fmt.Fprintln(os.Stderr, "Warning: no OpenAI API key configured, LLM features disabled")
|
||||
return llm.NewNoop()
|
||||
}
|
||||
return llm.NewOpenAI(key, cfg.LLM.Model, nil)
|
||||
return llm.NewOpenAI(key, model, nil)
|
||||
case "gemini":
|
||||
key := os.Getenv("GEMINI_API_KEY")
|
||||
key := envKey("GEMINI_API_KEY")
|
||||
if key == "" {
|
||||
fmt.Fprintln(os.Stderr, "Warning: GEMINI_API_KEY not set, LLM features disabled")
|
||||
fmt.Fprintln(os.Stderr, "Warning: no Gemini API key configured, LLM features disabled")
|
||||
return llm.NewNoop()
|
||||
}
|
||||
return llm.NewGemini(key, cfg.LLM.Model, nil)
|
||||
return llm.NewGemini(key, model, nil)
|
||||
case "ollama":
|
||||
return llm.NewOllama(cfg.LLM.Model, cfg.LLM.Endpoint, nil)
|
||||
return llm.NewOllama(model, endpoint, nil)
|
||||
default:
|
||||
return llm.NewNoop()
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user