Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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.

Expand All @@ -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:
Expand Down
40 changes: 32 additions & 8 deletions tests/tooling/services/test_send_chat_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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):
Expand Down
Loading