From 478cfc90c33781f9658f43243596ae28f93e8c39 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 05:55:53 +0000 Subject: [PATCH 1/2] Initial plan From 15f56ccc6c3bb76d12d6818d6621cc458cbccaa8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 27 Jan 2026 06:00:28 +0000 Subject: [PATCH 2/2] Fix send_chat_history to send request even with empty chat_history_messages - Removed early return for empty chat_history_messages that was short-circuiting HTTP request - Updated docstring to document that empty lists are allowed and will still send request - Updated unit test to verify HTTP requests are made with empty chat history - Moved json import to top of test file Co-authored-by: pontemonti <7850950+pontemonti@users.noreply.github.com> --- .../mcp_tool_server_configuration_service.py | 11 +++-- .../services/test_send_chat_history.py | 40 +++++++++++++++---- 2 files changed, 37 insertions(+), 14 deletions(-) diff --git a/libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/services/mcp_tool_server_configuration_service.py b/libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/services/mcp_tool_server_configuration_service.py index 71d2ee5d..edc9c4db 100644 --- a/libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/services/mcp_tool_server_configuration_service.py +++ b/libraries/microsoft-agents-a365-tooling/microsoft_agents_a365/tooling/services/mcp_tool_server_configuration_service.py @@ -569,7 +569,8 @@ async def send_chat_history( Must have a valid activity with conversation.id, activity.id, and activity.text. chat_history_messages: List of ChatHistoryMessage objects representing the chat - history. Must be non-empty. + history. May be empty - an empty list will still send a + request to the MCP platform with empty chat history. options: Optional ToolOptions instance containing optional parameters. Returns: @@ -578,7 +579,7 @@ async def send_chat_history( On failure, returns OperationResult.failed() with error details. Raises: - ValueError: If turn_context is None, chat_history_messages is None or empty, + ValueError: If turn_context is None, chat_history_messages is None, turn_context.activity is None, or any of the required fields (conversation.id, activity.id, activity.text) are missing or empty. @@ -602,10 +603,8 @@ async def send_chat_history( if chat_history_messages is None: raise ValueError("chat_history_messages cannot be None") - # Handle empty messages - return success with warning (consistent with extension behavior) - if len(chat_history_messages) == 0: - self._logger.warning("Empty message list provided to send_chat_history") - return OperationResult.success() + # Note: Empty chat_history_messages is allowed - we still send the request to MCP platform + # The platform needs to receive the request even with empty chat history # Extract required information from turn context if not turn_context.activity: diff --git a/tests/tooling/services/test_send_chat_history.py b/tests/tooling/services/test_send_chat_history.py index 60b56c80..e966462c 100644 --- a/tests/tooling/services/test_send_chat_history.py +++ b/tests/tooling/services/test_send_chat_history.py @@ -3,6 +3,7 @@ """Unit tests for send_chat_history method in McpToolServerConfigurationService.""" +import json from datetime import UTC, datetime from unittest.mock import AsyncMock, MagicMock, Mock, patch @@ -146,14 +147,37 @@ async def test_send_chat_history_validates_chat_history_messages( await service.send_chat_history(mock_turn_context, None) @pytest.mark.asyncio - async def test_send_chat_history_empty_list_returns_success(self, service, mock_turn_context): - """Test that send_chat_history returns success for empty list (CRM-008).""" - # Act - result = await service.send_chat_history(mock_turn_context, []) - - # Assert - empty list should return success, not raise exception - assert result.succeeded is True - assert len(result.errors) == 0 + async def test_send_chat_history_empty_list_sends_request(self, service, mock_turn_context): + """Test that send_chat_history sends request to MCP platform even with empty list.""" + # Arrange + mock_response = AsyncMock() + mock_response.status = 200 + mock_response.text = AsyncMock(return_value="OK") + + # Mock aiohttp.ClientSession + with patch("aiohttp.ClientSession") as mock_session: + mock_session_instance = MagicMock() + mock_post = AsyncMock() + mock_post.__aenter__.return_value = mock_response + mock_session_instance.post.return_value = mock_post + mock_session.return_value.__aenter__.return_value = mock_session_instance + + # Act + result = await service.send_chat_history(mock_turn_context, []) + + # Assert - empty list should still make HTTP request and return success + assert result.succeeded is True + assert len(result.errors) == 0 + + # Verify HTTP request was actually made + assert mock_session_instance.post.called + call_args = mock_session_instance.post.call_args + assert "real-time-threat-protection/chat-message" in call_args[0][0] + + # Verify the payload contains an empty chat history + data = call_args[1]["data"] + payload = json.loads(data) + assert payload["chatHistory"] == [] @pytest.mark.asyncio async def test_send_chat_history_validates_activity(self, service, chat_history_messages):