mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Fix FunctionInvocationDelegatingAgent to preserve all AgentRunOptions properties (#4179)
When converting base AgentRunOptions to ChatClientAgentRunOptions, the middleware now preserves AllowBackgroundResponses, ContinuationToken, and AdditionalProperties in addition to ResponseFormat. Added unit test verifying all properties are preserved during the conversion. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
Unverified
parent
ba454552c5
commit
892c177e93
@@ -32,7 +32,13 @@ internal sealed class FunctionInvocationDelegatingAgent : DelegatingAIAgent
|
||||
{
|
||||
if (options is null || options.GetType() == typeof(AgentRunOptions))
|
||||
{
|
||||
options = new ChatClientAgentRunOptions();
|
||||
options = new ChatClientAgentRunOptions()
|
||||
{
|
||||
ResponseFormat = options?.ResponseFormat,
|
||||
AllowBackgroundResponses = options?.AllowBackgroundResponses,
|
||||
ContinuationToken = options?.ContinuationToken,
|
||||
AdditionalProperties = options?.AdditionalProperties,
|
||||
};
|
||||
}
|
||||
|
||||
if (options is not ChatClientAgentRunOptions aco)
|
||||
|
||||
@@ -935,6 +935,60 @@ public sealed class FunctionInvocationDelegatingAgentTests
|
||||
|
||||
#endregion
|
||||
|
||||
#region Options Preservation Tests
|
||||
|
||||
/// <summary>
|
||||
/// Tests that FunctionInvocationDelegatingAgent preserves all original AgentRunOptions properties
|
||||
/// when converting base AgentRunOptions to ChatClientAgentRunOptions.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task RunAsync_WithBaseAgentRunOptions_PreservesAllOriginalOptionsAsync()
|
||||
{
|
||||
// Arrange
|
||||
AgentRunOptions? capturedOptions = null;
|
||||
var responseFormat = ChatResponseFormat.Json;
|
||||
var additionalProperties = new AdditionalPropertiesDictionary { ["key1"] = "value1" };
|
||||
|
||||
Mock<IChatClient> mockChatClient = new();
|
||||
var chatClientAgent = new ChatClientAgent(mockChatClient.Object);
|
||||
|
||||
// Wrap the inner agent in a spy that captures the converted options and returns a dummy response
|
||||
var spyAgent = new AnonymousDelegatingAIAgent(
|
||||
chatClientAgent,
|
||||
runFunc: (messages, session, options, innerAgent, ct) =>
|
||||
{
|
||||
capturedOptions = options;
|
||||
return Task.FromResult(new AgentResponse(new ChatResponse(new ChatMessage(ChatRole.Assistant, "test")) { ResponseId = "test" }));
|
||||
},
|
||||
runStreamingFunc: null);
|
||||
|
||||
static ValueTask<object?> MiddlewareCallbackAsync(AIAgent agent, FunctionInvocationContext context, Func<FunctionInvocationContext, CancellationToken, ValueTask<object?>> next, CancellationToken cancellationToken)
|
||||
=> next(context, cancellationToken);
|
||||
|
||||
var middleware = new FunctionInvocationDelegatingAgent(spyAgent, MiddlewareCallbackAsync);
|
||||
|
||||
var originalOptions = new AgentRunOptions
|
||||
{
|
||||
ResponseFormat = responseFormat,
|
||||
AllowBackgroundResponses = true,
|
||||
ContinuationToken = ResponseContinuationToken.FromBytes(new byte[] { 1, 2, 3 }),
|
||||
AdditionalProperties = additionalProperties,
|
||||
};
|
||||
|
||||
// Act
|
||||
await middleware.RunAsync([new(ChatRole.User, "Test")], null, originalOptions, CancellationToken.None);
|
||||
|
||||
// Assert - All original properties were preserved on the converted options
|
||||
Assert.NotNull(capturedOptions);
|
||||
Assert.IsType<ChatClientAgentRunOptions>(capturedOptions);
|
||||
Assert.Same(responseFormat, capturedOptions.ResponseFormat);
|
||||
Assert.True(capturedOptions.AllowBackgroundResponses);
|
||||
Assert.Same(originalOptions.ContinuationToken, capturedOptions.ContinuationToken);
|
||||
Assert.Same(additionalProperties, capturedOptions.AdditionalProperties);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Creates a mock IChatClient with predefined responses for testing.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user