fix(deepseek): use non-empty reasoning_content placeholder for V4 Pro thinking mode
DeepSeek V4 Pro tightened thinking-mode validation and rejects empty-string
reasoning_content with HTTP 400:
The reasoning content in the thinking mode must be passed back to the API.
run_agent.py injected "" at three fallback sites — the tool-call pad in
_build_assistant_message and both injection branches of
_copy_reasoning_content_for_api (cross-provider poison guard + unconditional
thinking pad). All three now emit " " (single space), which satisfies the
non-empty check on V4 Pro without leaking fabricated reasoning.
Also upgrades stale empty-string placeholders on replay: sessions persisted
before this change have reasoning_content="" pinned at creation time; when
the active provider enforces thinking-mode echo, the replay path now rewrites
"" -> " " so existing users don't 400 on their first V4 Pro turn after
updating. Non-thinking providers still round-trip "" verbatim.
Updates 9 existing assertions + adds 2 regression tests (stale-placeholder
upgrade, non-thinking verbatim preservation).
Refs #15250, #17400.
Closes #17341.
This commit is contained in:
@@ -1465,8 +1465,8 @@ class TestBuildAssistantMessage:
|
||||
|
||||
This preserves ``_copy_reasoning_content_for_api``'s downstream
|
||||
tiers at replay time — cross-provider leak guard (#15748),
|
||||
promote-from-``reasoning``, and DeepSeek/Kimi ""-pad — which
|
||||
would all be bypassed if we eagerly wrote ``reasoning_content=""``
|
||||
promote-from-``reasoning``, and DeepSeek/Kimi " "-pad — which
|
||||
would all be bypassed if we eagerly wrote ``reasoning_content=" "``
|
||||
on every assistant turn regardless of provider.
|
||||
"""
|
||||
msg = _mock_assistant_msg(content="plain answer")
|
||||
@@ -4617,7 +4617,7 @@ class TestReasoningReplayForStrictProviders:
|
||||
agent.compression_enabled = False
|
||||
agent.save_trajectories = False
|
||||
|
||||
def test_kimi_tool_replay_includes_empty_reasoning_content(self, agent):
|
||||
def test_kimi_tool_replay_includes_space_reasoning_content(self, agent):
|
||||
self._setup_agent(agent)
|
||||
agent.base_url = "https://api.kimi.com/coding/v1"
|
||||
agent._base_url_lower = agent.base_url.lower()
|
||||
@@ -4654,7 +4654,7 @@ class TestReasoningReplayForStrictProviders:
|
||||
assert replayed_assistant["role"] == "assistant"
|
||||
assert replayed_assistant["tool_calls"][0]["function"]["name"] == "terminal"
|
||||
assert "reasoning_content" in replayed_assistant
|
||||
assert replayed_assistant["reasoning_content"] == ""
|
||||
assert replayed_assistant["reasoning_content"] == " "
|
||||
|
||||
def test_explicit_reasoning_content_beats_normalized_reasoning_on_replay(self, agent):
|
||||
self._setup_agent(agent)
|
||||
|
||||
Reference in New Issue
Block a user