Skip to content
Open
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
15 changes: 9 additions & 6 deletions dotnet/src/Microsoft.Agents.AI/ChatClient/ChatClientAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -476,7 +476,7 @@ internal async Task NotifyProvidersOfNewMessagesAsync(
ChatOptions? chatOptions,
CancellationToken cancellationToken)
{
ChatHistoryProvider? chatHistoryProvider = this.ResolveChatHistoryProvider(chatOptions);
ChatHistoryProvider? chatHistoryProvider = this.ResolveChatHistoryProvider(session, chatOptions);

if (chatHistoryProvider is not null)
{
Expand Down Expand Up @@ -508,7 +508,7 @@ internal async Task NotifyProvidersOfFailureAsync(
ChatOptions? chatOptions,
CancellationToken cancellationToken)
{
ChatHistoryProvider? chatHistoryProvider = this.ResolveChatHistoryProvider(chatOptions);
ChatHistoryProvider? chatHistoryProvider = this.ResolveChatHistoryProvider(session, chatOptions);

if (chatHistoryProvider is not null)
{
Expand Down Expand Up @@ -974,14 +974,17 @@ private void WarnOnMissingPerServiceCallChatHistoryPersistingChatClient()
}
}

private ChatHistoryProvider? ResolveChatHistoryProvider(ChatOptions? chatOptions)
private ChatHistoryProvider? ResolveChatHistoryProvider(ChatClientAgentSession session, ChatOptions? chatOptions)
{
ChatHistoryProvider? provider = chatOptions?.ConversationId is null ? this.ChatHistoryProvider : null;
bool serviceStoresHistory = !this.RequiresPerServiceCallChatHistoryPersistence
&& (!string.IsNullOrWhiteSpace(session.ConversationId)
|| !string.IsNullOrWhiteSpace(chatOptions?.ConversationId));
ChatHistoryProvider? provider = serviceStoresHistory ? null : this.ChatHistoryProvider;

// If someone provided an override ChatHistoryProvider via AdditionalProperties, we should use that instead.
if (chatOptions?.AdditionalProperties?.TryGetValue(out ChatHistoryProvider? overrideProvider) is true)
{
if (this._agentOptions?.ThrowOnChatHistoryProviderConflict is true && string.IsNullOrWhiteSpace(chatOptions?.ConversationId) is false)
if (this._agentOptions?.ThrowOnChatHistoryProviderConflict is true && serviceStoresHistory)
{
throw new InvalidOperationException(
$"Only {nameof(ChatClientAgentSession.ConversationId)} or {nameof(this.ChatHistoryProvider)} may be used, but not both. The current {nameof(ChatClientAgentSession)} has a {nameof(ChatClientAgentSession.ConversationId)} indicating server-side chat history management, but an override {nameof(this.ChatHistoryProvider)} was provided via {nameof(AgentRunOptions.AdditionalProperties)}.");
Expand Down Expand Up @@ -1019,7 +1022,7 @@ internal async Task<IEnumerable<ChatMessage>> LoadChatHistoryAsync(
ChatOptions? chatOptions,
CancellationToken cancellationToken)
{
var chatHistoryProvider = this.ResolveChatHistoryProvider(chatOptions);
var chatHistoryProvider = this.ResolveChatHistoryProvider(session, chatOptions);
if (chatHistoryProvider is null)
{
return messages;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,11 +385,11 @@ public async Task RunAsync_Throws_WhenThrowEnabledRegardlessOfClearSettingAsync(
}

/// <summary>
/// Verify that RunAsync does not throw when no ChatHistoryProvider is configured on options,
/// even if the service returns a conversation id (default InMemoryChatHistoryProvider is used but not from options).
/// Verify that RunAsync does not persist to the default InMemoryChatHistoryProvider when
/// the service returns a conversation id.
/// </summary>
[Fact]
public async Task RunAsync_DoesNotThrow_WhenNoChatHistoryProviderInOptionsAndConversationIdReturnedAsync()
public async Task RunAsync_DoesNotUseDefaultInMemoryChatHistoryProvider_WhenConversationIdReturnedAsync()
{
// Arrange
Mock<IChatClient> mockService = new();
Expand All @@ -407,8 +407,10 @@ public async Task RunAsync_DoesNotThrow_WhenNoChatHistoryProviderInOptionsAndCon
ChatClientAgentSession? session = await agent.CreateSessionAsync() as ChatClientAgentSession;
await agent.RunAsync([new(ChatRole.User, "test")], session);

// Assert - no exception, session gets the conversation id
// Assert
Assert.Equal("ConvId", session!.ConversationId);
var inMemoryProvider = Assert.IsType<InMemoryChatHistoryProvider>(agent.ChatHistoryProvider);
Assert.Empty(inMemoryProvider.GetMessages(session));
}

#endregion
Expand Down