From 7a8ee0f200435af258e796c5b6a47fadbcb2bd39 Mon Sep 17 00:00:00 2001 From: h Date: Wed, 2 Sep 2026 01:44:02 +0200 Subject: [PATCH] feat(markdown): thinking blocks between hidden tool calls collapse to the first one --- .../frontends/markdown/renderer.py | 9 +++++++-- tests/test_markdown_renderer.py | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/beaver_gateway/frontends/markdown/renderer.py b/src/beaver_gateway/frontends/markdown/renderer.py index 218771a..7926dd7 100644 --- a/src/beaver_gateway/frontends/markdown/renderer.py +++ b/src/beaver_gateway/frontends/markdown/renderer.py @@ -48,14 +48,19 @@ def render_assistant_text(text: str) -> str: def render_assistant_message(message: Message) -> str: """Render an assistant ``Message`` into a turn block. - Tool-use blocks render to nothing; only text and thinking content reach - the file (see :mod:`.parser` for how the reverse strip works). + Tool-use blocks render to nothing; of the thinking blocks between two + texts only the first one reaches the file. """ parts: list[str] = ["### Assistant:", ""] + after_thinking = False for block in message.content: + thinking = isinstance(block, ThinkingBlock) + if thinking and after_thinking: + continue lines = list(_render_block(block)) if not lines: continue + after_thinking = thinking parts.extend(lines) parts.append("") return "\n".join(parts).rstrip() + "\n" diff --git a/tests/test_markdown_renderer.py b/tests/test_markdown_renderer.py index 4bf08a8..eecc64d 100644 --- a/tests/test_markdown_renderer.py +++ b/tests/test_markdown_renderer.py @@ -39,6 +39,23 @@ def test_thinking_renders_as_collapsed_callout() -> None: ) +def test_thinking_between_hidden_tool_calls_collapses_to_the_first() -> None: + message = _message( + ThinkingBlock(type="thinking", thinking="one", signature="s"), + ToolUseBlock(type="tool_use", id="t1", name="Read", input={}), + ThinkingBlock(type="thinking", thinking="two", signature="s"), + ToolUseBlock(type="tool_use", id="t2", name="Read", input={}), + ThinkingBlock(type="thinking", thinking="three", signature="s"), + TextBlock(type="text", text="answer"), + ThinkingBlock(type="thinking", thinking="four", signature="s"), + TextBlock(type="text", text="more"), + ) + assert renderer.render_assistant_message(message) == ( + "### Assistant:\n\n> [!thinking]-\n> one\n\nanswer\n\n" + "> [!thinking]-\n> four\n\nmore\n" + ) + + def test_user_scaffold_matches_rendered_user_turn_shape() -> None: body = renderer.append_to_body("### Assistant:\n\nhi\n", renderer.USER_SCAFFOLD) assert body.endswith("\n\n---\n\n### User:\n\n")