From d964b05ae77121772fe2bd393f8d6d5ccf40c360 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 21 Jul 2025 10:49:47 -0400 Subject: [PATCH] Add an AgentRunResponse ctor accepting a ChatResponse (#204) * Add an AgentRunResponse ctor accepting a ChatResponse * Update dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponseUpdate.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .../AgentRunResponse.cs | 15 +++++ .../AgentRunResponseUpdate.cs | 17 ++++++ .../ChatCompletion/ChatClientAgent.cs | 4 +- .../ChatCompletion/ChatResponseExtensions.cs | 60 ------------------- .../AgentRunResponseTests.cs | 22 +++++++ .../AgentRunResponseUpdatesTests.cs | 29 +++++++++ 6 files changed, 85 insertions(+), 62 deletions(-) delete mode 100644 dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatResponseExtensions.cs diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponse.cs b/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponse.cs index 14ff73e884..28e964fbce 100644 --- a/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponse.cs +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponse.cs @@ -44,6 +44,21 @@ public class AgentRunResponse this.Messages.Add(message); } + /// Initializes a new instance of the class. + /// The from which to seed this . + /// is . + public AgentRunResponse(ChatResponse response) + { + _ = Throw.IfNull(response); + + this.AdditionalProperties = response.AdditionalProperties; + this.CreatedAt = response.CreatedAt; + this.Messages = response.Messages; + this.RawRepresentation = response.RawRepresentation; + this.ResponseId = response.ResponseId; + this.Usage = response.Usage; + } + /// Initializes a new instance of the class. /// The response messages. public AgentRunResponse(IList? messages) diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponseUpdate.cs b/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponseUpdate.cs index 4ad5a3a4c9..642216c6f0 100644 --- a/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponseUpdate.cs +++ b/dotnet/src/Microsoft.Extensions.AI.Agents.Abstractions/AgentRunResponseUpdate.cs @@ -5,6 +5,7 @@ using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Text.Json.Serialization; +using Microsoft.Shared.Diagnostics; namespace Microsoft.Extensions.AI.Agents; @@ -58,6 +59,22 @@ public class AgentRunResponseUpdate this._contents = contents; } + /// Initializes a new instance of the class. + /// The from which to seed this . + public AgentRunResponseUpdate(ChatResponseUpdate chatResponseUpdate) + { + _ = Throw.IfNull(chatResponseUpdate); + + this.AdditionalProperties = chatResponseUpdate.AdditionalProperties; + this.AuthorName = chatResponseUpdate.AuthorName; + this.Contents = chatResponseUpdate.Contents; + this.CreatedAt = chatResponseUpdate.CreatedAt; + this.MessageId = chatResponseUpdate.MessageId; + this.RawRepresentation = chatResponseUpdate.RawRepresentation; + this.ResponseId = chatResponseUpdate.ResponseId; + this.Role = chatResponseUpdate.Role; + } + /// Gets or sets the name of the author of the response update. public string? AuthorName { diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatClientAgent.cs b/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatClientAgent.cs index 9d0b64011f..1d0616e0f6 100644 --- a/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatClientAgent.cs +++ b/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatClientAgent.cs @@ -130,7 +130,7 @@ public sealed class ChatClientAgent : AIAgent await this.NotifyThreadOfNewMessagesAsync(chatClientThread, chatResponseMessages, cancellationToken).ConfigureAwait(false); - return chatResponse.ToAgentRunResponse(this.Id); + return new(chatResponse) { AgentId = this.Id }; } /// @@ -167,7 +167,7 @@ public sealed class ChatClientAgent : AIAgent { responseUpdates.Add(update); update.AuthorName ??= this.Name; - yield return update.ToAgentRunResponseUpdate(this.Id); + yield return new(update) { AgentId = this.Id }; } hasUpdates = await responseUpdatesEnumerator.MoveNextAsync().ConfigureAwait(false); diff --git a/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatResponseExtensions.cs b/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatResponseExtensions.cs deleted file mode 100644 index 02c7d3950c..0000000000 --- a/dotnet/src/Microsoft.Extensions.AI.Agents/ChatCompletion/ChatResponseExtensions.cs +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright (c) Microsoft. All rights reserved. - -using Microsoft.Shared.Diagnostics; - -namespace Microsoft.Extensions.AI.Agents; - -/// -/// Contains extension methods for and . -/// -internal static class ChatResponseExtensions -{ - /// - /// Converts a instance to an . - /// - /// The to convert. Cannot be . - /// The ID of the agent that generated the response. Cannot be . - /// - /// An containing the messages, metadata, and additional properties from the - /// specified . - /// - public static AgentRunResponse ToAgentRunResponse(this ChatResponse chatResponse, string agentId) - { - _ = Throw.IfNull(chatResponse); - _ = Throw.IfNullOrWhitespace(agentId); - - return new AgentRunResponse(chatResponse.Messages) - { - AgentId = agentId, - ResponseId = chatResponse.ResponseId, - CreatedAt = chatResponse.CreatedAt, - Usage = chatResponse.Usage, - RawRepresentation = chatResponse, - AdditionalProperties = chatResponse.AdditionalProperties - }; - } - - /// - /// Converts a instance to an . - /// - /// The to convert. Cannot be . - /// The ID of the agent that generated the response. Cannot be . - /// An containing the properties from the specified . - public static AgentRunResponseUpdate ToAgentRunResponseUpdate(this ChatResponseUpdate chatResponseUpdate, string agentId) - { - _ = Throw.IfNull(chatResponseUpdate); - - return new() - { - AgentId = agentId, - Role = chatResponseUpdate.Role, - AuthorName = chatResponseUpdate.AuthorName, - Contents = chatResponseUpdate.Contents, - MessageId = chatResponseUpdate.MessageId, - ResponseId = chatResponseUpdate.ResponseId, - CreatedAt = chatResponseUpdate.CreatedAt, - RawRepresentation = chatResponseUpdate, - AdditionalProperties = chatResponseUpdate.AdditionalProperties - }; - } -} diff --git a/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseTests.cs b/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseTests.cs index a1b674a64b..ec95bee39b 100644 --- a/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseTests.cs +++ b/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseTests.cs @@ -43,6 +43,28 @@ public class AgentRunResponseTests Assert.Same(messages, response.Messages); } + [Fact] + public void ConstructorWithChatResponseRoundtrips() + { + ChatResponse chatResponse = new() + { + AdditionalProperties = new(), + CreatedAt = new DateTimeOffset(2022, 1, 1, 0, 0, 0, TimeSpan.Zero), + Messages = [new(ChatRole.Assistant, "This is a test message.")], + RawRepresentation = new object(), + ResponseId = "responseId", + Usage = new UsageDetails(), + }; + + AgentRunResponse response = new(chatResponse); + Assert.Same(chatResponse.AdditionalProperties, response.AdditionalProperties); + Assert.Equal(chatResponse.CreatedAt, response.CreatedAt); + Assert.Same(chatResponse.Messages, response.Messages); + Assert.Equal(chatResponse.ResponseId, response.ResponseId); + Assert.Same(chatResponse.RawRepresentation, response.RawRepresentation); + Assert.Same(chatResponse.Usage, response.Usage); + } + [Fact] public void PropertiesRoundtrip() { diff --git a/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseUpdatesTests.cs b/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseUpdatesTests.cs index cc6096a59a..9cac5b6151 100644 --- a/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseUpdatesTests.cs +++ b/dotnet/tests/Microsoft.Extensions.AI.Agents.Abstractions.UnitTests/AgentRunResponseUpdatesTests.cs @@ -24,6 +24,35 @@ public class AgentRunResponseUpdateTests Assert.Equal(string.Empty, update.ToString()); } + [Fact] + public void ConstructorWithChatResponseUpdateRoundtrips() + { + ChatResponseUpdate chatResponseUpdate = new() + { + AdditionalProperties = new(), + AuthorName = "author", + Contents = [new TextContent("hello")], + ConversationId = "conversationId", + CreatedAt = new DateTimeOffset(2022, 1, 1, 0, 0, 0, TimeSpan.Zero), + FinishReason = ChatFinishReason.Length, + MessageId = "messageId", + ModelId = "modelId", + RawRepresentation = new object(), + ResponseId = "responseId", + Role = ChatRole.Assistant, + }; + + AgentRunResponseUpdate response = new(chatResponseUpdate); + Assert.Same(chatResponseUpdate.AdditionalProperties, response.AdditionalProperties); + Assert.Equal(chatResponseUpdate.AuthorName, response.AuthorName); + Assert.Same(chatResponseUpdate.Contents, response.Contents); + Assert.Equal(chatResponseUpdate.CreatedAt, response.CreatedAt); + Assert.Equal(chatResponseUpdate.MessageId, response.MessageId); + Assert.Same(chatResponseUpdate.RawRepresentation, response.RawRepresentation); + Assert.Equal(chatResponseUpdate.ResponseId, response.ResponseId); + Assert.Equal(chatResponseUpdate.Role, response.Role); + } + [Fact] public void PropertiesRoundtrip() {