on main help sign in
feat: allow for using CRUSH_ prefixed env-vars without clobbering default env vars (#391)
65cd249Tai Groot
internal/config/load.go+30−1
@@ -93,8 +93,38 @@ func Load(workingDir string, debug bool) (*Config, error) {
93 return cfg, nil
93 return cfg, nil
94}
94}
95
95
96+func PushPopCrushEnv() func() {
97+ found := []string{}
98+ for _, ev := range os.Environ() {
99+ if strings.HasPrefix(ev, "CRUSH_") {
100+ pair := strings.SplitN(ev, "=", 2)
101+ if len(pair) != 2 {
102+ continue
103+ }
104+ found = append(found, strings.TrimPrefix(pair[0], "CRUSH_"))
105+ }
106+ }
107+ backups := make(map[string]string)
108+ for _, ev := range found {
109+ backups[ev] = os.Getenv(ev)
110+ }
111+
112+ for _, ev := range found {
113+ os.Setenv(ev, os.Getenv("CRUSH_"+ev))
114+ }
115+
116+ restore := func() {
117+ for k, v := range backups {
118+ os.Setenv(k, v)
119+ }
120+ }
121+ return restore
122+}
123+
96func (c *Config) configureProviders(env env.Env, resolver VariableResolver, knownProviders []catwalk.Provider) error {
124func (c *Config) configureProviders(env env.Env, resolver VariableResolver, knownProviders []catwalk.Provider) error {
97 knownProviderNames := make(map[string]bool)
125 knownProviderNames := make(map[string]bool)
126+ restore := PushPopCrushEnv()
127+ defer restore()
98 for _, p := range knownProviders {
128 for _, p := range knownProviders {
99 knownProviderNames[string(p.ID)] = true
129 knownProviderNames[string(p.ID)] = true
100 config, configExists := c.Providers.Get(string(p.ID))
130 config, configExists := c.Providers.Get(string(p.ID))
@@ -495,7 +525,6 @@ func hasAWSCredentials(env env.Env) bool {
495 env.Get("AWS_CONTAINER_CREDENTIALS_FULL_URI") != "" {
525 env.Get("AWS_CONTAINER_CREDENTIALS_FULL_URI") != "" {
496 return true
526 return true
497 }
527 }
498−
499 return false
528 return false
500}
529}
501
530
internal/llm/provider/provider.go+3
@@ -5,6 +5,7 @@ import (
5 "fmt"
5 "fmt"
6
6
7 "github.com/charmbracelet/catwalk/pkg/catwalk"
7 "github.com/charmbracelet/catwalk/pkg/catwalk"
8+
8 "github.com/charmbracelet/crush/internal/config"
9 "github.com/charmbracelet/crush/internal/config"
9 "github.com/charmbracelet/crush/internal/llm/tools"
10 "github.com/charmbracelet/crush/internal/llm/tools"
10 "github.com/charmbracelet/crush/internal/message"
11 "github.com/charmbracelet/crush/internal/message"
@@ -139,6 +140,8 @@ func WithMaxTokens(maxTokens int64) ProviderClientOption {
139}
140}
140
141
141func NewProvider(cfg config.ProviderConfig, opts ...ProviderClientOption) (Provider, error) {
142func NewProvider(cfg config.ProviderConfig, opts ...ProviderClientOption) (Provider, error) {
143+ restore := config.PushPopCrushEnv()
144+ defer restore()
142 resolvedAPIKey, err := config.Get().Resolve(cfg.APIKey)
145 resolvedAPIKey, err := config.Get().Resolve(cfg.APIKey)
143 if err != nil {
146 if err != nil {
144 return nil, fmt.Errorf("failed to resolve API key for provider %s: %w", cfg.ID, err)
147 return nil, fmt.Errorf("failed to resolve API key for provider %s: %w", cfg.ID, err)