From a8b4d3b48de4b9dc14826994cd5d62836ea41551 Mon Sep 17 00:00:00 2001 From: Dmitry Butko Date: Thu, 9 Apr 2026 20:37:56 +1000 Subject: [PATCH] fix: strip all trailing assistant messages without tool_calls Strengthens the strip to remove any trailing assistant message (not just empty ones) when it has no tool_calls. The Copilot proxy for Claude rejects conversations ending with any assistant message as unsupported prefill. This fixes the Telegram bot channel where the agent loop appends an assistant message with content. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- crates/openfang-runtime/src/drivers/openai.rs | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/crates/openfang-runtime/src/drivers/openai.rs b/crates/openfang-runtime/src/drivers/openai.rs index 93580c1b..90648676 100644 --- a/crates/openfang-runtime/src/drivers/openai.rs +++ b/crates/openfang-runtime/src/drivers/openai.rs @@ -262,18 +262,13 @@ struct OaiUsage { completion_tokens: u64, } -/// Strip trailing empty assistant messages from the message list. -/// Some API proxies (e.g. Copilot proxying Claude/Gemini) reject these as -/// unsupported "assistant message prefill". +/// Strip trailing assistant messages without tool calls from the message list. +/// The Copilot API proxy for Claude rejects conversations ending with an +/// assistant message as unsupported "assistant message prefill". Assistant +/// messages with tool_calls are kept (they're part of the tool call protocol). fn strip_trailing_empty_assistant(messages: &mut Vec) { while messages.last().map_or(false, |m| { - m.role == "assistant" - && m.tool_calls.is_none() - && match &m.content { - None => true, - Some(OaiMessageContent::Text(t)) => t.trim().is_empty(), - _ => false, - } + m.role == "assistant" && m.tool_calls.is_none() }) { messages.pop(); }