feat(reasoning): add reasoning-effort config settings#2775
Conversation
…zing agent-level fields
c6aa50a to
a50da3b
Compare
…parameters and scripts
…ion and add tests
| /// reasoning (e.g. `claude-opus-4-6`). Mutually exclusive with `thinking`. | ||
| #[derive(Serialize, Default, Debug, PartialEq, Eq)] | ||
| pub struct OutputConfig { | ||
| pub effort: String, |
There was a problem hiding this comment.
Use an enum type for type safety allow only the official variants.
There was a problem hiding this comment.
Done. Added an OutputEffort enum with only the four Anthropic-valid variants (Low, Medium, High, Max) and updated OutputConfig to use it. Non-Anthropic effort levels (None, Minimal, XHigh) are mapped to the nearest valid variant at conversion time.
crates/forge_domain/src/agent.rs
Outdated
| Effort::Max | ||
| } | ||
| } | ||
| } |
There was a problem hiding this comment.
Budget isn't required to be related to the effort. Lets only use the budget that is set in the config or work with defaults.
There was a problem hiding this comment.
Done. Removed the From<usize> for Effort impl from both forge_domain and forge_config (along with all associated tests). Also updated the SetReasoningEffort OpenAI transformer to no longer derive effort from max_tokens — when only a budget is configured, it now falls back to the default medium effort. Effort must be set explicitly in the config.
- Use OutputEffort enum in OutputConfig instead of String for type safety; only exposes Anthropic-valid variants (Low/Medium/High/Max) - Set default reasoning effort to 'high' in .forge.toml - Remove From<usize> for Effort impl: budget and effort are independent concerns; effort must be set explicitly in config - Update SetReasoningEffort transformer to not derive effort from max_tokens - Remove all budget-to-effort conversion tests Co-Authored-By: ForgeCode <noreply@forgecode.dev>
|
Should fix #1479 |
ca087f1 to
271e3d6
Compare
Summary
Implement dynamic reasoning configuration with provider-aware serialization, expanding the
Effortenum and routing reasoning parameters to the correct Anthropic API format based on model capability.Context
Reasoning support previously used a single fixed path: always serializing a
thinkingobject with a token budget. This approach didn't support newer Anthropic models (e.g.claude-opus-4-6) that use an effort-basedoutput_configAPI instead of a token budget. Additionally, theEffortenum only had three levels (Low,Medium,High), which didn't cover the full range supported by OpenAI/OpenRouter (none,minimal,xhigh,max). This PR unifies reasoning configuration across providers and adds proper serialization routing.Changes
ReasoningConfigstruct inforge_configwitheffort,max_tokens,exclude, andenabledfields, surfaced in the JSON schemaEffortenum in bothforge_configandforge_domainfrom 3 to 7 levels:None,Minimal,Low,Medium,High,XHigh,Maxusize → Effortbudget-to-effort mapping to cover all new levelsmax_tokens→thinkingobject (older models),effortwithout budget →output_config.effort(newer models),enabledonly →thinkingwith default budgetoutput_configfield to the AnthropicRequestDTO to support effort-based reasoning for newer modelsreasoningconfig to agents with agent-level fields taking priority (merge semantics)normalize_scriptandcreate_temp_zsh_scriptdead code.forge/skills/test-reasoningskill with comprehensive shell scripts for validating reasoning serialization across providersKey Implementation Details
The Anthropic serialization routing in
dto/anthropic/request.rsfollows three branches:enabled=true+max_tokens→thinkingobject (extended-thinking API, older models)enabled=true+effort(no budget) →output_config.effort(newer effort-based API)enabled=trueonly (no effort, no budget) →thinkingwith a default 10,000-token budgetFor config merging in
agent.rs, the config-levelEffortis converted to the domainEffortbefore merging, with agent-defined fields always taking priority over workflow defaults.Testing
Links