mirror of
https://github.com/anomalyco/opencode.git
synced 2026-02-01 22:48:16 +00:00
fix: strip reasoning parts from messages when switching to non-thinking models (#11571)
When switching from a model with extended thinking (e.g., Claude Opus) to a model without thinking support (e.g., GPT 5.2, Claude Sonnet without thinking) mid-session, reasoning parts from previous messages were still being sent to the API, causing validation errors. This fix ensures that reasoning parts are only included in providerOptions when the target model supports interleaved reasoning (capabilities.interleaved is an object with a field). For models that don't support interleaved reasoning, the reasoning parts are filtered out from the content array but not added to providerOptions, preventing the API error. Changes: - Modified normalizeMessages() in transform.ts to check if model supports interleaved reasoning before including reasoning in providerOptions - Reasoning parts are now correctly filtered for both thinking and non-thinking models
This commit is contained in:
@@ -129,40 +129,39 @@ export namespace ProviderTransform {
|
||||
return result
|
||||
}
|
||||
|
||||
if (typeof model.capabilities.interleaved === "object" && model.capabilities.interleaved.field) {
|
||||
const field = model.capabilities.interleaved.field
|
||||
return msgs.map((msg) => {
|
||||
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
||||
const reasoningParts = msg.content.filter((part: any) => part.type === "reasoning")
|
||||
const reasoningText = reasoningParts.map((part: any) => part.text).join("")
|
||||
const supportsInterleaved = typeof model.capabilities.interleaved === "object" && model.capabilities.interleaved.field
|
||||
const field = supportsInterleaved ? model.capabilities.interleaved.field : undefined
|
||||
|
||||
// Filter out reasoning parts from content
|
||||
const filteredContent = msg.content.filter((part: any) => part.type !== "reasoning")
|
||||
|
||||
// Include reasoning_content | reasoning_details directly on the message for all assistant messages
|
||||
if (reasoningText) {
|
||||
return {
|
||||
...msg,
|
||||
content: filteredContent,
|
||||
providerOptions: {
|
||||
...msg.providerOptions,
|
||||
openaiCompatible: {
|
||||
...(msg.providerOptions as any)?.openaiCompatible,
|
||||
[field]: reasoningText,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
return msgs.map((msg) => {
|
||||
if (msg.role === "assistant" && Array.isArray(msg.content)) {
|
||||
const reasoningParts = msg.content.filter((part: any) => part.type === "reasoning")
|
||||
const reasoningText = reasoningParts.map((part: any) => part.text).join("")
|
||||
// Filter out reasoning parts from content
|
||||
const filteredContent = msg.content.filter((part: any) => part.type !== "reasoning")
|
||||
|
||||
// Include reasoning_content | reasoning_details directly on message for models that support interleaved reasoning
|
||||
if (reasoningText && supportsInterleaved && field) {
|
||||
return {
|
||||
...msg,
|
||||
content: filteredContent,
|
||||
providerOptions: {
|
||||
...msg.providerOptions,
|
||||
openaiCompatible: {
|
||||
...(msg.providerOptions as any)?.openaiCompatible,
|
||||
[field]: reasoningText,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
})
|
||||
}
|
||||
return {
|
||||
...msg,
|
||||
content: filteredContent,
|
||||
}
|
||||
}
|
||||
|
||||
return msg
|
||||
})
|
||||
|
||||
return msgs
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user