on main help sign in
chore: allow custom providers without api key
134ee54Kujtim Hoxha
internal/config/config.go+2
@@ -60,6 +60,8 @@ type SelectedModel struct {
60type ProviderConfig struct {
60type ProviderConfig struct {
61 // The provider's id.
61 // The provider's id.
62 ID string `json:"id,omitempty"`
62 ID string `json:"id,omitempty"`
63+ // The provider's name, used for display purposes.
64+ Name string `json:"name,omitempty"`
63 // The provider's API endpoint.
65 // The provider's API endpoint.
64 BaseURL string `json:"base_url,omitempty"`
66 BaseURL string `json:"base_url,omitempty"`
65 // The provider type, e.g. "openai", "anthropic", etc. if empty it defaults to openai.
67 // 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
162 }
162 }
163 prepared := ProviderConfig{
163 prepared := ProviderConfig{
164 ID: string(p.ID),
164 ID: string(p.ID),
165+ Name: p.Name,
165 BaseURL: p.APIEndpoint,
166 BaseURL: p.APIEndpoint,
166 APIKey: p.APIKey,
167 APIKey: p.APIKey,
167 Type: p.Type,
168 Type: p.Type,
@@ -218,6 +219,9 @@ func (cfg *Config) configureProviders(env env.Env, resolver VariableResolver, kn
218
219
219 // Make sure the provider ID is set
220 // Make sure the provider ID is set
220 providerConfig.ID = id
221 providerConfig.ID = id
222+ if providerConfig.Name == "" {
223+ providerConfig.Name = id // Use ID as name if not set
224+ }
221 // default to OpenAI if not set
225 // default to OpenAI if not set
222 if providerConfig.Type == "" {
226 if providerConfig.Type == "" {
223 providerConfig.Type = provider.TypeOpenAI
227 providerConfig.Type = provider.TypeOpenAI
@@ -229,9 +233,7 @@ func (cfg *Config) configureProviders(env env.Env, resolver VariableResolver, kn
229 continue
233 continue
230 }
234 }
231 if providerConfig.APIKey == "" {
235 if providerConfig.APIKey == "" {
232− slog.Warn("Skipping custom provider due to missing API key", "provider", id)
236+ slog.Warn("Provider is missing API key, this might be OK for local providers", "provider", id)
233− delete(cfg.Providers, id)
234− continue
235 }
237 }
236 if providerConfig.BaseURL == "" {
238 if providerConfig.BaseURL == "" {
237 slog.Warn("Skipping custom provider due to missing API endpoint", "provider", id)
239 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
251
253
252 apiKey, err := resolver.ResolveValue(providerConfig.APIKey)
254 apiKey, err := resolver.ResolveValue(providerConfig.APIKey)
253 if apiKey == "" || err != nil {
255 if apiKey == "" || err != nil {
254− slog.Warn("Skipping custom provider due to missing API key", "provider", id, "error", err)
256+ slog.Warn("Provider is missing API key, this might be OK for local providers", "provider", id)
255− delete(cfg.Providers, id)
256− continue
257 }
257 }
258 baseURL, err := resolver.ResolveValue(providerConfig.BaseURL)
258 baseURL, err := resolver.ResolveValue(providerConfig.BaseURL)
259 if baseURL == "" || err != nil {
259 if baseURL == "" || err != nil {
internal/config/load_test.go+6−3
@@ -483,7 +483,7 @@ func TestConfig_configureProvidersWithDisabledProvider(t *testing.T) {
483}
483}
484
484
485func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
485func 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) {
487 cfg := &Config{
487 cfg := &Config{
488 Providers: map[string]ProviderConfig{
488 Providers: map[string]ProviderConfig{
489 "custom": {
489 "custom": {
@@ -492,6 +492,9 @@ func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
492 ID: "test-model",
492 ID: "test-model",
493 }},
493 }},
494 },
494 },
495+ "openai": {
496+ APIKey: "$MISSING",
497+ },
495 },
498 },
496 }
499 }
497 cfg.setDefaults("/tmp")
500 cfg.setDefaults("/tmp")
@@ -501,9 +504,9 @@ func TestConfig_configureProvidersCustomProviderValidation(t *testing.T) {
501 err := cfg.configureProviders(env, resolver, []provider.Provider{})
504 err := cfg.configureProviders(env, resolver, []provider.Provider{})
502 assert.NoError(t, err)
505 assert.NoError(t, err)
503
506
504− assert.Len(t, cfg.Providers, 0)
507+ assert.Len(t, cfg.Providers, 1)
505 _, exists := cfg.Providers["custom"]
508 _, exists := cfg.Providers["custom"]
506− assert.False(t, exists)
509+ assert.True(t, exists)
507 })
510 })
508
511
509 t.Run("custom provider with missing BaseURL is removed", func(t *testing.T) {
512 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 {
104 if !slices.Contains(knownProviders, provider.InferenceProvider(providerID)) {
104 if !slices.Contains(knownProviders, provider.InferenceProvider(providerID)) {
105 // Convert config provider to provider.Provider format
105 // Convert config provider to provider.Provider format
106 configProvider := provider.Provider{
106 configProvider := provider.Provider{
107− Name: string(providerID), // Use provider ID as name for unknown providers
107+ Name: providerConfig.Name,
108 ID: provider.InferenceProvider(providerID),
108 ID: provider.InferenceProvider(providerID),
109 Models: make([]provider.Model, len(providerConfig.Models)),
109 Models: make([]provider.Model, len(providerConfig.Models)),
110 }
110 }