@@ -7,6 +7,7 @@ import (
"github.com/charmbracelet/fantasy/ai"
"github.com/charmbracelet/fantasy/anthropic"
+ "github.com/stretchr/testify/require"
"gopkg.in/dnaeon/go-vcr.v4/pkg/recorder"
)
@@ -14,6 +15,53 @@ func TestAnthropicCommon(t *testing.T) {
testCommon(t, []builderPair{
{"claude-sonnet-4", builderAnthropicClaudeSonnet4, nil},
})
+
+ opts := ai.ProviderOptions{
+ anthropic.Name: &anthropic.ProviderOptions{
+ Thinking: &anthropic.ThinkingProviderOption{
+ BudgetTokens: 4000,
+ },
+ },
+ }
+ testThinking(t, []builderPair{
+ {"claude-sonnet-4", builderAnthropicClaudeSonnet4, opts},
+ }, testGoogleThinking)
+}
+
+func testAnthropicThinking(t *testing.T, result *ai.AgentResult) {
+ reasoningContentCount := 0
+ signaturesCount := 0
+ // Test if we got the signature
+ for _, step := range result.Steps {
+ for _, msg := range step.Messages {
+ for _, content := range msg.Content {
+ if content.GetType() == ai.ContentTypeReasoning {
+ reasoningContentCount += 1
+ reasoningContent, ok := ai.AsContentType[ai.ReasoningPart](content)
+ if !ok {
+ continue
+ }
+ if len(reasoningContent.ProviderOptions) == 0 {
+ continue
+ }
+
+ anthropicReasoningMetadata, ok := reasoningContent.ProviderOptions[anthropic.Name]
+ if !ok {
+ continue
+ }
+ if reasoningContent.Text != "" {
+ if typed, ok := anthropicReasoningMetadata.(*anthropic.ReasoningOptionMetadata); ok {
+ require.NotEmpty(t, typed.Signature)
+ signaturesCount += 1
+ }
+ }
+ }
+ }
+ }
+ }
+ require.Greater(t, reasoningContentCount, 0)
+ require.Greater(t, signaturesCount, 0)
+ require.Equal(t, reasoningContentCount, signaturesCount)
}
func builderAnthropicClaudeSonnet4(r *recorder.Recorder) (ai.LanguageModel, error) {
@@ -0,0 +1,63 @@
+---
+version: 2
+interactions:
+ - id: 0
+ request:
+ proto: HTTP/1.1
+ proto_major: 1
+ proto_minor: 1
+ content_length: 548
+ host: ""
+ body: '{"max_tokens":8096,"messages":[{"content":[{"text":"What''s the weather in Florence, Italy?","type":"text"}],"role":"user"}],"model":"claude-sonnet-4-20250514","system":[{"text":"You are a helpful assistant","type":"text"}],"thinking":{"budget_tokens":4000,"type":"enabled"},"tool_choice":{"disable_parallel_tool_use":false,"type":"auto"},"tools":[{"input_schema":{"properties":{"location":{"description":"the city","type":"string"}},"required":["location"],"type":"object"},"name":"weather","description":"Get weather information for a location"}]}'
+ headers:
+ Accept:
+ - application/json
+ Content-Type:
+ - application/json
+ User-Agent:
+ - Anthropic/Go 1.10.0
+ url: https://api.anthropic.com/v1/messages
+ method: POST
+ response:
+ proto: HTTP/2.0
+ proto_major: 2
+ proto_minor: 0
+ content_length: -1
+ uncompressed: true