diff options
| author | Paul Buetow <paul@buetow.org> | 2026-03-23 09:04:17 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-03-23 09:04:17 +0200 |
| commit | 462184dff3eef32f01f06634305da1355ac1bec2 (patch) | |
| tree | 026ffaaeacfe152957298c985e1df77ff661b723 /internal/llm/provider.go | |
| parent | 667f2d3384643aa877de2eefcbad3923965bad09 (diff) | |
chore: bump version to v0.25.9v0.25.9
Code quality fixes from audit:
- Log silently discarded errors in status sinks and stats.Update call sites
- Fix json.Marshal errors silently ignored in LSP handlers
- Replace time.Sleep in tests with channel signaling (mcp) and fake clock (stats)
- Make context cancellation work in production time.Sleep sites (handlers_document, cmdentry)
- Remove init()-based provider registration from llm package; use explicit RegisterAllProviders()
- Add WaitGroup goroutine tracking to MCP server Run()
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/llm/provider.go')
| -rw-r--r-- | internal/llm/provider.go | 29 |
1 files changed, 19 insertions, 10 deletions
diff --git a/internal/llm/provider.go b/internal/llm/provider.go index 3c72181..6c0c04b 100644 --- a/internal/llm/provider.go +++ b/internal/llm/provider.go @@ -103,20 +103,17 @@ type ProviderKeys struct { // ProviderFactory builds an LLM client for a named provider. type ProviderFactory func(cfg Config, keys ProviderKeys) (Client, error) -// providerRegistry is a package-level singleton populated by init() calls in -// each provider file (anthropic.go, openai.go, etc.). It must be a -// package-level var — rather than a constructor argument — because Go's -// init() mechanism runs before any application code, and the alternative -// (an explicit RegisterAll() in main) would require every binary that uses -// the llm package to manually enumerate all providers. The RWMutex makes the -// map safe for the rare case where RegisterProvider is called from a test -// goroutine after init() has completed. +// providerRegistry is a package-level singleton populated via RegisterAllProviders. +// Callers (binaries and tests) must call RegisterAllProviders before creating any +// clients. The RWMutex makes the map safe for concurrent reads once populated. var ( - providerRegistryMu sync.RWMutex - providerRegistry = map[string]ProviderFactory{} + providerRegistryMu sync.RWMutex + providerRegistry = map[string]ProviderFactory{} + registerProvidersOnce sync.Once ) // RegisterProvider registers a provider factory by normalized name. +// Panics on empty name, nil factory, or duplicate registration. func RegisterProvider(name string, factory ProviderFactory) { normalized := normalizeProvider(name) if normalized == "" { @@ -133,6 +130,18 @@ func RegisterProvider(name string, factory ProviderFactory) { providerRegistry[normalized] = factory } +// RegisterAllProviders registers all built-in LLM providers (anthropic, openai, +// openrouter, ollama). It is safe to call from multiple entry points because the +// actual registration runs only once via sync.Once. +func RegisterAllProviders() { + registerProvidersOnce.Do(func() { + RegisterProvider("anthropic", anthropicProviderFactory) + RegisterProvider("openai", openAIProviderFactory) + RegisterProvider("openrouter", openRouterProviderFactory) + RegisterProvider("ollama", ollamaProviderFactory) + }) +} + // NewFromConfig creates an LLM client using only the supplied configuration. // The OpenAI API key is supplied separately and may be read from the environment // by the caller; other environment-based configuration is not used. |
