diff --git a/.changeset/deepseek-empty-reasoning.md b/.changeset/deepseek-empty-reasoning.md new file mode 100644 index 0000000000..3ce8eebd8a --- /dev/null +++ b/.changeset/deepseek-empty-reasoning.md @@ -0,0 +1,5 @@ +--- +"@kilocode/cli": patch +--- + +Fix multi-turn tool calls with DeepSeek thinking mode by preserving empty `reasoning_content` in the interleaved transform. diff --git a/packages/opencode/src/provider/transform.ts b/packages/opencode/src/provider/transform.ts index cd0de1505a..f3dee7e6ec 100644 --- a/packages/opencode/src/provider/transform.ts +++ b/packages/opencode/src/provider/transform.ts @@ -193,25 +193,23 @@ function normalizeMessages( // 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?.openaiCompatible, - [field]: reasoningText, - }, - }, - } - } - + // kilocode_change start - cherry-picked from anomalyco/opencode#24146; + // will be reverted on the next wholesale upstream merge. + // Include reasoning_content | reasoning_details directly on the message for all assistant messages. + // Always set the field even when empty — some providers (e.g. DeepSeek) may return empty + // reasoning_content which still needs to be sent back in subsequent requests. return { ...msg, content: filteredContent, + providerOptions: { + ...msg.providerOptions, + openaiCompatible: { + ...msg.providerOptions?.openaiCompatible, + [field]: reasoningText, + }, + }, } + // kilocode_change end } return msg