chore: upgrade anthropic-sdk-go to v1.9.1 and add beta feature support for context-1m

## CHANGES

- Upgrade anthropic-sdk-go from v1.7.0 to v1.9.1
- Upgrade golang.org/x/crypto from v0.39.0 to v0.40.0
- Add modelBetas map for beta feature configuration
- Implement context-1m-2025-08-07 beta for Claude Sonnet 4
- Add beta header support in streaming requests
- Add beta header support in standard requests
- Implement fallback mechanism when beta features fail
- Preserve existing beta headers in OAuth transport
- Add test coverage for model beta configuration
This commit is contained in:
Kayvan Sylvan 2025-08-12 22:30:27 -07:00
parent 1b2d9ec0ed
commit 17b7d96da1
6 changed files with 64 additions and 13 deletions

View file

@ -0,0 +1,7 @@
### PR [#1698](https://github.com/danielmiessler/Fabric/pull/1698) by [ksylvan](https://github.com/ksylvan): Enable One Million Token Context Beta Feature for Sonnet-4
- Chore: upgrade anthropic-sdk-go to v1.9.1 and add beta feature support for context-1m
- Add modelBetas map for beta feature configuration
- Implement context-1m-2025-08-07 beta for Claude Sonnet 4
- Add beta header support with fallback handling
- Preserve existing beta headers in OAuth transport

4
go.mod
View file

@ -5,7 +5,7 @@ go 1.24.0
toolchain go1.24.2
require (
github.com/anthropics/anthropic-sdk-go v1.7.0
github.com/anthropics/anthropic-sdk-go v1.9.1
github.com/atotto/clipboard v0.1.4
github.com/aws/aws-sdk-go-v2 v1.36.4
github.com/aws/aws-sdk-go-v2/config v1.27.27
@ -117,7 +117,7 @@ require (
go.opentelemetry.io/otel/metric v1.36.0 // indirect
go.opentelemetry.io/otel/trace v1.36.0 // indirect
golang.org/x/arch v0.18.0 // indirect
golang.org/x/crypto v0.39.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b // indirect
golang.org/x/net v0.41.0 // indirect
golang.org/x/sync v0.16.0 // indirect

12
go.sum
View file

@ -17,8 +17,8 @@ github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kk
github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8=
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4=
github.com/anthropics/anthropic-sdk-go v1.7.0 h1:5iVf5fG/2gqVsOce8mq02r/WdgqpokM/8DXg2Ue6C9Y=
github.com/anthropics/anthropic-sdk-go v1.7.0/go.mod h1:3qSNQ5NrAmjC8A2ykuruSQttfqfdEYNZY5o8c0XSHB8=
github.com/anthropics/anthropic-sdk-go v1.9.1 h1:raRhZKmayVSVZtLpLDd6IsMXvxLeeSU03/2IBTerWlg=
github.com/anthropics/anthropic-sdk-go v1.9.1/go.mod h1:WTz31rIUHUHqai2UslPpw5CwXrQP3geYBioRV4WOLvE=
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhPwqqXc4/vE0f7GvRjuAsbW+HOIe8KnA=
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
@ -268,8 +268,8 @@ golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliY
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM=
golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U=
golang.org/x/crypto v0.40.0 h1:r4x+VvoG5Fm+eJcxMaY8CQM7Lb0l1lsmjGBQ6s8BfKM=
golang.org/x/crypto v0.40.0/go.mod h1:Qr1vMER5WyS2dfPHAlsOj01wgLbsyWtFn/aY+5+ZdxY=
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b h1:QoALfVG9rhQ/M7vYDScfPdWjGL9dlsVVM5VGh7aKoAA=
golang.org/x/exp v0.0.0-20250531010427-b6e5de432a8b/go.mod h1:U6Lno4MTRCDY+Ba7aCcauB9T60gsv5s4ralQzP72ZoQ=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
@ -327,8 +327,8 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/term v0.32.0 h1:DR4lr0TjUs3epypdhTOkMmuF5CDFJ/8pOnbzMZPQ7bg=
golang.org/x/term v0.32.0/go.mod h1:uZG1FhGx848Sqfsq4/DlJr3xGGsYMu/L5GW4abiaEPQ=
golang.org/x/term v0.33.0 h1:NuFncQrRcaRvVmgRkvM3j/F00gWIAlcmlB8ACEKmGIg=
golang.org/x/term v0.33.0/go.mod h1:s18+ql9tYWp1IfpV9DmCtQDDSRBUjKaw9M1eAv5UeF0=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=

View file

@ -4,6 +4,7 @@ import (
"context"
"fmt"
"net/http"
"os"
"strings"
"github.com/anthropics/anthropic-sdk-go"
@ -49,6 +50,10 @@ func NewClient() (ret *Client) {
string(anthropic.ModelClaudeOpus4_1_20250805),
}
ret.modelBetas = map[string][]string{
string(anthropic.ModelClaudeSonnet4_20250514): {"context-1m-2025-08-07"},
}
return
}
@ -93,6 +98,7 @@ type Client struct {
maxTokens int
defaultRequiredUserMessage string
models []string
modelBetas map[string][]string
client anthropic.Client
}
@ -160,7 +166,17 @@ func (an *Client) SendStream(
ctx := context.Background()
stream := an.client.Messages.NewStreaming(ctx, an.buildMessageParams(messages, opts))
params := an.buildMessageParams(messages, opts)
betas := an.modelBetas[opts.Model]
var reqOpts []option.RequestOption
if len(betas) > 0 {
reqOpts = append(reqOpts, option.WithHeader("anthropic-beta", strings.Join(betas, ",")))
}
stream := an.client.Messages.NewStreaming(ctx, params, reqOpts...)
if stream.Err() != nil && len(betas) > 0 {
fmt.Fprintf(os.Stderr, "Anthropic beta feature %s failed: %v\n", strings.Join(betas, ","), stream.Err())
stream = an.client.Messages.NewStreaming(ctx, params)
}
for stream.Next() {
event := stream.Current()
@ -226,6 +242,7 @@ func (an *Client) buildMessageParams(msgs []anthropic.MessageParam, opts *domain
{OfWebSearchTool20250305: &webTool},
}
}
return
}
@ -239,8 +256,21 @@ func (an *Client) Send(ctx context.Context, msgs []*chat.ChatCompletionMessage,
}
var message *anthropic.Message
if message, err = an.client.Messages.New(ctx, an.buildMessageParams(messages, opts)); err != nil {
return
params := an.buildMessageParams(messages, opts)
betas := an.modelBetas[opts.Model]
var reqOpts []option.RequestOption
if len(betas) > 0 {
reqOpts = append(reqOpts, option.WithHeader("anthropic-beta", strings.Join(betas, ",")))
}
if message, err = an.client.Messages.New(ctx, params, reqOpts...); err != nil {
if len(betas) > 0 {
fmt.Fprintf(os.Stderr, "Anthropic beta feature %s failed: %v\n", strings.Join(betas, ","), err)
if message, err = an.client.Messages.New(ctx, params); err != nil {
return
}
} else {
return
}
}
var textParts []string

View file

@ -168,6 +168,15 @@ func TestBuildMessageParams_WithSearchAndLocation(t *testing.T) {
}
}
func TestModelBetasConfiguration(t *testing.T) {
client := NewClient()
model := string(anthropic.ModelClaudeSonnet4_20250514)
betas, ok := client.modelBetas[model]
if !ok || len(betas) != 1 || betas[0] != "context-1m-2025-08-07" {
t.Errorf("expected beta mapping for %s", model)
}
}
func TestCitationFormatting(t *testing.T) {
// Test the citation formatting logic by creating a mock message with citations
message := &anthropic.Message{

View file

@ -46,8 +46,13 @@ func (t *OAuthTransport) RoundTrip(req *http.Request) (*http.Response, error) {
// Add OAuth Bearer token
newReq.Header.Set("Authorization", "Bearer "+token)
// Add the anthropic-beta header for OAuth
newReq.Header.Set("anthropic-beta", "oauth-2025-04-20")
// Add the anthropic-beta header for OAuth, preserving existing betas
existing := newReq.Header.Get("anthropic-beta")
beta := "oauth-2025-04-20"
if existing != "" {
beta = existing + "," + beta
}
newReq.Header.Set("anthropic-beta", beta)
// Set User-Agent to match AI SDK exactly
newReq.Header.Set("User-Agent", "ai-sdk/anthropic")