Skip to content

Commit 79119e3

Browse files
authored
provider: list Bedrock models dynamically
1 parent 8ffdc6c commit 79119e3

5 files changed

Lines changed: 284 additions & 16 deletions

File tree

‎go.mod‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,9 @@ require (
77
github.com/GoCodeAlone/workflow v0.85.2
88
github.com/GoCodeAlone/workflow-plugin-authz v0.5.4
99
github.com/anthropics/anthropic-sdk-go v1.26.0
10-
github.com/aws/aws-sdk-go-v2 v1.41.6
10+
github.com/aws/aws-sdk-go-v2 v1.42.1
1111
github.com/aws/aws-sdk-go-v2/credentials v1.19.15
12+
github.com/aws/aws-sdk-go-v2/service/bedrock v1.64.2
1213
github.com/bmatcuk/doublestar/v4 v4.10.0
1314
github.com/coder/acp-go-sdk v0.6.3
1415
github.com/creack/pty v1.1.24
@@ -56,8 +57,8 @@ require (
5657
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 // indirect
5758
github.com/aws/aws-sdk-go-v2/config v1.32.16 // indirect
5859
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 // indirect
59-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 // indirect
60-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 // indirect
60+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30 // indirect
61+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30 // indirect
6162
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 // indirect
6263
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 // indirect
6364
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 // indirect
@@ -66,7 +67,7 @@ require (
6667
github.com/aws/aws-sdk-go-v2/service/sso v1.30.16 // indirect
6768
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 // indirect
6869
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 // indirect
69-
github.com/aws/smithy-go v1.25.0 // indirect
70+
github.com/aws/smithy-go v1.27.3 // indirect
7071
github.com/bahlo/generic-list-go v0.2.0 // indirect
7172
github.com/beorn7/perks v1.0.1 // indirect
7273
github.com/bits-and-blooms/bitset v1.24.5 // indirect

‎go.sum‎

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -64,8 +64,8 @@ github.com/antithesishq/antithesis-sdk-go v0.7.2 h1:oEEedg1Xgi8drRjqB0f9tfjhLoIn
6464
github.com/antithesishq/antithesis-sdk-go v0.7.2/go.mod h1:FQyySiasQQM8735Ddel3MRojmy4dA1IqCeyJ5jmPMbI=
6565
github.com/armon/go-metrics v0.4.1 h1:hR91U9KYmb6bLBYLQjyM+3j+rcd/UhE+G78SFnF8gJA=
6666
github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+3JqfkOG4=
67-
github.com/aws/aws-sdk-go-v2 v1.41.6 h1:1AX0AthnBQzMx1vbmir3Y4WsnJgiydmnJjiLu+LvXOg=
68-
github.com/aws/aws-sdk-go-v2 v1.41.6/go.mod h1:dy0UzBIfwSeot4grGvY1AqFWN5zgziMmWGzysDnHFcQ=
67+
github.com/aws/aws-sdk-go-v2 v1.42.1 h1:9eOTgu1z/dVtYpNZ3/8/XbbaX0x/BqE3HUzAzs6K0ek=
68+
github.com/aws/aws-sdk-go-v2 v1.42.1/go.mod h1:5pKeft2eJj+gElQ38Jqg4ibCqh+/AK33/0X3hip7IjM=
6969
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8 h1:eBMB84YGghSocM7PsjmmPffTa+1FBUeNvGvFou6V/4o=
7070
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.8/go.mod h1:lyw7GFp3qENLh7kwzf7iMzAxDn+NzjXEAGjKS2UOKqI=
7171
github.com/aws/aws-sdk-go-v2/config v1.32.16 h1:Q0iQ7quUgJP0F/SCRTieScnaMdXr9h/2+wze1u3cNeM=
@@ -74,12 +74,14 @@ github.com/aws/aws-sdk-go-v2/credentials v1.19.15 h1:fyvgWTszojq8hEnMi8PPBTvZdTt
7474
github.com/aws/aws-sdk-go-v2/credentials v1.19.15/go.mod h1:gJiYyMOjNg8OEdRWOf3CrFQxM2a98qmrtjx1zuiQfB8=
7575
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22 h1:IOGsJ1xVWhsi+ZO7/NW8OuZZBtMJLZbk4P5HDjJO0jQ=
7676
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.18.22/go.mod h1:b+hYdbU+jGKfXE8kKM6g1+h+L/Go3vMvzlxBsiuGsxg=
77-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22 h1:GmLa5Kw1ESqtFpXsx5MmC84QWa/ZrLZvlJGa2y+4kcQ=
78-
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.22/go.mod h1:6sW9iWm9DK9YRpRGga/qzrzNLgKpT2cIxb7Vo2eNOp0=
79-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22 h1:dY4kWZiSaXIzxnKlj17nHnBcXXBfac6UlsAx2qL6XrU=
80-
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.22/go.mod h1:KIpEUx0JuRZLO7U6cbV204cWAEco2iC3l061IxlwLtI=
77+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30 h1:xM/Is9cKMHa8Jj8zkvWhvrFkZsXJV9E+BB4g0HW0duQ=
78+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.30/go.mod h1:WueJeNDZvK1fMYEWJIkcivBfEzUkTpBhzlrUKKY8EuA=
79+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30 h1:jn46zC9LdsVR/ZpMIJqMqb8hHv31BlLx3ulVqNspUOk=
80+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.30/go.mod h1:1hTMsAgbdS/AtUi4bw8+gUuh1pceo+eXRLfpSuSQj3M=
8181
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23 h1:FPXsW9+gMuIeKmz7j6ENWcWtBGTe1kH8r9thNt5Uxx4=
8282
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.23/go.mod h1:7J8iGMdRKk6lw2C+cMIphgAnT8uTwBwNOsGkyOCm80U=
83+
github.com/aws/aws-sdk-go-v2/service/bedrock v1.64.2 h1:TYXv5HG0jLpgeLa8huezwTCTJS2VKnQknkVyRIEZZSY=
84+
github.com/aws/aws-sdk-go-v2/service/bedrock v1.64.2/go.mod h1:pYNYOEFQKBsKwkNQZjVwEuPFTkmSLvAsbSd0HZUwiDw=
8385
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8 h1:HtOTYcbVcGABLOVuPYaIihj6IlkqubBwFj10K5fxRek=
8486
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.8/go.mod h1:VsK9abqQeGlzPgUr+isNWzPlK2vKe9INMLWnY65f5Xs=
8587
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.22 h1:PUmZeJU6Y1Lbvt9WFuJ0ugUK2xn6hIWUBBbKuOWF30s=
@@ -94,8 +96,8 @@ github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20 h1:oK/njaL8GtyEihkWMD4k3Vg
9496
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.35.20/go.mod h1:JHs8/y1f3zY7U5WcuzoJ/yAYGYtNIVPKLIbp61euvmg=
9597
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0 h1:ks8KBcZPh3PYISr5dAiXCM5/Thcuxk8l+PG4+A0exds=
9698
github.com/aws/aws-sdk-go-v2/service/sts v1.42.0/go.mod h1:pFw33T0WLvXU3rw1WBkpMlkgIn54eCB5FYLhjDc9Foo=
97-
github.com/aws/smithy-go v1.25.0 h1:Sz/XJ64rwuiKtB6j98nDIPyYrV1nVNJ4YU74gttcl5U=
98-
github.com/aws/smithy-go v1.25.0/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
99+
github.com/aws/smithy-go v1.27.3 h1:F3Zb497UhhskkfpJmfkXswyo+t0sh9OTBnIHjogWbVY=
100+
github.com/aws/smithy-go v1.27.3/go.mod h1:YE2RhdIuDbA5E5bTdciG9KrW3+TiEONeUWCqxX9i1Fc=
99101
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
100102
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
101103
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=

‎provider/bedrock_models_test.go‎

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
package provider
2+
3+
import (
4+
"context"
5+
"errors"
6+
"testing"
7+
8+
awsbedrock "github.com/aws/aws-sdk-go-v2/service/bedrock"
9+
"github.com/aws/aws-sdk-go-v2/service/bedrock/types"
10+
)
11+
12+
type fakeBedrockModelLister struct {
13+
input *awsbedrock.ListFoundationModelsInput
14+
out *awsbedrock.ListFoundationModelsOutput
15+
err error
16+
}
17+
18+
func (f *fakeBedrockModelLister) ListFoundationModels(ctx context.Context, in *awsbedrock.ListFoundationModelsInput, optFns ...func(*awsbedrock.Options)) (*awsbedrock.ListFoundationModelsOutput, error) {
19+
f.input = in
20+
return f.out, f.err
21+
}
22+
23+
func TestListBedrockModelsFromAPIListsAnthropicTextModels(t *testing.T) {
24+
streaming := true
25+
api := &fakeBedrockModelLister{out: &awsbedrock.ListFoundationModelsOutput{
26+
ModelSummaries: []types.FoundationModelSummary{
27+
{
28+
ModelId: strPtr("anthropic.claude-sonnet-4-20250514-v1:0"),
29+
ModelName: strPtr("Claude Sonnet 4"),
30+
ProviderName: strPtr("Anthropic"),
31+
OutputModalities: []types.ModelModality{types.ModelModalityText},
32+
InferenceTypesSupported: []types.InferenceType{types.InferenceTypeOnDemand},
33+
ResponseStreamingSupported: &streaming,
34+
},
35+
{
36+
ModelId: strPtr("amazon.titan-text-lite-v1"),
37+
ModelName: strPtr("Titan Text Lite"),
38+
ProviderName: strPtr("Amazon"),
39+
OutputModalities: []types.ModelModality{types.ModelModalityText},
40+
InferenceTypesSupported: []types.InferenceType{types.InferenceTypeOnDemand},
41+
ResponseStreamingSupported: &streaming,
42+
},
43+
{
44+
ModelId: strPtr("anthropic.claude-image-only"),
45+
ModelName: strPtr("Claude Image Only"),
46+
ProviderName: strPtr("Anthropic"),
47+
OutputModalities: []types.ModelModality{types.ModelModalityImage},
48+
InferenceTypesSupported: []types.InferenceType{types.InferenceTypeOnDemand},
49+
},
50+
},
51+
}}
52+
53+
models, err := listBedrockModelsFromAPI(context.Background(), api)
54+
if err != nil {
55+
t.Fatalf("listBedrockModelsFromAPI: %v", err)
56+
}
57+
if api.input == nil {
58+
t.Fatal("ListFoundationModels was not called")
59+
}
60+
if api.input.ByProvider == nil || *api.input.ByProvider != "Anthropic" {
61+
t.Fatalf("ByProvider = %#v", api.input.ByProvider)
62+
}
63+
if api.input.ByOutputModality != types.ModelModalityText {
64+
t.Fatalf("ByOutputModality = %q", api.input.ByOutputModality)
65+
}
66+
if api.input.ByInferenceType != types.InferenceTypeOnDemand {
67+
t.Fatalf("ByInferenceType = %q", api.input.ByInferenceType)
68+
}
69+
if len(models) != 1 {
70+
t.Fatalf("models = %+v", models)
71+
}
72+
if models[0].ID != "anthropic.claude-sonnet-4-20250514-v1:0" {
73+
t.Fatalf("model ID = %q", models[0].ID)
74+
}
75+
if models[0].Name != "Anthropic Claude Sonnet 4" {
76+
t.Fatalf("model name = %q", models[0].Name)
77+
}
78+
}
79+
80+
func TestListBedrockModelsFromAPIReturnsErrors(t *testing.T) {
81+
api := &fakeBedrockModelLister{err: errors.New("access denied")}
82+
_, err := listBedrockModelsFromAPI(context.Background(), api)
83+
if err == nil {
84+
t.Fatal("expected error")
85+
}
86+
}
87+
88+
func TestListModelsWithSettingsBedrockRequiresCredentials(t *testing.T) {
89+
_, err := ListModelsWithSettings(context.Background(), "anthropic_bedrock", "", "", nil)
90+
if err == nil {
91+
t.Fatal("expected missing credentials error")
92+
}
93+
}
94+
95+
func TestBedrockModelListConfigFromJSONCredentials(t *testing.T) {
96+
cfg, err := bedrockModelListConfigFromRequest(ModelListRequest{
97+
APIKey: `{"region":"us-west-2","access_key_id":"AKIAEXAMPLE","secret_access_key":"secret","session_token":"token"}`,
98+
})
99+
if err != nil {
100+
t.Fatalf("bedrockModelListConfigFromRequest: %v", err)
101+
}
102+
if cfg.Region != "us-west-2" {
103+
t.Fatalf("Region = %q", cfg.Region)
104+
}
105+
if cfg.AccessKeyID != "AKIAEXAMPLE" {
106+
t.Fatalf("AccessKeyID = %q", cfg.AccessKeyID)
107+
}
108+
if cfg.SecretAccessKey != "secret" {
109+
t.Fatalf("SecretAccessKey = %q", cfg.SecretAccessKey)
110+
}
111+
if cfg.SessionToken != "token" {
112+
t.Fatalf("SessionToken = %q", cfg.SessionToken)
113+
}
114+
}
115+
116+
func strPtr(s string) *string { return &s }

‎provider/models.go‎

Lines changed: 152 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,10 @@ import (
1010
"sort"
1111
"strings"
1212

13+
"github.com/aws/aws-sdk-go-v2/aws"
14+
"github.com/aws/aws-sdk-go-v2/credentials"
15+
awsbedrock "github.com/aws/aws-sdk-go-v2/service/bedrock"
16+
bedrocktypes "github.com/aws/aws-sdk-go-v2/service/bedrock/types"
1317
"github.com/google/generative-ai-go/genai"
1418
"google.golang.org/api/iterator"
1519
googleoption "google.golang.org/api/option"
@@ -26,6 +30,7 @@ type ModelListRequest struct {
2630
ProviderType string
2731
APIKey string
2832
BaseURL string
33+
Settings map[string]string
2934
}
3035

3136
type ModelLister func(ctx context.Context, req ModelListRequest) ([]ModelInfo, error)
@@ -53,11 +58,15 @@ type copilotTokenResponse struct {
5358
// ListModels fetches available models from the given provider type.
5459
// Only requires an API key and optional base URL — no saved provider needed.
5560
func ListModels(ctx context.Context, providerType, apiKey, baseURL string) ([]ModelInfo, error) {
61+
return ListModelsWithSettings(ctx, providerType, apiKey, baseURL, nil)
62+
}
63+
64+
func ListModelsWithSettings(ctx context.Context, providerType, apiKey, baseURL string, settings map[string]string) ([]ModelInfo, error) {
5665
lister, ok := modelListers[providerType]
5766
if !ok {
5867
return nil, fmt.Errorf("unsupported provider type: %s", providerType)
5968
}
60-
return lister(ctx, ModelListRequest{ProviderType: providerType, APIKey: apiKey, BaseURL: baseURL})
69+
return lister(ctx, ModelListRequest{ProviderType: providerType, APIKey: apiKey, BaseURL: baseURL, Settings: settings})
6170
}
6271

6372
var modelListers = map[string]ModelLister{
@@ -90,8 +99,8 @@ var modelListers = map[string]ModelLister{
9099
"openai_azure": func(context.Context, ModelListRequest) ([]ModelInfo, error) {
91100
return nil, dynamicModelListingUnsupported("openai_azure")
92101
},
93-
"anthropic_bedrock": func(context.Context, ModelListRequest) ([]ModelInfo, error) {
94-
return nil, dynamicModelListingUnsupported("anthropic_bedrock")
102+
"anthropic_bedrock": func(ctx context.Context, req ModelListRequest) ([]ModelInfo, error) {
103+
return listBedrockModels(ctx, req)
95104
},
96105
"anthropic_vertex": func(context.Context, ModelListRequest) ([]ModelInfo, error) {
97106
return nil, dynamicModelListingUnsupported("anthropic_vertex")
@@ -604,6 +613,146 @@ func dynamicModelListingUnsupported(providerType string) error {
604613
return fmt.Errorf("%s: dynamic model listing is not implemented for this provider; specify a custom model ID", providerType)
605614
}
606615

616+
type bedrockModelListConfig struct {
617+
Region string
618+
AccessKeyID string
619+
SecretAccessKey string
620+
SessionToken string
621+
}
622+
623+
type bedrockFoundationModelLister interface {
624+
ListFoundationModels(context.Context, *awsbedrock.ListFoundationModelsInput, ...func(*awsbedrock.Options)) (*awsbedrock.ListFoundationModelsOutput, error)
625+
}
626+
627+
func bedrockModelListConfigFromRequest(req ModelListRequest) (bedrockModelListConfig, error) {
628+
cfg := bedrockModelListConfig{
629+
Region: req.Settings["region"],
630+
AccessKeyID: req.Settings["access_key_id"],
631+
SecretAccessKey: req.APIKey,
632+
SessionToken: req.Settings["session_token"],
633+
}
634+
if strings.TrimSpace(req.APIKey) != "" && strings.HasPrefix(strings.TrimSpace(req.APIKey), "{") {
635+
var secret struct {
636+
Region string `json:"region"`
637+
AccessKeyID string `json:"access_key_id"`
638+
SecretAccessKey string `json:"secret_access_key"`
639+
SessionToken string `json:"session_token"`
640+
}
641+
if err := json.Unmarshal([]byte(req.APIKey), &secret); err != nil {
642+
return bedrockModelListConfig{}, fmt.Errorf("anthropic_bedrock: parse credential JSON: %w", err)
643+
}
644+
cfg.SecretAccessKey = ""
645+
if cfg.Region == "" {
646+
cfg.Region = secret.Region
647+
}
648+
if cfg.AccessKeyID == "" {
649+
cfg.AccessKeyID = secret.AccessKeyID
650+
}
651+
if cfg.SecretAccessKey == "" {
652+
cfg.SecretAccessKey = secret.SecretAccessKey
653+
}
654+
if cfg.SessionToken == "" {
655+
cfg.SessionToken = secret.SessionToken
656+
}
657+
}
658+
if cfg.Region == "" {
659+
cfg.Region = defaultBedrockRegion
660+
}
661+
cfg.AccessKeyID = strings.TrimSpace(cfg.AccessKeyID)
662+
cfg.SecretAccessKey = strings.TrimSpace(cfg.SecretAccessKey)
663+
cfg.SessionToken = strings.TrimSpace(cfg.SessionToken)
664+
if cfg.AccessKeyID == "" {
665+
return bedrockModelListConfig{}, fmt.Errorf("anthropic_bedrock: access_key_id setting is required for model discovery")
666+
}
667+
if cfg.SecretAccessKey == "" {
668+
return bedrockModelListConfig{}, fmt.Errorf("anthropic_bedrock: secret access key is required for model discovery")
669+
}
670+
return cfg, nil
671+
}
672+
673+
func listBedrockModels(ctx context.Context, req ModelListRequest) ([]ModelInfo, error) {
674+
if err := ValidateBaseURL(req.BaseURL); err != nil {
675+
return nil, err
676+
}
677+
cfg, err := bedrockModelListConfigFromRequest(req)
678+
if err != nil {
679+
return nil, err
680+
}
681+
awsCfg := aws.Config{
682+
Region: cfg.Region,
683+
Credentials: credentials.NewStaticCredentialsProvider(cfg.AccessKeyID, cfg.SecretAccessKey, cfg.SessionToken),
684+
HTTPClient: modelHTTPClient,
685+
}
686+
opts := []func(*awsbedrock.Options){}
687+
if req.BaseURL != "" {
688+
opts = append(opts, func(o *awsbedrock.Options) {
689+
o.BaseEndpoint = aws.String(strings.TrimRight(req.BaseURL, "/"))
690+
})
691+
}
692+
return listBedrockModelsFromAPI(ctx, awsbedrock.NewFromConfig(awsCfg, opts...))
693+
}
694+
695+
func listBedrockModelsFromAPI(ctx context.Context, api bedrockFoundationModelLister) ([]ModelInfo, error) {
696+
out, err := api.ListFoundationModels(ctx, &awsbedrock.ListFoundationModelsInput{
697+
ByProvider: aws.String("Anthropic"),
698+
ByOutputModality: bedrocktypes.ModelModalityText,
699+
ByInferenceType: bedrocktypes.InferenceTypeOnDemand,
700+
})
701+
if err != nil {
702+
return nil, fmt.Errorf("anthropic_bedrock: list foundation models: %w", err)
703+
}
704+
models := make([]ModelInfo, 0, len(out.ModelSummaries))
705+
for _, summary := range out.ModelSummaries {
706+
id := strings.TrimSpace(aws.ToString(summary.ModelId))
707+
if id == "" {
708+
continue
709+
}
710+
if providerName := strings.TrimSpace(aws.ToString(summary.ProviderName)); providerName != "" && !strings.EqualFold(providerName, "Anthropic") {
711+
continue
712+
}
713+
if len(summary.OutputModalities) > 0 && !modelModalitiesContain(summary.OutputModalities, bedrocktypes.ModelModalityText) {
714+
continue
715+
}
716+
if len(summary.InferenceTypesSupported) > 0 && !inferenceTypesContain(summary.InferenceTypesSupported, bedrocktypes.InferenceTypeOnDemand) {
717+
continue
718+
}
719+
name := strings.TrimSpace(aws.ToString(summary.ModelName))
720+
if name == "" {
721+
name = id
722+
}
723+
providerName := strings.TrimSpace(aws.ToString(summary.ProviderName))
724+
if providerName != "" && !strings.HasPrefix(strings.ToLower(name), strings.ToLower(providerName)+" ") {
725+
name = providerName + " " + name
726+
}
727+
models = append(models, ModelInfo{ID: id, Name: name})
728+
}
729+
if len(models) == 0 {
730+
return nil, fmt.Errorf("anthropic_bedrock: no selectable Anthropic text models returned")
731+
}
732+
sort.Slice(models, func(i, j int) bool {
733+
return models[i].ID < models[j].ID
734+
})
735+
return models, nil
736+
}
737+
738+
func modelModalitiesContain(values []bedrocktypes.ModelModality, want bedrocktypes.ModelModality) bool {
739+
for _, v := range values {
740+
if v == want {
741+
return true
742+
}
743+
}
744+
return false
745+
}
746+
747+
func inferenceTypesContain(values []bedrocktypes.InferenceType, want bedrocktypes.InferenceType) bool {
748+
for _, v := range values {
749+
if v == want {
750+
return true
751+
}
752+
}
753+
return false
754+
}
755+
607756
// listOllamaModels lists models available on a local Ollama server.
608757
func listOllamaModels(ctx context.Context, baseURL string) ([]ModelInfo, error) {
609758
c := NewOllamaClient(baseURL)

‎provider/models_dynamic_test.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
)
88

99
func TestListModelsHostedProviderVariantsRequireDynamicCatalog(t *testing.T) {
10-
for _, providerType := range []string{"openai_azure", "anthropic_bedrock", "anthropic_vertex", "anthropic_foundry"} {
10+
for _, providerType := range []string{"openai_azure", "anthropic_vertex", "anthropic_foundry"} {
1111
t.Run(providerType, func(t *testing.T) {
1212
_, err := ListModels(context.Background(), providerType, "", "")
1313
if err == nil {

0 commit comments

Comments
 (0)