mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Fix streaming path to include chat history in messages sent to chat client (#3798)
RunCoreStreamingAsync was passing inputMessagesForProviders (which lacks chat history) to GetStreamingResponseAsync instead of inputMessagesForChatClient (which includes chat history). This caused streaming runs to lose conversation context on subsequent calls. The non-streaming path (RunCoreAsync) already correctly used inputMessagesForChatClient. This aligns the streaming path to match. Also adds a unit test that validates chat history is included in messages sent to the chat client during streaming on subsequent calls. Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
8ad66637d8
commit
6c37ce8450
@@ -226,7 +226,7 @@ public sealed partial class ChatClientAgent : AIAgent
|
||||
try
|
||||
{
|
||||
// Using the enumerator to ensure we consider the case where no updates are returned for notification.
|
||||
responseUpdatesEnumerator = chatClient.GetStreamingResponseAsync(inputMessagesForProviders, chatOptions, cancellationToken).GetAsyncEnumerator(cancellationToken);
|
||||
responseUpdatesEnumerator = chatClient.GetStreamingResponseAsync(inputMessagesForChatClient, chatOptions, cancellationToken).GetAsyncEnumerator(cancellationToken);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
|
||||
@@ -1320,6 +1320,45 @@ public partial class ChatClientAgentTests
|
||||
mockFactory.Verify(f => f(It.IsAny<ChatClientAgentOptions.ChatHistoryProviderFactoryContext>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that RunStreamingAsync includes chat history in messages sent to the chat client on subsequent calls.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunStreamingAsyncIncludesChatHistoryInMessagesToChatClientAsync()
|
||||
{
|
||||
// Arrange
|
||||
List<IEnumerable<ChatMessage>> capturedMessages = [];
|
||||
Mock<IChatClient> mockService = new();
|
||||
ChatResponseUpdate[] returnUpdates =
|
||||
[
|
||||
new ChatResponseUpdate(role: ChatRole.Assistant, content: "response"),
|
||||
];
|
||||
mockService.Setup(
|
||||
s => s.GetStreamingResponseAsync(
|
||||
It.IsAny<IEnumerable<ChatMessage>>(),
|
||||
It.IsAny<ChatOptions>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns(ToAsyncEnumerableAsync(returnUpdates))
|
||||
.Callback<IEnumerable<ChatMessage>, ChatOptions?, CancellationToken>((msgs, _, _) => capturedMessages.Add(msgs.ToList()));
|
||||
ChatClientAgent agent = new(mockService.Object, options: new()
|
||||
{
|
||||
ChatOptions = new() { Instructions = "test instructions" },
|
||||
});
|
||||
|
||||
// Act
|
||||
ChatClientAgentSession? session = await agent.CreateSessionAsync() as ChatClientAgentSession;
|
||||
await agent.RunStreamingAsync([new(ChatRole.User, "first")], session).ToListAsync();
|
||||
await agent.RunStreamingAsync([new(ChatRole.User, "second")], session).ToListAsync();
|
||||
|
||||
// Assert - the second call should include chat history (first user message + first response) plus the new message
|
||||
Assert.Equal(2, capturedMessages.Count);
|
||||
var secondCallMessages = capturedMessages[1].ToList();
|
||||
Assert.Equal(3, secondCallMessages.Count);
|
||||
Assert.Equal("first", secondCallMessages[0].Text);
|
||||
Assert.Equal("response", secondCallMessages[1].Text);
|
||||
Assert.Equal("second", secondCallMessages[2].Text);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that RunStreamingAsync throws when a <see cref="ChatHistoryProvider"/> factory is provided and the chat client returns a conversation id.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user