fix: preserve empty reasoning_content for DeepSeek v4 thinking mode (#399)

This commit is contained in:
James Feng 2026-06-01 17:27:14 +08:00
parent c82794a69a
commit 911877e0a5
2 changed files with 22 additions and 13 deletions

View File

@ -250,9 +250,13 @@ function convertInternalAssistantMessage(
},
})
} else if (block.type === 'thinking' && preserveReasoning) {
// DeepSeek thinking mode: preserve reasoning_content for tool call iterations
// DeepSeek thinking mode: always preserve reasoning_content,
// including the empty-string case. DeepSeek v4 may return
// reasoning_content: "" when the model answers directly, and the
// empty value must be echoed back in the next request — otherwise
// DeepSeek returns 400 ("reasoning_content ... must be passed back").
const thinkingText = (block as Record<string, unknown>).thinking
if (typeof thinkingText === 'string' && thinkingText) {
if (typeof thinkingText === 'string') {
reasoningParts.push(thinkingText)
}
}

View File

@ -90,10 +90,13 @@ export async function* adaptOpenAIStreamToAnthropic(
if (!delta) continue
// Handle reasoning_content → Anthropic thinking block
// DeepSeek and compatible providers send delta.reasoning_content
// Handle reasoning_content → Anthropic thinking block.
// Empty string is a valid signal: DeepSeek v4 thinking mode sometimes
// returns reasoning_content: "" when the model answers directly. The
// empty thinking block must round-trip back to the API in subsequent
// requests, otherwise DeepSeek rejects with 400.
const reasoningContent = (delta as any).reasoning_content
if (reasoningContent != null && reasoningContent !== '') {
if (reasoningContent != null) {
if (!thinkingBlockOpen) {
currentContentIndex++
thinkingBlockOpen = true
@ -110,14 +113,16 @@ export async function* adaptOpenAIStreamToAnthropic(
} as BetaRawMessageStreamEvent
}
yield {
type: 'content_block_delta',
index: currentContentIndex,
delta: {
type: 'thinking_delta',
thinking: reasoningContent,
},
} as BetaRawMessageStreamEvent
if (reasoningContent !== '') {
yield {
type: 'content_block_delta',
index: currentContentIndex,
delta: {
type: 'thinking_delta',
thinking: reasoningContent,
},
} as BetaRawMessageStreamEvent
}
}
// Handle text content