From 64465da3d7333568ea21f6132717e72bb35ac0e5 Mon Sep 17 00:00:00 2001 From: jh-block Date: Wed, 20 May 2026 12:40:47 +0200 Subject: [PATCH] Default Opus adaptive effort to high Use the Anthropic API default effort when no unified thinking effort is configured. Explicit max still maps to xhigh for Opus 4.7, but an omitted effort now stays at high and is covered by a regression test. Signed-off-by: jh-block --- .../goose/src/providers/formats/anthropic.rs | 50 ++++++++++++++++--- 1 file changed, 43 insertions(+), 7 deletions(-) diff --git a/crates/goose/src/providers/formats/anthropic.rs b/crates/goose/src/providers/formats/anthropic.rs index da7f6b2251..af7371ae78 100644 --- a/crates/goose/src/providers/formats/anthropic.rs +++ b/crates/goose/src/providers/formats/anthropic.rs @@ -504,13 +504,12 @@ pub fn thinking_effort(model_config: &ModelConfig) -> ThinkingEffort { } fn adaptive_effort_value(model_config: &ModelConfig) -> &'static str { - match thinking_effort(model_config) { - ThinkingEffort::Off => "high", - ThinkingEffort::Low => "low", - ThinkingEffort::Medium => "medium", - ThinkingEffort::High => "high", - ThinkingEffort::Max if is_claude_opus_47(&model_config.model_name) => "xhigh", - ThinkingEffort::Max => "max", + match model_config.thinking_effort() { + Some(ThinkingEffort::Low) => "low", + Some(ThinkingEffort::Medium) => "medium", + Some(ThinkingEffort::Max) if is_claude_opus_47(&model_config.model_name) => "xhigh", + Some(ThinkingEffort::Max) => "max", + Some(ThinkingEffort::Off | ThinkingEffort::High) | None => "high", } } @@ -1245,6 +1244,43 @@ mod tests { Ok(()) } + #[test] + fn test_create_request_preserved_opus_47_context_defaults_to_high_effort() -> Result<()> { + let _guard = env_lock::lock_env([ + ("GOOSE_THINKING_EFFORT", None::<&str>), + ("CLAUDE_THINKING_TYPE", None::<&str>), + ("CLAUDE_THINKING_ENABLED", None::<&str>), + ("ANTHROPIC_THINKING_BUDGET", None::<&str>), + ("CLAUDE_THINKING_BUDGET", None::<&str>), + ("ANTHROPIC_PRESERVE_THINKING_CONTEXT", None::<&str>), + ("ANTHROPIC_PRESERVE_UNSIGNED_THINKING", None::<&str>), + ]); + + let mut config = cfg("claude-opus-4-7"); + config.max_tokens = Some(4096); + let messages = vec![ + Message::assistant().with_content(MessageContent::thinking("internal", "")), + Message::user().with_text("Continue"), + ]; + + let payload = create_request_with_options( + &config, + "system", + &messages, + &[], + AnthropicFormatOptions { + preserve_unsigned_thinking: true, + preserve_thinking_context: true, + }, + )?; + + assert_eq!(payload["thinking"]["type"], "adaptive"); + assert_eq!(payload["output_config"]["effort"], "high"); + assert_eq!(payload["max_tokens"], 4096); + + Ok(()) + } + #[test] fn test_create_request_omits_temperature_for_opus_47() -> Result<()> { let _guard = env_lock::lock_env([("GOOSE_THINKING_EFFORT", None::<&str>)]);