mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Rename AI Agent packages to use Microsoft.Agents.AI (#913)
* Rename AI Agent packages to use Microsoft.Agents.AI * Fix for build * Fix formatting * Fix formatting * Ignore in VSTHRD200 in migration samples * Ignore in VSTHRD200 in migration samples * Add some missing projects and run format * Fix build errors * Address code review feedback * Fix merge issues --------- Co-authored-by: Mark Wallace <markwallace@microsoft.com>
This commit is contained in:
co-authored by
Mark Wallace
parent
a480ccfd16
commit
32e054f1fe
@@ -0,0 +1,221 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Moq;
|
||||
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
/// <summary>
|
||||
/// Unit tests for the <see cref="ChatClientAgentOptions"/> class.
|
||||
/// </summary>
|
||||
public class ChatClientAgentOptionsTests
|
||||
{
|
||||
[Fact]
|
||||
public void DefaultConstructor_InitializesWithNullValues()
|
||||
{
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions();
|
||||
|
||||
// Assert
|
||||
Assert.Null(options.Name);
|
||||
Assert.Null(options.Instructions);
|
||||
Assert.Null(options.Description);
|
||||
Assert.Null(options.ChatOptions);
|
||||
Assert.Null(options.ChatMessageStoreFactory);
|
||||
Assert.Null(options.AIContextProviderFactory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterizedConstructor_WithNullValues_SetsPropertiesCorrectly()
|
||||
{
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions(
|
||||
instructions: null,
|
||||
name: null,
|
||||
description: null,
|
||||
tools: null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(options.Name);
|
||||
Assert.Null(options.Instructions);
|
||||
Assert.Null(options.Description);
|
||||
Assert.Null(options.ChatOptions);
|
||||
Assert.Null(options.AIContextProviderFactory);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterizedConstructor_WithInstructionsOnly_SetsChatOptionsWithInstructions()
|
||||
{
|
||||
// Arrange
|
||||
const string Instructions = "Test instructions";
|
||||
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions(
|
||||
instructions: Instructions,
|
||||
name: null,
|
||||
description: null,
|
||||
tools: null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(options.Name);
|
||||
Assert.Equal(Instructions, options.Instructions);
|
||||
Assert.Null(options.Description);
|
||||
Assert.NotNull(options.ChatOptions);
|
||||
Assert.Equal(Instructions, options.ChatOptions.Instructions);
|
||||
Assert.Null(options.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterizedConstructor_WithToolsOnly_SetsChatOptionsWithTools()
|
||||
{
|
||||
// Arrange
|
||||
var tools = new List<AITool> { AIFunctionFactory.Create(() => "test") };
|
||||
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions(
|
||||
instructions: null,
|
||||
name: null,
|
||||
description: null,
|
||||
tools: tools);
|
||||
|
||||
// Assert
|
||||
Assert.Null(options.Name);
|
||||
Assert.Null(options.Instructions);
|
||||
Assert.Null(options.Description);
|
||||
Assert.NotNull(options.ChatOptions);
|
||||
Assert.Null(options.ChatOptions.Instructions);
|
||||
Assert.Same(tools, options.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterizedConstructor_WithInstructionsAndTools_SetsChatOptionsWithBoth()
|
||||
{
|
||||
// Arrange
|
||||
const string Instructions = "Test instructions";
|
||||
var tools = new List<AITool> { AIFunctionFactory.Create(() => "test") };
|
||||
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions(
|
||||
instructions: Instructions,
|
||||
name: null,
|
||||
description: null,
|
||||
tools: tools);
|
||||
|
||||
// Assert
|
||||
Assert.Null(options.Name);
|
||||
Assert.Equal(Instructions, options.Instructions);
|
||||
Assert.Null(options.Description);
|
||||
Assert.NotNull(options.ChatOptions);
|
||||
Assert.Equal(Instructions, options.ChatOptions.Instructions);
|
||||
Assert.Same(tools, options.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterizedConstructor_WithAllParameters_SetsAllPropertiesCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
const string Instructions = "Test instructions";
|
||||
const string Name = "Test name";
|
||||
const string Description = "Test description";
|
||||
var tools = new List<AITool> { AIFunctionFactory.Create(() => "test") };
|
||||
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions(
|
||||
instructions: Instructions,
|
||||
name: Name,
|
||||
description: Description,
|
||||
tools: tools);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(Name, options.Name);
|
||||
Assert.Equal(Instructions, options.Instructions);
|
||||
Assert.Equal(Description, options.Description);
|
||||
Assert.NotNull(options.ChatOptions);
|
||||
Assert.Equal(Instructions, options.ChatOptions.Instructions);
|
||||
Assert.Same(tools, options.ChatOptions.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ParameterizedConstructor_WithNameAndDescriptionOnly_DoesNotCreateChatOptions()
|
||||
{
|
||||
// Arrange
|
||||
const string Name = "Test name";
|
||||
const string Description = "Test description";
|
||||
|
||||
// Act
|
||||
var options = new ChatClientAgentOptions(
|
||||
instructions: null,
|
||||
name: Name,
|
||||
description: Description,
|
||||
tools: null);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(Name, options.Name);
|
||||
Assert.Null(options.Instructions);
|
||||
Assert.Equal(Description, options.Description);
|
||||
Assert.Null(options.ChatOptions);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clone_CreatesDeepCopyWithSameValues()
|
||||
{
|
||||
// Arrange
|
||||
const string Instructions = "Test instructions";
|
||||
const string Name = "Test name";
|
||||
const string Description = "Test description";
|
||||
var tools = new List<AITool> { AIFunctionFactory.Create(() => "test") };
|
||||
static ChatMessageStore ChatMessageStoreFactory(ChatClientAgentOptions.ChatMessageStoreFactoryContext ctx) => new Mock<ChatMessageStore>().Object;
|
||||
static AIContextProvider AIContextProviderFactory(ChatClientAgentOptions.AIContextProviderFactoryContext ctx) => new Mock<AIContextProvider>().Object;
|
||||
|
||||
var original = new ChatClientAgentOptions(Instructions, Name, Description, tools)
|
||||
{
|
||||
Id = "test-id",
|
||||
ChatMessageStoreFactory = ChatMessageStoreFactory,
|
||||
AIContextProviderFactory = AIContextProviderFactory
|
||||
};
|
||||
|
||||
// Act
|
||||
var clone = original.Clone();
|
||||
|
||||
// Assert
|
||||
Assert.NotSame(original, clone);
|
||||
Assert.Equal(original.Id, clone.Id);
|
||||
Assert.Equal(original.Name, clone.Name);
|
||||
Assert.Equal(original.Instructions, clone.Instructions);
|
||||
Assert.Equal(original.Description, clone.Description);
|
||||
Assert.Same(original.ChatMessageStoreFactory, clone.ChatMessageStoreFactory);
|
||||
Assert.Same(original.AIContextProviderFactory, clone.AIContextProviderFactory);
|
||||
|
||||
// ChatOptions should be cloned, not the same reference
|
||||
Assert.NotSame(original.ChatOptions, clone.ChatOptions);
|
||||
Assert.Equal(original.ChatOptions?.Instructions, clone.ChatOptions?.Instructions);
|
||||
Assert.Equal(original.ChatOptions?.Tools, clone.ChatOptions?.Tools);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Clone_WithNullChatOptions_ClonesCorrectly()
|
||||
{
|
||||
// Arrange
|
||||
var original = new ChatClientAgentOptions
|
||||
{
|
||||
Id = "test-id",
|
||||
Name = "Test name",
|
||||
Instructions = "Test instructions",
|
||||
Description = "Test description"
|
||||
};
|
||||
|
||||
// Act
|
||||
var clone = original.Clone();
|
||||
|
||||
// Assert
|
||||
Assert.NotSame(original, clone);
|
||||
Assert.Equal(original.Id, clone.Id);
|
||||
Assert.Equal(original.Name, clone.Name);
|
||||
Assert.Equal(original.Instructions, clone.Instructions);
|
||||
Assert.Equal(original.Description, clone.Description);
|
||||
Assert.Null(clone.ChatOptions);
|
||||
Assert.Null(clone.ChatMessageStoreFactory);
|
||||
Assert.Null(clone.AIContextProviderFactory);
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
public class ChatClientAgentRunOptionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions constructor works with null chatOptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ConstructorWorksWithNullChatOptions()
|
||||
{
|
||||
// Act
|
||||
var runOptions = new ChatClientAgentRunOptions();
|
||||
|
||||
// Assert
|
||||
Assert.Null(runOptions.ChatOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions ChatOptions property is set and mutable.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ChatOptionsPropertyIsReadOnly()
|
||||
{
|
||||
// Arrange
|
||||
var chatOptions = new ChatOptions { MaxOutputTokens = 100 };
|
||||
var runOptions = new ChatClientAgentRunOptions(chatOptions);
|
||||
chatOptions.MaxOutputTokens = 200; // Change the property to verify mutability
|
||||
|
||||
// Act & Assert
|
||||
Assert.Same(chatOptions, runOptions.ChatOptions);
|
||||
|
||||
// Verify that the property doesn't have a setter by checking if it's the same instance
|
||||
var retrievedOptions = runOptions.ChatOptions!;
|
||||
Assert.Same(chatOptions, retrievedOptions);
|
||||
Assert.Equal(200, retrievedOptions.MaxOutputTokens); // Ensure the change is reflected
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,394 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.Json;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.Extensions.AI;
|
||||
using Moq;
|
||||
|
||||
#pragma warning disable CA1861 // Avoid constant arrays as arguments
|
||||
|
||||
namespace Microsoft.Agents.AI.UnitTests;
|
||||
|
||||
public class ChatClientAgentThreadTests
|
||||
{
|
||||
#region Constructor and Property Tests
|
||||
|
||||
[Fact]
|
||||
public void ConstructorSetsDefaults()
|
||||
{
|
||||
// Arrange & Act
|
||||
var thread = new ChatClientAgentThread();
|
||||
|
||||
// Assert
|
||||
Assert.Null(thread.ConversationId);
|
||||
Assert.Null(thread.MessageStore);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetConversationIdRoundtrips()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread();
|
||||
const string ConversationId = "test-thread-id";
|
||||
|
||||
// Act
|
||||
thread.ConversationId = ConversationId;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(ConversationId, thread.ConversationId);
|
||||
Assert.Null(thread.MessageStore);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetChatMessageStoreRoundtrips()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread();
|
||||
var messageStore = new InMemoryChatMessageStore();
|
||||
|
||||
// Act
|
||||
thread.MessageStore = messageStore;
|
||||
|
||||
// Assert
|
||||
Assert.Same(messageStore, thread.MessageStore);
|
||||
Assert.Null(thread.ConversationId);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetConversationIdThrowsWhenMessageStoreIsSet()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread
|
||||
{
|
||||
MessageStore = new InMemoryChatMessageStore()
|
||||
};
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => thread.ConversationId = "new-thread-id");
|
||||
Assert.Equal("Only the ConversationId or MessageStore may be set, but not both and switching from one to another is not supported.", exception.Message);
|
||||
Assert.NotNull(thread.MessageStore);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SetChatMessageStoreThrowsWhenConversationIdIsSet()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread
|
||||
{
|
||||
ConversationId = "existing-thread-id"
|
||||
};
|
||||
var store = new InMemoryChatMessageStore();
|
||||
|
||||
// Act & Assert
|
||||
var exception = Assert.Throws<InvalidOperationException>(() => thread.MessageStore = store);
|
||||
Assert.Equal("Only the ConversationId or MessageStore may be set, but not both and switching from one to another is not supported.", exception.Message);
|
||||
Assert.NotNull(thread.ConversationId);
|
||||
}
|
||||
|
||||
#endregion Constructor and Property Tests
|
||||
|
||||
#region OnNewMessagesAsync Tests
|
||||
|
||||
[Fact]
|
||||
public async Task OnNewMessagesAsyncDoesNothingWhenAgentServiceIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread { ConversationId = "thread-123" };
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new(ChatRole.User, "Hello"),
|
||||
new(ChatRole.Assistant, "Hi there!")
|
||||
};
|
||||
var agent = new MessageSendingAgent();
|
||||
|
||||
// Act
|
||||
await agent.SendMessagesAsync(thread, messages, CancellationToken.None);
|
||||
Assert.Equal("thread-123", thread.ConversationId);
|
||||
Assert.Null(thread.MessageStore);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task OnNewMessagesAsyncAddsMessagesToStoreAsync()
|
||||
{
|
||||
// Arrange
|
||||
var store = new InMemoryChatMessageStore();
|
||||
var thread = new ChatClientAgentThread { MessageStore = store };
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new(ChatRole.User, "Hello"),
|
||||
new(ChatRole.Assistant, "Hi there!")
|
||||
};
|
||||
var agent = new MessageSendingAgent();
|
||||
|
||||
// Act
|
||||
await agent.SendMessagesAsync(thread, messages, CancellationToken.None);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, store.Count);
|
||||
Assert.Equal("Hello", store[0].Text);
|
||||
Assert.Equal("Hi there!", store[1].Text);
|
||||
}
|
||||
|
||||
#endregion OnNewMessagesAsync Tests
|
||||
|
||||
#region Deserialize Tests
|
||||
|
||||
[Fact]
|
||||
public async Task VerifyDeserializeConstructorWithMessagesAsync()
|
||||
{
|
||||
// Arrange
|
||||
var json = JsonSerializer.Deserialize("""
|
||||
{
|
||||
"storeState": { "messages": [{"authorName": "testAuthor"}] }
|
||||
}
|
||||
""", TestJsonSerializerContext.Default.JsonElement);
|
||||
|
||||
// Act.
|
||||
var thread = new ChatClientAgentThread(json);
|
||||
|
||||
// Assert
|
||||
Assert.Null(thread.ConversationId);
|
||||
|
||||
var messageStore = thread.MessageStore as InMemoryChatMessageStore;
|
||||
Assert.NotNull(messageStore);
|
||||
Assert.Single(messageStore);
|
||||
Assert.Equal("testAuthor", messageStore[0].AuthorName);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifyDeserializeConstructorWithIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var json = JsonSerializer.Deserialize("""
|
||||
{
|
||||
"conversationId": "TestConvId"
|
||||
}
|
||||
""", TestJsonSerializerContext.Default.JsonElement);
|
||||
|
||||
// Act
|
||||
var thread = new ChatClientAgentThread(json);
|
||||
|
||||
// Assert
|
||||
Assert.Equal("TestConvId", thread.ConversationId);
|
||||
Assert.Null(thread.MessageStore);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifyDeserializeConstructorWithAIContextProviderAsync()
|
||||
{
|
||||
// Arrange
|
||||
var json = JsonSerializer.Deserialize("""
|
||||
{
|
||||
"conversationId": "TestConvId",
|
||||
"aiContextProviderState": ["CP1"]
|
||||
}
|
||||
""", TestJsonSerializerContext.Default.JsonElement);
|
||||
Mock<AIContextProvider> mockProvider = new();
|
||||
|
||||
// Act
|
||||
var thread = new ChatClientAgentThread(json, aiContextProviderFactory: (_, _) => mockProvider.Object);
|
||||
|
||||
// Assert
|
||||
Assert.Null(thread.MessageStore);
|
||||
Assert.Same(thread.AIContextProvider, mockProvider.Object);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeserializeContructorWithInvalidJsonThrowsAsync()
|
||||
{
|
||||
// Arrange
|
||||
var invalidJson = JsonSerializer.Deserialize("[42]", TestJsonSerializerContext.Default.JsonElement);
|
||||
var thread = new ChatClientAgentThread();
|
||||
|
||||
// Act & Assert
|
||||
Assert.Throws<ArgumentException>(() => new ChatClientAgentThread(invalidJson));
|
||||
}
|
||||
|
||||
#endregion Deserialize Tests
|
||||
|
||||
#region Serialize Tests
|
||||
|
||||
/// <summary>
|
||||
/// Verify thread serialization to JSON when the thread has an id.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task VerifyThreadSerializationWithIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread { ConversationId = "TestConvId" };
|
||||
|
||||
// Act
|
||||
var json = await thread.SerializeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.Object, json.ValueKind);
|
||||
|
||||
Assert.True(json.TryGetProperty("conversationId", out var idProperty));
|
||||
Assert.Equal("TestConvId", idProperty.GetString());
|
||||
|
||||
Assert.False(json.TryGetProperty("storeState", out _));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify thread serialization to JSON when the thread has messages.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task VerifyThreadSerializationWithMessagesAsync()
|
||||
{
|
||||
// Arrange
|
||||
InMemoryChatMessageStore store = [new(ChatRole.User, "TestContent") { AuthorName = "TestAuthor" }];
|
||||
var thread = new ChatClientAgentThread { MessageStore = store };
|
||||
|
||||
// Act
|
||||
var json = await thread.SerializeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.Object, json.ValueKind);
|
||||
|
||||
Assert.False(json.TryGetProperty("conversationId", out _));
|
||||
|
||||
Assert.True(json.TryGetProperty("storeState", out var storeStateProperty));
|
||||
Assert.Equal(JsonValueKind.Object, storeStateProperty.ValueKind);
|
||||
|
||||
Assert.True(storeStateProperty.TryGetProperty("messages", out var messagesProperty));
|
||||
Assert.Equal(JsonValueKind.Array, messagesProperty.ValueKind);
|
||||
Assert.Single(messagesProperty.EnumerateArray());
|
||||
|
||||
var message = messagesProperty.EnumerateArray().First();
|
||||
Assert.Equal("TestAuthor", message.GetProperty("authorName").GetString());
|
||||
Assert.True(message.TryGetProperty("contents", out var contentsProperty));
|
||||
Assert.Equal(JsonValueKind.Array, contentsProperty.ValueKind);
|
||||
Assert.Single(contentsProperty.EnumerateArray());
|
||||
|
||||
var textContent = contentsProperty.EnumerateArray().First();
|
||||
Assert.Equal("TestContent", textContent.GetProperty("text").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task VerifyThreadSerializationWithWithAIContextProviderAsync()
|
||||
{
|
||||
// Arrange
|
||||
Mock<AIContextProvider> mockProvider = new();
|
||||
var providerStateElement = JsonSerializer.SerializeToElement(["CP1"], TestJsonSerializerContext.Default.StringArray);
|
||||
mockProvider
|
||||
.Setup(m => m.SerializeAsync(It.IsAny<JsonSerializerOptions?>(), It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(providerStateElement);
|
||||
|
||||
var thread = new ChatClientAgentThread
|
||||
{
|
||||
AIContextProvider = mockProvider.Object
|
||||
};
|
||||
|
||||
// Act
|
||||
var json = await thread.SerializeAsync();
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.Object, json.ValueKind);
|
||||
Assert.True(json.TryGetProperty("aiContextProviderState", out var providerStateProperty));
|
||||
Assert.Equal(JsonValueKind.Array, providerStateProperty.ValueKind);
|
||||
Assert.Single(providerStateProperty.EnumerateArray());
|
||||
Assert.Equal("CP1", providerStateProperty.EnumerateArray().First().GetString());
|
||||
mockProvider.Verify(m => m.SerializeAsync(It.IsAny<JsonSerializerOptions?>(), It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify thread serialization to JSON with custom options.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task VerifyThreadSerializationWithCustomOptionsAsync()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread();
|
||||
JsonSerializerOptions options = new() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
|
||||
options.TypeInfoResolverChain.Add(AgentAbstractionsJsonUtilities.DefaultOptions.TypeInfoResolver!);
|
||||
|
||||
var storeStateElement = JsonSerializer.SerializeToElement(
|
||||
new Dictionary<string, object> { ["Key"] = "TestValue" },
|
||||
TestJsonSerializerContext.Default.DictionaryStringObject);
|
||||
|
||||
var messageStoreMock = new Mock<ChatMessageStore>();
|
||||
messageStoreMock
|
||||
.Setup(m => m.SerializeStateAsync(options, It.IsAny<CancellationToken>()))
|
||||
.ReturnsAsync(storeStateElement);
|
||||
thread.MessageStore = messageStoreMock.Object;
|
||||
|
||||
// Act
|
||||
var json = await thread.SerializeAsync(options);
|
||||
|
||||
// Assert
|
||||
Assert.Equal(JsonValueKind.Object, json.ValueKind);
|
||||
|
||||
Assert.False(json.TryGetProperty("conversationId", out var idProperty));
|
||||
|
||||
Assert.True(json.TryGetProperty("storeState", out var storeStateProperty));
|
||||
Assert.Equal(JsonValueKind.Object, storeStateProperty.ValueKind);
|
||||
|
||||
Assert.True(storeStateProperty.TryGetProperty("Key", out var keyProperty));
|
||||
Assert.Equal("TestValue", keyProperty.GetString());
|
||||
|
||||
messageStoreMock.Verify(m => m.SerializeStateAsync(options, It.IsAny<CancellationToken>()), Times.Once);
|
||||
}
|
||||
|
||||
#endregion Serialize Tests
|
||||
|
||||
#region GetService Tests
|
||||
|
||||
[Fact]
|
||||
public void GetService_RequestingAIContextProvider_ReturnsAIContextProvider()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread();
|
||||
var mockProvider = new Mock<AIContextProvider>();
|
||||
mockProvider
|
||||
.Setup(m => m.GetService(It.Is<Type>(x => x == typeof(AIContextProvider)), null))
|
||||
.Returns(mockProvider.Object);
|
||||
thread.AIContextProvider = mockProvider.Object;
|
||||
|
||||
// Act
|
||||
var result = thread.GetService(typeof(AIContextProvider));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Same(mockProvider.Object, result);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetService_RequestingChatMessageStore_ReturnsChatMessageStore()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new ChatClientAgentThread();
|
||||
var messageStore = new InMemoryChatMessageStore();
|
||||
thread.MessageStore = messageStore;
|
||||
|
||||
// Act
|
||||
var result = thread.GetService(typeof(ChatMessageStore));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.Same(messageStore, result);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private sealed class MessageSendingAgent : AIAgent
|
||||
{
|
||||
public override AgentThread DeserializeThread(JsonElement serializedThread, JsonSerializerOptions? jsonSerializerOptions = null)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public override AgentThread GetNewThread()
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public override Task<AgentRunResponse> RunAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> throw new NotImplementedException();
|
||||
|
||||
public Task SendMessagesAsync(AgentThread thread, IEnumerable<ChatMessage> messages, CancellationToken cancellationToken = default)
|
||||
=> NotifyThreadOfNewMessagesAsync(thread, messages, cancellationToken);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user