1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
package llmutils
import (
"os"
"strings"
"codeberg.org/snonux/hexai/internal/appconfig"
"codeberg.org/snonux/hexai/internal/llm"
)
// CanonicalProvider normalizes provider names and defaults to openai.
func CanonicalProvider(name string) string {
provider := strings.ToLower(strings.TrimSpace(name))
if provider == "" {
return "openai"
}
return provider
}
// DefaultModelForProvider returns the configured default model for a provider.
func DefaultModelForProvider(cfg appconfig.App, provider string) string {
switch CanonicalProvider(provider) {
case "openrouter":
return strings.TrimSpace(cfg.OpenRouterModel)
case "ollama":
return strings.TrimSpace(cfg.OllamaModel)
case "anthropic":
return strings.TrimSpace(cfg.AnthropicModel)
default:
return strings.TrimSpace(cfg.OpenAIModel)
}
}
// ConfigForProvider returns cfg adjusted for the selected provider/model.
func ConfigForProvider(cfg appconfig.App, provider, modelOverride string) appconfig.App {
derived := cfg
if strings.TrimSpace(provider) == "" {
provider = cfg.Provider
}
normalized := CanonicalProvider(provider)
derived.Provider = normalized
model := strings.TrimSpace(modelOverride)
if model == "" {
return derived
}
switch normalized {
case "openrouter":
derived.OpenRouterModel = model
case "ollama":
derived.OllamaModel = model
case "anthropic":
derived.AnthropicModel = model
default:
derived.OpenAIModel = model
}
return derived
}
// NewClientFromAppForProvider builds a client for a specific provider/model.
func NewClientFromAppForProvider(cfg appconfig.App, provider, modelOverride string) (llm.Client, error) {
return NewClientFromApp(ConfigForProvider(cfg, provider, modelOverride))
}
// NewClientFromApp builds an llm.Client using app config and environment keys.
func NewClientFromApp(cfg appconfig.App) (llm.Client, error) {
llmCfg := llm.Config{
Provider: cfg.Provider,
RequestTimeout: cfg.RequestTimeout,
OpenAIBaseURL: cfg.OpenAIBaseURL,
OpenAIModel: cfg.OpenAIModel,
OpenAITemperature: cfg.OpenAITemperature,
OpenRouterBaseURL: cfg.OpenRouterBaseURL,
OpenRouterModel: cfg.OpenRouterModel,
OpenRouterTemperature: cfg.OpenRouterTemperature,
OllamaBaseURL: cfg.OllamaBaseURL,
OllamaModel: cfg.OllamaModel,
OllamaTemperature: cfg.OllamaTemperature,
AnthropicBaseURL: cfg.AnthropicBaseURL,
AnthropicModel: cfg.AnthropicModel,
AnthropicTemperature: cfg.AnthropicTemperature,
}
oaKey := os.Getenv("HEXAI_OPENAI_API_KEY")
if strings.TrimSpace(oaKey) == "" {
oaKey = os.Getenv("OPENAI_API_KEY")
}
orKey := os.Getenv("HEXAI_OPENROUTER_API_KEY")
if strings.TrimSpace(orKey) == "" {
orKey = os.Getenv("OPENROUTER_API_KEY")
}
anKey := os.Getenv("HEXAI_ANTHROPIC_API_KEY")
if strings.TrimSpace(anKey) == "" {
anKey = os.Getenv("ANTHROPIC_API_KEY")
}
return llm.NewFromConfig(llmCfg, oaKey, orKey, anKey)
}
|