Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -180,9 +180,9 @@ describe('DeepSeekOpenAICompatibleProvider', () => {
});

// https://github.com/QwenLM/qwen-code/issues/3695 — DeepSeek's thinking
// mode rejects subsequent requests when a prior tool-calling assistant
// turn omits reasoning_content, even if the model itself returned no
// reasoning text. The provider must always send the field.
// mode rejects subsequent requests when any prior assistant turn omits
// reasoning_content, even if the model itself returned no reasoning text.
// The provider must always send the field.
it('injects empty reasoning_content on tool-calling assistant turns missing it', () => {
const originalRequest: OpenAI.Chat.ChatCompletionCreateParams = {
model: 'deepseek-v4-flash',
Expand Down Expand Up @@ -245,7 +245,7 @@ describe('DeepSeekOpenAICompatibleProvider', () => {
expect(assistant.reasoning_content).toBe('Let me glob first.');
});

it('does not add reasoning_content to assistant turns without tool_calls', () => {
it('injects empty reasoning_content on assistant turns without tool_calls', () => {
const originalRequest: OpenAI.Chat.ChatCompletionCreateParams = {
model: 'deepseek-v4-flash',
messages: [
Expand All @@ -259,7 +259,7 @@ describe('DeepSeekOpenAICompatibleProvider', () => {
const assistant = result.messages?.[1] as {
reasoning_content?: string;
};
expect(assistant.reasoning_content).toBeUndefined();
expect(assistant.reasoning_content).toBe('');
});
});

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,19 +108,16 @@ function flattenContentParts(
}

// DeepSeek's thinking mode requires reasoning_content to be replayed on every
// prior assistant turn that carried tool_calls. The model may legitimately
// return a tool round without reasoning text, so the field can be missing
// when we rebuild the request. Send an empty string in that case so the API
// contract is satisfied. https://github.com/QwenLM/qwen-code/issues/3695
// prior assistant turn, including ones without tool_calls. The model may
// legitimately return a turn without reasoning text, so the field can be
// missing when we rebuild the request. Send an empty string in that case so
// the API contract is satisfied. https://github.com/QwenLM/qwen-code/issues/3695
function ensureReasoningContentOnToolCalls(
message: OpenAI.Chat.ChatCompletionMessageParam,
): OpenAI.Chat.ChatCompletionMessageParam {
if (message.role !== 'assistant') {
return message;
}
if (!Array.isArray(message.tool_calls) || message.tool_calls.length === 0) {
return message;
}
const extended = message as ExtendedChatCompletionAssistantMessageParam;
if (
typeof extended.reasoning_content === 'string' &&
Expand Down
Loading