From f9ffb6fb2da5d7913b33af7bac531f3348fdad17 Mon Sep 17 00:00:00 2001 From: Marvin Date: Mon, 7 Sep 2026 22:07:20 -0300 Subject: [PATCH] fix(server): strip executed Bailing blocks whenever calls exist The generic template-driven PEG can return structured calls while leaving the block text in reasoning_content. The rescue-only strip missed those turns, so raw XML kept reaching client Reasoning panels. Apply the terminator strip on any final turn carrying tool calls, regardless of which layer parsed them. Reasoning with no calls is never touched. --- examples/server/server-context.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/examples/server/server-context.cpp b/examples/server/server-context.cpp index a9897dce..8c0b86d3 100644 --- a/examples/server/server-context.cpp +++ b/examples/server/server-context.cpp @@ -756,6 +756,17 @@ const common_chat_msg& server_slot::update_chat_msg(bool is_partial, std::vector bailing::remove_executed_blocks(new_msg.reasoning_content); } } + // Same terminator semantic for calls the PEG layer parsed itself: the + // generic template-driven parser can return structured calls while + // leaving the block text in reasoning_content. Strip executed blocks + // whenever the turn carries calls, no matter which layer parsed them. + // Reasoning with no calls is never touched. Revert with the block above. + if (!is_partial && !new_msg.tool_calls.empty() + && bailing::has_complete_block(new_msg.reasoning_content)) { + new_msg.reasoning_content = + bailing::remove_executed_blocks(new_msg.reasoning_content); + LLAMA_LOG_WARN("Bailing strip: removed executed call block(s) from reasoning_content\n"); + } //new_msg.ensure_tool_call_ids_set(generated_tool_call_ids, gen_tool_call_id); new_msg.set_tool_call_ids(generated_tool_call_ids, gen_tool_call_id); chat_msg = new_msg;