diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentMetadataTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentMetadataTests.cs
new file mode 100644
index 0000000000..764f7f2122
--- /dev/null
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentMetadataTests.cs
@@ -0,0 +1,42 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+namespace Microsoft.Agents.AI.Abstractions.UnitTests;
+
+///
+/// Unit tests for the class.
+///
+public class AIAgentMetadataTests
+{
+ [Fact]
+ public void Constructor_WithNoArguments_SetsProviderNameToNull()
+ {
+ // Arrange & Act
+ AIAgentMetadata metadata = new();
+
+ // Assert
+ Assert.Null(metadata.ProviderName);
+ }
+
+ [Fact]
+ public void Constructor_WithProviderName_SetsProperty()
+ {
+ // Arrange
+ const string ProviderName = "TestProvider";
+
+ // Act
+ AIAgentMetadata metadata = new(ProviderName);
+
+ // Assert
+ Assert.Equal(ProviderName, metadata.ProviderName);
+ }
+
+ [Fact]
+ public void Constructor_WithNullProviderName_SetsProviderNameToNull()
+ {
+ // Arrange & Act
+ AIAgentMetadata metadata = new(null);
+
+ // Assert
+ Assert.Null(metadata.ProviderName);
+ }
+}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentTests.cs
index cd2cbd4700..c65cb66e59 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIAgentTests.cs
@@ -364,6 +364,74 @@ public void GetService_Generic_ReturnsNullForUnrelatedType()
#endregion
+ #region Name and Description Property Tests
+
+ ///
+ /// Verify that Name property returns the value from the derived class.
+ ///
+ [Fact]
+ public void Name_ReturnsValueFromDerivedClass()
+ {
+ // Arrange
+ var agent = new MockAgentWithName("TestAgentName", "TestAgentDescription");
+
+ // Act
+ string? name = agent.Name;
+
+ // Assert
+ Assert.Equal("TestAgentName", name);
+ }
+
+ ///
+ /// Verify that Description property returns the value from the derived class.
+ ///
+ [Fact]
+ public void Description_ReturnsValueFromDerivedClass()
+ {
+ // Arrange
+ var agent = new MockAgentWithName("TestAgentName", "TestAgentDescription");
+
+ // Act
+ string? description = agent.Description;
+
+ // Assert
+ Assert.Equal("TestAgentDescription", description);
+ }
+
+ ///
+ /// Verify that Name property returns null when not overridden.
+ ///
+ [Fact]
+ public void Name_ReturnsNullByDefault()
+ {
+ // Arrange
+ var agent = new MockAgent();
+
+ // Act
+ string? name = agent.Name;
+
+ // Assert
+ Assert.Null(name);
+ }
+
+ ///
+ /// Verify that Description property returns null when not overridden.
+ ///
+ [Fact]
+ public void Description_ReturnsNullByDefault()
+ {
+ // Arrange
+ var agent = new MockAgent();
+
+ // Act
+ string? description = agent.Description;
+
+ // Assert
+ Assert.Null(description);
+ }
+
+ #endregion
+
///
/// Typed mock session.
///
@@ -402,6 +470,44 @@ protected override IAsyncEnumerable RunCoreStreamingAsync(
throw new NotImplementedException();
}
+ private sealed class MockAgentWithName : AIAgent
+ {
+ private readonly string? _name;
+ private readonly string? _description;
+
+ public MockAgentWithName(string? name, string? description)
+ {
+ this._name = name;
+ this._description = description;
+ }
+
+ public override string? Name => this._name;
+ public override string? Description => this._description;
+
+ public override ValueTask CreateSessionAsync(CancellationToken cancellationToken = default)
+ => throw new NotImplementedException();
+
+ public override ValueTask DeserializeSessionAsync(JsonElement serializedSession, JsonSerializerOptions? jsonSerializerOptions = null, CancellationToken cancellationToken = default)
+ => throw new NotImplementedException();
+
+ public override JsonElement SerializeSession(AgentSession session, JsonSerializerOptions? jsonSerializerOptions = null)
+ => throw new NotImplementedException();
+
+ protected override Task RunCoreAsync(
+ IEnumerable messages,
+ AgentSession? session = null,
+ AgentRunOptions? options = null,
+ CancellationToken cancellationToken = default) =>
+ throw new NotImplementedException();
+
+ protected override IAsyncEnumerable RunCoreStreamingAsync(
+ IEnumerable messages,
+ AgentSession? session = null,
+ AgentRunOptions? options = null,
+ CancellationToken cancellationToken = default) =>
+ throw new NotImplementedException();
+ }
+
private static async IAsyncEnumerable ToAsyncEnumerableAsync(IEnumerable values)
{
await Task.Yield();
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs
index b287c8b304..b6aabd081e 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AIContextProviderTests.cs
@@ -1,6 +1,7 @@
// Copyright (c) Microsoft. All rights reserved.
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Threading;
using System.Threading.Tasks;
@@ -155,6 +156,111 @@ public void GetService_Generic_ReturnsNullForUnrelatedType()
#endregion
+ #region InvokingContext Tests
+
+ [Fact]
+ public void InvokingContext_RequestMessages_SetterThrowsForNull()
+ {
+ // Arrange
+ var messages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var context = new AIContextProvider.InvokingContext(messages);
+
+ // Act & Assert
+ Assert.Throws(() => context.RequestMessages = null!);
+ }
+
+ [Fact]
+ public void InvokingContext_RequestMessages_SetterRoundtrips()
+ {
+ // Arrange
+ var initialMessages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var newMessages = new List { new(ChatRole.User, "New message") };
+ var context = new AIContextProvider.InvokingContext(initialMessages);
+
+ // Act
+ context.RequestMessages = newMessages;
+
+ // Assert
+ Assert.Same(newMessages, context.RequestMessages);
+ }
+
+ #endregion
+
+ #region InvokedContext Tests
+
+ [Fact]
+ public void InvokedContext_RequestMessages_SetterThrowsForNull()
+ {
+ // Arrange
+ var messages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var context = new AIContextProvider.InvokedContext(messages, aiContextProviderMessages: null);
+
+ // Act & Assert
+ Assert.Throws(() => context.RequestMessages = null!);
+ }
+
+ [Fact]
+ public void InvokedContext_RequestMessages_SetterRoundtrips()
+ {
+ // Arrange
+ var initialMessages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var newMessages = new List { new(ChatRole.User, "New message") };
+ var context = new AIContextProvider.InvokedContext(initialMessages, aiContextProviderMessages: null);
+
+ // Act
+ context.RequestMessages = newMessages;
+
+ // Assert
+ Assert.Same(newMessages, context.RequestMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_AIContextProviderMessages_Roundtrips()
+ {
+ // Arrange
+ var requestMessages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var aiContextMessages = new List { new(ChatRole.System, "AI context message") };
+ var context = new AIContextProvider.InvokedContext(requestMessages, aiContextProviderMessages: null);
+
+ // Act
+ context.AIContextProviderMessages = aiContextMessages;
+
+ // Assert
+ Assert.Same(aiContextMessages, context.AIContextProviderMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_ResponseMessages_Roundtrips()
+ {
+ // Arrange
+ var requestMessages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var responseMessages = new List { new(ChatRole.Assistant, "Response message") };
+ var context = new AIContextProvider.InvokedContext(requestMessages, aiContextProviderMessages: null);
+
+ // Act
+ context.ResponseMessages = responseMessages;
+
+ // Assert
+ Assert.Same(responseMessages, context.ResponseMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_InvokeException_Roundtrips()
+ {
+ // Arrange
+ var requestMessages = new ReadOnlyCollection([new(ChatRole.User, "Hello")]);
+ var exception = new InvalidOperationException("Test exception");
+ var context = new AIContextProvider.InvokedContext(requestMessages, aiContextProviderMessages: null);
+
+ // Act
+ context.InvokeException = exception;
+
+ // Assert
+ Assert.Same(exception, context.InvokeException);
+ }
+
+ #endregion
+
private sealed class TestAIContextProvider : AIContextProvider
{
public override ValueTask InvokingAsync(InvokingContext context, CancellationToken cancellationToken = default)
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseTests.cs
index 75bc90ca8e..87cdbf4f20 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseTests.cs
@@ -346,4 +346,91 @@ public void TryParseAsStructuredOutputFailsWithIncorrectTypedJson()
// Act & Assert.
Assert.False(response.TryDeserialize(TestJsonSerializerContext.Default.Options, out _));
}
+
+ [Fact]
+ public void UserInputRequests_ReturnsEmptyWhenNoMessages()
+ {
+ // Arrange
+ AgentResponse response = new();
+
+ // Act
+ IEnumerable requests = response.UserInputRequests;
+
+ // Assert
+ Assert.Empty(requests);
+ }
+
+ [Fact]
+ public void UserInputRequests_ReturnsEmptyWhenNoUserInputRequestContent()
+ {
+ // Arrange
+ AgentResponse response = new(new ChatMessage(ChatRole.Assistant, "Hello"));
+
+ // Act
+ IEnumerable requests = response.UserInputRequests;
+
+ // Assert
+ Assert.Empty(requests);
+ }
+
+ [Fact]
+ public void ToAgentResponseUpdatesWithNoMessagesProducesEmptyArray()
+ {
+ // Arrange
+ AgentResponse response = new();
+
+ // Act
+ AgentResponseUpdate[] updates = response.ToAgentResponseUpdates();
+
+ // Assert
+ Assert.Empty(updates);
+ }
+
+ [Fact]
+ public void ToAgentResponseUpdatesWithUsageOnlyProducesSingleUpdate()
+ {
+ // Arrange
+ AgentResponse response = new()
+ {
+ Usage = new UsageDetails { TotalTokenCount = 100 }
+ };
+
+ // Act
+ AgentResponseUpdate[] updates = response.ToAgentResponseUpdates();
+
+ // Assert
+ AgentResponseUpdate update = Assert.Single(updates);
+ UsageContent usageContent = Assert.IsType(update.Contents[0]);
+ Assert.Equal(100, usageContent.Details.TotalTokenCount);
+ }
+
+ [Fact]
+ public void ToAgentResponseUpdatesWithAdditionalPropertiesOnlyProducesSingleUpdate()
+ {
+ // Arrange
+ AgentResponse response = new()
+ {
+ AdditionalProperties = new() { ["key"] = "value" }
+ };
+
+ // Act
+ AgentResponseUpdate[] updates = response.ToAgentResponseUpdates();
+
+ // Assert
+ AgentResponseUpdate update = Assert.Single(updates);
+ Assert.NotNull(update.AdditionalProperties);
+ Assert.Equal("value", update.AdditionalProperties!["key"]);
+ }
+
+ [Fact]
+ public void Deserialize_ThrowsWhenDeserializationReturnsNull()
+ {
+ // Arrange
+ AgentResponse response = new(new ChatMessage(ChatRole.Assistant, "null"));
+
+ // Act & Assert
+ InvalidOperationException exception = Assert.Throws(
+ () => response.Deserialize(TestJsonSerializerContext.Default.Options));
+ Assert.Equal("The deserialized response is null.", exception.Message);
+ }
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs
index 2723ed081a..790298ddf9 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateExtensionsTests.cs
@@ -299,6 +299,161 @@ public async Task ToAgentResponse_TimestampFoldingAsync(bool useAsync, string? t
Assert.Equal(expected, response.CreatedAt);
}
+ #region AsChatResponse Tests
+
+ [Fact]
+ public void AsChatResponse_WithNullArgument_ThrowsArgumentNullException()
+ {
+ // Arrange & Act & Assert
+ Assert.Throws("response", () => ((AgentResponse)null!).AsChatResponse());
+ }
+
+ [Fact]
+ public void AsChatResponse_WithRawRepresentationAsChatResponse_ReturnsSameInstance()
+ {
+ // Arrange
+ ChatResponse originalChatResponse = new()
+ {
+ ResponseId = "original-response",
+ Messages = [new ChatMessage(ChatRole.Assistant, "Hello")]
+ };
+ AgentResponse agentResponse = new(originalChatResponse);
+
+ // Act
+ ChatResponse result = agentResponse.AsChatResponse();
+
+ // Assert
+ Assert.Same(originalChatResponse, result);
+ }
+
+ [Fact]
+ public void AsChatResponse_WithoutRawRepresentation_CreatesNewChatResponse()
+ {
+ // Arrange
+ AgentResponse agentResponse = new(new ChatMessage(ChatRole.Assistant, "Test message"))
+ {
+ ResponseId = "test-response-id",
+ CreatedAt = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero),
+ Usage = new UsageDetails { TotalTokenCount = 50 },
+ AdditionalProperties = new() { ["key"] = "value" },
+ ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
+ };
+
+ // Act
+ ChatResponse result = agentResponse.AsChatResponse();
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("test-response-id", result.ResponseId);
+ Assert.Equal(new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero), result.CreatedAt);
+ Assert.Same(agentResponse.Messages, result.Messages);
+ Assert.Same(agentResponse, result.RawRepresentation);
+ Assert.Same(agentResponse.Usage, result.Usage);
+ Assert.Same(agentResponse.AdditionalProperties, result.AdditionalProperties);
+ Assert.Equal(agentResponse.ContinuationToken, result.ContinuationToken);
+ }
+
+ #endregion
+
+ #region AsChatResponseUpdate Tests
+
+ [Fact]
+ public void AsChatResponseUpdate_WithNullArgument_ThrowsArgumentNullException()
+ {
+ // Arrange & Act & Assert
+ Assert.Throws("responseUpdate", () => ((AgentResponseUpdate)null!).AsChatResponseUpdate());
+ }
+
+ [Fact]
+ public void AsChatResponseUpdate_WithRawRepresentationAsChatResponseUpdate_ReturnsSameInstance()
+ {
+ // Arrange
+ ChatResponseUpdate originalChatResponseUpdate = new()
+ {
+ ResponseId = "original-update",
+ Contents = [new TextContent("Hello")]
+ };
+ AgentResponseUpdate agentResponseUpdate = new(originalChatResponseUpdate);
+
+ // Act
+ ChatResponseUpdate result = agentResponseUpdate.AsChatResponseUpdate();
+
+ // Assert
+ Assert.Same(originalChatResponseUpdate, result);
+ }
+
+ [Fact]
+ public void AsChatResponseUpdate_WithoutRawRepresentation_CreatesNewChatResponseUpdate()
+ {
+ // Arrange
+ AgentResponseUpdate agentResponseUpdate = new(ChatRole.Assistant, "Test")
+ {
+ AuthorName = "TestAuthor",
+ ResponseId = "update-id",
+ MessageId = "message-id",
+ CreatedAt = new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero),
+ AdditionalProperties = new() { ["key"] = "value" },
+ ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
+ };
+
+ // Act
+ ChatResponseUpdate result = agentResponseUpdate.AsChatResponseUpdate();
+
+ // Assert
+ Assert.NotNull(result);
+ Assert.Equal("TestAuthor", result.AuthorName);
+ Assert.Equal("update-id", result.ResponseId);
+ Assert.Equal("message-id", result.MessageId);
+ Assert.Equal(new DateTimeOffset(2024, 1, 1, 12, 0, 0, TimeSpan.Zero), result.CreatedAt);
+ Assert.Equal(ChatRole.Assistant, result.Role);
+ Assert.Same(agentResponseUpdate.Contents, result.Contents);
+ Assert.Same(agentResponseUpdate, result.RawRepresentation);
+ Assert.Same(agentResponseUpdate.AdditionalProperties, result.AdditionalProperties);
+ Assert.Equal(agentResponseUpdate.ContinuationToken, result.ContinuationToken);
+ }
+
+ #endregion
+
+ #region AsChatResponseUpdatesAsync Tests
+
+ [Fact]
+ public async Task AsChatResponseUpdatesAsync_WithNullArgument_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange & Act & Assert
+ await Assert.ThrowsAsync("responseUpdates", async () =>
+ {
+ await foreach (ChatResponseUpdate _ in ((IAsyncEnumerable)null!).AsChatResponseUpdatesAsync())
+ {
+ // Do nothing
+ }
+ });
+ }
+
+ [Fact]
+ public async Task AsChatResponseUpdatesAsync_ConvertsUpdatesAsync()
+ {
+ // Arrange
+ AgentResponseUpdate[] updates =
+ [
+ new(ChatRole.Assistant, "First"),
+ new(ChatRole.Assistant, "Second"),
+ ];
+
+ // Act
+ List results = [];
+ await foreach (ChatResponseUpdate update in YieldAsync(updates).AsChatResponseUpdatesAsync())
+ {
+ results.Add(update);
+ }
+
+ // Assert
+ Assert.Equal(2, results.Count);
+ Assert.Equal("First", Assert.IsType(results[0].Contents[0]).Text);
+ Assert.Equal("Second", Assert.IsType(results[1].Contents[0]).Text);
+ }
+
+ #endregion
+
private static async IAsyncEnumerable YieldAsync(IEnumerable updates)
{
foreach (AgentResponseUpdate update in updates)
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateTests.cs
index 7fda5f680b..1b42188c92 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/AgentResponseUpdateTests.cs
@@ -199,4 +199,30 @@ public void JsonSerializationRoundtrips()
Assert.NotNull(result.ContinuationToken);
Assert.Equivalent(ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }), result.ContinuationToken);
}
+
+ [Fact]
+ public void UserInputRequests_ReturnsEmptyWhenNoContents()
+ {
+ // Arrange
+ AgentResponseUpdate update = new();
+
+ // Act
+ IEnumerable requests = update.UserInputRequests;
+
+ // Assert
+ Assert.Empty(requests);
+ }
+
+ [Fact]
+ public void UserInputRequests_ReturnsEmptyWhenNoUserInputRequestContent()
+ {
+ // Arrange
+ AgentResponseUpdate update = new(ChatRole.Assistant, "Hello");
+
+ // Act
+ IEnumerable requests = update.UserInputRequests;
+
+ // Assert
+ Assert.Empty(requests);
+ }
}
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs
index 02955f4a25..a26ef199d9 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/ChatHistoryProviderTests.cs
@@ -76,6 +76,140 @@ public void GetService_Generic_ReturnsNullForUnrelatedType()
#endregion
+ #region InvokingContext Tests
+
+ [Fact]
+ public void InvokingContext_Constructor_ThrowsForNullMessages()
+ {
+ // Arrange & Act & Assert
+ Assert.Throws(() => new ChatHistoryProvider.InvokingContext(null!));
+ }
+
+ [Fact]
+ public void InvokingContext_RequestMessages_SetterThrowsForNull()
+ {
+ // Arrange
+ var messages = new List { new(ChatRole.User, "Hello") };
+ var context = new ChatHistoryProvider.InvokingContext(messages);
+
+ // Act & Assert
+ Assert.Throws(() => context.RequestMessages = null!);
+ }
+
+ [Fact]
+ public void InvokingContext_RequestMessages_SetterRoundtrips()
+ {
+ // Arrange
+ var initialMessages = new List { new(ChatRole.User, "Hello") };
+ var newMessages = new List { new(ChatRole.User, "New message") };
+ var context = new ChatHistoryProvider.InvokingContext(initialMessages);
+
+ // Act
+ context.RequestMessages = newMessages;
+
+ // Assert
+ Assert.Same(newMessages, context.RequestMessages);
+ }
+
+ #endregion
+
+ #region InvokedContext Tests
+
+ [Fact]
+ public void InvokedContext_Constructor_ThrowsForNullRequestMessages()
+ {
+ // Arrange & Act & Assert
+ Assert.Throws(() => new ChatHistoryProvider.InvokedContext(null!, []));
+ }
+
+ [Fact]
+ public void InvokedContext_RequestMessages_SetterThrowsForNull()
+ {
+ // Arrange
+ var requestMessages = new List { new(ChatRole.User, "Hello") };
+ var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
+
+ // Act & Assert
+ Assert.Throws(() => context.RequestMessages = null!);
+ }
+
+ [Fact]
+ public void InvokedContext_RequestMessages_SetterRoundtrips()
+ {
+ // Arrange
+ var initialMessages = new List { new(ChatRole.User, "Hello") };
+ var newMessages = new List { new(ChatRole.User, "New message") };
+ var context = new ChatHistoryProvider.InvokedContext(initialMessages, []);
+
+ // Act
+ context.RequestMessages = newMessages;
+
+ // Assert
+ Assert.Same(newMessages, context.RequestMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_ChatHistoryProviderMessages_SetterRoundtrips()
+ {
+ // Arrange
+ var requestMessages = new List { new(ChatRole.User, "Hello") };
+ var newProviderMessages = new List { new(ChatRole.System, "System message") };
+ var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
+
+ // Act
+ context.ChatHistoryProviderMessages = newProviderMessages;
+
+ // Assert
+ Assert.Same(newProviderMessages, context.ChatHistoryProviderMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_AIContextProviderMessages_Roundtrips()
+ {
+ // Arrange
+ var requestMessages = new List { new(ChatRole.User, "Hello") };
+ var aiContextMessages = new List { new(ChatRole.System, "AI context message") };
+ var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
+
+ // Act
+ context.AIContextProviderMessages = aiContextMessages;
+
+ // Assert
+ Assert.Same(aiContextMessages, context.AIContextProviderMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_ResponseMessages_Roundtrips()
+ {
+ // Arrange
+ var requestMessages = new List { new(ChatRole.User, "Hello") };
+ var responseMessages = new List { new(ChatRole.Assistant, "Response message") };
+ var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
+
+ // Act
+ context.ResponseMessages = responseMessages;
+
+ // Assert
+ Assert.Same(responseMessages, context.ResponseMessages);
+ }
+
+ [Fact]
+ public void InvokedContext_InvokeException_Roundtrips()
+ {
+ // Arrange
+ var requestMessages = new List { new(ChatRole.User, "Hello") };
+ var exception = new InvalidOperationException("Test exception");
+ var context = new ChatHistoryProvider.InvokedContext(requestMessages, []);
+
+ // Act
+ context.InvokeException = exception;
+
+ // Assert
+ Assert.Same(exception, context.InvokeException);
+ }
+
+ #endregion
+
private sealed class TestChatHistoryProvider : ChatHistoryProvider
{
public override ValueTask> InvokingAsync(InvokingContext context, CancellationToken cancellationToken = default)
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/DelegatingAIAgentTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/DelegatingAIAgentTests.cs
index 6320d9c900..3c49f6f178 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/DelegatingAIAgentTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/DelegatingAIAgentTests.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
@@ -145,6 +146,26 @@ public async Task CreateSessionAsync_DelegatesToInnerAgentAsync()
this._innerAgentMock.Verify(x => x.CreateSessionAsync(), Times.Once);
}
+ ///
+ /// Verify that DeserializeSessionAsync delegates to inner agent.
+ ///
+ [Fact]
+ public async Task DeserializeSessionAsync_DelegatesToInnerAgentAsync()
+ {
+ // Arrange
+ var serializedSession = JsonSerializer.SerializeToElement("test-session-id", TestJsonSerializerContext.Default.String);
+ this._innerAgentMock
+ .Setup(x => x.DeserializeSessionAsync(It.IsAny(), null, It.IsAny()))
+ .ReturnsAsync(this._testSession);
+
+ // Act
+ var session = await this._delegatingAgent.DeserializeSessionAsync(serializedSession);
+
+ // Assert
+ Assert.Same(this._testSession, session);
+ this._innerAgentMock.Verify(x => x.DeserializeSessionAsync(It.IsAny(), null, It.IsAny()), Times.Once);
+ }
+
///
/// Verify that RunAsync delegates to inner agent with correct parameters.
///
diff --git a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs
index debaff73ef..ff31d0afc9 100644
--- a/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs
+++ b/dotnet/tests/Microsoft.Agents.AI.Abstractions.UnitTests/InMemoryChatHistoryProviderTests.cs
@@ -614,6 +614,42 @@ public async Task GetMessagesAsync_WithReducer_ButWrongTrigger_DoesNotInvokeRedu
reducerMock.Verify(r => r.ReduceAsync(It.IsAny>(), It.IsAny()), Times.Never);
}
+ [Fact]
+ public async Task InvokedAsync_WithException_DoesNotAddMessagesAsync()
+ {
+ // Arrange
+ var provider = new InMemoryChatHistoryProvider();
+ var requestMessages = new List
+ {
+ new(ChatRole.User, "Hello")
+ };
+ var responseMessages = new List
+ {
+ new(ChatRole.Assistant, "Hi there!")
+ };
+ var context = new ChatHistoryProvider.InvokedContext(requestMessages, [])
+ {
+ ResponseMessages = responseMessages,
+ InvokeException = new InvalidOperationException("Test exception")
+ };
+
+ // Act
+ await provider.InvokedAsync(context, CancellationToken.None);
+
+ // Assert
+ Assert.Empty(provider);
+ }
+
+ [Fact]
+ public async Task InvokingAsync_WithNullContext_ThrowsArgumentNullExceptionAsync()
+ {
+ // Arrange
+ var provider = new InMemoryChatHistoryProvider();
+
+ // Act & Assert
+ await Assert.ThrowsAsync(() => provider.InvokingAsync(null!, CancellationToken.None).AsTask());
+ }
+
public class TestAIContent(string testData) : AIContent
{
public string TestData => testData;