Detailed changes
@@ -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
@@ -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=
@@ -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
}
@@ -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())
@@ -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 ""