mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
Further fixes for compatibility with Microsoft.Extensions repo. (#555)
This commit is contained in:
committed by
GitHub
Unverified
parent
0acc18805a
commit
1ed46e41a7
@@ -205,7 +205,7 @@ public class AgentThread
|
||||
}
|
||||
|
||||
// If we don't have any IChatMessageStore state return here.
|
||||
if (state?.StoreState is null || state?.StoreState?.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null)
|
||||
if (state?.StoreState is null || state?.StoreState.Value.ValueKind is JsonValueKind.Undefined or JsonValueKind.Null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -219,7 +219,7 @@ public class AgentThread
|
||||
await this._messageStore.DeserializeStateAsync(state!.StoreState.Value, jsonSerializerOptions, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
internal class ThreadState
|
||||
internal sealed class ThreadState
|
||||
{
|
||||
public string? ConversationId { get; set; }
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@ namespace Microsoft.Extensions.AI.Agents;
|
||||
/// <summary>
|
||||
/// Represents an in-memory store for chat messages associated with a specific thread.
|
||||
/// </summary>
|
||||
internal class InMemoryChatMessageStore : IList<ChatMessage>, IChatMessageStore
|
||||
internal sealed class InMemoryChatMessageStore : IList<ChatMessage>, IChatMessageStore
|
||||
{
|
||||
private readonly List<ChatMessage> _messages = new();
|
||||
|
||||
@@ -114,7 +114,7 @@ internal class InMemoryChatMessageStore : IList<ChatMessage>, IChatMessageStore
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
=> this.GetEnumerator();
|
||||
|
||||
internal class StoreState
|
||||
internal sealed class StoreState
|
||||
{
|
||||
public IList<ChatMessage> Messages { get; set; } = new List<ChatMessage>();
|
||||
}
|
||||
|
||||
@@ -231,7 +231,7 @@ public sealed class ChatClientAgent : AIAgent
|
||||
// If no request chat options were provided, use the agent's chat options clone.
|
||||
if (requestChatOptions is null)
|
||||
{
|
||||
return this._agentOptions?.ChatOptions?.Clone();
|
||||
return this._agentOptions?.ChatOptions.Clone();
|
||||
}
|
||||
|
||||
// If both are present, we need to merge them.
|
||||
|
||||
+2
-2
@@ -33,7 +33,7 @@ public static class ChatClientAgentExtensions
|
||||
Throw.IfNull(agent);
|
||||
Throw.IfNull(messages);
|
||||
|
||||
return agent.RunAsync(messages, thread, new ChatClientAgentRunOptions(agentRunOptions, chatOptions), cancellationToken);
|
||||
return agent.RunAsync(messages, thread, new ChatClientAgentRunOptions(chatOptions), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -80,7 +80,7 @@ public static class ChatClientAgentExtensions
|
||||
Throw.IfNull(agent);
|
||||
Throw.IfNull(messages);
|
||||
|
||||
return agent.RunStreamingAsync(messages, thread, new ChatClientAgentRunOptions(agentRunOptions, chatOptions), cancellationToken);
|
||||
return agent.RunStreamingAsync(messages, thread, new ChatClientAgentRunOptions(chatOptions), cancellationToken);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -53,6 +53,7 @@ public class ChatClientAgentOptions
|
||||
/// Gets or sets the agent id.
|
||||
/// </summary>
|
||||
public string? Id { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the agent name.
|
||||
/// </summary>
|
||||
@@ -77,7 +78,7 @@ public class ChatClientAgentOptions
|
||||
/// Gets or sets a factory function to create an instance of <see cref="IChatMessageStore"/>
|
||||
/// which will be used to store chat messages for this agent.
|
||||
/// </summary>
|
||||
public Func<IChatMessageStore>? ChatMessageStoreFactory { get; set; } = null;
|
||||
public Func<IChatMessageStore>? ChatMessageStoreFactory { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets a value indicating whether to use the provided <see cref="IChatClient"/> instance as is,
|
||||
@@ -91,7 +92,7 @@ public class ChatClientAgentOptions
|
||||
/// than the default ones. The provided <see cref="IChatClient"/> instance should then already be decorated
|
||||
/// with the desired decorators.
|
||||
/// </remarks>
|
||||
public bool UseProvidedChatClientAsIs { get; set; } = false;
|
||||
public bool UseProvidedChatClientAsIs { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="ChatClientAgentOptions"/> with the same values as this instance.
|
||||
|
||||
@@ -12,16 +12,6 @@ public sealed class ChatClientAgentRunOptions : AgentRunOptions
|
||||
/// </summary>
|
||||
/// <param name="chatOptions">Optional chat options to pass to the agent's invocation.</param>
|
||||
public ChatClientAgentRunOptions(ChatOptions? chatOptions = null)
|
||||
: this(null, chatOptions)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ChatClientAgentRunOptions"/> class.
|
||||
/// </summary>
|
||||
/// <param name="source">Optional source <see cref="AgentRunOptions"/> to clone.</param>
|
||||
/// <param name="chatOptions">Optional chat options to pass to the agent's invocation.</param>
|
||||
internal ChatClientAgentRunOptions(AgentRunOptions? source, ChatOptions? chatOptions = null)
|
||||
{
|
||||
this.ChatOptions = chatOptions;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
#pragma warning disable S3717 // Track use of "NotImplementedException"
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
@@ -44,7 +46,7 @@ public class AIAgentTests
|
||||
this._agentThreadMock.Object,
|
||||
It.IsAny<AgentRunOptions?>(),
|
||||
It.IsAny<CancellationToken>()))
|
||||
.Returns(this._invokeStreamingResponses.ToAsyncEnumerable());
|
||||
.Returns(ToAsyncEnumerableAsync(this._invokeStreamingResponses));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -370,7 +372,7 @@ public class AIAgentTests
|
||||
AgentRunOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
public override IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
@@ -379,7 +381,16 @@ public class AIAgentTests
|
||||
AgentRunOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
throw new System.NotImplementedException();
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
|
||||
private static async IAsyncEnumerable<T> ToAsyncEnumerableAsync<T>(IEnumerable<T> values)
|
||||
{
|
||||
await Task.Yield();
|
||||
foreach (var update in values)
|
||||
{
|
||||
yield return update;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -259,7 +259,7 @@ public class AgentRunResponseTests
|
||||
var response = new AgentRunResponse(new ChatMessage(ChatRole.Assistant, JsonSerializer.Serialize(expectedResult, TestJsonSerializerContext.Default.Animal)));
|
||||
|
||||
// Act.
|
||||
var animal = response.Deserialize<Animal>(TestJsonSerializerContext.Default.Options);
|
||||
response.TryDeserialize<Animal>(TestJsonSerializerContext.Default.Options, out Animal? animal);
|
||||
|
||||
// Assert.
|
||||
Assert.NotNull(animal);
|
||||
|
||||
+20
-20
@@ -10,6 +10,26 @@ namespace Microsoft.Extensions.AI.Agents.Abstractions.UnitTests;
|
||||
|
||||
public class AgentRunResponseUpdateExtensionsTests
|
||||
{
|
||||
public static IEnumerable<object[]> ToAgentRunResponseCoalescesVariousSequenceAndGapLengthsMemberData()
|
||||
{
|
||||
foreach (bool useAsync in new[] { false, true })
|
||||
{
|
||||
for (int numSequences = 1; numSequences <= 3; numSequences++)
|
||||
{
|
||||
for (int sequenceLength = 1; sequenceLength <= 3; sequenceLength++)
|
||||
{
|
||||
for (int gapLength = 1; gapLength <= 3; gapLength++)
|
||||
{
|
||||
foreach (bool gapBeginningEnd in new[] { false, true })
|
||||
{
|
||||
yield return new object[] { useAsync, numSequences, sequenceLength, gapLength, false };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToAgentRunResponseWithInvalidArgsThrows()
|
||||
{
|
||||
@@ -59,26 +79,6 @@ public class AgentRunResponseUpdateExtensionsTests
|
||||
Assert.Equal("Hello, world!", response.Text);
|
||||
}
|
||||
|
||||
public static IEnumerable<object[]> ToAgentRunResponseCoalescesVariousSequenceAndGapLengthsMemberData()
|
||||
{
|
||||
foreach (bool useAsync in new[] { false, true })
|
||||
{
|
||||
for (int numSequences = 1; numSequences <= 3; numSequences++)
|
||||
{
|
||||
for (int sequenceLength = 1; sequenceLength <= 3; sequenceLength++)
|
||||
{
|
||||
for (int gapLength = 1; gapLength <= 3; gapLength++)
|
||||
{
|
||||
foreach (bool gapBeginningEnd in new[] { false, true })
|
||||
{
|
||||
yield return new object[] { useAsync, numSequences, sequenceLength, gapLength, false };
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[MemberData(nameof(ToAgentRunResponseCoalescesVariousSequenceAndGapLengthsMemberData))]
|
||||
public async Task ToAgentRunResponseCoalescesVariousSequenceAndGapLengthsAsync(bool useAsync, int numSequences, int sequenceLength, int gapLength, bool gapBeginningEnd)
|
||||
|
||||
+29
-16
@@ -97,7 +97,7 @@ public class AgentThreadTests
|
||||
var thread = new AgentThread();
|
||||
|
||||
// Act
|
||||
var messages = await thread.GetMessagesAsync(CancellationToken.None).ToListAsync();
|
||||
var messages = await ToListAsync(thread.GetMessagesAsync(CancellationToken.None));
|
||||
|
||||
// Assert
|
||||
Assert.Empty(messages);
|
||||
@@ -107,10 +107,10 @@ public class AgentThreadTests
|
||||
public async Task GetMessagesAsyncReturnsEmptyListWhenAgentServiceIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new AgentThread() { ConversationId = "thread-123" };
|
||||
var thread = new AgentThread { ConversationId = "thread-123" };
|
||||
|
||||
// Act
|
||||
var messages = await thread.GetMessagesAsync(CancellationToken.None).ToListAsync();
|
||||
var messages = await ToListAsync(thread.GetMessagesAsync(CancellationToken.None));
|
||||
|
||||
// Assert
|
||||
Assert.Empty(messages);
|
||||
@@ -125,10 +125,10 @@ public class AgentThreadTests
|
||||
new ChatMessage(ChatRole.User, "Hello"),
|
||||
new ChatMessage(ChatRole.Assistant, "Hi there!")
|
||||
};
|
||||
var thread = new AgentThread() { MessageStore = store };
|
||||
var thread = new AgentThread { MessageStore = store };
|
||||
|
||||
// Act
|
||||
var messages = await thread.GetMessagesAsync(CancellationToken.None).ToListAsync();
|
||||
var messages = await ToListAsync(thread.GetMessagesAsync(CancellationToken.None));
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, messages.Count);
|
||||
@@ -144,7 +144,7 @@ public class AgentThreadTests
|
||||
public async Task OnNewMessagesAsyncDoesNothingWhenAgentServiceIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new AgentThread() { ConversationId = "thread-123" };
|
||||
var thread = new AgentThread { ConversationId = "thread-123" };
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new(ChatRole.User, "Hello"),
|
||||
@@ -162,7 +162,7 @@ public class AgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var store = new InMemoryChatMessageStore();
|
||||
var thread = new AgentThread() { MessageStore = store };
|
||||
var thread = new AgentThread { MessageStore = store };
|
||||
var messages = new List<ChatMessage>
|
||||
{
|
||||
new(ChatRole.User, "Hello"),
|
||||
@@ -187,12 +187,12 @@ public class AgentThreadTests
|
||||
{
|
||||
// Arrange
|
||||
var chatMessageStore = new InMemoryChatMessageStore();
|
||||
var json = JsonSerializer.Deserialize<JsonElement>("""
|
||||
var json = JsonSerializer.Deserialize("""
|
||||
{
|
||||
"storeState": { "messages": [{"authorName": "testAuthor"}] }
|
||||
}
|
||||
""");
|
||||
var thread = new AgentThread() { MessageStore = chatMessageStore };
|
||||
""", TestJsonSerializerContext.Default.JsonElement);
|
||||
var thread = new AgentThread { MessageStore = chatMessageStore };
|
||||
|
||||
// Act.
|
||||
await thread.DeserializeAsync(json);
|
||||
@@ -208,11 +208,11 @@ public class AgentThreadTests
|
||||
public async Task VerifyDeserializeWithIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var json = JsonSerializer.Deserialize<JsonElement>("""
|
||||
var json = JsonSerializer.Deserialize("""
|
||||
{
|
||||
"conversationId": "TestConvId"
|
||||
}
|
||||
""");
|
||||
""", TestJsonSerializerContext.Default.JsonElement);
|
||||
var thread = new AgentThread();
|
||||
|
||||
// Act
|
||||
@@ -227,7 +227,7 @@ public class AgentThreadTests
|
||||
public async Task DeserializeWithInvalidJsonThrowsAsync()
|
||||
{
|
||||
// Arrange
|
||||
var invalidJson = JsonSerializer.Deserialize<JsonElement>("[42]");
|
||||
var invalidJson = JsonSerializer.Deserialize("[42]", TestJsonSerializerContext.Default.JsonElement);
|
||||
var thread = new AgentThread();
|
||||
|
||||
// Act & Assert
|
||||
@@ -245,7 +245,7 @@ public class AgentThreadTests
|
||||
public async Task VerifyThreadSerializationWithIdAsync()
|
||||
{
|
||||
// Arrange
|
||||
var thread = new AgentThread() { ConversationId = "TestConvId" };
|
||||
var thread = new AgentThread { ConversationId = "TestConvId" };
|
||||
|
||||
// Act
|
||||
var json = await thread.SerializeAsync();
|
||||
@@ -268,7 +268,7 @@ public class AgentThreadTests
|
||||
// Arrange
|
||||
var store = new InMemoryChatMessageStore();
|
||||
store.Add(new ChatMessage(ChatRole.User, "TestContent") { AuthorName = "TestAuthor" });
|
||||
var thread = new AgentThread() { MessageStore = store };
|
||||
var thread = new AgentThread { MessageStore = store };
|
||||
|
||||
// Act
|
||||
var json = await thread.SerializeAsync();
|
||||
@@ -306,7 +306,9 @@ public class AgentThreadTests
|
||||
JsonSerializerOptions options = new() { PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower };
|
||||
options.TypeInfoResolverChain.Add(AgentAbstractionsJsonUtilities.DefaultOptions.TypeInfoResolver!);
|
||||
|
||||
var storeStateElement = JsonSerializer.SerializeToElement(new { Key = "TestValue" });
|
||||
var storeStateElement = JsonSerializer.SerializeToElement(
|
||||
new Dictionary<string, object> { ["Key"] = "TestValue" },
|
||||
TestJsonSerializerContext.Default.DictionaryStringObject);
|
||||
|
||||
var messageStoreMock = new Mock<IChatMessageStore>();
|
||||
messageStoreMock
|
||||
@@ -332,4 +334,15 @@ public class AgentThreadTests
|
||||
}
|
||||
|
||||
#endregion Serialize Tests
|
||||
|
||||
private static async Task<List<T>> ToListAsync<T>(IAsyncEnumerable<T> values)
|
||||
{
|
||||
var result = new List<T>();
|
||||
await foreach (var v in values)
|
||||
{
|
||||
result.Add(v);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
+11
-5
@@ -62,7 +62,7 @@ public class InMemoryChatMessageStoreTests
|
||||
{
|
||||
var newStore = new InMemoryChatMessageStore();
|
||||
|
||||
var emptyObject = JsonSerializer.Deserialize<JsonElement>("{}");
|
||||
var emptyObject = JsonSerializer.Deserialize<JsonElement>("{}", TestJsonSerializerContext.Default.JsonElement);
|
||||
|
||||
await newStore.DeserializeStateAsync(emptyObject);
|
||||
|
||||
@@ -129,7 +129,9 @@ public class InMemoryChatMessageStoreTests
|
||||
{
|
||||
// Arrange
|
||||
var store = new InMemoryChatMessageStore();
|
||||
var stateWithEmptyMessages = JsonSerializer.SerializeToElement(new { Messages = new List<ChatMessage>() });
|
||||
var stateWithEmptyMessages = JsonSerializer.SerializeToElement(
|
||||
new Dictionary<string, object> { ["Messages"] = new List<ChatMessage>() },
|
||||
TestJsonSerializerContext.Default.IDictionaryStringObject);
|
||||
|
||||
// Act
|
||||
await store.DeserializeStateAsync(stateWithEmptyMessages);
|
||||
@@ -143,7 +145,9 @@ public class InMemoryChatMessageStoreTests
|
||||
{
|
||||
// Arrange
|
||||
var store = new InMemoryChatMessageStore();
|
||||
var stateWithNullMessages = JsonSerializer.SerializeToElement(new { Messages = (List<ChatMessage>?)null });
|
||||
var stateWithNullMessages = JsonSerializer.SerializeToElement(
|
||||
new Dictionary<string, object> { ["Messages"] = null! },
|
||||
TestJsonSerializerContext.Default.DictionaryStringObject);
|
||||
|
||||
// Act
|
||||
await store.DeserializeStateAsync(stateWithNullMessages);
|
||||
@@ -162,8 +166,10 @@ public class InMemoryChatMessageStoreTests
|
||||
new(ChatRole.User, "User message"),
|
||||
new(ChatRole.Assistant, "Assistant message")
|
||||
};
|
||||
var state = new { Messages = messages };
|
||||
var serializedState = JsonSerializer.SerializeToElement(state);
|
||||
var state = new Dictionary<string, object> { ["Messages"] = messages };
|
||||
var serializedState = JsonSerializer.SerializeToElement(
|
||||
state,
|
||||
TestJsonSerializerContext.Default.DictionaryStringObject);
|
||||
|
||||
// Act
|
||||
await store.DeserializeStateAsync(serializedState);
|
||||
|
||||
+4
@@ -1,5 +1,7 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using Microsoft.Extensions.AI.Agents.Abstractions.UnitTests.Models;
|
||||
|
||||
@@ -13,4 +15,6 @@ namespace Microsoft.Extensions.AI.Agents.Abstractions.UnitTests;
|
||||
[JsonSerializable(typeof(AgentRunResponseUpdate))]
|
||||
[JsonSerializable(typeof(AgentRunOptions))]
|
||||
[JsonSerializable(typeof(Animal))]
|
||||
[JsonSerializable(typeof(JsonElement))]
|
||||
[JsonSerializable(typeof(Dictionary<string, object?>))]
|
||||
internal sealed partial class TestJsonSerializerContext : JsonSerializerContext;
|
||||
|
||||
+3
-52
@@ -5,10 +5,10 @@ namespace Microsoft.Extensions.AI.Agents.UnitTests.ChatCompletion;
|
||||
public class ChatClientAgentRunOptionsTests
|
||||
{
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions constructor works with null source and null chatOptions.
|
||||
/// Verify that ChatClientAgentRunOptions constructor works with null chatOptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ConstructorWorksWithNullSourceAndNullChatOptions()
|
||||
public void ConstructorWorksWithNullChatOptions()
|
||||
{
|
||||
// Act
|
||||
var runOptions = new ChatClientAgentRunOptions();
|
||||
@@ -17,55 +17,6 @@ public class ChatClientAgentRunOptionsTests
|
||||
Assert.Null(runOptions.ChatOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions constructor works with null source and provided chatOptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ConstructorWorksWithNullSourceAndProvidedChatOptions()
|
||||
{
|
||||
// Arrange
|
||||
var chatOptions = new ChatOptions { MaxOutputTokens = 100 };
|
||||
|
||||
// Act
|
||||
var runOptions = new ChatClientAgentRunOptions(null, chatOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Same(chatOptions, runOptions.ChatOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions constructor copies properties from source AgentRunOptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ConstructorCopiesPropertiesFromSourceAgentRunOptions()
|
||||
{
|
||||
// Arrange
|
||||
var sourceRunOptions = new AgentRunOptions();
|
||||
var chatOptions = new ChatOptions { MaxOutputTokens = 200 };
|
||||
|
||||
// Act
|
||||
var runOptions = new ChatClientAgentRunOptions(sourceRunOptions, chatOptions);
|
||||
|
||||
// Assert
|
||||
Assert.Same(chatOptions, runOptions.ChatOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions constructor works with source but null chatOptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public void ConstructorWorksWithSourceButNullChatOptions()
|
||||
{
|
||||
// Arrange
|
||||
var sourceRunOptions = new AgentRunOptions();
|
||||
|
||||
// Act
|
||||
var runOptions = new ChatClientAgentRunOptions(sourceRunOptions, null);
|
||||
|
||||
// Assert
|
||||
Assert.Null(runOptions.ChatOptions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verify that ChatClientAgentRunOptions ChatOptions property is set and mutable.
|
||||
/// </summary>
|
||||
@@ -74,7 +25,7 @@ public class ChatClientAgentRunOptionsTests
|
||||
{
|
||||
// Arrange
|
||||
var chatOptions = new ChatOptions { MaxOutputTokens = 100 };
|
||||
var runOptions = new ChatClientAgentRunOptions(null, chatOptions);
|
||||
var runOptions = new ChatClientAgentRunOptions(chatOptions);
|
||||
chatOptions.MaxOutputTokens = 200; // Change the property to verify mutability
|
||||
|
||||
// Act & Assert
|
||||
|
||||
+35
-19
@@ -2,7 +2,6 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Moq;
|
||||
@@ -114,7 +113,7 @@ public class ChatClientAgentTests
|
||||
ChatClientAgent agent = new(mockService.Object, options: new() { Instructions = "test instructions" });
|
||||
|
||||
// Act
|
||||
await agent.RunAsync([new(ChatRole.User, "test")], chatOptions: chatOptions);
|
||||
await agent.RunAsync([new(ChatRole.User, "test")], options: new ChatClientAgentRunOptions(chatOptions));
|
||||
|
||||
// Assert
|
||||
mockService.Verify(
|
||||
@@ -320,7 +319,7 @@ public class ChatClientAgentTests
|
||||
AgentThread thread = new() { ConversationId = "ConvId" };
|
||||
|
||||
// Act & Assert
|
||||
var response = await agent.RunAsync([new(ChatRole.User, "test")], thread, chatOptions: chatOptions);
|
||||
var response = await agent.RunAsync([new(ChatRole.User, "test")], thread, options: new ChatClientAgentRunOptions(chatOptions));
|
||||
Assert.NotNull(response);
|
||||
}
|
||||
|
||||
@@ -340,7 +339,7 @@ public class ChatClientAgentTests
|
||||
AgentThread thread = new() { ConversationId = "ThreadId" };
|
||||
|
||||
// Act & Assert
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => agent.RunAsync([new(ChatRole.User, "test")], thread, chatOptions: chatOptions));
|
||||
await Assert.ThrowsAsync<InvalidOperationException>(() => agent.RunAsync([new(ChatRole.User, "test")], thread, options: new ChatClientAgentRunOptions(chatOptions)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -363,7 +362,7 @@ public class ChatClientAgentTests
|
||||
AgentThread thread = new() { ConversationId = "ConvId" };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync([new(ChatRole.User, "test")], thread, chatOptions: chatOptions);
|
||||
await agent.RunAsync([new(ChatRole.User, "test")], thread, options: new ChatClientAgentRunOptions(chatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.Null(chatOptions.ConversationId);
|
||||
@@ -757,7 +756,7 @@ public class ChatClientAgentTests
|
||||
var messages = new List<ChatMessage> { new(ChatRole.User, "test") };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync(messages, chatOptions: requestChatOptions);
|
||||
await agent.RunAsync(messages, options: new ChatClientAgentRunOptions(requestChatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedChatOptions);
|
||||
@@ -780,21 +779,21 @@ public class ChatClientAgentTests
|
||||
Temperature = 0.7f,
|
||||
TopP = 0.9f,
|
||||
ModelId = "agent-model",
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary() { ["key"] = "agent-value" }
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary { ["key"] = "agent-value" }
|
||||
};
|
||||
var requestChatOptions = new ChatOptions
|
||||
{
|
||||
// TopP and ModelId not set, should use agent values
|
||||
MaxOutputTokens = 200,
|
||||
Temperature = 0.3f,
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary() { ["key"] = "request-value" },
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary { ["key"] = "request-value" },
|
||||
Instructions = "request instructions"
|
||||
// TopP and ModelId not set, should use agent values
|
||||
};
|
||||
var expectedChatOptionsMerge = new ChatOptions
|
||||
{
|
||||
MaxOutputTokens = 200, // Request value takes priority
|
||||
Temperature = 0.3f, // Request value takes priority
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary() { ["key"] = "request-value" }, // Request value takes priority
|
||||
AdditionalProperties = new AdditionalPropertiesDictionary { ["key"] = "request-value" }, // Request value takes priority
|
||||
TopP = 0.9f, // Agent value used when request doesn't specify
|
||||
ModelId = "agent-model", // Agent value used when request doesn't specify
|
||||
Instructions = "test instructions\nrequest instructions" // Request is in addition to agent instructions
|
||||
@@ -819,7 +818,7 @@ public class ChatClientAgentTests
|
||||
var messages = new List<ChatMessage> { new(ChatRole.User, "test") };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync(messages, chatOptions: requestChatOptions);
|
||||
await agent.RunAsync(messages, options: new ChatClientAgentRunOptions(requestChatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedChatOptions);
|
||||
@@ -898,12 +897,13 @@ public class ChatClientAgentTests
|
||||
var messages = new List<ChatMessage> { new(ChatRole.User, "test") };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync(messages, chatOptions: requestChatOptions);
|
||||
await agent.RunAsync(messages, options: new ChatClientAgentRunOptions(requestChatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedChatOptions);
|
||||
Assert.NotNull(capturedChatOptions.Tools);
|
||||
Assert.Equal(2, capturedChatOptions.Tools.Count);
|
||||
|
||||
// Request tools should come first, then agent tools
|
||||
Assert.Contains(requestTool, capturedChatOptions.Tools);
|
||||
Assert.Contains(agentTool, capturedChatOptions.Tools);
|
||||
@@ -924,8 +924,8 @@ public class ChatClientAgentTests
|
||||
};
|
||||
var requestChatOptions = new ChatOptions
|
||||
{
|
||||
MaxOutputTokens = 100
|
||||
// No Tools specified
|
||||
MaxOutputTokens = 100
|
||||
};
|
||||
|
||||
Mock<IChatClient> mockService = new();
|
||||
@@ -947,7 +947,7 @@ public class ChatClientAgentTests
|
||||
var messages = new List<ChatMessage> { new(ChatRole.User, "test") };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync(messages, chatOptions: requestChatOptions);
|
||||
await agent.RunAsync(messages, options: new ChatClientAgentRunOptions(requestChatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedChatOptions);
|
||||
@@ -994,7 +994,7 @@ public class ChatClientAgentTests
|
||||
var messages = new List<ChatMessage> { new(ChatRole.User, "test") };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync(messages, chatOptions: requestChatOptions);
|
||||
await agent.RunAsync(messages, options: new ChatClientAgentRunOptions(requestChatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedChatOptions);
|
||||
@@ -1029,6 +1029,7 @@ public class ChatClientAgentTests
|
||||
MaxOutputTokens = 200,
|
||||
Temperature = 0.3f,
|
||||
Instructions = "request instructions",
|
||||
|
||||
// Other properties not set, should use agent values
|
||||
StopSequences = ["request-stop"]
|
||||
};
|
||||
@@ -1072,7 +1073,7 @@ public class ChatClientAgentTests
|
||||
var messages = new List<ChatMessage> { new(ChatRole.User, "test") };
|
||||
|
||||
// Act
|
||||
await agent.RunAsync(messages, chatOptions: requestChatOptions);
|
||||
await agent.RunAsync(messages, options: new ChatClientAgentRunOptions(requestChatOptions));
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(capturedChatOptions);
|
||||
@@ -1148,6 +1149,7 @@ public class ChatClientAgentTests
|
||||
// Assert
|
||||
Assert.NotNull(result);
|
||||
Assert.IsAssignableFrom<IChatClient>(result);
|
||||
|
||||
// Note: The result will be the AgentInvokedChatClient wrapper, not the original mock
|
||||
Assert.Equal("AgentInvokedChatClient", result.GetType().Name);
|
||||
}
|
||||
@@ -1490,7 +1492,7 @@ public class ChatClientAgentTests
|
||||
s => s.GetStreamingResponseAsync(
|
||||
It.IsAny<IEnumerable<ChatMessage>>(),
|
||||
It.IsAny<ChatOptions>(),
|
||||
It.IsAny<CancellationToken>())).Returns(returnUpdates.ToAsyncEnumerable());
|
||||
It.IsAny<CancellationToken>())).Returns(ToAsyncEnumerableAsync(returnUpdates));
|
||||
|
||||
ChatClientAgent agent =
|
||||
new(mockService.Object, options: new()
|
||||
@@ -1499,10 +1501,15 @@ public class ChatClientAgentTests
|
||||
});
|
||||
|
||||
// Act
|
||||
var result = await agent.RunStreamingAsync([new ChatMessage(ChatRole.User, "Hello")]).ToArrayAsync();
|
||||
var updates = agent.RunStreamingAsync([new ChatMessage(ChatRole.User, "Hello")]);
|
||||
List<AgentRunResponseUpdate> result = [];
|
||||
await foreach (var update in updates)
|
||||
{
|
||||
result.Add(update);
|
||||
}
|
||||
|
||||
// Assert
|
||||
Assert.Equal(2, result.Length);
|
||||
Assert.Equal(2, result.Count);
|
||||
Assert.Equal("wh", result[0].Text);
|
||||
Assert.Equal("at?", result[1].Text);
|
||||
|
||||
@@ -1516,4 +1523,13 @@ public class ChatClientAgentTests
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static async IAsyncEnumerable<T> ToAsyncEnumerableAsync<T>(IEnumerable<T> values)
|
||||
{
|
||||
await Task.Yield();
|
||||
foreach (var update in values)
|
||||
{
|
||||
yield return update;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user