From 0490a8a6b48f7bd956a9a017f87549a0540c68a3 Mon Sep 17 00:00:00 2001 From: John Jansen Date: Wed, 13 May 2026 08:31:49 +1200 Subject: [PATCH] fix(bedrock): honor reasoning_effort for Anthropic-on-Bedrock models (#2887) Bedrock routes through Fantasy's Anthropic implementation with a different display name, so provider options must still be filed under anthropic.Name for the language model to pick them up. Previously the bedrock provider type was missing from getProviderOptions entirely, so reasoning_effort and think were silently dropped. Co-authored-by: JJ Bot --- internal/agent/coordinator.go | 2 +- internal/agent/coordinator_test.go | 35 ++++++++++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/internal/agent/coordinator.go b/internal/agent/coordinator.go index 106e637a1d6f6b5a1456bae326547717a2cb8789..08e3ad7d0819742cd894dc61e730df19412fa199 100644 --- a/internal/agent/coordinator.go +++ b/internal/agent/coordinator.go @@ -286,7 +286,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy. options[openai.Name] = parsed } } - case anthropic.Name: + case anthropic.Name, bedrock.Name: var ( _, hasEffort = mergedOptions["effort"] _, hasThink = mergedOptions["thinking"] diff --git a/internal/agent/coordinator_test.go b/internal/agent/coordinator_test.go index 17f9ff656022be88acfb235c05b4b821e6d71a0b..1dd90d91e75421f1e8a6d3e3b54f12a009643c1c 100644 --- a/internal/agent/coordinator_test.go +++ b/internal/agent/coordinator_test.go @@ -7,6 +7,8 @@ import ( "charm.land/catwalk/pkg/catwalk" "charm.land/fantasy" + "charm.land/fantasy/providers/anthropic" + "charm.land/fantasy/providers/bedrock" "github.com/charmbracelet/crush/internal/config" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -383,3 +385,36 @@ func TestUpdateParentSessionCost(t *testing.T) { assert.InDelta(t, 0.0, updated.Cost, 1e-9) }) } + +func TestGetProviderOptionsReasoningEffort(t *testing.T) { + // Bedrock is Fantasy's Anthropic under a different provider name; options + // must land under anthropic.Name so the Anthropic language model picks them up. + tests := []struct { + name string + providerType catwalk.Type + }{ + {"anthropic honors reasoning_effort", catwalk.Type(anthropic.Name)}, + {"bedrock honors reasoning_effort", catwalk.Type(bedrock.Name)}, + } + for _, tc := range tests { + t.Run(tc.name, func(t *testing.T) { + model := Model{ + CatwalkCfg: catwalk.Model{ID: "claude-opus-4-7"}, + ModelCfg: config.SelectedModel{ + Provider: "test", + ReasoningEffort: "max", + }, + } + providerCfg := config.ProviderConfig{ID: "test", Type: tc.providerType} + + opts := getProviderOptions(model, providerCfg) + + raw, ok := opts[anthropic.Name] + require.True(t, ok, "options should be keyed under anthropic.Name for type %q", tc.providerType) + parsed, ok := raw.(*anthropic.ProviderOptions) + require.True(t, ok) + require.NotNil(t, parsed.Effort) + assert.Equal(t, anthropic.Effort("max"), *parsed.Effort) + }) + } +}