on main help sign in
feat: allow to paste bedrock api keys (#2407)

Crush currently only allows to authentication on Bedrock via local setup (`aws login`) or `AWS_BEARER_TOKEN_BEDROCK`, but we weren't allowing the user to simply paste the API key in the input (validation was failed). If `AWS_BEARER_TOKEN_BEDROCK` works, there's no reason to not allow the user to simply paste that key.

commiteaa9a4a9bffb62a3adadc53986a51c033bece785 authorAndrey Nering <andreynering@users.noreply.github.com> dateFri 13 Mar 2026, 16:19 (7 months ago) parent451faa7
2 files changed+18−5
internal/agent/coordinator.go+9−5 internal/config/config.go+9
internal/agent/coordinator.go+9−5
@@ -725,7 +725,7 @@ func (c *coordinator) buildAzureProvider(baseURL, apiKey string, headers map[str
725725 return azure.New(opts...)
726726}
727727
728−func (c *coordinator) buildBedrockProvider(headers map[string]string) (fantasy.Provider, error) {
728+func (c *coordinator) buildBedrockProvider(apiKey string, headers map[string]string) (fantasy.Provider, error) {
729729 var opts []bedrock.Option
730730 if c.cfg.Config().Options.Debug {
731731 httpClient := log.NewHTTPClient()
@@ -734,9 +734,13 @@ func (c *coordinator) buildBedrockProvider(headers map[string]string) (fantasy.P
734734 if len(headers) > 0 {
735735 opts = append(opts, bedrock.WithHeaders(headers))
736736 }
737− bearerToken := os.Getenv("AWS_BEARER_TOKEN_BEDROCK")
738− if bearerToken != "" {
739− opts = append(opts, bedrock.WithAPIKey(bearerToken))
737+ switch {
738+ case apiKey != "":
739+ opts = append(opts, bedrock.WithAPIKey(apiKey))
740+ case os.Getenv("AWS_BEARER_TOKEN_BEDROCK") != "":
741+ opts = append(opts, bedrock.WithAPIKey(os.Getenv("AWS_BEARER_TOKEN_BEDROCK")))
742+ default:
743+ // Skip, let the SDK do authentication.
740744 }
741745 return bedrock.New(opts...)
742746}
@@ -824,7 +828,7 @@ func (c *coordinator) buildProvider(providerCfg config.ProviderConfig, model con
824828 case azure.Name:
825829 return c.buildAzureProvider(baseURL, apiKey, headers, providerCfg.ExtraParams)
826830 case bedrock.Name:
827− return c.buildBedrockProvider(headers)
831+ return c.buildBedrockProvider(apiKey, headers)
828832 case google.Name:
829833 return c.buildGoogleProvider(baseURL, apiKey, headers)
830834 case "google-vertex":
internal/config/config.go+9
@@ -3,6 +3,7 @@ package config
33import (
44 "cmp"
55 "context"
6+ "errors"
67 "fmt"
78 "log/slog"
89 "maps"
@@ -584,6 +585,14 @@ func (c *ProviderConfig) TestConnection(resolver VariableResolver) error {
584585 baseURL, _ := resolver.ResolveValue(c.BaseURL)
585586 baseURL = cmp.Or(baseURL, "https://generativelanguage.googleapis.com")
586587 testURL = baseURL + "/v1beta/models?key=" + url.QueryEscape(apiKey)
588+ case catwalk.TypeBedrock:
589+ // NOTE: Bedrock has a `/foundation-models` endpoint that we could in
590+ // theory use, but apparently the authorization is region-specific,
591+ // so it's not so trivial.
592+ if strings.HasPrefix(apiKey, "ABSK") { // Bedrock API keys
593+ return nil
594+ }
595+ return errors.New("not a valid bedrock api key")
587596 }
588597
589598 ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)