diff --git a/go.mod b/go.mod index 3c5d732389a9221ceb940873a659b497b6c695ec..b26254dfe659d962398c1e0704f8259faf19e89e 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,7 @@ require ( github.com/charmbracelet/x/exp/charmtone v0.0.0-20260109001716-2fbdffcb221f github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f github.com/charmbracelet/x/exp/ordered v0.1.0 - github.com/charmbracelet/x/exp/slice v0.0.0-20251201173703-9f73bfd934ff + github.com/charmbracelet/x/exp/slice v0.0.0-20260209194814-eeb2896ac759 github.com/charmbracelet/x/exp/strings v0.1.0 github.com/charmbracelet/x/powernap v0.0.0-20260209132835-6b065b8ba62c github.com/charmbracelet/x/term v0.2.2 diff --git a/go.sum b/go.sum index 6f9b10920535d8ad22a3c0786d2a3a3b5b68dd21..d7c510862fa0e34657869c99e853c371ccc9b6b4 100644 --- a/go.sum +++ b/go.sum @@ -116,8 +116,8 @@ github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f h1:pk6g github.com/charmbracelet/x/exp/golden v0.0.0-20250806222409-83e3a29d542f/go.mod h1:IfZAMTHB6XkZSeXUqriemErjAWCCzT0LwjKFYCZyw0I= github.com/charmbracelet/x/exp/ordered v0.1.0 h1:55/qLwjIh0gL0Vni+QAWk7T/qRVP6sBf+2agPBgnOFE= github.com/charmbracelet/x/exp/ordered v0.1.0/go.mod h1:5UHwmG+is5THxMyCJHNPCn2/ecI07aKNrW+LcResjJ8= -github.com/charmbracelet/x/exp/slice v0.0.0-20251201173703-9f73bfd934ff h1:Uwr+/JS+qnRcO/++xjYEDtW7x+P5E4+4cBiOHTt2Xfk= -github.com/charmbracelet/x/exp/slice v0.0.0-20251201173703-9f73bfd934ff/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA= +github.com/charmbracelet/x/exp/slice v0.0.0-20260209194814-eeb2896ac759 h1:96wFGlst+IDv3dIf5q29nw470wJYB3YAgemiciLZcG0= +github.com/charmbracelet/x/exp/slice v0.0.0-20260209194814-eeb2896ac759/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA= github.com/charmbracelet/x/exp/strings v0.1.0 h1:i69S2XI7uG1u4NLGeJPSYU++Nmjvpo9nwd6aoEm7gkA= github.com/charmbracelet/x/exp/strings v0.1.0/go.mod h1:/ehtMPNh9K4odGFkqYJKpIYyePhdp1hLBRvyY4bWkH8= github.com/charmbracelet/x/json v0.2.0 h1:DqB+ZGx2h+Z+1s98HOuOyli+i97wsFQIxP2ZQANTPrQ= diff --git a/internal/config/load.go b/internal/config/load.go index 0815f86d0faa4b94476c6c57670371b3eb5632f6..7753a50e25a4f6ed419feb1355a99c040a43d9e0 100644 --- a/internal/config/load.go +++ b/internal/config/load.go @@ -331,6 +331,11 @@ func (c *Config) configureProviders(env env.Env, resolver VariableResolver, know c.Providers.Set(id, providerConfig) } + + if c.Providers.Len() == 0 && c.Options.DisableDefaultProviders { + return fmt.Errorf("default providers are disabled and there are no custom providers are configured") + } + return nil } diff --git a/internal/config/load_test.go b/internal/config/load_test.go index 7229ac51d4a4c0616f268ea2a592cb12e1b818bb..93d2245193463e2a6539e23aeb0e16ac14c0ccef 100644 --- a/internal/config/load_test.go +++ b/internal/config/load_test.go @@ -1127,7 +1127,7 @@ func TestConfig_configureProvidersDisableDefaultProviders(t *testing.T) { }) resolver := NewEnvironmentVariableResolver(env) err := cfg.configureProviders(env, resolver, knownProviders) - require.NoError(t, err) + require.ErrorContains(t, err, "no custom providers") // openai should NOT be present because it lacks base_url and models. require.Equal(t, 0, cfg.Providers.Len()) @@ -1252,7 +1252,7 @@ func TestConfig_configureProvidersDisableDefaultProviders(t *testing.T) { env := env.NewFromMap(map[string]string{}) resolver := NewEnvironmentVariableResolver(env) err := cfg.configureProviders(env, resolver, []catwalk.Provider{}) - require.NoError(t, err) + require.ErrorContains(t, err, "no custom providers") // Provider should be rejected for missing models. require.Equal(t, 0, cfg.Providers.Len()) @@ -1276,7 +1276,7 @@ func TestConfig_configureProvidersDisableDefaultProviders(t *testing.T) { env := env.NewFromMap(map[string]string{}) resolver := NewEnvironmentVariableResolver(env) err := cfg.configureProviders(env, resolver, []catwalk.Provider{}) - require.NoError(t, err) + require.ErrorContains(t, err, "no custom providers") // Provider should be rejected for missing base_url. require.Equal(t, 0, cfg.Providers.Len()) diff --git a/internal/ui/dialog/models.go b/internal/ui/dialog/models.go index d77d8952fc1d9a413d35cc3a4c3ae315e0881c60..7594c2476218ae241c4b21cbb455b19f00923c47 100644 --- a/internal/ui/dialog/models.go +++ b/internal/ui/dialog/models.go @@ -4,7 +4,6 @@ import ( "cmp" "fmt" "slices" - "strings" "charm.land/bubbles/v2/help" "charm.land/bubbles/v2/key" @@ -15,6 +14,7 @@ import ( "github.com/charmbracelet/crush/internal/ui/common" "github.com/charmbracelet/crush/internal/ui/util" uv "github.com/charmbracelet/ultraviolet" + xslice "github.com/charmbracelet/x/exp/slice" ) // ModelType represents the type of model to select. @@ -143,12 +143,14 @@ func NewModels(com *common.Common, isOnboarding bool) (*Models, error) { ) m.keyMap.Close = CloseKey - providers, err := getFilteredProviders(com.Config()) - if err != nil { - return nil, fmt.Errorf("failed to get providers: %w", err) - } - - m.providers = providers + m.providers = slices.Collect( + xslice.Map( + com.Config().Providers.Seq(), + func(pc config.ProviderConfig) catwalk.Provider { + return pc.ToProvider() + }, + ), + ) if err := m.setProviderItems(); err != nil { return nil, fmt.Errorf("failed to set provider items: %w", err) } @@ -521,27 +523,6 @@ func (m *Models) setProviderItems() error { return nil } -func getFilteredProviders(cfg *config.Config) ([]catwalk.Provider, error) { - providers, err := config.Providers(cfg) - if err != nil { - return nil, fmt.Errorf("failed to get providers: %w", err) - } - var filteredProviders []catwalk.Provider - for _, p := range providers { - var ( - isAzure = p.ID == catwalk.InferenceProviderAzure - isCopilot = p.ID == catwalk.InferenceProviderCopilot - isHyper = string(p.ID) == "hyper" - hasAPIKeyEnv = strings.HasPrefix(p.APIKey, "$") - _, isConfigured = cfg.Providers.Get(string(p.ID)) - ) - if isAzure || isCopilot || isHyper || hasAPIKeyEnv || isConfigured { - filteredProviders = append(filteredProviders, p) - } - } - return filteredProviders, nil -} - func modelKey(providerID, modelID string) string { if providerID == "" || modelID == "" { return ""