on main help sign in
fix: fix sometimes sending reasoning effort when it shouldn't (#2982)
2faa467Andrey Nering
internal/agent/coordinator.go+8−5
@@ -283,10 +283,13 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
283 return options
283 return options
284 }
284 }
285
285
286+ shouldSetEffort := model.CatwalkCfg.CanReason &&
287+ slices.Contains(model.CatwalkCfg.ReasoningLevels, model.ModelCfg.ReasoningEffort)
288+
286 switch providerCfg.Type {
289 switch providerCfg.Type {
287 case openai.Name, azure.Name:
290 case openai.Name, azure.Name:
288 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
291 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
289− if !hasReasoningEffort && model.ModelCfg.ReasoningEffort != "" && model.CatwalkCfg.CanReason {
292+ if !hasReasoningEffort && shouldSetEffort {
290 mergedOptions["reasoning_effort"] = model.ModelCfg.ReasoningEffort
293 mergedOptions["reasoning_effort"] = model.ModelCfg.ReasoningEffort
291 }
294 }
292 if openai.IsResponsesModel(model.CatwalkCfg.ID) {
295 if openai.IsResponsesModel(model.CatwalkCfg.ID) {
@@ -310,7 +313,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
310 _, hasThink = mergedOptions["thinking"]
313 _, hasThink = mergedOptions["thinking"]
311 )
314 )
312 switch {
315 switch {
313− case !hasEffort && model.ModelCfg.ReasoningEffort != "" && model.CatwalkCfg.CanReason:
316+ case !hasEffort && shouldSetEffort:
314 mergedOptions["effort"] = model.ModelCfg.ReasoningEffort
317 mergedOptions["effort"] = model.ModelCfg.ReasoningEffort
315 case !hasThink && model.ModelCfg.Think:
318 case !hasThink && model.ModelCfg.Think:
316 mergedOptions["thinking"] = map[string]any{"budget_tokens": 2000}
319 mergedOptions["thinking"] = map[string]any{"budget_tokens": 2000}
@@ -322,7 +325,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
322
325
323 case openrouter.Name:
326 case openrouter.Name:
324 _, hasReasoning := mergedOptions["reasoning"]
327 _, hasReasoning := mergedOptions["reasoning"]
325− if !hasReasoning && model.ModelCfg.ReasoningEffort != "" {
328+ if !hasReasoning && shouldSetEffort {
326 mergedOptions["reasoning"] = map[string]any{
329 mergedOptions["reasoning"] = map[string]any{
327 "enabled": true,
330 "enabled": true,
328 "effort": model.ModelCfg.ReasoningEffort,
331 "effort": model.ModelCfg.ReasoningEffort,
@@ -334,7 +337,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
334 }
337 }
335 case vercel.Name:
338 case vercel.Name:
336 _, hasReasoning := mergedOptions["reasoning"]
339 _, hasReasoning := mergedOptions["reasoning"]
337− if !hasReasoning && model.ModelCfg.ReasoningEffort != "" {
340+ if !hasReasoning && shouldSetEffort {
338 mergedOptions["reasoning"] = map[string]any{
341 mergedOptions["reasoning"] = map[string]any{
339 "enabled": true,
342 "enabled": true,
340 "effort": model.ModelCfg.ReasoningEffort,
343 "effort": model.ModelCfg.ReasoningEffort,
@@ -367,7 +370,7 @@ func getProviderOptions(model Model, providerCfg config.ProviderConfig) fantasy.
367 extraBody := make(map[string]any)
370 extraBody := make(map[string]any)
368
371
369 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
372 _, hasReasoningEffort := mergedOptions["reasoning_effort"]
370− if !hasReasoningEffort && model.ModelCfg.ReasoningEffort != "" && model.CatwalkCfg.CanReason {
373+ if !hasReasoningEffort && shouldSetEffort {
371 switch providerCfg.ID {
374 switch providerCfg.ID {
372 case string(catwalk.InferenceProviderIoNet):
375 case string(catwalk.InferenceProviderIoNet):
373 extraBody["reasoning"] = map[string]string{"effort": model.ModelCfg.ReasoningEffort}
376 extraBody["reasoning"] = map[string]string{"effort": model.ModelCfg.ReasoningEffort}
internal/agent/coordinator_test.go+5−1
@@ -399,7 +399,11 @@ func TestGetProviderOptionsReasoningEffort(t *testing.T) {
399 for _, tc := range tests {
399 for _, tc := range tests {
400 t.Run(tc.name, func(t *testing.T) {
400 t.Run(tc.name, func(t *testing.T) {
401 model := Model{
401 model := Model{
402− CatwalkCfg: catwalk.Model{ID: "claude-opus-4-7", CanReason: true},
402+ CatwalkCfg: catwalk.Model{
403+ ID: "claude-opus-4-7",
404+ CanReason: true,
405+ ReasoningLevels: []string{"max"},
406+ },
403 ModelCfg: config.SelectedModel{
407 ModelCfg: config.SelectedModel{
404 Provider: "test",
408 Provider: "test",
405 ReasoningEffort: "max",
409 ReasoningEffort: "max",