Send empty assistant content when DeepSeek thinks without calling a tool.
A thinking-only turn was replayed as content=null with no tool_calls, which the API rejects with 400 and skipped IC review. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -111,8 +111,11 @@ def messages_to_openai(messages: list[Message], *, vision: bool) -> list[dict]:
|
||||
tool_calls = [b for b in m.content if isinstance(b, ToolCall)]
|
||||
msg: dict[str, Any] = {"role": "assistant"}
|
||||
text = "".join(text_parts)
|
||||
msg["content"] = text if text else None
|
||||
# DeepSeek 400s with "content or tool_calls must be set" when
|
||||
# thinking-mode returns reasoning only (content=null, no tools).
|
||||
# Tool turns may keep content=null; text-only turns need "".
|
||||
if tool_calls:
|
||||
msg["content"] = text if text else None
|
||||
msg["tool_calls"] = [
|
||||
{
|
||||
"id": tc.id,
|
||||
@@ -124,6 +127,8 @@ def messages_to_openai(messages: list[Message], *, vision: bool) -> list[dict]:
|
||||
}
|
||||
for tc in tool_calls
|
||||
]
|
||||
else:
|
||||
msg["content"] = text
|
||||
reasoning = _reasoning_from_blocks(m.content)
|
||||
if reasoning:
|
||||
msg["reasoning_content"] = reasoning
|
||||
|
||||
@@ -72,6 +72,33 @@ def test_messages_to_openai_pdf_becomes_text(sample_pdf: Path):
|
||||
assert "Extract the pin table" in blob
|
||||
|
||||
|
||||
def test_thinking_only_assistant_sends_empty_content():
|
||||
"""Thinking with no visible text and no tools must still set content."""
|
||||
out = messages_to_openai(
|
||||
[Message("assistant", [
|
||||
TextBlock("", reasoning_content="Need to inspect pin 3 first."),
|
||||
])],
|
||||
vision=False,
|
||||
)
|
||||
assert out[0]["role"] == "assistant"
|
||||
assert out[0]["content"] == ""
|
||||
assert out[0]["reasoning_content"] == "Need to inspect pin 3 first."
|
||||
assert "tool_calls" not in out[0]
|
||||
|
||||
|
||||
def test_tool_call_assistant_may_have_null_content():
|
||||
out = messages_to_openai(
|
||||
[Message("assistant", [
|
||||
ToolCall(id="c1", name="get_pintable", input={"ref": "U2"},
|
||||
reasoning_content="look up pins"),
|
||||
])],
|
||||
vision=False,
|
||||
)
|
||||
assert out[0]["content"] is None
|
||||
assert out[0]["tool_calls"][0]["function"]["name"] == "get_pintable"
|
||||
assert out[0]["reasoning_content"] == "look up pins"
|
||||
|
||||
|
||||
def test_messages_to_openai_tool_roundtrip():
|
||||
messages = [
|
||||
Message("assistant", [
|
||||
|
||||
Reference in New Issue
Block a user