on main help sign in
chore: allow custom providers without api key

- allow users to setup custom providers without api keys for local providers - use the name of the provider in the model list

commit134ee540a4656a2bb2100286f49363a7614f2913 authorKujtim Hoxha <kujtimii.h@gmail.com> dateTue 8 Jul 2025, 18:17 (1 year ago) parent862baeb
4 files changed+15−10
internal/config/config.go+2 internal/config/load.go+6−6 internal/config/load_test.go+6−3 internal/tui/components/dialogs/models/list.go+1−1
internal/config/config.go+2
@@ -60,6 +60,8 @@ type SelectedModel struct {
6060type ProviderConfig struct {
6161 // The provider's id.
6262 ID string `json:"id,omitempty"`
63+ // The provider's name, used for display purposes.
64+ Name string `json:"name,omitempty"`
6365 // The provider's API endpoint.
6466 BaseURL string `json:"base_url,omitempty"`
6567 // The provider type, e.g. "openai", "anthropic", etc. if empty it defaults to openai.
internal/config/load.go+6−6
@@ -162,6 +162,7 @@ func (cfg *Config) configureProviders(env env.Env, resolver VariableResolver, kn
162162 }
163163 prepared := ProviderConfig{
164164 ID: string(p.ID),
165+ Name: p.Name,
165166 BaseURL: p.APIEndpoint,
166167 APIKey: p.APIKey,
167168 Type: p.Type,
@@ -218,6 +219,9 @@ func (cfg *Config) configureProviders(env env.Env, resolver VariableResolver, kn
218219
219220 // Make sure the provider ID is set
220221 providerConfig.ID = id
222+ if providerConfig.Name == "" {
223+ providerConfig.Name = id // Use ID as name if not set
224+ }
221225 // default to OpenAI if not set
222226 if providerConfig.Type == "" {
223227 providerConfig.Type = provider.TypeOpenAI
@@ -229,9 +233,7 @@ func (cfg *Config) configureProviders(env env.Env, resolver VariableResolver, kn
229233 continue
230234 }
231235 if providerConfig.APIKey == "" {
232− slog.Warn("Skipping custom provider due to missing API key", "provider", id)
233− delete(cfg.Providers, id)
234− continue
236+ slog.Warn("Provider is missing API key, this might be OK for local providers", "provider", id)
235237 }
236238 if providerConfig.BaseURL == "" {
237239 slog.Warn("Skipping custom provider due to missing API endpoint", "provider", id)
@@ -251,9 +253,7 @@ func (cfg *Config) configureProviders(env env.Env, resolver VariableResolver, kn
251253
252254 apiKey, err := resolver.ResolveValue(providerConfig.APIKey)
253255 if apiKey == "" || err != nil {
254− slog.Warn("Skipping custom provider due to missing API key", "provider", id, "error", err)
255− delete(cfg.Providers, id)
256− continue
256+ slog.Warn("Provider is missing API key, this might be OK for local providers", "provider", id)
257257 }
258258 baseURL, err := resolver.ResolveValue(providerConfig.BaseURL)
259259 if baseURL == "" || err != nil {
internal/config/load_test.go+6−3
@@ -483,7 +483,7 @@ func TestConfig_configureProvidersWithDisabledProvider(t *testing.T) {
483483}
484484
485485func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
486− t.Run("custom provider with missing API key is removed", func(t *testing.T) {
486+ t.Run("custom provider with missing API key is allowed, but not known providers", func(t *testing.T) {
487487 cfg := &Config{
488488 Providers: map[string]ProviderConfig{
489489 "custom": {
@@ -492,6 +492,9 @@ func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
492492 ID: "test-model",
493493 }},
494494 },
495+ "openai": {
496+ APIKey: "$MISSING",
497+ },
495498 },
496499 }
497500 cfg.setDefaults("/tmp")
@@ -501,9 +504,9 @@ func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
501504 err := cfg.configureProviders(env, resolver, []provider.Provider{})
502505 assert.NoError(t, err)
503506
504− assert.Len(t, cfg.Providers, 0)
507+ assert.Len(t, cfg.Providers, 1)
505508 _, exists := cfg.Providers["custom"]
506− assert.False(t, exists)
509+ assert.True(t, exists)
507510 })
508511
509512 t.Run("custom provider with missing BaseURL is removed", func(t *testing.T) {
internal/tui/components/dialogs/models/list.go+1−1
@@ -104,7 +104,7 @@ func (m *ModelListComponent) SetModelType(modelType int) tea.Cmd {
104104 if !slices.Contains(knownProviders, provider.InferenceProvider(providerID)) {
105105 // Convert config provider to provider.Provider format
106106 configProvider := provider.Provider{
107− Name: string(providerID), // Use provider ID as name for unknown providers
107+ Name: providerConfig.Name,
108108 ID: provider.InferenceProvider(providerID),
109109 Models: make([]provider.Model, len(providerConfig.Models)),
110110 }