mirror of
https://github.com/CherryHQ/cherry-studio.git
synced 2026-07-06 05:55:28 +08:00
fix(aiCore): bypass AI SDK model ID allowlist for reasoning detection (#13463)
### What this PR does Before this PR: When using reasoning models (e.g., GPT-5.2) through third-party OpenAI-compatible providers that use the Responses API endpoint, `reasoningEffort` and `reasoningSummary` settings from the UI are silently ignored. The AI SDK logs a warning: `reasoningEffort is not supported for non-reasoning models`. After this PR: Reasoning parameters are correctly included in the Responses API request body for all providers, regardless of model ID format. Fixes #13454 ### Why we need it and why it was done in this way The following tradeoffs were made: The `@ai-sdk/openai` Responses model uses a hardcoded model ID allowlist (`modelId.startsWith('gpt-5')`, etc.) to determine if a model supports reasoning. Third-party providers often use non-canonical model IDs (e.g., `openai/gpt-5.2`) that fail these checks, causing reasoning params to be silently dropped. The fix uses `forceReasoning: true` — a bypass mechanism provided by the AI SDK — when Cherry Studio's own `isReasoningModel()` detects the model as a reasoning model. This is semantically correct: Cherry Studio's model detection is more comprehensive than the AI SDK's allowlist. The following alternatives were considered: - Migrating to `@ai-sdk/open-responses` (tracked in #13462) — better long-term solution but larger scope - Stripping model ID prefixes before passing to the AI SDK — fragile and provider-specific - Using `openai-compatible` provider with manual reasoning parameter handling — would lose Responses API features ### Breaking changes None. ### Testing - [x] Manual test passed: confirmed `reasoning.effort` and `reasoning.summary` are now correctly included in the Responses API request body when using a third-party provider with non-canonical model IDs. ### Special notes for your reviewer - The `forceReasoning` option is an official AI SDK feature, not a hack. It's documented for exactly this use case: "stealth" reasoning models where the model ID is not recognized by the SDK's allowlist. - `isReasoningModel(model)` is used instead of `enableReasoning` because `forceReasoning` should reflect model capability, not user preference. - A TODO comment links to #13462 for the longer-term migration to `@ai-sdk/open-responses`. ### Checklist - [x] PR: The PR description is expressive enough and will help future contributors - [x] Code: Write code that humans can understand and Keep it simple - [x] Refactor: You have left the code cleaner than you found it (Boy Scout Rule) - [ ] Upgrade: Impact of this change on upgrade flows was considered and addressed if required - [ ] Documentation: A user-guide update was considered and is present (link) or not required. - [x] Self-review: I have reviewed my own code before requesting review from others ### Release note ```release-note fix: reasoning effort and summary mode settings now correctly apply for third-party OpenAI-compatible providers using the Responses API endpoint ``` Signed-off-by: icarus <eurfelux@gmail.com> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -13,6 +13,7 @@ import {
|
||||
isOpenAIModel,
|
||||
isOpenAIOpenWeightModel,
|
||||
isQwenMTModel,
|
||||
isReasoningModel,
|
||||
isSupportFlexServiceTierModel,
|
||||
isSupportVerbosityModel
|
||||
} from '@renderer/config/models'
|
||||
@@ -382,7 +383,12 @@ function buildOpenAIProviderOptions(
|
||||
const reasoningParams = getOpenAIReasoningParams(assistant, model)
|
||||
providerOptions = {
|
||||
...providerOptions,
|
||||
...reasoningParams
|
||||
...reasoningParams,
|
||||
// TODO: Remove this workaround after migrating to @ai-sdk/open-responses (#13462)
|
||||
// Bypass @ai-sdk/openai's model ID allowlist for reasoning detection.
|
||||
// Third-party providers often use non-canonical model IDs (e.g., "openai/gpt-5.2")
|
||||
// that fail the SDK's startsWith() checks, causing reasoning params to be silently dropped.
|
||||
...(isReasoningModel(model) && { forceReasoning: true })
|
||||
}
|
||||
}
|
||||
const provider = getProviderById(model.provider)
|
||||
|
||||
Reference in New Issue
Block a user