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
96
97
98
99
|
package lsp
import (
"strings"
"sync"
"codeberg.org/snonux/hexai/internal/appconfig"
"codeberg.org/snonux/hexai/internal/llm"
"codeberg.org/snonux/hexai/internal/logging"
)
type llmClientBuilder func(appconfig.App, string, string) (llm.Client, error)
type llmClientRegistry struct {
clientsMu sync.RWMutex
llmClient llm.Client
llmProvider string
altClients map[string]llm.Client
}
func newLLMClientRegistry() llmClientRegistry {
return llmClientRegistry{
altClients: make(map[string]llm.Client),
}
}
func (r *llmClientRegistry) applyOptions(client llm.Client, configuredProvider string) {
provider := canonicalProvider(configuredProvider)
if client != nil {
if name := canonicalProvider(client.Name()); name != "" {
provider = name
}
}
r.clientsMu.Lock()
defer r.clientsMu.Unlock()
r.llmClient = client
r.llmProvider = provider
r.altClients = make(map[string]llm.Client)
}
func (r *llmClientRegistry) current() llm.Client {
r.clientsMu.RLock()
defer r.clientsMu.RUnlock()
return r.llmClient
}
func (r *llmClientRegistry) clientFor(spec requestSpec, cfg appconfig.App, build llmClientBuilder) llm.Client {
provider := canonicalProvider(spec.provider)
r.clientsMu.RLock()
baseProvider := r.llmProvider
baseClient := r.llmClient
if baseClient != nil && strings.TrimSpace(baseProvider) == "" {
baseProvider = canonicalProvider(baseClient.Name())
}
if provider == "" {
provider = baseProvider
}
if provider == baseProvider && baseClient != nil {
r.clientsMu.RUnlock()
return baseClient
}
if cached, ok := r.altClients[provider]; ok {
r.clientsMu.RUnlock()
return cached
}
r.clientsMu.RUnlock()
modelOverride := strings.TrimSpace(spec.entry.Model)
if modelOverride == "" {
modelOverride = strings.TrimSpace(spec.fallbackModel)
}
client, err := build(cfg, provider, modelOverride)
if err != nil {
logging.Logf("lsp ", "failed to build client for provider=%s: %v", provider, err)
if baseClient != nil {
return baseClient
}
return nil
}
r.clientsMu.Lock()
defer r.clientsMu.Unlock()
if provider == r.llmProvider {
if r.llmClient == nil {
r.llmClient = client
r.llmProvider = provider
}
return r.llmClient
}
if existing, ok := r.altClients[provider]; ok {
return existing
}
if r.altClients == nil {
r.altClients = make(map[string]llm.Client)
}
r.altClients[provider] = client
return client
}
|