refactor(thinking): pass source and target formats to ApplyThinking for cross-format validation

Update ApplyThinking signature to accept fromFormat and toFormat parameters
instead of a single provider string. This enables:

- Proper level-to-budget conversion when source is level-based (openai/codex)
  and target is budget-based (gemini/claude)
- Strict budget range validation when source and target formats match
- Level clamping to nearest supported level for cross-format requests
- Format alias resolution in SDK translator registry for codex/openai-response

Also adds ErrBudgetOutOfRange error code and improves iflow config extraction
to fall back to openai format when iflow-specific config is not present.
This commit is contained in:
hkfires
2026-01-17 22:53:10 +08:00
parent d5ef4a6d15
commit c7e8830a56
15 changed files with 341 additions and 171 deletions

View File

@@ -27,28 +27,32 @@ func StripThinkingConfig(body []byte, provider string) []byte {
return body
}
var paths []string
switch provider {
case "claude":
result, _ := sjson.DeleteBytes(body, "thinking")
return result
paths = []string{"thinking"}
case "gemini":
result, _ := sjson.DeleteBytes(body, "generationConfig.thinkingConfig")
return result
paths = []string{"generationConfig.thinkingConfig"}
case "gemini-cli", "antigravity":
result, _ := sjson.DeleteBytes(body, "request.generationConfig.thinkingConfig")
return result
paths = []string{"request.generationConfig.thinkingConfig"}
case "openai":
result, _ := sjson.DeleteBytes(body, "reasoning_effort")
return result
paths = []string{"reasoning_effort"}
case "codex":
result, _ := sjson.DeleteBytes(body, "reasoning.effort")
return result
paths = []string{"reasoning.effort"}
case "iflow":
result, _ := sjson.DeleteBytes(body, "chat_template_kwargs.enable_thinking")
result, _ = sjson.DeleteBytes(result, "chat_template_kwargs.clear_thinking")
result, _ = sjson.DeleteBytes(result, "reasoning_split")
return result
paths = []string{
"chat_template_kwargs.enable_thinking",
"chat_template_kwargs.clear_thinking",
"reasoning_split",
"reasoning_effort",
}
default:
return body
}
result := body
for _, path := range paths {
result, _ = sjson.DeleteBytes(result, path)
}
return result
}