From 0941e4036365ad9a57db604d35d98f0356022b54 Mon Sep 17 00:00:00 2001 From: Sameer Kankute Date: Wed, 18 Mar 2026 16:30:42 +0530 Subject: [PATCH] fix(prompting): address greptile review - fix SyntaxError, restore backward compat, add trailing tool-call test - Remove stray ): on line 303 (P0 SyntaxError) - Restore backward-compatible trailing-assistant behavior (P1) - Add test_ensure_alternating_roles_trailing_tool_call_assistant - Keep role check alongside _counts_for_alternation (P2 is false positive) Made-with: Cursor --- .../prompt_templates/common_utils.py | 10 ++---- tests/llm_translation/test_prompt_factory.py | 34 +++++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/litellm/litellm_core_utils/prompt_templates/common_utils.py b/litellm/litellm_core_utils/prompt_templates/common_utils.py index f5e3ffdb749..d7c1cc708b0 100644 --- a/litellm/litellm_core_utils/prompt_templates/common_utils.py +++ b/litellm/litellm_core_utils/prompt_templates/common_utils.py @@ -300,7 +300,6 @@ def _insert_user_continue_message( curr_message = result_messages[i] inserted_continue_message = False if _counts_for_alternation(curr_message) and curr_message["role"] == "assistant": - ): j = i - 1 while j >= 0: previous_message = result_messages[j] @@ -314,12 +313,9 @@ def _insert_user_continue_message( if not inserted_continue_message: i += 1 - # Handle final message - if ( - result_messages[-1]["role"] == "assistant" - and _counts_for_alternation(result_messages[-1]) - and ensure_alternating_roles - ): + # Handle final message — append user_continue after any trailing assistant, + # including ones with tool_calls, to preserve backward compatibility. + if result_messages[-1]["role"] == "assistant" and ensure_alternating_roles: result_messages.append(continue_message) return result_messages diff --git a/tests/llm_translation/test_prompt_factory.py b/tests/llm_translation/test_prompt_factory.py index f146e2811a9..b02ed3ebea1 100644 --- a/tests/llm_translation/test_prompt_factory.py +++ b/tests/llm_translation/test_prompt_factory.py @@ -903,6 +903,40 @@ def test_ensure_alternating_roles_does_not_split_tool_call_chain(): ] +def test_ensure_alternating_roles_trailing_tool_call_assistant(): + messages = [ + {"role": "user", "content": "What's the weather?"}, + { + "role": "assistant", + "content": None, + "tool_calls": [ + { + "id": "call_abc", + "type": "function", + "function": { + "name": "get_weather", + "arguments": '{"location": "NYC"}', + }, + } + ], + }, + ] + + transformed_messages = get_completion_messages( + messages=messages, + assistant_continue_message=None, + user_continue_message=None, + ensure_alternating_roles=True, + ) + + # Backward compat: trailing assistant (even with tool_calls) gets user_continue + # appended, then assistant_continue bridges the user→user gap. + assert transformed_messages[-1] == {"role": "user", "content": "Please continue."} + assert transformed_messages[0] == {"role": "user", "content": "What's the weather?"} + assert transformed_messages[1]["role"] == "assistant" + assert transformed_messages[1].get("tool_calls") is not None + + def test_alternating_roles_e2e(): from litellm.llms.custom_httpx.http_handler import HTTPHandler import json