From 631fdb4a46dda2f44754e78d704109c3cafe8d70 Mon Sep 17 00:00:00 2001 From: chengyongru <2755839590@qq.com> Date: Sun, 7 Jun 2026 23:13:51 +0800 Subject: [PATCH] test: cover empty reasoning_content history preservation maintainer edit: add SDK-object and tool-call history regressions so the empty-string reasoning_content fix is covered across both parse branches and the sanitized request path. --- tests/providers/test_reasoning_content.py | 51 +++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/tests/providers/test_reasoning_content.py b/tests/providers/test_reasoning_content.py index 8bb0b45fd..f61d385c8 100644 --- a/tests/providers/test_reasoning_content.py +++ b/tests/providers/test_reasoning_content.py @@ -8,6 +8,7 @@ from types import SimpleNamespace from unittest.mock import patch from nanobot.providers.openai_compat_provider import OpenAICompatProvider +from nanobot.utils.helpers import build_assistant_message # ── _parse: non-streaming ───────────────────────────────────────────────── @@ -77,6 +78,56 @@ def test_parse_dict_reasoning_content_empty_string_preserved() -> None: assert result.reasoning_content == "" +def test_parse_sdk_reasoning_content_empty_string_preserved() -> None: + """SDK response objects preserve reasoning_content=\"\".""" + with patch("nanobot.providers.openai_compat_provider.AsyncOpenAI"): + provider = OpenAICompatProvider() + + message = SimpleNamespace(content="answer", reasoning_content="", tool_calls=None) + choice = SimpleNamespace(message=message, finish_reason="stop") + response = SimpleNamespace(choices=[choice], usage=None) + + result = provider._parse(response) + + assert result.content == "answer" + assert result.reasoning_content == "" + + +def test_tool_call_history_preserves_empty_reasoning_content_after_sanitize() -> None: + """Empty reasoning_content survives the tool-call history round trip.""" + with patch("nanobot.providers.openai_compat_provider.AsyncOpenAI"): + provider = OpenAICompatProvider() + + response = { + "choices": [{ + "message": { + "content": "", + "reasoning_content": "", + "tool_calls": [{ + "id": "call_1", + "type": "function", + "function": {"name": "lookup", "arguments": "{}"}, + }], + }, + "finish_reason": "tool_calls", + }], + } + + result = provider._parse(response) + assistant_message = build_assistant_message( + result.content or "", + tool_calls=[tc.to_openai_tool_call() for tc in result.tool_calls], + reasoning_content=result.reasoning_content, + ) + sanitized = provider._sanitize_messages([ + {"role": "user", "content": "look something up"}, + assistant_message, + {"role": "tool", "tool_call_id": "call_1", "content": "done"}, + ]) + + assert sanitized[1]["reasoning_content"] == "" + + # ── _parse_chunks: streaming dict branch ─────────────────────────────────