From 63bf7a29b6a3eb03d37b749decbd6a5d9a70543b Mon Sep 17 00:00:00 2001 From: FocusFlow Dev Date: Sun, 26 Apr 2026 12:16:32 +0800 Subject: [PATCH] fix(run_agent): prevent reasoning_content regression in DeepSeek/Kimi tool-call replay PR #15478 fixed missing reasoning_content for DeepSeek API but introduced a regression: tool-call messages with genuine 'reasoning' field were overwritten by empty-string fallback before promotion. Re-order _copy_reasoning_content_for_api steps: 1. Preserve explicit reasoning_content 2. Promote 'reasoning' field (MOVED UP) 3. DeepSeek/Kimi tool-call empty-string fallback (MOVED DOWN) 4. Non-thinking provider cleanup Fixes #15812, relates #15749, #15478. --- run_agent.py | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/run_agent.py b/run_agent.py index 43c367e460..b567b96545 100644 --- a/run_agent.py +++ b/run_agent.py @@ -7868,7 +7868,17 @@ class AIAgent: api_msg["reasoning_content"] = existing return - # 2. DeepSeek / Kimi thinking mode: tool-call turns that lack + # 2. Healthy session: promote 'reasoning' field to 'reasoning_content' + # for providers that use the internal 'reasoning' key. + # This must happen BEFORE the DeepSeek/Kimi tool-call check so that + # genuine reasoning content is not overwritten by the empty-string + # fallback (#15812 regression in PR #15478). + normalized_reasoning = source_msg.get("reasoning") + if isinstance(normalized_reasoning, str) and normalized_reasoning: + api_msg["reasoning_content"] = normalized_reasoning + return + + # 3. DeepSeek / Kimi thinking mode: tool-call turns that lack # reasoning_content are "poisoned history" — a prior provider (MiniMax, # etc.) left them empty. DeepSeek returns HTTP 400 if reasoning_content # is absent on replay; inject "" to satisfy the provider's requirement @@ -7884,13 +7894,6 @@ class AIAgent: api_msg["reasoning_content"] = "" return - # 3. Healthy session: promote 'reasoning' field to 'reasoning_content' - # for providers that use the internal 'reasoning' key. - normalized_reasoning = source_msg.get("reasoning") - if isinstance(normalized_reasoning, str) and normalized_reasoning: - api_msg["reasoning_content"] = normalized_reasoning - return - # 4. DeepSeek / Kimi thinking mode: all assistant messages need # reasoning_content. Inject "" to satisfy the provider's requirement # when no explicit reasoning content is present.