Skip to content
This repository was archived by the owner on Mar 9, 2026. It is now read-only.

Commit 627e5aa

Browse files
committed
feat(anthropic): Add support for AWS Bedrock
This a simple change to provide access to Anthropic models through AWS Bedrock. Please let me know what do you think, or if you have any suggestion to improve it.
1 parent 7966027 commit 627e5aa

5 files changed

Lines changed: 69 additions & 10 deletions

File tree

‎config_template.yml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,7 @@ apis:
160160
max-input-chars: 4194304
161161
anthropic:
162162
base-url: https://api.anthropic.com/v1
163+
# AWS Bedrock Anthropic models can be used by setting api-key to "AwsBedrock", AWS client need to be properly set.
163164
api-key:
164165
api-key-env: ANTHROPIC_API_KEY
165166
models: # https://docs.anthropic.com/en/docs/about-claude/models

‎go.mod‎

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/adrg/xdg v0.5.3
77
github.com/anthropics/anthropic-sdk-go v1.4.0
88
github.com/atotto/clipboard v0.1.4
9+
github.com/aws/aws-sdk-go-v2/config v1.27.27
910
github.com/caarlos0/duration v0.0.0-20240108180406-5d492514f3c7
1011
github.com/caarlos0/env/v9 v9.0.0
1112
github.com/caarlos0/go-shellwords v1.0.12
@@ -41,6 +42,17 @@ require (
4142
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
4243
github.com/alecthomas/chroma/v2 v2.14.0 // indirect
4344
github.com/aws/aws-sdk-go-v2 v1.30.3 // indirect
45+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 // indirect
46+
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
47+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 // indirect
48+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 // indirect
49+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 // indirect
50+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
51+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
52+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
53+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 // indirect
54+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 // indirect
55+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 // indirect
4456
github.com/aws/smithy-go v1.20.3 // indirect
4557
github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect
4658
github.com/aymanbagabas/go-udiff v0.2.0 // indirect

‎go.sum‎

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,30 @@ github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z
2424
github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI=
2525
github.com/aws/aws-sdk-go-v2 v1.30.3 h1:jUeBtG0Ih+ZIFH0F4UkmL9w3cSpaMv9tYYDbzILP8dY=
2626
github.com/aws/aws-sdk-go-v2 v1.30.3/go.mod h1:nIQjQVp5sfpQcTc9mPSr1B0PaWK5ByX9MOoDadSN4lc=
27+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3 h1:tW1/Rkad38LA15X4UQtjXZXNKsCgkshC3EbmcUmghTg=
28+
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.3/go.mod h1:UbnqO+zjqk3uIt9yCACHJ9IVNhyhOCnYk8yA19SAWrM=
29+
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
30+
github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
31+
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
32+
github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
33+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
34+
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
35+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15 h1:SoNJ4RlFEQEbtDcCEt+QG56MY4fm4W8rYirAmq+/DdU=
36+
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.15/go.mod h1:U9ke74k1n2bf+RIgoX1SXFed1HLs51OgUSs+Ph0KJP8=
37+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15 h1:C6WHdGnTDIYETAm5iErQUiVNsclNx9qbJVPIt03B6bI=
38+
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.15/go.mod h1:ZQLZqhcu+JhSrA9/NXRm8SkDvsycE+JkV3WGY41e+IM=
39+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
40+
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
41+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
42+
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
43+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
44+
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17/go.mod h1:RkZEx4l0EHYDJpWppMJ3nD9wZJAa8/0lq9aVC+r2UII=
45+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4 h1:BXx0ZIxvrJdSgSvKTZ+yRBeSqqgPM89VPlulEcl37tM=
46+
github.com/aws/aws-sdk-go-v2/service/sso v1.22.4/go.mod h1:ooyCOXjvJEsUw7x+ZDHeISPMhtwI3ZCB7ggFMcFfWLU=
47+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4 h1:yiwVzJW2ZxZTurVbYWA7QOrAaCYQR72t0wrSBfoesUE=
48+
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.26.4/go.mod h1:0oxfLkpz3rQ/CHlx5hB7H69YUpFiI1tql6Q6Ne+1bCw=
49+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3 h1:ZsDKRLXGWHk8WdtyYMoGNO7bTudrvuKpDKgMVRlepGE=
50+
github.com/aws/aws-sdk-go-v2/service/sts v1.30.3/go.mod h1:zwySh8fpFyXp9yOr/KVzxOl8SRqgf/IDw5aUt9UKFcQ=
2751
github.com/aws/smithy-go v1.20.3 h1:ryHwveWzPV5BIof6fyDvor6V3iUL7nTfiTKXHiW05nE=
2852
github.com/aws/smithy-go v1.20.3/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E=
2953
github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k=

‎internal/anthropic/anthropic.go‎

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ package anthropic
33

44
import (
55
"context"
6+
"fmt"
67
"net/http"
78
"strings"
89

910
"github.com/anthropics/anthropic-sdk-go"
11+
"github.com/anthropics/anthropic-sdk-go/bedrock"
1012
"github.com/anthropics/anthropic-sdk-go/option"
1113
"github.com/anthropics/anthropic-sdk-go/packages/ssestream"
14+
awsCfg "github.com/aws/aws-sdk-go-v2/config"
1215
"github.com/charmbracelet/mods/internal/proto"
1316
"github.com/charmbracelet/mods/internal/stream"
1417
)
@@ -75,18 +78,28 @@ func DefaultConfig(authToken string) Config {
7578
}
7679

7780
// New anthropic client with the given configuration.
78-
func New(config Config) *Client {
79-
opts := []option.RequestOption{
80-
option.WithAPIKey(config.AuthToken),
81-
option.WithHTTPClient(config.HTTPClient),
82-
}
83-
if config.BaseURL != "" {
84-
opts = append(opts, option.WithBaseURL(strings.TrimSuffix(config.BaseURL, "/v1")))
81+
func New(config Config) (*Client, error) {
82+
var opts []option.RequestOption
83+
if config.AuthToken == "AwsBedrock" {
84+
awsCfg, err := awsCfg.LoadDefaultConfig(context.TODO())
85+
if err != nil {
86+
return nil, fmt.Errorf("failed to load AWS config: %w", err)
87+
}
88+
89+
opts = append(opts, bedrock.WithConfig(awsCfg))
90+
} else {
91+
opts = []option.RequestOption{
92+
option.WithAPIKey(config.AuthToken),
93+
option.WithHTTPClient(config.HTTPClient),
94+
}
95+
if config.BaseURL != "" {
96+
opts = append(opts, option.WithBaseURL(strings.TrimSuffix(config.BaseURL, "/v1")))
97+
}
8598
}
8699
client := anthropic.NewClient(opts...)
87100
return &Client{
88101
Client: &client,
89-
}
102+
}, nil
90103
}
91104

92105
// Stream represents a stream for chat completion.
@@ -149,7 +162,16 @@ func (s *Stream) Current() (proto.Chunk, error) {
149162
}
150163

151164
// Err implements stream.Stream.
152-
func (s *Stream) Err() error { return s.stream.Err() } //nolint:wrapcheck
165+
func (s *Stream) Err() error {
166+
err := s.stream.Err()
167+
168+
// EOF is not an error for streams - it indicates normal completion
169+
if err != nil && err.Error() == "EOF" {
170+
return nil
171+
}
172+
173+
return err //nolint:wrapcheck
174+
}
153175

154176
// Messages implements stream.Stream.
155177
func (s *Stream) Messages() []proto.Message { return s.messages }

‎mods.go‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ func (m *Mods) startCompletionCmd(content string) tea.Cmd {
432432
var client stream.Client
433433
switch mod.API {
434434
case "anthropic":
435-
client = anthropic.New(accfg)
435+
client, err = anthropic.New(accfg)
436436
case "google":
437437
client = google.New(gccfg)
438438
case "cohere":

0 commit comments

Comments
 (0)