Skip to content

Commit 041f303

Browse files
committed
fix(deepseek): strip reasoning_content when extra_body disables thinking
When extra_body sets thinking.type to 'disabled', the extra_body wrapper runs after the DeepSeek provider wrapper which may have already backfilled reasoning_content on assistant messages. The stale reasoning_content then causes DeepSeek to reject the payload with 400. Strip reasoning_content from all messages after extra_body is applied whenever the final payload has thinking.type === 'disabled'. Fixes #74374
1 parent 542821c commit 041f303

2 files changed

Lines changed: 53 additions & 0 deletions

File tree

src/agents/pi-embedded-runner-extraparams.test.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -946,6 +946,42 @@ describe("applyExtraParamsToAgent", () => {
946946
expect(payload).not.toHaveProperty("store");
947947
});
948948

949+
it("strips reasoning_content when extra_body sets thinking to disabled (#74374)", () => {
950+
const payload = runResponsesPayloadMutationCase({
951+
applyProvider: "deepseek",
952+
applyModelId: "deepseek-v4-pro",
953+
cfg: {
954+
agents: {
955+
defaults: {
956+
models: {
957+
"deepseek/deepseek-v4-pro": {
958+
params: {
959+
extra_body: { thinking: { type: "disabled" } },
960+
},
961+
},
962+
},
963+
},
964+
},
965+
},
966+
model: {
967+
api: "openai-completions",
968+
provider: "deepseek",
969+
id: "deepseek-v4-pro",
970+
baseUrl: "https://api.deepseek.com",
971+
} as Model<"openai-completions">,
972+
payload: {
973+
messages: [
974+
{ role: "user", content: "hello" },
975+
{ role: "assistant", content: "hi", reasoning_content: "let me think" },
976+
],
977+
},
978+
});
979+
980+
expect(payload.thinking).toEqual({ type: "disabled" });
981+
const messages = payload.messages as Record<string, unknown>[];
982+
expect(messages[1]).not.toHaveProperty("reasoning_content");
983+
});
984+
949985
it("forwards chat_template_kwargs params as top-level openai-completions payload fields", () => {
950986
const payload = runResponsesPayloadMutationCase({
951987
applyProvider: "vllm",

src/agents/pi-embedded-runner/extra-params.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -504,6 +504,23 @@ function createOpenAICompletionsExtraBodyWrapper(
504504
log.warn(`extra_body overwriting request payload keys: ${collisions.join(", ")}`);
505505
}
506506
Object.assign(payloadObj, extraBody);
507+
508+
// When extra_body sets thinking to disabled after a provider wrapper may have
509+
// backfilled reasoning_content, strip it to avoid DeepSeek 400 errors.
510+
// See: https://github.com/openclaw/openclaw/issues/74374
511+
const thinking = payloadObj.thinking;
512+
if (
513+
thinking &&
514+
typeof thinking === "object" &&
515+
(thinking as Record<string, unknown>).type === "disabled" &&
516+
Array.isArray(payloadObj.messages)
517+
) {
518+
for (const message of payloadObj.messages) {
519+
if (message && typeof message === "object") {
520+
delete (message as Record<string, unknown>).reasoning_content;
521+
}
522+
}
523+
}
507524
});
508525
};
509526
}

0 commit comments

Comments
 (0)