Skip to content

Commit 304f4e8

Browse files
committed
refactor(provider): split provider.go into aliases / defaults / factory
provider.go had grown to ~600 lines mixing four concerns: the alias registry, config defaults / merging, the dispatch logic that picks a concrete provider client, and the public Provider interfaces. This commit splits it into four focused files with a short package doc comment that explains the layout, while preserving every symbol and its visibility: * provider.go - public Provider interfaces and the New / NewWithModels entry points only. * aliases.go - Alias struct, the Aliases table, LookupAlias, EachAlias, and the AllProviders / IsKnownProvider / CatalogProviders / IsCatalogProvider helpers built on top of it. * defaults.go - applyProviderDefaults and its helpers (mergeFromProviderConfig, applyAliasFallbacks, setIfNil, setProviderOptIfAbsent, cloneModelConfig), the model-defaults logic (applyModelDefaults, ensureInterleavedThinking), and the model-name predicates (isOpenAIThinkingOnlyModel, isBedrockClaudeModel, gemini3Family, ...). Also hosts resolveProviderType / resolveEffectiveProvider / isOpenAICompatibleProvider since they participate in the same merge pipeline. * factory.go - createDirectProvider, the providerFactory type and providerFactories registry, the per-provider factory functions, the resolveRoutedModel helper and the createRuleBasedRouter wrapper. Pure code reorganisation: no behaviour change, no API change. go test ./pkg/model/provider/... and golangci-lint both pass. Assisted-By: docker-agent
1 parent 84e8306 commit 304f4e8

4 files changed

Lines changed: 587 additions & 548 deletions

File tree

pkg/model/provider/aliases.go

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package provider
2+
3+
import (
4+
"iter"
5+
"maps"
6+
"slices"
7+
"strings"
8+
)
9+
10+
// Alias defines the configuration for a provider alias.
11+
type Alias struct {
12+
APIType string // The actual API type to use (openai, anthropic, etc.)
13+
BaseURL string // Default base URL for the provider
14+
TokenEnvVar string // Environment variable name for the API token
15+
}
16+
17+
// CoreProviders lists all natively implemented provider types.
18+
// These are the provider types that have direct implementations (not aliases).
19+
var CoreProviders = []string{
20+
"openai",
21+
"anthropic",
22+
"google",
23+
"dmr",
24+
"amazon-bedrock",
25+
}
26+
27+
// Aliases maps provider names to their corresponding configurations.
28+
//
29+
// Most consumers should call [LookupAlias] for a single lookup or [EachAlias]
30+
// to iterate, both of which keep the rest of the codebase decoupled from this
31+
// concrete map. Direct mutation of Aliases is not supported.
32+
var Aliases = map[string]Alias{
33+
"requesty": {
34+
APIType: "openai",
35+
BaseURL: "https://router.requesty.ai/v1",
36+
TokenEnvVar: "REQUESTY_API_KEY",
37+
},
38+
"azure": {
39+
APIType: "openai",
40+
TokenEnvVar: "AZURE_API_KEY",
41+
},
42+
"xai": {
43+
APIType: "openai",
44+
BaseURL: "https://api.x.ai/v1",
45+
TokenEnvVar: "XAI_API_KEY",
46+
},
47+
"nebius": {
48+
APIType: "openai",
49+
BaseURL: "https://api.studio.nebius.com/v1",
50+
TokenEnvVar: "NEBIUS_API_KEY",
51+
},
52+
"mistral": {
53+
APIType: "openai",
54+
BaseURL: "https://api.mistral.ai/v1",
55+
TokenEnvVar: "MISTRAL_API_KEY",
56+
},
57+
"ollama": {
58+
APIType: "openai",
59+
BaseURL: "http://localhost:11434/v1",
60+
},
61+
"minimax": {
62+
APIType: "openai",
63+
BaseURL: "https://api.minimax.io/v1",
64+
TokenEnvVar: "MINIMAX_API_KEY",
65+
},
66+
"github-copilot": {
67+
APIType: "openai",
68+
BaseURL: "https://api.githubcopilot.com",
69+
TokenEnvVar: "GITHUB_TOKEN",
70+
},
71+
}
72+
73+
// LookupAlias returns the Alias registered for the given name (if any).
74+
// Lookup is case-sensitive; callers that need case-insensitive matching
75+
// should normalise the name first (e.g. [strings.ToLower]).
76+
func LookupAlias(name string) (Alias, bool) {
77+
alias, ok := Aliases[name]
78+
return alias, ok
79+
}
80+
81+
// EachAlias returns an iterator over every registered (name, Alias) pair.
82+
// Iteration order is not guaranteed; callers that need a deterministic order
83+
// should sort by name.
84+
func EachAlias() iter.Seq2[string, Alias] {
85+
return func(yield func(string, Alias) bool) {
86+
for name, alias := range Aliases {
87+
if !yield(name, alias) {
88+
return
89+
}
90+
}
91+
}
92+
}
93+
94+
// AllProviders returns all known provider names (core providers + aliases),
95+
// sorted for deterministic output.
96+
func AllProviders() []string {
97+
providers := slices.Concat(CoreProviders, slices.Collect(maps.Keys(Aliases)))
98+
slices.Sort(providers)
99+
return providers
100+
}
101+
102+
// IsKnownProvider returns true if the provider name is a core provider or an alias.
103+
func IsKnownProvider(name string) bool {
104+
if slices.Contains(CoreProviders, strings.ToLower(name)) {
105+
return true
106+
}
107+
_, exists := LookupAlias(strings.ToLower(name))
108+
return exists
109+
}
110+
111+
// CatalogProviders returns the list of provider names that should be shown in the model catalog.
112+
// This includes core providers and aliases that have a defined BaseURL (self-contained endpoints).
113+
// Aliases without a BaseURL (like azure) require user configuration and are excluded.
114+
func CatalogProviders() []string {
115+
providers := make([]string, 0, len(CoreProviders)+len(Aliases))
116+
117+
// Add all core providers
118+
providers = append(providers, CoreProviders...)
119+
120+
// Add aliases that have a defined BaseURL (they work out of the box)
121+
for name, alias := range EachAlias() {
122+
if alias.BaseURL != "" {
123+
providers = append(providers, name)
124+
}
125+
}
126+
127+
return providers
128+
}
129+
130+
// IsCatalogProvider returns true if the provider name is valid for the model catalog.
131+
func IsCatalogProvider(name string) bool {
132+
// Check core providers
133+
if slices.Contains(CoreProviders, name) {
134+
return true
135+
}
136+
// Check aliases with BaseURL
137+
if alias, exists := LookupAlias(name); exists && alias.BaseURL != "" {
138+
return true
139+
}
140+
return false
141+
}

0 commit comments

Comments
 (0)