mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: [Breaking] RenameAgentRunResponse and AgentRunResponseUpdate classes (#3197)
* rename AgentRunResponse and AgentRunResponseUpdate classes - part1 * rename varialbles, parameters, methods and tests * rollback unnecessary changes
This commit is contained in:
@@ -68,7 +68,7 @@ public sealed class A2AAgent : AIAgent
|
||||
=> new(new A2AAgentThread(serializedThread, jsonSerializerOptions));
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
protected override async Task<AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
_ = Throw.IfNull(messages);
|
||||
|
||||
@@ -99,7 +99,7 @@ public sealed class A2AAgent : AIAgent
|
||||
{
|
||||
UpdateThread(typedThread, message.ContextId);
|
||||
|
||||
return new AgentRunResponse
|
||||
return new AgentResponse
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = message.MessageId,
|
||||
@@ -113,7 +113,7 @@ public sealed class A2AAgent : AIAgent
|
||||
{
|
||||
UpdateThread(typedThread, agentTask.ContextId, agentTask.Id);
|
||||
|
||||
var response = new AgentRunResponse
|
||||
var response = new AgentResponse
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = agentTask.Id,
|
||||
@@ -135,7 +135,7 @@ public sealed class A2AAgent : AIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
_ = Throw.IfNull(messages);
|
||||
|
||||
@@ -291,9 +291,9 @@ public sealed class A2AAgent : AIAgent
|
||||
return null;
|
||||
}
|
||||
|
||||
private AgentRunResponseUpdate ConvertToAgentResponseUpdate(AgentMessage message)
|
||||
private AgentResponseUpdate ConvertToAgentResponseUpdate(AgentMessage message)
|
||||
{
|
||||
return new AgentRunResponseUpdate
|
||||
return new AgentResponseUpdate
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = message.MessageId,
|
||||
@@ -305,9 +305,9 @@ public sealed class A2AAgent : AIAgent
|
||||
};
|
||||
}
|
||||
|
||||
private AgentRunResponseUpdate ConvertToAgentResponseUpdate(AgentTask task)
|
||||
private AgentResponseUpdate ConvertToAgentResponseUpdate(AgentTask task)
|
||||
{
|
||||
return new AgentRunResponseUpdate
|
||||
return new AgentResponseUpdate
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = task.Id,
|
||||
@@ -318,9 +318,9 @@ public sealed class A2AAgent : AIAgent
|
||||
};
|
||||
}
|
||||
|
||||
private AgentRunResponseUpdate ConvertToAgentResponseUpdate(TaskUpdateEvent taskUpdateEvent)
|
||||
private AgentResponseUpdate ConvertToAgentResponseUpdate(TaskUpdateEvent taskUpdateEvent)
|
||||
{
|
||||
AgentRunResponseUpdate responseUpdate = new()
|
||||
AgentResponseUpdate responseUpdate = new()
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = taskUpdateEvent.TaskId,
|
||||
|
||||
@@ -146,12 +146,12 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <remarks>
|
||||
/// This overload is useful when the agent has sufficient context from previous messages in the thread
|
||||
/// or from its initial configuration to generate a meaningful response without additional input.
|
||||
/// </remarks>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
public Task<AgentResponse> RunAsync(
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
@@ -167,13 +167,13 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <exception cref="ArgumentException"><paramref name="message"/> is <see langword="null"/>, empty, or contains only whitespace.</exception>
|
||||
/// <remarks>
|
||||
/// The provided text will be wrapped in a <see cref="ChatMessage"/> with the <see cref="ChatRole.User"/> role
|
||||
/// before being sent to the agent. This is a convenience method for simple text-based interactions.
|
||||
/// </remarks>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
public Task<AgentResponse> RunAsync(
|
||||
string message,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -194,9 +194,9 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
public Task<AgentResponse> RunAsync(
|
||||
ChatMessage message,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -217,7 +217,7 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This method delegates to <see cref="RunCoreAsync"/> to perform the actual agent invocation. It handles collections of messages,
|
||||
@@ -229,7 +229,7 @@ public abstract class AIAgent
|
||||
/// The agent's response will also be added to <paramref name="thread"/> if one is provided.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
public Task<AgentResponse> RunAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -246,7 +246,7 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is the primary invocation method that implementations must override. It handles collections of messages,
|
||||
@@ -258,7 +258,7 @@ public abstract class AIAgent
|
||||
/// The agent's response will also be added to <paramref name="thread"/> if one is provided.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
protected abstract Task<AgentRunResponse> RunCoreAsync(
|
||||
protected abstract Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -273,8 +273,8 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
@@ -290,13 +290,13 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <exception cref="ArgumentException"><paramref name="message"/> is <see langword="null"/>, empty, or contains only whitespace.</exception>
|
||||
/// <remarks>
|
||||
/// The provided text will be wrapped in a <see cref="ChatMessage"/> with the <see cref="ChatRole.User"/> role.
|
||||
/// Streaming invocation provides real-time updates as the agent generates its response.
|
||||
/// </remarks>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
string message,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -317,9 +317,9 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
ChatMessage message,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -340,18 +340,18 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This method delegates to <see cref="RunCoreStreamingAsync"/> to perform the actual streaming invocation. It provides real-time
|
||||
/// updates as the agent processes the input and generates its response, enabling more responsive user experiences.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Each <see cref="AgentRunResponseUpdate"/> represents a portion of the complete response, allowing consumers
|
||||
/// Each <see cref="AgentResponseUpdate"/> represents a portion of the complete response, allowing consumers
|
||||
/// to display partial results, implement progressive loading, or provide immediate feedback to users.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -368,18 +368,18 @@ public abstract class AIAgent
|
||||
/// </param>
|
||||
/// <param name="options">Optional configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is the primary streaming invocation method that implementations must override. It provides real-time
|
||||
/// updates as the agent processes the input and generates its response, enabling more responsive user experiences.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// Each <see cref="AgentRunResponseUpdate"/> represents a portion of the complete response, allowing consumers
|
||||
/// Each <see cref="AgentResponseUpdate"/> represents a portion of the complete response, allowing consumers
|
||||
/// to display partial results, implement progressive loading, or provide immediate feedback to users.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
protected abstract IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected abstract IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
|
||||
@@ -76,10 +76,10 @@ public static partial class AgentAbstractionsJsonUtilities
|
||||
|
||||
// Agent abstraction types
|
||||
[JsonSerializable(typeof(AgentRunOptions))]
|
||||
[JsonSerializable(typeof(AgentRunResponse))]
|
||||
[JsonSerializable(typeof(AgentRunResponse[]))]
|
||||
[JsonSerializable(typeof(AgentRunResponseUpdate))]
|
||||
[JsonSerializable(typeof(AgentRunResponseUpdate[]))]
|
||||
[JsonSerializable(typeof(AgentResponse))]
|
||||
[JsonSerializable(typeof(AgentResponse[]))]
|
||||
[JsonSerializable(typeof(AgentResponseUpdate))]
|
||||
[JsonSerializable(typeof(AgentResponseUpdate[]))]
|
||||
[JsonSerializable(typeof(ServiceIdAgentThread.ServiceIdAgentThreadState))]
|
||||
[JsonSerializable(typeof(InMemoryAgentThread.InMemoryAgentThreadState))]
|
||||
[JsonSerializable(typeof(InMemoryChatMessageStore.StoreState))]
|
||||
|
||||
+20
-20
@@ -24,30 +24,30 @@ namespace Microsoft.Agents.AI;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <see cref="AgentRunResponse"/> provides one or more response messages and metadata about the response.
|
||||
/// <see cref="AgentResponse"/> provides one or more response messages and metadata about the response.
|
||||
/// A typical response will contain a single message, however a response may contain multiple messages
|
||||
/// in a variety of scenarios. For example, if the agent internally invokes functions or tools, performs
|
||||
/// RAG retrievals or has other complex logic, a single run by the agent may produce many messages showing
|
||||
/// the intermediate progress that the agent made towards producing the agent result.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// To get the text result of the response, use the <see cref="Text"/> property or simply call <see cref="ToString()"/> on the <see cref="AgentRunResponse"/>.
|
||||
/// To get the text result of the response, use the <see cref="Text"/> property or simply call <see cref="ToString()"/> on the <see cref="AgentResponse"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public class AgentRunResponse
|
||||
public class AgentResponse
|
||||
{
|
||||
/// <summary>The response messages.</summary>
|
||||
private IList<ChatMessage>? _messages;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponse"/> class.</summary>
|
||||
public AgentRunResponse()
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponse"/> class.</summary>
|
||||
public AgentResponse()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponse"/> class.</summary>
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponse"/> class.</summary>
|
||||
/// <param name="message">The response message to include in this response.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public AgentRunResponse(ChatMessage message)
|
||||
public AgentResponse(ChatMessage message)
|
||||
{
|
||||
_ = Throw.IfNull(message);
|
||||
|
||||
@@ -55,16 +55,16 @@ public class AgentRunResponse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunResponse"/> class from an existing <see cref="ChatResponse"/>.
|
||||
/// Initializes a new instance of the <see cref="AgentResponse"/> class from an existing <see cref="ChatResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="response">The <see cref="ChatResponse"/> from which to populate this <see cref="AgentRunResponse"/>.</param>
|
||||
/// <param name="response">The <see cref="ChatResponse"/> from which to populate this <see cref="AgentResponse"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor creates an agent response that wraps an existing <see cref="ChatResponse"/>, preserving all
|
||||
/// metadata and storing the original response in <see cref="RawRepresentation"/> for access to
|
||||
/// the underlying implementation details.
|
||||
/// </remarks>
|
||||
public AgentRunResponse(ChatResponse response)
|
||||
public AgentResponse(ChatResponse response)
|
||||
{
|
||||
_ = Throw.IfNull(response);
|
||||
|
||||
@@ -78,10 +78,10 @@ public class AgentRunResponse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunResponse"/> class with the specified collection of messages.
|
||||
/// Initializes a new instance of the <see cref="AgentResponse"/> class with the specified collection of messages.
|
||||
/// </summary>
|
||||
/// <param name="messages">The collection of response messages, or <see langword="null"/> to create an empty response.</param>
|
||||
public AgentRunResponse(IList<ChatMessage>? messages)
|
||||
public AgentResponse(IList<ChatMessage>? messages)
|
||||
{
|
||||
this._messages = messages;
|
||||
}
|
||||
@@ -201,7 +201,7 @@ public class AgentRunResponse
|
||||
|
||||
/// <summary>Gets or sets the raw representation of the run response from an underlying implementation.</summary>
|
||||
/// <remarks>
|
||||
/// If a <see cref="AgentRunResponse"/> is created to represent some underlying object from another object
|
||||
/// If a <see cref="AgentResponse"/> is created to represent some underlying object from another object
|
||||
/// model, this property can be used to store that original object. This can be useful for debugging or
|
||||
/// for enabling a consumer to access the underlying object model if needed.
|
||||
/// </remarks>
|
||||
@@ -226,11 +226,11 @@ public class AgentRunResponse
|
||||
public override string ToString() => this.Text;
|
||||
|
||||
/// <summary>
|
||||
/// Converts this <see cref="AgentRunResponse"/> into a collection of <see cref="AgentRunResponseUpdate"/> instances
|
||||
/// Converts this <see cref="AgentResponse"/> into a collection of <see cref="AgentResponseUpdate"/> instances
|
||||
/// suitable for streaming scenarios.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// An array of <see cref="AgentRunResponseUpdate"/> instances that collectively represent
|
||||
/// An array of <see cref="AgentResponseUpdate"/> instances that collectively represent
|
||||
/// the same information as this response.
|
||||
/// </returns>
|
||||
/// <remarks>
|
||||
@@ -245,12 +245,12 @@ public class AgentRunResponse
|
||||
/// original message sequence.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public AgentRunResponseUpdate[] ToAgentRunResponseUpdates()
|
||||
public AgentResponseUpdate[] ToAgentResponseUpdates()
|
||||
{
|
||||
AgentRunResponseUpdate? extra = null;
|
||||
AgentResponseUpdate? extra = null;
|
||||
if (this.AdditionalProperties is not null || this.Usage is not null)
|
||||
{
|
||||
extra = new AgentRunResponseUpdate
|
||||
extra = new AgentResponseUpdate
|
||||
{
|
||||
AdditionalProperties = this.AdditionalProperties,
|
||||
};
|
||||
@@ -262,13 +262,13 @@ public class AgentRunResponse
|
||||
}
|
||||
|
||||
int messageCount = this._messages?.Count ?? 0;
|
||||
var updates = new AgentRunResponseUpdate[messageCount + (extra is not null ? 1 : 0)];
|
||||
var updates = new AgentResponseUpdate[messageCount + (extra is not null ? 1 : 0)];
|
||||
|
||||
int i;
|
||||
for (i = 0; i < messageCount; i++)
|
||||
{
|
||||
ChatMessage message = this._messages![i];
|
||||
updates[i] = new AgentRunResponseUpdate
|
||||
updates[i] = new AgentResponseUpdate
|
||||
{
|
||||
AdditionalProperties = message.AdditionalProperties,
|
||||
AuthorName = message.AuthorName,
|
||||
+42
-42
@@ -11,24 +11,24 @@ using Microsoft.Shared.Diagnostics;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for working with <see cref="AgentRunResponse"/> and <see cref="AgentRunResponseUpdate"/> instances.
|
||||
/// Provides extension methods for working with <see cref="AgentResponse"/> and <see cref="AgentResponseUpdate"/> instances.
|
||||
/// </summary>
|
||||
public static class AgentRunResponseExtensions
|
||||
public static class AgentResponseExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChatResponse"/> from an <see cref="AgentRunResponse"/> instance.
|
||||
/// Creates a <see cref="ChatResponse"/> from an <see cref="AgentResponse"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="response">The <see cref="AgentRunResponse"/> to convert.</param>
|
||||
/// <param name="response">The <see cref="AgentResponse"/> to convert.</param>
|
||||
/// <returns>A <see cref="ChatResponse"/> built from the specified <paramref name="response"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// If the <paramref name="response"/>'s <see cref="AgentRunResponse.RawRepresentation"/> is already a
|
||||
/// If the <paramref name="response"/>'s <see cref="AgentResponse.RawRepresentation"/> is already a
|
||||
/// <see cref="ChatResponse"/> instance, that instance is returned directly.
|
||||
/// Otherwise, a new <see cref="ChatResponse"/> is created and populated with the data from the <paramref name="response"/>.
|
||||
/// The resulting instance is a shallow copy; any reference-type members (e.g. <see cref="AgentRunResponse.Messages"/>)
|
||||
/// The resulting instance is a shallow copy; any reference-type members (e.g. <see cref="AgentResponse.Messages"/>)
|
||||
/// will be shared between the two instances.
|
||||
/// </remarks>
|
||||
public static ChatResponse AsChatResponse(this AgentRunResponse response)
|
||||
public static ChatResponse AsChatResponse(this AgentResponse response)
|
||||
{
|
||||
Throw.IfNull(response);
|
||||
|
||||
@@ -47,19 +47,19 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="ChatResponseUpdate"/> from an <see cref="AgentRunResponseUpdate"/> instance.
|
||||
/// Creates a <see cref="ChatResponseUpdate"/> from an <see cref="AgentResponseUpdate"/> instance.
|
||||
/// </summary>
|
||||
/// <param name="responseUpdate">The <see cref="AgentRunResponseUpdate"/> to convert.</param>
|
||||
/// <param name="responseUpdate">The <see cref="AgentResponseUpdate"/> to convert.</param>
|
||||
/// <returns>A <see cref="ChatResponseUpdate"/> built from the specified <paramref name="responseUpdate"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="responseUpdate"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// If the <paramref name="responseUpdate"/>'s <see cref="AgentRunResponseUpdate.RawRepresentation"/> is already a
|
||||
/// If the <paramref name="responseUpdate"/>'s <see cref="AgentResponseUpdate.RawRepresentation"/> is already a
|
||||
/// <see cref="ChatResponseUpdate"/> instance, that instance is returned directly.
|
||||
/// Otherwise, a new <see cref="ChatResponseUpdate"/> is created and populated with the data from the <paramref name="responseUpdate"/>.
|
||||
/// The resulting instance is a shallow copy; any reference-type members (e.g. <see cref="AgentRunResponseUpdate.Contents"/>)
|
||||
/// The resulting instance is a shallow copy; any reference-type members (e.g. <see cref="AgentResponseUpdate.Contents"/>)
|
||||
/// will be shared between the two instances.
|
||||
/// </remarks>
|
||||
public static ChatResponseUpdate AsChatResponseUpdate(this AgentRunResponseUpdate responseUpdate)
|
||||
public static ChatResponseUpdate AsChatResponseUpdate(this AgentResponseUpdate responseUpdate)
|
||||
{
|
||||
Throw.IfNull(responseUpdate);
|
||||
|
||||
@@ -81,17 +81,17 @@ public static class AgentRunResponseExtensions
|
||||
|
||||
/// <summary>
|
||||
/// Creates an asynchronous enumerable of <see cref="ChatResponseUpdate"/> instances from an asynchronous
|
||||
/// enumerable of <see cref="AgentRunResponseUpdate"/> instances.
|
||||
/// enumerable of <see cref="AgentResponseUpdate"/> instances.
|
||||
/// </summary>
|
||||
/// <param name="responseUpdates">The sequence of <see cref="AgentRunResponseUpdate"/> instances to convert.</param>
|
||||
/// <param name="responseUpdates">The sequence of <see cref="AgentResponseUpdate"/> instances to convert.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="ChatResponseUpdate"/> instances built from <paramref name="responseUpdates"/>.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="responseUpdates"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// Each <see cref="AgentRunResponseUpdate"/> is converted to a <see cref="ChatResponseUpdate"/> using
|
||||
/// Each <see cref="AgentResponseUpdate"/> is converted to a <see cref="ChatResponseUpdate"/> using
|
||||
/// <see cref="AsChatResponseUpdate"/>.
|
||||
/// </remarks>
|
||||
public static async IAsyncEnumerable<ChatResponseUpdate> AsChatResponseUpdatesAsync(
|
||||
this IAsyncEnumerable<AgentRunResponseUpdate> responseUpdates)
|
||||
this IAsyncEnumerable<AgentResponseUpdate> responseUpdates)
|
||||
{
|
||||
Throw.IfNull(responseUpdates);
|
||||
|
||||
@@ -102,71 +102,71 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Combines a sequence of <see cref="AgentRunResponseUpdate"/> instances into a single <see cref="AgentRunResponse"/>.
|
||||
/// Combines a sequence of <see cref="AgentResponseUpdate"/> instances into a single <see cref="AgentResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="updates">The sequence of updates to be combined into a single response.</param>
|
||||
/// <returns>A single <see cref="AgentRunResponse"/> that represents the combined state of all the updates.</returns>
|
||||
/// <returns>A single <see cref="AgentResponse"/> that represents the combined state of all the updates.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="updates"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// As part of combining <paramref name="updates"/> into a single <see cref="AgentRunResponse"/>, the method will attempt to reconstruct
|
||||
/// <see cref="ChatMessage"/> instances. This includes using <see cref="AgentRunResponseUpdate.MessageId"/> to determine
|
||||
/// As part of combining <paramref name="updates"/> into a single <see cref="AgentResponse"/>, the method will attempt to reconstruct
|
||||
/// <see cref="ChatMessage"/> instances. This includes using <see cref="AgentResponseUpdate.MessageId"/> to determine
|
||||
/// message boundaries, as well as coalescing contiguous <see cref="AIContent"/> items where applicable, e.g. multiple
|
||||
/// <see cref="TextContent"/> instances in a row may be combined into a single <see cref="TextContent"/>.
|
||||
/// </remarks>
|
||||
public static AgentRunResponse ToAgentRunResponse(
|
||||
this IEnumerable<AgentRunResponseUpdate> updates)
|
||||
public static AgentResponse ToAgentResponse(
|
||||
this IEnumerable<AgentResponseUpdate> updates)
|
||||
{
|
||||
_ = Throw.IfNull(updates);
|
||||
|
||||
AgentRunResponseDetails additionalDetails = new();
|
||||
AgentResponseDetails additionalDetails = new();
|
||||
ChatResponse chatResponse =
|
||||
AsChatResponseUpdatesWithAdditionalDetails(updates, additionalDetails)
|
||||
.ToChatResponse();
|
||||
|
||||
return new AgentRunResponse(chatResponse)
|
||||
return new AgentResponse(chatResponse)
|
||||
{
|
||||
AgentId = additionalDetails.AgentId,
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Asynchronously combines a sequence of <see cref="AgentRunResponseUpdate"/> instances into a single <see cref="AgentRunResponse"/>.
|
||||
/// Asynchronously combines a sequence of <see cref="AgentResponseUpdate"/> instances into a single <see cref="AgentResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="updates">The asynchronous sequence of updates to be combined into a single response.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains a single <see cref="AgentRunResponse"/> that represents the combined state of all the updates.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains a single <see cref="AgentResponse"/> that represents the combined state of all the updates.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="updates"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// This is the asynchronous version of <see cref="ToAgentRunResponse(IEnumerable{AgentRunResponseUpdate})"/>.
|
||||
/// This is the asynchronous version of <see cref="ToAgentResponse(IEnumerable{AgentResponseUpdate})"/>.
|
||||
/// It performs the same combining logic but operates on an asynchronous enumerable of updates.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// As part of combining <paramref name="updates"/> into a single <see cref="AgentRunResponse"/>, the method will attempt to reconstruct
|
||||
/// <see cref="ChatMessage"/> instances. This includes using <see cref="AgentRunResponseUpdate.MessageId"/> to determine
|
||||
/// As part of combining <paramref name="updates"/> into a single <see cref="AgentResponse"/>, the method will attempt to reconstruct
|
||||
/// <see cref="ChatMessage"/> instances. This includes using <see cref="AgentResponseUpdate.MessageId"/> to determine
|
||||
/// message boundaries, as well as coalescing contiguous <see cref="AIContent"/> items where applicable, e.g. multiple
|
||||
/// <see cref="TextContent"/> instances in a row may be combined into a single <see cref="TextContent"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public static Task<AgentRunResponse> ToAgentRunResponseAsync(
|
||||
this IAsyncEnumerable<AgentRunResponseUpdate> updates,
|
||||
public static Task<AgentResponse> ToAgentResponseAsync(
|
||||
this IAsyncEnumerable<AgentResponseUpdate> updates,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
_ = Throw.IfNull(updates);
|
||||
|
||||
return ToAgentRunResponseAsync(updates, cancellationToken);
|
||||
return ToAgentResponseAsync(updates, cancellationToken);
|
||||
|
||||
static async Task<AgentRunResponse> ToAgentRunResponseAsync(
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> updates,
|
||||
static async Task<AgentResponse> ToAgentResponseAsync(
|
||||
IAsyncEnumerable<AgentResponseUpdate> updates,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
AgentRunResponseDetails additionalDetails = new();
|
||||
AgentResponseDetails additionalDetails = new();
|
||||
ChatResponse chatResponse = await
|
||||
AsChatResponseUpdatesWithAdditionalDetailsAsync(updates, additionalDetails, cancellationToken)
|
||||
.ToChatResponseAsync(cancellationToken)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
return new AgentRunResponse(chatResponse)
|
||||
return new AgentResponse(chatResponse)
|
||||
{
|
||||
AgentId = additionalDetails.AgentId,
|
||||
};
|
||||
@@ -174,8 +174,8 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
|
||||
private static IEnumerable<ChatResponseUpdate> AsChatResponseUpdatesWithAdditionalDetails(
|
||||
IEnumerable<AgentRunResponseUpdate> updates,
|
||||
AgentRunResponseDetails additionalDetails)
|
||||
IEnumerable<AgentResponseUpdate> updates,
|
||||
AgentResponseDetails additionalDetails)
|
||||
{
|
||||
foreach (var update in updates)
|
||||
{
|
||||
@@ -185,8 +185,8 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
|
||||
private static async IAsyncEnumerable<ChatResponseUpdate> AsChatResponseUpdatesWithAdditionalDetailsAsync(
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> updates,
|
||||
AgentRunResponseDetails additionalDetails,
|
||||
IAsyncEnumerable<AgentResponseUpdate> updates,
|
||||
AgentResponseDetails additionalDetails,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken)
|
||||
{
|
||||
await foreach (var update in updates.WithCancellation(cancellationToken).ConfigureAwait(false))
|
||||
@@ -196,7 +196,7 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
}
|
||||
|
||||
private static void UpdateAdditionalDetails(AgentRunResponseUpdate update, AgentRunResponseDetails details)
|
||||
private static void UpdateAdditionalDetails(AgentResponseUpdate update, AgentResponseDetails details)
|
||||
{
|
||||
if (update.AgentId is { Length: > 0 })
|
||||
{
|
||||
@@ -204,7 +204,7 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
}
|
||||
|
||||
private sealed class AgentRunResponseDetails
|
||||
private sealed class AgentResponseDetails
|
||||
{
|
||||
public string? AgentId { get; set; }
|
||||
}
|
||||
+20
-20
@@ -16,54 +16,54 @@ namespace Microsoft.Agents.AI;
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// <see cref="AgentRunResponseUpdate"/> is so named because it represents updates
|
||||
/// <see cref="AgentResponseUpdate"/> is so named because it represents updates
|
||||
/// that layer on each other to form a single agent response. Conceptually, this combines the roles of
|
||||
/// <see cref="AgentRunResponse"/> and <see cref="ChatMessage"/> in streaming output.
|
||||
/// <see cref="AgentResponse"/> and <see cref="ChatMessage"/> in streaming output.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// To get the text result of this response chunk, use the <see cref="Text"/> property or simply call <see cref="ToString()"/> on the <see cref="AgentRunResponseUpdate"/>.
|
||||
/// To get the text result of this response chunk, use the <see cref="Text"/> property or simply call <see cref="ToString()"/> on the <see cref="AgentResponseUpdate"/>.
|
||||
/// </para>
|
||||
/// <para>
|
||||
/// The relationship between <see cref="AgentRunResponse"/> and <see cref="AgentRunResponseUpdate"/> is
|
||||
/// codified in the <see cref="AgentRunResponseExtensions.ToAgentRunResponseAsync"/> and
|
||||
/// <see cref="AgentRunResponse.ToAgentRunResponseUpdates"/>, which enable bidirectional conversions
|
||||
/// The relationship between <see cref="AgentResponse"/> and <see cref="AgentResponseUpdate"/> is
|
||||
/// codified in the <see cref="AgentResponseExtensions.ToAgentResponseAsync"/> and
|
||||
/// <see cref="AgentResponse.ToAgentResponseUpdates"/>, which enable bidirectional conversions
|
||||
/// between the two. Note, however, that the provided conversions may be lossy, for example if multiple
|
||||
/// updates all have different <see cref="RawRepresentation"/> objects whereas there's only one slot for
|
||||
/// such an object available in <see cref="AgentRunResponse.RawRepresentation"/>.
|
||||
/// such an object available in <see cref="AgentResponse.RawRepresentation"/>.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
[DebuggerDisplay("[{Role}] {ContentForDebuggerDisplay}{EllipsesForDebuggerDisplay,nq}")]
|
||||
public class AgentRunResponseUpdate
|
||||
public class AgentResponseUpdate
|
||||
{
|
||||
/// <summary>The response update content items.</summary>
|
||||
private IList<AIContent>? _contents;
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponseUpdate"/> class.</summary>
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponseUpdate"/> class.</summary>
|
||||
[JsonConstructor]
|
||||
public AgentRunResponseUpdate()
|
||||
public AgentResponseUpdate()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponseUpdate"/> class.</summary>
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponseUpdate"/> class.</summary>
|
||||
/// <param name="role">The role of the author of the update.</param>
|
||||
/// <param name="content">The text content of the update.</param>
|
||||
public AgentRunResponseUpdate(ChatRole? role, string? content)
|
||||
public AgentResponseUpdate(ChatRole? role, string? content)
|
||||
: this(role, content is null ? null : [new TextContent(content)])
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponseUpdate"/> class.</summary>
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponseUpdate"/> class.</summary>
|
||||
/// <param name="role">The role of the author of the update.</param>
|
||||
/// <param name="contents">The contents of the update.</param>
|
||||
public AgentRunResponseUpdate(ChatRole? role, IList<AIContent>? contents)
|
||||
public AgentResponseUpdate(ChatRole? role, IList<AIContent>? contents)
|
||||
{
|
||||
this.Role = role;
|
||||
this._contents = contents;
|
||||
}
|
||||
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponseUpdate"/> class.</summary>
|
||||
/// <param name="chatResponseUpdate">The <see cref="ChatResponseUpdate"/> from which to seed this <see cref="AgentRunResponseUpdate"/>.</param>
|
||||
public AgentRunResponseUpdate(ChatResponseUpdate chatResponseUpdate)
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponseUpdate"/> class.</summary>
|
||||
/// <param name="chatResponseUpdate">The <see cref="ChatResponseUpdate"/> from which to seed this <see cref="AgentResponseUpdate"/>.</param>
|
||||
public AgentResponseUpdate(ChatResponseUpdate chatResponseUpdate)
|
||||
{
|
||||
_ = Throw.IfNull(chatResponseUpdate);
|
||||
|
||||
@@ -112,7 +112,7 @@ public class AgentRunResponseUpdate
|
||||
|
||||
/// <summary>Gets or sets the raw representation of the response update from an underlying implementation.</summary>
|
||||
/// <remarks>
|
||||
/// If a <see cref="AgentRunResponseUpdate"/> is created to represent some underlying object from another object
|
||||
/// If a <see cref="AgentResponseUpdate"/> is created to represent some underlying object from another object
|
||||
/// model, this property can be used to store that original object. This can be useful for debugging or
|
||||
/// for enabling a consumer to access the underlying object model if needed.
|
||||
/// </remarks>
|
||||
@@ -136,8 +136,8 @@ public class AgentRunResponseUpdate
|
||||
/// Some providers may consider streaming responses to be a single message, and in that case
|
||||
/// the value of this property may be the same as the response ID.
|
||||
///
|
||||
/// This value is used when <see cref="AgentRunResponseExtensions.ToAgentRunResponseAsync(IAsyncEnumerable{AgentRunResponseUpdate}, System.Threading.CancellationToken)"/>
|
||||
/// groups <see cref="AgentRunResponseUpdate"/> instances into <see cref="AgentRunResponse"/> instances.
|
||||
/// This value is used when <see cref="AgentResponseExtensions.ToAgentResponseAsync(IAsyncEnumerable{AgentResponseUpdate}, System.Threading.CancellationToken)"/>
|
||||
/// groups <see cref="AgentResponseUpdate"/> instances into <see cref="AgentResponse"/> instances.
|
||||
/// The value must be unique to each call to the underlying provider, and must be shared by
|
||||
/// all updates that are part of the same logical message within a streaming response.
|
||||
/// </remarks>
|
||||
+6
-6
@@ -8,18 +8,18 @@ namespace Microsoft.Agents.AI;
|
||||
/// Represents the response of the specified type <typeparamref name="T"/> to an <see cref="AIAgent"/> run request.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of value expected from the agent.</typeparam>
|
||||
public abstract class AgentRunResponse<T> : AgentRunResponse
|
||||
public abstract class AgentResponse<T> : AgentResponse
|
||||
{
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentRunResponse{T}"/> class.</summary>
|
||||
protected AgentRunResponse()
|
||||
/// <summary>Initializes a new instance of the <see cref="AgentResponse{T}"/> class.</summary>
|
||||
protected AgentResponse()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunResponse{T}"/> class from an existing <see cref="ChatResponse"/>.
|
||||
/// Initializes a new instance of the <see cref="AgentResponse{T}"/> class from an existing <see cref="ChatResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="response">The <see cref="ChatResponse"/> from which to populate this <see cref="AgentRunResponse{T}"/>.</param>
|
||||
protected AgentRunResponse(ChatResponse response) : base(response)
|
||||
/// <param name="response">The <see cref="ChatResponse"/> from which to populate this <see cref="AgentResponse{T}"/>.</param>
|
||||
protected AgentResponse(ChatResponse response) : base(response)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -43,10 +43,10 @@ public class AgentRunOptions
|
||||
/// This property is used for background responses that can be activated via the <see cref="AllowBackgroundResponses"/>
|
||||
/// property if the <see cref="AIAgent"/> implementation supports them.
|
||||
/// Streamed background responses, such as those returned by default by <see cref="AIAgent.RunStreamingAsync(AgentThread?, AgentRunOptions?, System.Threading.CancellationToken)"/>
|
||||
/// can be resumed if interrupted. This means that a continuation token obtained from the <see cref="AgentRunResponseUpdate.ContinuationToken"/>
|
||||
/// can be resumed if interrupted. This means that a continuation token obtained from the <see cref="AgentResponseUpdate.ContinuationToken"/>
|
||||
/// of an update just before the interruption occurred can be passed to this property to resume the stream from the point of interruption.
|
||||
/// Non-streamed background responses, such as those returned by <see cref="AIAgent.RunAsync(AgentThread?, AgentRunOptions?, System.Threading.CancellationToken)"/>,
|
||||
/// can be polled for completion by obtaining the token from the <see cref="AgentRunResponse.ContinuationToken"/> property
|
||||
/// can be polled for completion by obtaining the token from the <see cref="AgentResponse.ContinuationToken"/> property
|
||||
/// and passing it via this property on subsequent calls to <see cref="AIAgent.RunAsync(AgentThread?, AgentRunOptions?, System.Threading.CancellationToken)"/>.
|
||||
/// </remarks>
|
||||
public ResponseContinuationToken? ContinuationToken { get; set; }
|
||||
|
||||
@@ -81,7 +81,7 @@ public abstract class DelegatingAIAgent : AIAgent
|
||||
=> this.InnerAgent.DeserializeThreadAsync(serializedThread, jsonSerializerOptions, cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -89,7 +89,7 @@ public abstract class DelegatingAIAgent : AIAgent
|
||||
=> this.InnerAgent.RunAsync(messages, thread, options, cancellationToken);
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
|
||||
@@ -58,7 +58,7 @@ public class CopilotStudioAgent : AIAgent
|
||||
=> new(new CopilotStudioAgentThread(serializedThread, jsonSerializerOptions));
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override async Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -88,7 +88,7 @@ public class CopilotStudioAgent : AIAgent
|
||||
// TODO: Review list of ChatResponse properties to ensure we set all availble values.
|
||||
// Setting ResponseId and MessageId end up being particularly important for streaming consumers
|
||||
// so that they can tell things like response boundaries.
|
||||
return new AgentRunResponse(responseMessagesList)
|
||||
return new AgentResponse(responseMessagesList)
|
||||
{
|
||||
AgentId = this.Id,
|
||||
ResponseId = responseMessagesList.LastOrDefault()?.MessageId,
|
||||
@@ -96,7 +96,7 @@ public class CopilotStudioAgent : AIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -125,7 +125,7 @@ public class CopilotStudioAgent : AIAgent
|
||||
// TODO: Review list of ChatResponse properties to ensure we set all availble values.
|
||||
// Setting ResponseId and MessageId end up being particularly important for streaming consumers
|
||||
// so that they can tell things like response boundaries.
|
||||
yield return new AgentRunResponseUpdate(message.Role, message.Contents)
|
||||
yield return new AgentResponseUpdate(message.Role, message.Contents)
|
||||
{
|
||||
AgentId = this.Id,
|
||||
AdditionalProperties = message.AdditionalProperties,
|
||||
|
||||
@@ -21,7 +21,7 @@ internal class AgentEntity(IServiceProvider services, CancellationToken cancella
|
||||
? cancellationToken
|
||||
: services.GetService<IHostApplicationLifetime>()?.ApplicationStopping ?? CancellationToken.None;
|
||||
|
||||
public Task<AgentRunResponse> RunAgentAsync(RunRequest request)
|
||||
public Task<AgentResponse> RunAgentAsync(RunRequest request)
|
||||
{
|
||||
return this.Run(request);
|
||||
}
|
||||
@@ -29,7 +29,7 @@ internal class AgentEntity(IServiceProvider services, CancellationToken cancella
|
||||
// IDE1006 and VSTHRD200 disabled to allow method name to match the common cross-platform entity operation name.
|
||||
#pragma warning disable IDE1006
|
||||
#pragma warning disable VSTHRD200
|
||||
public async Task<AgentRunResponse> Run(RunRequest request)
|
||||
public async Task<AgentResponse> Run(RunRequest request)
|
||||
#pragma warning restore VSTHRD200
|
||||
#pragma warning restore IDE1006
|
||||
{
|
||||
@@ -43,7 +43,7 @@ internal class AgentEntity(IServiceProvider services, CancellationToken cancella
|
||||
if (request.Messages.Count == 0)
|
||||
{
|
||||
logger.LogInformation("Ignoring empty request");
|
||||
return new AgentRunResponse();
|
||||
return new AgentResponse();
|
||||
}
|
||||
|
||||
this.State.Data.ConversationHistory.Add(DurableAgentStateRequest.FromRunRequest(request));
|
||||
@@ -65,29 +65,29 @@ internal class AgentEntity(IServiceProvider services, CancellationToken cancella
|
||||
try
|
||||
{
|
||||
// Start the agent response stream
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> responseStream = agentWrapper.RunStreamingAsync(
|
||||
IAsyncEnumerable<AgentResponseUpdate> responseStream = agentWrapper.RunStreamingAsync(
|
||||
this.State.Data.ConversationHistory.SelectMany(e => e.Messages).Select(m => m.ToChatMessage()),
|
||||
await agentWrapper.GetNewThreadAsync(cancellationToken).ConfigureAwait(false),
|
||||
options: null,
|
||||
this._cancellationToken);
|
||||
|
||||
AgentRunResponse response;
|
||||
AgentResponse response;
|
||||
if (this._messageHandler is null)
|
||||
{
|
||||
// If no message handler is provided, we can just get the full response at once.
|
||||
// This is expected to be the common case for non-interactive agents.
|
||||
response = await responseStream.ToAgentRunResponseAsync(this._cancellationToken);
|
||||
response = await responseStream.ToAgentResponseAsync(this._cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
List<AgentRunResponseUpdate> responseUpdates = [];
|
||||
List<AgentResponseUpdate> responseUpdates = [];
|
||||
|
||||
// To support interactive chat agents, we need to stream the responses to an IAgentMessageHandler.
|
||||
// The user-provided message handler can be implemented to send the responses to the user.
|
||||
// We assume that only non-empty text updates are useful for the user.
|
||||
async IAsyncEnumerable<AgentRunResponseUpdate> StreamResultsAsync()
|
||||
async IAsyncEnumerable<AgentResponseUpdate> StreamResultsAsync()
|
||||
{
|
||||
await foreach (AgentRunResponseUpdate update in responseStream)
|
||||
await foreach (AgentResponseUpdate update in responseStream)
|
||||
{
|
||||
// We need the full response further down, so we piece it together as we go.
|
||||
responseUpdates.Add(update);
|
||||
@@ -98,12 +98,12 @@ internal class AgentEntity(IServiceProvider services, CancellationToken cancella
|
||||
}
|
||||
|
||||
await this._messageHandler.OnStreamingResponseUpdateAsync(StreamResultsAsync(), this._cancellationToken);
|
||||
response = responseUpdates.ToAgentRunResponse();
|
||||
response = responseUpdates.ToAgentResponse();
|
||||
}
|
||||
|
||||
// Persist the agent response to the entity state for client polling
|
||||
this.State.Data.ConversationHistory.Add(
|
||||
DurableAgentStateResponse.FromRunResponse(request.CorrelationId, response));
|
||||
DurableAgentStateResponse.FromResponse(request.CorrelationId, response));
|
||||
|
||||
string responseText = response.Text;
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ internal sealed class AgentRunHandle
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>The agent response corresponding to this request.</returns>
|
||||
/// <exception cref="InvalidOperationException">Thrown when the response is not found after polling.</exception>
|
||||
public async Task<AgentRunResponse> ReadAgentResponseAsync(CancellationToken cancellationToken = default)
|
||||
public async Task<AgentResponse> ReadAgentResponseAsync(CancellationToken cancellationToken = default)
|
||||
{
|
||||
TimeSpan pollInterval = TimeSpan.FromMilliseconds(50); // Start with 50ms
|
||||
TimeSpan maxPollInterval = TimeSpan.FromSeconds(3); // Maximum 3 seconds
|
||||
@@ -69,7 +69,7 @@ internal sealed class AgentRunHandle
|
||||
if (response is not null)
|
||||
{
|
||||
this._logger.LogDonePollingForResponse(this.SessionId, this.CorrelationId);
|
||||
return response.ToRunResponse();
|
||||
return response.ToResponse();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ public sealed class DurableAIAgent : AIAgent
|
||||
/// <exception cref="AgentNotRegisteredException">Thrown when the agent has not been registered.</exception>
|
||||
/// <exception cref="ArgumentException">Thrown when the provided thread is not valid for a durable agent.</exception>
|
||||
/// <exception cref="NotSupportedException">Thrown when cancellation is requested (cancellation is not supported for durable agents).</exception>
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override async Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -107,7 +107,7 @@ public sealed class DurableAIAgent : AIAgent
|
||||
|
||||
try
|
||||
{
|
||||
return await this._context.Entities.CallEntityAsync<AgentRunResponse>(
|
||||
return await this._context.Entities.CallEntityAsync<AgentResponse>(
|
||||
durableThread.SessionId,
|
||||
nameof(AgentEntity.Run),
|
||||
request);
|
||||
@@ -130,7 +130,7 @@ public sealed class DurableAIAgent : AIAgent
|
||||
/// <param name="options">Optional run options.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A streaming response enumerable.</returns>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -138,8 +138,8 @@ public sealed class DurableAIAgent : AIAgent
|
||||
{
|
||||
// Streaming is not supported for durable agents, so we just return the full response
|
||||
// as a single update.
|
||||
AgentRunResponse response = await this.RunAsync(messages, thread, options, cancellationToken);
|
||||
foreach (AgentRunResponseUpdate update in response.ToAgentRunResponseUpdates())
|
||||
AgentResponse response = await this.RunAsync(messages, thread, options, cancellationToken);
|
||||
foreach (AgentResponseUpdate update in response.ToAgentResponseUpdates())
|
||||
{
|
||||
yield return update;
|
||||
}
|
||||
@@ -162,7 +162,7 @@ public sealed class DurableAIAgent : AIAgent
|
||||
/// Thrown when the agent response is empty or cannot be deserialized.
|
||||
/// </exception>
|
||||
/// <returns>The output from the agent.</returns>
|
||||
public async Task<AgentRunResponse<T>> RunAsync<T>(
|
||||
public async Task<AgentResponse<T>> RunAsync<T>(
|
||||
string message,
|
||||
AgentThread? thread = null,
|
||||
JsonSerializerOptions? serializerOptions = null,
|
||||
@@ -196,7 +196,7 @@ public sealed class DurableAIAgent : AIAgent
|
||||
/// <returns>The output from the agent.</returns>
|
||||
[UnconditionalSuppressMessage("Trimming", "IL2026", Justification = "Fallback to reflection-based deserialization is intentional for library flexibility with user-defined types.")]
|
||||
[UnconditionalSuppressMessage("ReflectionAnalysis", "IL3050", Justification = "Fallback to reflection-based deserialization is intentional for library flexibility with user-defined types.")]
|
||||
public async Task<AgentRunResponse<T>> RunAsync<T>(
|
||||
public async Task<AgentResponse<T>> RunAsync<T>(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
JsonSerializerOptions? serializerOptions = null,
|
||||
@@ -223,7 +223,7 @@ public sealed class DurableAIAgent : AIAgent
|
||||
// Create the JSON schema for the response type
|
||||
durableOptions.ResponseFormat = ChatResponseFormat.ForJsonSchema<T>();
|
||||
|
||||
AgentRunResponse response = await this.RunAsync(messages, thread, durableOptions, cancellationToken);
|
||||
AgentResponse response = await this.RunAsync(messages, thread, durableOptions, cancellationToken);
|
||||
|
||||
// Deserialize the response text to the requested type
|
||||
if (string.IsNullOrEmpty(response.Text))
|
||||
@@ -242,11 +242,11 @@ public sealed class DurableAIAgent : AIAgent
|
||||
: JsonSerializer.Deserialize<T>(response.Text, serializerOptions))
|
||||
?? throw new InvalidOperationException($"Failed to deserialize agent response to type {typeof(T).Name}.");
|
||||
|
||||
return new DurableAIAgentRunResponse<T>(response, result);
|
||||
return new DurableAIAgentResponse<T>(response, result);
|
||||
}
|
||||
|
||||
private sealed class DurableAIAgentRunResponse<T>(AgentRunResponse response, T result)
|
||||
: AgentRunResponse<T>(response.AsChatResponse())
|
||||
private sealed class DurableAIAgentResponse<T>(AgentResponse response, T result)
|
||||
: AgentResponse<T>(response.AsChatResponse())
|
||||
{
|
||||
public override T Result { get; } = result;
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ internal class DurableAIAgentProxy(string name, IDurableAgentClient agentClient)
|
||||
return ValueTask.FromResult<AgentThread>(new DurableAgentThread(AgentSessionId.WithRandomKey(this.Name!)));
|
||||
}
|
||||
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override async Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -64,13 +64,13 @@ internal class DurableAIAgentProxy(string name, IDurableAgentClient agentClient)
|
||||
if (isFireAndForget)
|
||||
{
|
||||
// If the request is fire and forget, return an empty response.
|
||||
return new AgentRunResponse();
|
||||
return new AgentResponse();
|
||||
}
|
||||
|
||||
return await agentRunHandle.ReadAgentResponseAsync(cancellationToken);
|
||||
}
|
||||
|
||||
protected override IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Microsoft.Agents.AI.DurableTask;
|
||||
/// <item><description><see cref="JsonSerializerDefaults.Web"/> baseline defaults.</description></item>
|
||||
/// <item><description><see cref="JsonIgnoreCondition.WhenWritingNull"/> for default null-value suppression.</description></item>
|
||||
/// <item><description><see cref="JsonNumberHandling.AllowReadingFromString"/> to tolerate numbers encoded as strings.</description></item>
|
||||
/// <item><description>Chained type info resolvers from shared agent abstractions to cover cross-package types (e.g. <see cref="ChatMessage"/>, <see cref="AgentRunResponse"/>).</description></item>
|
||||
/// <item><description>Chained type info resolvers from shared agent abstractions to cover cross-package types (e.g. <see cref="ChatMessage"/>, <see cref="AgentResponse"/>).</description></item>
|
||||
/// </list>
|
||||
/// <para>
|
||||
/// Keep the list of <c>[JsonSerializable]</c> types in sync with the Durable Agent data model anytime new state or request/response
|
||||
|
||||
@@ -21,13 +21,13 @@ internal sealed class EntityAgentWrapper(
|
||||
// The ID of the agent is always the entity ID.
|
||||
protected override string? IdCore => this._entityContext.Id.ToString();
|
||||
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override async Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
AgentRunResponse response = await base.RunCoreAsync(
|
||||
AgentResponse response = await base.RunCoreAsync(
|
||||
messages,
|
||||
thread,
|
||||
this.GetAgentEntityRunOptions(options),
|
||||
@@ -37,13 +37,13 @@ internal sealed class EntityAgentWrapper(
|
||||
return response;
|
||||
}
|
||||
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
await foreach (AgentRunResponseUpdate update in base.RunCoreStreamingAsync(
|
||||
await foreach (AgentResponseUpdate update in base.RunCoreStreamingAsync(
|
||||
messages,
|
||||
thread,
|
||||
this.GetAgentEntityRunOptions(options),
|
||||
|
||||
@@ -17,7 +17,7 @@ public interface IAgentResponseHandler
|
||||
/// Signals that the operation should be cancelled.
|
||||
/// </param>
|
||||
ValueTask OnStreamingResponseUpdateAsync(
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> messageStream,
|
||||
IAsyncEnumerable<AgentResponseUpdate> messageStream,
|
||||
CancellationToken cancellationToken);
|
||||
|
||||
/// <summary>
|
||||
@@ -30,6 +30,6 @@ public interface IAgentResponseHandler
|
||||
/// Signals that the operation should be cancelled.
|
||||
/// </param>
|
||||
ValueTask OnAgentResponseAsync(
|
||||
AgentRunResponse message,
|
||||
AgentResponse message,
|
||||
CancellationToken cancellationToken);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<TargetFrameworks>$(TargetFrameworksCore)</TargetFrameworks>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<!-- CA2007: This rule should generally be suppressed in Durable Task libraries -->
|
||||
<!-- MEAI001: UserInputRequestContent is experimental but used in source-generated code for AgentRunResponse -->
|
||||
<!-- MEAI001: UserInputRequestContent is experimental but used in source-generated code for AgentResponse -->
|
||||
<NoWarn>$(NoWarn);CA2007;MEAI001</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -17,12 +17,12 @@ internal sealed class DurableAgentStateResponse : DurableAgentStateEntry
|
||||
public DurableAgentStateUsage? Usage { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates a <see cref="DurableAgentStateResponse"/> from an <see cref="AgentRunResponse"/>.
|
||||
/// Creates a <see cref="DurableAgentStateResponse"/> from an <see cref="AgentResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="correlationId">The correlation ID linking this response to its request.</param>
|
||||
/// <param name="response">The <see cref="AgentRunResponse"/> to convert.</param>
|
||||
/// <param name="response">The <see cref="AgentResponse"/> to convert.</param>
|
||||
/// <returns>A <see cref="DurableAgentStateResponse"/> representing the original response.</returns>
|
||||
public static DurableAgentStateResponse FromRunResponse(string correlationId, AgentRunResponse response)
|
||||
public static DurableAgentStateResponse FromResponse(string correlationId, AgentResponse response)
|
||||
{
|
||||
return new DurableAgentStateResponse()
|
||||
{
|
||||
@@ -34,12 +34,12 @@ internal sealed class DurableAgentStateResponse : DurableAgentStateEntry
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this <see cref="DurableAgentStateResponse"/> back to an <see cref="AgentRunResponse"/>.
|
||||
/// Converts this <see cref="DurableAgentStateResponse"/> back to an <see cref="AgentResponse"/>.
|
||||
/// </summary>
|
||||
/// <returns>A <see cref="AgentRunResponse"/> representing this response.</returns>
|
||||
public AgentRunResponse ToRunResponse()
|
||||
/// <returns>A <see cref="AgentResponse"/> representing this response.</returns>
|
||||
public AgentResponse ToResponse()
|
||||
{
|
||||
return new AgentRunResponse()
|
||||
return new AgentResponse()
|
||||
{
|
||||
CreatedAt = this.CreatedAt,
|
||||
Messages = this.Messages.Select(m => m.ToChatMessage()).ToList(),
|
||||
|
||||
@@ -119,7 +119,7 @@ internal static class BuiltInFunctions
|
||||
|
||||
if (waitForResponse)
|
||||
{
|
||||
AgentRunResponse agentResponse = await agentProxy.RunAsync(
|
||||
AgentResponse agentResponse = await agentProxy.RunAsync(
|
||||
message: new ChatMessage(ChatRole.User, message),
|
||||
thread: new DurableAgentThread(sessionId),
|
||||
options: options,
|
||||
@@ -170,7 +170,7 @@ internal static class BuiltInFunctions
|
||||
|
||||
AIAgent agentProxy = client.AsDurableAgentProxy(functionContext, agentName);
|
||||
|
||||
AgentRunResponse agentResponse = await agentProxy.RunAsync(
|
||||
AgentResponse agentResponse = await agentProxy.RunAsync(
|
||||
message: new ChatMessage(ChatRole.User, query),
|
||||
thread: new DurableAgentThread(sessionId),
|
||||
options: null);
|
||||
@@ -224,7 +224,7 @@ internal static class BuiltInFunctions
|
||||
FunctionContext context,
|
||||
HttpStatusCode statusCode,
|
||||
string threadId,
|
||||
AgentRunResponse agentResponse)
|
||||
AgentResponse agentResponse)
|
||||
{
|
||||
HttpResponseData response = req.CreateResponse(statusCode);
|
||||
response.Headers.Add("x-ms-thread-id", threadId);
|
||||
@@ -321,7 +321,7 @@ internal static class BuiltInFunctions
|
||||
private sealed record AgentRunSuccessResponse(
|
||||
[property: JsonPropertyName("status")] int Status,
|
||||
[property: JsonPropertyName("thread_id")] string ThreadId,
|
||||
[property: JsonPropertyName("response")] AgentRunResponse Response);
|
||||
[property: JsonPropertyName("response")] AgentResponse Response);
|
||||
|
||||
/// <summary>
|
||||
/// Represents an accepted (fire-and-forget) agent run response.
|
||||
|
||||
@@ -77,7 +77,7 @@ public static async Task<string> SpamDetectionOrchestration(
|
||||
AgentThread spamThread = await spamDetectionAgent.GetNewThreadAsync();
|
||||
|
||||
// Step 1: Check if the email is spam
|
||||
AgentRunResponse<DetectionResult> spamDetectionResponse = await spamDetectionAgent.RunAsync<DetectionResult>(
|
||||
AgentResponse<DetectionResult> spamDetectionResponse = await spamDetectionAgent.RunAsync<DetectionResult>(
|
||||
message:
|
||||
$"""
|
||||
Analyze this email for spam content and return a JSON response with 'is_spam' (boolean) and 'reason' (string) fields:
|
||||
@@ -99,7 +99,7 @@ public static async Task<string> SpamDetectionOrchestration(
|
||||
DurableAIAgent emailAssistantAgent = context.GetAgent("EmailAssistantAgent");
|
||||
AgentThread emailThread = await emailAssistantAgent.GetNewThreadAsync();
|
||||
|
||||
AgentRunResponse<EmailResponse> emailAssistantResponse = await emailAssistantAgent.RunAsync<EmailResponse>(
|
||||
AgentResponse<EmailResponse> emailAssistantResponse = await emailAssistantAgent.RunAsync<EmailResponse>(
|
||||
message:
|
||||
$"""
|
||||
Draft a professional response to this email. Return a JSON response with a 'response' field containing the reply:
|
||||
|
||||
+5
-5
@@ -70,18 +70,18 @@ internal static class AIAgentChatCompletionsProcessor
|
||||
DateTimeOffset? createdAt = null;
|
||||
var chunkId = IdGenerator.NewId(prefix: "chatcmpl", delimiter: "-", stringLength: 13);
|
||||
|
||||
await foreach (var agentRunResponseUpdate in agent.RunStreamingAsync(chatMessages, options: options, cancellationToken: cancellationToken).WithCancellation(cancellationToken))
|
||||
await foreach (var agentResponseUpdate in agent.RunStreamingAsync(chatMessages, options: options, cancellationToken: cancellationToken).WithCancellation(cancellationToken))
|
||||
{
|
||||
var finishReason = (agentRunResponseUpdate.RawRepresentation is ChatResponseUpdate { FinishReason: not null } chatResponseUpdate)
|
||||
var finishReason = (agentResponseUpdate.RawRepresentation is ChatResponseUpdate { FinishReason: not null } chatResponseUpdate)
|
||||
? chatResponseUpdate.FinishReason.ToString()
|
||||
: "stop";
|
||||
|
||||
var choiceChunks = new List<ChatCompletionChoiceChunk>();
|
||||
CompletionUsage? usageDetails = null;
|
||||
|
||||
createdAt ??= agentRunResponseUpdate.CreatedAt;
|
||||
createdAt ??= agentResponseUpdate.CreatedAt;
|
||||
|
||||
foreach (var content in agentRunResponseUpdate.Contents)
|
||||
foreach (var content in agentResponseUpdate.Contents)
|
||||
{
|
||||
// usage content is handled separately
|
||||
if (content is UsageContent usageContent && usageContent.Details != null)
|
||||
@@ -124,7 +124,7 @@ internal static class AIAgentChatCompletionsProcessor
|
||||
continue;
|
||||
}
|
||||
|
||||
delta.Role = agentRunResponseUpdate.Role?.Value ?? "user";
|
||||
delta.Role = agentResponseUpdate.Role?.Value ?? "user";
|
||||
|
||||
var choiceChunk = new ChatCompletionChoiceChunk
|
||||
{
|
||||
|
||||
+8
-8
@@ -12,33 +12,33 @@ namespace Microsoft.Agents.AI.Hosting.OpenAI.ChatCompletions;
|
||||
/// <summary>
|
||||
/// Extension methods for converting agent responses to ChatCompletion models.
|
||||
/// </summary>
|
||||
internal static class AgentRunResponseExtensions
|
||||
internal static class AgentResponseExtensions
|
||||
{
|
||||
public static ChatCompletion ToChatCompletion(this AgentRunResponse agentRunResponse, CreateChatCompletion request)
|
||||
public static ChatCompletion ToChatCompletion(this AgentResponse agentResponse, CreateChatCompletion request)
|
||||
{
|
||||
IList<ChatCompletionChoice> choices = agentRunResponse.ToChoices();
|
||||
IList<ChatCompletionChoice> choices = agentResponse.ToChoices();
|
||||
|
||||
return new ChatCompletion
|
||||
{
|
||||
Id = IdGenerator.NewId(prefix: "chatcmpl", delimiter: "-", stringLength: 13),
|
||||
Choices = choices,
|
||||
Created = (agentRunResponse.CreatedAt ?? DateTimeOffset.UtcNow).ToUnixTimeSeconds(),
|
||||
Created = (agentResponse.CreatedAt ?? DateTimeOffset.UtcNow).ToUnixTimeSeconds(),
|
||||
Model = request.Model,
|
||||
Usage = agentRunResponse.Usage.ToCompletionUsage(),
|
||||
Usage = agentResponse.Usage.ToCompletionUsage(),
|
||||
ServiceTier = request.ServiceTier ?? "default"
|
||||
};
|
||||
}
|
||||
|
||||
public static List<ChatCompletionChoice> ToChoices(this AgentRunResponse agentRunResponse)
|
||||
public static List<ChatCompletionChoice> ToChoices(this AgentResponse agentResponse)
|
||||
{
|
||||
var chatCompletionChoices = new List<ChatCompletionChoice>();
|
||||
var index = 0;
|
||||
|
||||
var finishReason = (agentRunResponse.RawRepresentation is ChatResponse { FinishReason: not null } chatResponse)
|
||||
var finishReason = (agentResponse.RawRepresentation is ChatResponse { FinishReason: not null } chatResponse)
|
||||
? chatResponse.FinishReason.ToString()
|
||||
: "stop"; // "stop" is a natural stop point; returning this by-default
|
||||
|
||||
foreach (var message in agentRunResponse.Messages)
|
||||
foreach (var message in agentResponse.Messages)
|
||||
{
|
||||
foreach (var content in message.Contents)
|
||||
{
|
||||
+7
-7
@@ -13,19 +13,19 @@ namespace Microsoft.Agents.AI.Hosting.OpenAI.Responses;
|
||||
/// <summary>
|
||||
/// Extension methods for converting agent responses to Response models.
|
||||
/// </summary>
|
||||
internal static class AgentRunResponseExtensions
|
||||
internal static class AgentResponseExtensions
|
||||
{
|
||||
private static ChatRole s_DeveloperRole => new("developer");
|
||||
|
||||
/// <summary>
|
||||
/// Converts an AgentRunResponse to a Response model.
|
||||
/// Converts an AgentResponse to a Response model.
|
||||
/// </summary>
|
||||
/// <param name="agentRunResponse">The agent run response to convert.</param>
|
||||
/// <param name="agentResponse">The agent response to convert.</param>
|
||||
/// <param name="request">The original create response request.</param>
|
||||
/// <param name="context">The agent invocation context.</param>
|
||||
/// <returns>A Response model.</returns>
|
||||
public static Response ToResponse(
|
||||
this AgentRunResponse agentRunResponse,
|
||||
this AgentResponse agentResponse,
|
||||
CreateResponse request,
|
||||
AgentInvocationContext context)
|
||||
{
|
||||
@@ -41,7 +41,7 @@ internal static class AgentRunResponseExtensions
|
||||
});
|
||||
}
|
||||
|
||||
output.AddRange(agentRunResponse.Messages
|
||||
output.AddRange(agentResponse.Messages
|
||||
.SelectMany(msg => msg.ToItemResource(context.IdGenerator, context.JsonSerializerOptions)));
|
||||
|
||||
return new Response
|
||||
@@ -49,7 +49,7 @@ internal static class AgentRunResponseExtensions
|
||||
Agent = request.Agent?.ToAgentId(),
|
||||
Background = request.Background,
|
||||
Conversation = request.Conversation ?? (context.ConversationId != null ? new ConversationReference { Id = context.ConversationId } : null),
|
||||
CreatedAt = (agentRunResponse.CreatedAt ?? DateTimeOffset.UtcNow).ToUnixTimeSeconds(),
|
||||
CreatedAt = (agentResponse.CreatedAt ?? DateTimeOffset.UtcNow).ToUnixTimeSeconds(),
|
||||
Error = null,
|
||||
Id = context.ResponseId,
|
||||
Instructions = request.Instructions,
|
||||
@@ -74,7 +74,7 @@ internal static class AgentRunResponseExtensions
|
||||
TopLogprobs = request.TopLogprobs,
|
||||
TopP = request.TopP ?? 1.0,
|
||||
Truncation = request.Truncation,
|
||||
Usage = agentRunResponse.Usage.ToResponseUsage(),
|
||||
Usage = agentResponse.Usage.ToResponseUsage(),
|
||||
#pragma warning disable CS0618 // Type or member is obsolete
|
||||
User = request.User,
|
||||
#pragma warning restore CS0618 // Type or member is obsolete
|
||||
+6
-6
@@ -16,12 +16,12 @@ using Microsoft.Extensions.AI;
|
||||
namespace Microsoft.Agents.AI.Hosting.OpenAI.Responses;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="AgentRunResponseUpdate"/>.
|
||||
/// Extension methods for <see cref="AgentResponseUpdate"/>.
|
||||
/// </summary>
|
||||
internal static class AgentRunResponseUpdateExtensions
|
||||
internal static class AgentResponseUpdateExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts a stream of <see cref="AgentRunResponseUpdate"/> to stream of <see cref="StreamingResponseEvent"/>.
|
||||
/// Converts a stream of <see cref="AgentResponseUpdate"/> to stream of <see cref="StreamingResponseEvent"/>.
|
||||
/// </summary>
|
||||
/// <param name="updates">The agent run response updates.</param>
|
||||
/// <param name="request">The create response request.</param>
|
||||
@@ -29,7 +29,7 @@ internal static class AgentRunResponseUpdateExtensions
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>A stream of response events.</returns>
|
||||
public static async IAsyncEnumerable<StreamingResponseEvent> ToStreamingResponseAsync(
|
||||
this IAsyncEnumerable<AgentRunResponseUpdate> updates,
|
||||
this IAsyncEnumerable<AgentResponseUpdate> updates,
|
||||
CreateResponse request,
|
||||
AgentInvocationContext context,
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
@@ -48,7 +48,7 @@ internal static class AgentRunResponseUpdateExtensions
|
||||
// Track active item IDs by executor ID to pair invoked/completed/failed events
|
||||
Dictionary<string, string> executorItemIds = [];
|
||||
|
||||
AgentRunResponseUpdate? previousUpdate = null;
|
||||
AgentResponseUpdate? previousUpdate = null;
|
||||
StreamingEventGenerator? generator = null;
|
||||
while (await updateEnumerator.MoveNextAsync().ConfigureAwait(false))
|
||||
{
|
||||
@@ -279,7 +279,7 @@ internal static class AgentRunResponseUpdateExtensions
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsSameMessage(AgentRunResponseUpdate? first, AgentRunResponseUpdate? second)
|
||||
private static bool IsSameMessage(AgentResponseUpdate? first, AgentResponseUpdate? second)
|
||||
{
|
||||
return IsSameValue(first?.MessageId, second?.MessageId)
|
||||
&& IsSameValue(first?.AuthorName, second?.AuthorName)
|
||||
+3
-3
@@ -7,9 +7,9 @@ namespace Microsoft.Agents.AI.OpenAI;
|
||||
|
||||
internal sealed class AsyncStreamingChatCompletionUpdateCollectionResult : AsyncCollectionResult<StreamingChatCompletionUpdate>
|
||||
{
|
||||
private readonly IAsyncEnumerable<AgentRunResponseUpdate> _updates;
|
||||
private readonly IAsyncEnumerable<AgentResponseUpdate> _updates;
|
||||
|
||||
internal AsyncStreamingChatCompletionUpdateCollectionResult(IAsyncEnumerable<AgentRunResponseUpdate> updates)
|
||||
internal AsyncStreamingChatCompletionUpdateCollectionResult(IAsyncEnumerable<AgentResponseUpdate> updates)
|
||||
{
|
||||
this._updates = updates;
|
||||
}
|
||||
@@ -23,7 +23,7 @@ internal sealed class AsyncStreamingChatCompletionUpdateCollectionResult : Async
|
||||
|
||||
protected override IAsyncEnumerable<StreamingChatCompletionUpdate> GetValuesFromPageAsync(ClientResult page)
|
||||
{
|
||||
var updates = ((ClientResult<IAsyncEnumerable<AgentRunResponseUpdate>>)page).Value;
|
||||
var updates = ((ClientResult<IAsyncEnumerable<AgentResponseUpdate>>)page).Value;
|
||||
|
||||
return updates.AsChatResponseUpdatesAsync().AsOpenAIStreamingChatCompletionUpdatesAsync();
|
||||
}
|
||||
|
||||
+3
-3
@@ -7,9 +7,9 @@ namespace Microsoft.Agents.AI.OpenAI;
|
||||
|
||||
internal sealed class AsyncStreamingResponseUpdateCollectionResult : AsyncCollectionResult<StreamingResponseUpdate>
|
||||
{
|
||||
private readonly IAsyncEnumerable<AgentRunResponseUpdate> _updates;
|
||||
private readonly IAsyncEnumerable<AgentResponseUpdate> _updates;
|
||||
|
||||
internal AsyncStreamingResponseUpdateCollectionResult(IAsyncEnumerable<AgentRunResponseUpdate> updates)
|
||||
internal AsyncStreamingResponseUpdateCollectionResult(IAsyncEnumerable<AgentResponseUpdate> updates)
|
||||
{
|
||||
this._updates = updates;
|
||||
}
|
||||
@@ -23,7 +23,7 @@ internal sealed class AsyncStreamingResponseUpdateCollectionResult : AsyncCollec
|
||||
|
||||
protected async override IAsyncEnumerable<StreamingResponseUpdate> GetValuesFromPageAsync(ClientResult page)
|
||||
{
|
||||
var updates = ((ClientResult<IAsyncEnumerable<AgentRunResponseUpdate>>)page).Value;
|
||||
var updates = ((ClientResult<IAsyncEnumerable<AgentResponseUpdate>>)page).Value;
|
||||
|
||||
await foreach (var update in updates.ConfigureAwait(false))
|
||||
{
|
||||
|
||||
@@ -55,7 +55,7 @@ internal sealed class StreamingUpdatePipelineResponse : PipelineResponse
|
||||
// No resources to dispose.
|
||||
}
|
||||
|
||||
internal StreamingUpdatePipelineResponse(IAsyncEnumerable<AgentRunResponseUpdate> updates)
|
||||
internal StreamingUpdatePipelineResponse(IAsyncEnumerable<AgentResponseUpdate> updates)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ namespace Microsoft.Agents.AI;
|
||||
/// These extensions bridge the gap between the Microsoft Extensions AI framework and the OpenAI SDK,
|
||||
/// allowing developers to work with native OpenAI types while leveraging the AI Agent framework.
|
||||
/// The methods handle the conversion between OpenAI chat message types and Microsoft Extensions AI types,
|
||||
/// and return OpenAI <see cref="ChatCompletion"/> objects directly from the agent's <see cref="AgentRunResponse"/>.
|
||||
/// and return OpenAI <see cref="ChatCompletion"/> objects directly from the agent's <see cref="AgentResponse"/>.
|
||||
/// </remarks>
|
||||
public static class AIAgentWithOpenAIExtensions
|
||||
{
|
||||
@@ -34,7 +34,7 @@ public static class AIAgentWithOpenAIExtensions
|
||||
/// <exception cref="NotSupportedException">Thrown when any message in <paramref name="messages"/> has a type that is not supported by the message conversion method.</exception>
|
||||
/// <remarks>
|
||||
/// This method converts the OpenAI chat messages to the Microsoft Extensions AI format using the appropriate conversion method,
|
||||
/// runs the agent with the converted message collection, and then extracts the native OpenAI <see cref="ChatCompletion"/> from the response using <see cref="AgentRunResponseExtensions.AsOpenAIChatCompletion"/>.
|
||||
/// runs the agent with the converted message collection, and then extracts the native OpenAI <see cref="ChatCompletion"/> from the response using <see cref="AgentResponseExtensions.AsOpenAIChatCompletion"/>.
|
||||
/// </remarks>
|
||||
public static async Task<ChatCompletion> RunAsync(this AIAgent agent, IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -60,14 +60,14 @@ public static class AIAgentWithOpenAIExtensions
|
||||
/// <exception cref="NotSupportedException">Thrown when the <paramref name="messages"/> type is not supported by the message conversion method.</exception>
|
||||
/// <remarks>
|
||||
/// This method converts the OpenAI chat messages to the Microsoft Extensions AI format using the appropriate conversion method,
|
||||
/// runs the agent, and then extracts the native OpenAI <see cref="ChatCompletion"/> from the response using <see cref="AgentRunResponseExtensions.AsOpenAIChatCompletion"/>.
|
||||
/// runs the agent, and then extracts the native OpenAI <see cref="ChatCompletion"/> from the response using <see cref="AgentResponseExtensions.AsOpenAIChatCompletion"/>.
|
||||
/// </remarks>
|
||||
public static AsyncCollectionResult<StreamingChatCompletionUpdate> RunStreamingAsync(this AIAgent agent, IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(agent);
|
||||
Throw.IfNull(messages);
|
||||
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> response = agent.RunStreamingAsync([.. messages.AsChatMessages()], thread, options, cancellationToken);
|
||||
IAsyncEnumerable<AgentResponseUpdate> response = agent.RunStreamingAsync([.. messages.AsChatMessages()], thread, options, cancellationToken);
|
||||
|
||||
return new AsyncStreamingChatCompletionUpdateCollectionResult(response);
|
||||
}
|
||||
@@ -86,7 +86,7 @@ public static class AIAgentWithOpenAIExtensions
|
||||
/// <exception cref="NotSupportedException">Thrown when any message in <paramref name="messages"/> has a type that is not supported by the message conversion method.</exception>
|
||||
/// <remarks>
|
||||
/// This method converts the OpenAI response items to the Microsoft Extensions AI format using the appropriate conversion method,
|
||||
/// runs the agent with the converted message collection, and then extracts the native OpenAI <see cref="ResponseResult"/> from the response using <see cref="AgentRunResponseExtensions.AsOpenAIResponse"/>.
|
||||
/// runs the agent with the converted message collection, and then extracts the native OpenAI <see cref="ResponseResult"/> from the response using <see cref="AgentResponseExtensions.AsOpenAIResponse"/>.
|
||||
/// </remarks>
|
||||
public static async Task<ResponseResult> RunAsync(this AIAgent agent, IEnumerable<ResponseItem> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
@@ -121,7 +121,7 @@ public static class AIAgentWithOpenAIExtensions
|
||||
Throw.IfNull(agent);
|
||||
Throw.IfNull(messages);
|
||||
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> response = agent.RunStreamingAsync([.. messages.AsChatMessages()], thread, options, cancellationToken);
|
||||
IAsyncEnumerable<AgentResponseUpdate> response = agent.RunStreamingAsync([.. messages.AsChatMessages()], thread, options, cancellationToken);
|
||||
|
||||
return new AsyncStreamingResponseUpdateCollectionResult(response);
|
||||
}
|
||||
|
||||
+6
-6
@@ -8,18 +8,18 @@ using OpenAI.Responses;
|
||||
namespace Microsoft.Agents.AI;
|
||||
|
||||
/// <summary>
|
||||
/// Provides extension methods for <see cref="AgentRunResponse"/> and <see cref="AgentRunResponseUpdate"/> instances to
|
||||
/// Provides extension methods for <see cref="AgentResponse"/> and <see cref="AgentResponseUpdate"/> instances to
|
||||
/// create or extract native OpenAI response objects from the Microsoft Agent Framework responses.
|
||||
/// </summary>
|
||||
public static class AgentRunResponseExtensions
|
||||
public static class AgentResponseExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates or extracts a native OpenAI <see cref="ChatCompletion"/> object from an <see cref="AgentRunResponse"/>.
|
||||
/// Creates or extracts a native OpenAI <see cref="ChatCompletion"/> object from an <see cref="AgentResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="response">The agent response.</param>
|
||||
/// <returns>The OpenAI <see cref="ChatCompletion"/> object.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
public static ChatCompletion AsOpenAIChatCompletion(this AgentRunResponse response)
|
||||
public static ChatCompletion AsOpenAIChatCompletion(this AgentResponse response)
|
||||
{
|
||||
Throw.IfNull(response);
|
||||
|
||||
@@ -29,12 +29,12 @@ public static class AgentRunResponseExtensions
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates or extracts a native OpenAI <see cref="ResponseResult"/> object from an <see cref="AgentRunResponse"/>.
|
||||
/// Creates or extracts a native OpenAI <see cref="ResponseResult"/> object from an <see cref="AgentResponse"/>.
|
||||
/// </summary>
|
||||
/// <param name="response">The agent response.</param>
|
||||
/// <returns>The OpenAI <see cref="ResponseResult"/> object.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
public static ResponseResult AsOpenAIResponse(this AgentRunResponse response)
|
||||
public static ResponseResult AsOpenAIResponse(this AgentResponse response)
|
||||
{
|
||||
Throw.IfNull(response);
|
||||
|
||||
@@ -42,16 +42,16 @@ internal class PurviewAgent : AIAgent, IDisposable
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
protected override Task<AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return this._purviewWrapper.ProcessAgentContentAsync(messages, thread, options, this._innerAgent, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = await this._purviewWrapper.ProcessAgentContentAsync(messages, thread, options, this._innerAgent, cancellationToken).ConfigureAwait(false);
|
||||
foreach (var update in response.ToAgentRunResponseUpdates())
|
||||
foreach (var update in response.ToAgentResponseUpdates())
|
||||
{
|
||||
yield return update;
|
||||
}
|
||||
|
||||
@@ -134,7 +134,7 @@ internal sealed class PurviewWrapper : IDisposable
|
||||
/// <param name="innerAgent">The wrapped agent.</param>
|
||||
/// <param name="cancellationToken">The cancellation token used to interrupt async operations.</param>
|
||||
/// <returns>The agent's response. This could be the response from the agent or a message indicating that Purview has blocked the prompt or response.</returns>
|
||||
public async Task<AgentRunResponse> ProcessAgentContentAsync(IEnumerable<ChatMessage> messages, AgentThread? thread, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken)
|
||||
public async Task<AgentResponse> ProcessAgentContentAsync(IEnumerable<ChatMessage> messages, AgentThread? thread, AgentRunOptions? options, AIAgent innerAgent, CancellationToken cancellationToken)
|
||||
{
|
||||
string threadId = GetThreadIdFromAgentThread(thread, messages);
|
||||
|
||||
@@ -151,7 +151,7 @@ internal sealed class PurviewWrapper : IDisposable
|
||||
this._logger.LogInformation("Prompt blocked by policy. Sending message: {Message}", this._purviewSettings.BlockedPromptMessage);
|
||||
}
|
||||
|
||||
return new AgentRunResponse(new ChatMessage(ChatRole.System, this._purviewSettings.BlockedPromptMessage));
|
||||
return new AgentResponse(new ChatMessage(ChatRole.System, this._purviewSettings.BlockedPromptMessage));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
@@ -167,7 +167,7 @@ internal sealed class PurviewWrapper : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
AgentRunResponse response = await innerAgent.RunAsync(messages, thread, options, cancellationToken).ConfigureAwait(false);
|
||||
AgentResponse response = await innerAgent.RunAsync(messages, thread, options, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -180,7 +180,7 @@ internal sealed class PurviewWrapper : IDisposable
|
||||
this._logger.LogInformation("Response blocked by policy. Sending message: {Message}", this._purviewSettings.BlockedResponseMessage);
|
||||
}
|
||||
|
||||
return new AgentRunResponse(new ChatMessage(ChatRole.System, this._purviewSettings.BlockedResponseMessage));
|
||||
return new AgentResponse(new ChatMessage(ChatRole.System, this._purviewSettings.BlockedResponseMessage));
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
||||
@@ -211,7 +211,7 @@ The policy logic is identical; the only difference is the hook point in the pipe
|
||||
|
||||
## Middleware Lifecycle
|
||||
1. Before sending the prompt to the agent, the middleware checks the app and user metadata against Purview's protection scopes and evaluates all the `ChatMessage`s in the prompt.
|
||||
2. If the content was blocked, the middleware returns a `ChatResponse` or `AgentRunResponse` containing the `BlockedPromptMessage` text. The blocked content does not get passed to the agent.
|
||||
2. If the content was blocked, the middleware returns a `ChatResponse` or `AgentResponse` containing the `BlockedPromptMessage` text. The blocked content does not get passed to the agent.
|
||||
3. If the evaluation did not block the content, the middleware passes the prompt data to the agent and waits for a response.
|
||||
4. After receiving a response from the agent, the middleware calls Purview again to evaluate the response content.
|
||||
5. If the content was blocked, the middleware returns a response containing the `BlockedResponseMessage`.
|
||||
|
||||
@@ -90,7 +90,7 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override async IAsyncEnumerable<AgentRunResponseUpdate> InvokeAgentAsync(
|
||||
public override async IAsyncEnumerable<AgentResponseUpdate> InvokeAgentAsync(
|
||||
string agentId,
|
||||
string? agentVersion,
|
||||
string? conversationId,
|
||||
@@ -120,12 +120,12 @@ public sealed class AzureAgentProvider(Uri projectEndpoint, TokenCredential proj
|
||||
|
||||
ChatClientAgentRunOptions runOptions = new(chatOptions);
|
||||
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> agentResponse =
|
||||
IAsyncEnumerable<AgentResponseUpdate> agentResponse =
|
||||
messages is not null ?
|
||||
agent.RunStreamingAsync([.. messages], null, runOptions, cancellationToken) :
|
||||
agent.RunStreamingAsync([new ChatMessage(ChatRole.User, string.Empty)], null, runOptions, cancellationToken);
|
||||
|
||||
await foreach (AgentRunResponseUpdate update in agentResponse.ConfigureAwait(false))
|
||||
await foreach (AgentResponseUpdate update in agentResponse.ConfigureAwait(false))
|
||||
{
|
||||
update.AuthorName = agentVersionResult.Name;
|
||||
yield return update;
|
||||
|
||||
+1
-1
@@ -64,7 +64,7 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
EvaluateListExpression<ChatMessage>(this.Model.Input?.Messages, "inputMessages");
|
||||
this.Write(@"
|
||||
|
||||
AgentRunResponse agentResponse =
|
||||
AgentResponse agentResponse =
|
||||
await InvokeAgentAsync(
|
||||
context,
|
||||
agentName,
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ internal sealed class <#= this.Name #>Executor(FormulaSession session, WorkflowA
|
||||
EvaluateBoolExpression(this.Model.Output?.AutoSend, "autoSend", defaultValue: true);
|
||||
EvaluateListExpression<ChatMessage>(this.Model.Input?.Messages, "inputMessages");#>
|
||||
|
||||
AgentRunResponse agentResponse =
|
||||
AgentResponse agentResponse =
|
||||
await InvokeAgentAsync(
|
||||
context,
|
||||
agentName,
|
||||
|
||||
+1
-1
@@ -71,7 +71,7 @@ if (this.Model.Activity is MessageActivityTemplate messageActivity)
|
||||
|
||||
}
|
||||
|
||||
this.Write("\n );\n AgentRunResponse response = new([new ChatMessage(ChatRole" +
|
||||
this.Write("\n );\n AgentResponse response = new([new ChatMessage(ChatRole" +
|
||||
".Assistant, activityText)]);\n await context.AddEventAsync(new AgentRunRes" +
|
||||
"ponseEvent(this.Id, response)).ConfigureAwait(false);");
|
||||
|
||||
|
||||
+1
-1
@@ -25,7 +25,7 @@ if (this.Model.Activity is MessageActivityTemplate messageActivity)
|
||||
}
|
||||
#>
|
||||
);
|
||||
AgentRunResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]);
|
||||
AgentResponse response = new([new ChatMessage(ChatRole.Assistant, activityText)]);
|
||||
await context.AddEventAsync(new AgentRunResponseEvent(this.Id, response)).ConfigureAwait(false);<#
|
||||
} #>
|
||||
|
||||
|
||||
@@ -13,21 +13,21 @@ public sealed class ExternalInputRequest
|
||||
/// <summary>
|
||||
/// The source message that triggered the request for external input.
|
||||
/// </summary>
|
||||
public AgentRunResponse AgentResponse { get; }
|
||||
public AgentResponse AgentResponse { get; }
|
||||
|
||||
[JsonConstructor]
|
||||
internal ExternalInputRequest(AgentRunResponse agentResponse)
|
||||
internal ExternalInputRequest(AgentResponse agentResponse)
|
||||
{
|
||||
this.AgentResponse = agentResponse;
|
||||
}
|
||||
|
||||
internal ExternalInputRequest(ChatMessage message)
|
||||
{
|
||||
this.AgentResponse = new AgentRunResponse(message);
|
||||
this.AgentResponse = new AgentResponse(message);
|
||||
}
|
||||
|
||||
internal ExternalInputRequest(string text)
|
||||
{
|
||||
this.AgentResponse = new AgentRunResponse(new ChatMessage(ChatRole.User, text));
|
||||
this.AgentResponse = new AgentResponse(new ChatMessage(ChatRole.User, text));
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -9,7 +9,7 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.Extensions;
|
||||
|
||||
internal static class AgentProviderExtensions
|
||||
{
|
||||
public static async ValueTask<AgentRunResponse> InvokeAgentAsync(
|
||||
public static async ValueTask<AgentResponse> InvokeAgentAsync(
|
||||
this WorkflowAgentProvider agentProvider,
|
||||
string executorId,
|
||||
IWorkflowContext context,
|
||||
@@ -20,15 +20,15 @@ internal static class AgentProviderExtensions
|
||||
IDictionary<string, object?>? inputArguments = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> agentUpdates = agentProvider.InvokeAgentAsync(agentName, null, conversationId, inputMessages, inputArguments, cancellationToken);
|
||||
IAsyncEnumerable<AgentResponseUpdate> agentUpdates = agentProvider.InvokeAgentAsync(agentName, null, conversationId, inputMessages, inputArguments, cancellationToken);
|
||||
|
||||
// Enable "autoSend" behavior if this is the workflow conversation.
|
||||
bool isWorkflowConversation = context.IsWorkflowConversation(conversationId, out string? workflowConversationId);
|
||||
autoSend |= isWorkflowConversation;
|
||||
|
||||
// Process the agent response updates.
|
||||
List<AgentRunResponseUpdate> updates = [];
|
||||
await foreach (AgentRunResponseUpdate update in agentUpdates.ConfigureAwait(false))
|
||||
List<AgentResponseUpdate> updates = [];
|
||||
await foreach (AgentResponseUpdate update in agentUpdates.ConfigureAwait(false))
|
||||
{
|
||||
await AssignConversationIdAsync(((ChatResponseUpdate?)update.RawRepresentation)?.ConversationId).ConfigureAwait(false);
|
||||
|
||||
@@ -40,7 +40,7 @@ internal static class AgentProviderExtensions
|
||||
}
|
||||
}
|
||||
|
||||
AgentRunResponse response = updates.ToAgentRunResponse();
|
||||
AgentResponse response = updates.ToAgentResponse();
|
||||
|
||||
if (autoSend)
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@ public abstract class AgentExecutor(string id, FormulaSession session, WorkflowA
|
||||
/// <param name="inputMessages">Optional messages to add to the conversation prior to invocation.</param>
|
||||
/// <param name="cancellationToken">A token that can be used to observe cancellation.</param>
|
||||
/// <returns></returns>
|
||||
protected ValueTask<AgentRunResponse> InvokeAgentAsync(
|
||||
protected ValueTask<AgentResponse> InvokeAgentAsync(
|
||||
IWorkflowContext context,
|
||||
string agentName,
|
||||
string? conversationId,
|
||||
|
||||
+1
-1
@@ -30,7 +30,7 @@ internal sealed class AddConversationMessageExecutor(AddConversationMessage mode
|
||||
|
||||
if (isWorkflowConversation)
|
||||
{
|
||||
await context.AddEventAsync(new AgentRunResponseEvent(this.Id, new AgentRunResponse(newMessage)), cancellationToken).ConfigureAwait(false);
|
||||
await context.AddEventAsync(new AgentRunResponseEvent(this.Id, new AgentResponse(newMessage)), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
return default;
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ internal sealed class CopyConversationMessagesExecutor(CopyConversationMessages
|
||||
|
||||
if (isWorkflowConversation)
|
||||
{
|
||||
await context.AddEventAsync(new AgentRunResponseEvent(this.Id, new AgentRunResponse([.. inputMessages])), cancellationToken).ConfigureAwait(false);
|
||||
await context.AddEventAsync(new AgentRunResponseEvent(this.Id, new AgentResponse([.. inputMessages])), cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+3
-3
@@ -61,12 +61,12 @@ internal sealed class InvokeAzureAgentExecutor(InvokeAzureAgent model, WorkflowA
|
||||
string agentName = this.GetAgentName();
|
||||
bool autoSend = this.GetAutoSendValue();
|
||||
Dictionary<string, object?>? inputParameters = this.GetStructuredInputs();
|
||||
AgentRunResponse agentResponse = await agentProvider.InvokeAgentAsync(this.Id, context, agentName, conversationId, autoSend, messages, inputParameters, cancellationToken).ConfigureAwait(false);
|
||||
AgentResponse agentResponse = await agentProvider.InvokeAgentAsync(this.Id, context, agentName, conversationId, autoSend, messages, inputParameters, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
ChatMessage[] actionableMessages = FilterActionableContent(agentResponse).ToArray();
|
||||
if (actionableMessages.Length > 0)
|
||||
{
|
||||
AgentRunResponse filteredResponse =
|
||||
AgentResponse filteredResponse =
|
||||
new(actionableMessages)
|
||||
{
|
||||
AdditionalProperties = agentResponse.AdditionalProperties,
|
||||
@@ -137,7 +137,7 @@ internal sealed class InvokeAzureAgentExecutor(InvokeAzureAgent model, WorkflowA
|
||||
return userInput?.ToChatMessages();
|
||||
}
|
||||
|
||||
private static IEnumerable<ChatMessage> FilterActionableContent(AgentRunResponse agentResponse)
|
||||
private static IEnumerable<ChatMessage> FilterActionableContent(AgentResponse agentResponse)
|
||||
{
|
||||
HashSet<string> functionResultIds =
|
||||
[.. agentResponse.Messages
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ internal sealed class RequestExternalInputExecutor(RequestExternalInput model, W
|
||||
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ExternalInputRequest inputRequest = new(new AgentRunResponse());
|
||||
ExternalInputRequest inputRequest = new(new AgentResponse());
|
||||
|
||||
await context.SendMessageAsync(inputRequest, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
||||
@@ -91,8 +91,8 @@ public abstract class WorkflowAgentProvider
|
||||
/// <param name="messages">The messages to include in the invocation.</param>
|
||||
/// <param name="inputArguments">Optional input arguments for agents that provide support.</param>
|
||||
/// <param name="cancellationToken">A token that propagates notification when operation should be canceled.</param>
|
||||
/// <returns>Asynchronous set of <see cref="AgentRunResponseUpdate"/>.</returns>
|
||||
public abstract IAsyncEnumerable<AgentRunResponseUpdate> InvokeAgentAsync(
|
||||
/// <returns>Asynchronous set of <see cref="AgentResponseUpdate"/>.</returns>
|
||||
public abstract IAsyncEnumerable<AgentResponseUpdate> InvokeAgentAsync(
|
||||
string agentId,
|
||||
string? agentVersion,
|
||||
string? conversationId,
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Microsoft.Agents.AI.Workflows;
|
||||
|
||||
internal static class AIAgentsAbstractionsExtensions
|
||||
{
|
||||
public static ChatMessage ToChatMessage(this AgentRunResponseUpdate update) =>
|
||||
public static ChatMessage ToChatMessage(this AgentResponseUpdate update) =>
|
||||
new()
|
||||
{
|
||||
AuthorName = update.AuthorName,
|
||||
|
||||
@@ -14,7 +14,7 @@ public class AgentRunResponseEvent : ExecutorEvent
|
||||
/// </summary>
|
||||
/// <param name="executorId">The identifier of the executor that generated this event.</param>
|
||||
/// <param name="response">The agent run response.</param>
|
||||
public AgentRunResponseEvent(string executorId, AgentRunResponse response) : base(executorId, data: response)
|
||||
public AgentRunResponseEvent(string executorId, AgentResponse response) : base(executorId, data: response)
|
||||
{
|
||||
this.Response = Throw.IfNull(response);
|
||||
}
|
||||
@@ -22,5 +22,5 @@ public class AgentRunResponseEvent : ExecutorEvent
|
||||
/// <summary>
|
||||
/// Gets the agent run response.
|
||||
/// </summary>
|
||||
public AgentRunResponse Response { get; }
|
||||
public AgentResponse Response { get; }
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ public class AgentRunUpdateEvent : ExecutorEvent
|
||||
/// </summary>
|
||||
/// <param name="executorId">The identifier of the executor that generated this event.</param>
|
||||
/// <param name="update">The agent run response update.</param>
|
||||
public AgentRunUpdateEvent(string executorId, AgentRunResponseUpdate update) : base(executorId, data: update)
|
||||
public AgentRunUpdateEvent(string executorId, AgentResponseUpdate update) : base(executorId, data: update)
|
||||
{
|
||||
this.Update = Throw.IfNull(update);
|
||||
}
|
||||
@@ -23,15 +23,15 @@ public class AgentRunUpdateEvent : ExecutorEvent
|
||||
/// <summary>
|
||||
/// Gets the agent run response update.
|
||||
/// </summary>
|
||||
public AgentRunResponseUpdate Update { get; }
|
||||
public AgentResponseUpdate Update { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Converts this event to an <see cref="AgentRunResponse"/> containing just this update.
|
||||
/// Converts this event to an <see cref="AgentResponse"/> containing just this update.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public AgentRunResponse AsResponse()
|
||||
public AgentResponse AsResponse()
|
||||
{
|
||||
IEnumerable<AgentRunResponseUpdate> updates = [this.Update];
|
||||
return updates.ToAgentRunResponse();
|
||||
IEnumerable<AgentResponseUpdate> updates = [this.Update];
|
||||
return updates.ToAgentResponse();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,10 @@ internal sealed class MessageMerger
|
||||
{
|
||||
public string? ResponseId { get; } = responseId;
|
||||
|
||||
public Dictionary<string, List<AgentRunResponseUpdate>> UpdatesByMessageId { get; } = [];
|
||||
public List<AgentRunResponseUpdate> DanglingUpdates { get; } = [];
|
||||
public Dictionary<string, List<AgentResponseUpdate>> UpdatesByMessageId { get; } = [];
|
||||
public List<AgentResponseUpdate> DanglingUpdates { get; } = [];
|
||||
|
||||
public void AddUpdate(AgentRunResponseUpdate update)
|
||||
public void AddUpdate(AgentResponseUpdate update)
|
||||
{
|
||||
if (update.MessageId is null)
|
||||
{
|
||||
@@ -25,7 +25,7 @@ internal sealed class MessageMerger
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!this.UpdatesByMessageId.TryGetValue(update.MessageId, out List<AgentRunResponseUpdate>? updates))
|
||||
if (!this.UpdatesByMessageId.TryGetValue(update.MessageId, out List<AgentResponseUpdate>? updates))
|
||||
{
|
||||
this.UpdatesByMessageId[update.MessageId] = updates = [];
|
||||
}
|
||||
@@ -34,24 +34,24 @@ internal sealed class MessageMerger
|
||||
}
|
||||
}
|
||||
|
||||
public AgentRunResponse ComputeMerged(string messageId)
|
||||
public AgentResponse ComputeMerged(string messageId)
|
||||
{
|
||||
if (this.UpdatesByMessageId.TryGetValue(Throw.IfNull(messageId), out List<AgentRunResponseUpdate>? updates))
|
||||
if (this.UpdatesByMessageId.TryGetValue(Throw.IfNull(messageId), out List<AgentResponseUpdate>? updates))
|
||||
{
|
||||
return updates.ToAgentRunResponse();
|
||||
return updates.ToAgentResponse();
|
||||
}
|
||||
|
||||
throw new KeyNotFoundException($"No updates found for message ID '{messageId}' in response '{this.ResponseId}'.");
|
||||
}
|
||||
|
||||
public AgentRunResponse ComputeDangling()
|
||||
public AgentResponse ComputeDangling()
|
||||
{
|
||||
if (this.DanglingUpdates.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException("No dangling updates to compute a response from.");
|
||||
}
|
||||
|
||||
return this.DanglingUpdates.ToAgentRunResponse();
|
||||
return this.DanglingUpdates.ToAgentResponse();
|
||||
}
|
||||
|
||||
public List<ChatMessage> ComputeFlattened()
|
||||
@@ -66,7 +66,7 @@ internal sealed class MessageMerger
|
||||
|
||||
IList<ChatMessage> AggregateUpdatesToMessage(string messageId)
|
||||
{
|
||||
List<AgentRunResponseUpdate> updates = this.UpdatesByMessageId[messageId];
|
||||
List<AgentResponseUpdate> updates = this.UpdatesByMessageId[messageId];
|
||||
if (updates.Count == 0)
|
||||
{
|
||||
throw new InvalidOperationException($"No updates found for message ID '{messageId}' in response '{this.ResponseId}'.");
|
||||
@@ -80,7 +80,7 @@ internal sealed class MessageMerger
|
||||
private readonly Dictionary<string, ResponseMergeState> _mergeStates = [];
|
||||
private readonly ResponseMergeState _danglingState = new(null);
|
||||
|
||||
public void AddUpdate(AgentRunResponseUpdate update)
|
||||
public void AddUpdate(AgentResponseUpdate update)
|
||||
{
|
||||
if (update.ResponseId is null)
|
||||
{
|
||||
@@ -97,7 +97,7 @@ internal sealed class MessageMerger
|
||||
}
|
||||
}
|
||||
|
||||
private int CompareByDateTimeOffset(AgentRunResponse left, AgentRunResponse right)
|
||||
private int CompareByDateTimeOffset(AgentResponse left, AgentResponse right)
|
||||
{
|
||||
const int LESS = -1, EQ = 0, GREATER = 1;
|
||||
|
||||
@@ -119,17 +119,17 @@ internal sealed class MessageMerger
|
||||
return left.CreatedAt.Value.CompareTo(right.CreatedAt.Value);
|
||||
}
|
||||
|
||||
public AgentRunResponse ComputeMerged(string primaryResponseId, string? primaryAgentId = null, string? primaryAgentName = null)
|
||||
public AgentResponse ComputeMerged(string primaryResponseId, string? primaryAgentId = null, string? primaryAgentName = null)
|
||||
{
|
||||
List<ChatMessage> messages = [];
|
||||
Dictionary<string, AgentRunResponse> responses = [];
|
||||
Dictionary<string, AgentResponse> responses = [];
|
||||
HashSet<string> agentIds = [];
|
||||
|
||||
foreach (string responseId in this._mergeStates.Keys)
|
||||
{
|
||||
ResponseMergeState mergeState = this._mergeStates[responseId];
|
||||
|
||||
List<AgentRunResponse> responseList = mergeState.UpdatesByMessageId.Keys.Select(mergeState.ComputeMerged).ToList();
|
||||
List<AgentResponse> responseList = mergeState.UpdatesByMessageId.Keys.Select(mergeState.ComputeMerged).ToList();
|
||||
if (mergeState.DanglingUpdates.Count > 0)
|
||||
{
|
||||
responseList.Add(mergeState.ComputeDangling());
|
||||
@@ -144,7 +144,7 @@ internal sealed class MessageMerger
|
||||
AdditionalPropertiesDictionary? additionalProperties = null;
|
||||
HashSet<DateTimeOffset> createdTimes = [];
|
||||
|
||||
foreach (AgentRunResponse response in responses.Values)
|
||||
foreach (AgentResponse response in responses.Values)
|
||||
{
|
||||
if (response.AgentId is not null)
|
||||
{
|
||||
@@ -176,7 +176,7 @@ internal sealed class MessageMerger
|
||||
}
|
||||
messages.RemoveAll(m => m.Contents.Count == 0);
|
||||
|
||||
return new AgentRunResponse(messages)
|
||||
return new AgentResponse(messages)
|
||||
{
|
||||
ResponseId = primaryResponseId,
|
||||
AgentId = primaryAgentId
|
||||
@@ -187,7 +187,7 @@ internal sealed class MessageMerger
|
||||
AdditionalProperties = additionalProperties
|
||||
};
|
||||
|
||||
static AgentRunResponse MergeResponses(AgentRunResponse? current, AgentRunResponse incoming)
|
||||
static AgentResponse MergeResponses(AgentResponse? current, AgentResponse incoming)
|
||||
{
|
||||
if (current is null)
|
||||
{
|
||||
@@ -214,7 +214,7 @@ internal sealed class MessageMerger
|
||||
};
|
||||
}
|
||||
|
||||
static IEnumerable<ChatMessage> GetMessagesWithCreatedAt(AgentRunResponse response)
|
||||
static IEnumerable<ChatMessage> GetMessagesWithCreatedAt(AgentResponse response)
|
||||
{
|
||||
if (response.Messages.Count == 0)
|
||||
{
|
||||
|
||||
@@ -54,14 +54,14 @@ internal sealed class AIAgentHostExecutor : ChatProtocolExecutor
|
||||
if (emitEvents ?? this._emitEvents)
|
||||
{
|
||||
// Run the agent in streaming mode only when agent run update events are to be emitted.
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> agentStream = this._agent.RunStreamingAsync(
|
||||
IAsyncEnumerable<AgentResponseUpdate> agentStream = this._agent.RunStreamingAsync(
|
||||
messages,
|
||||
await this.EnsureThreadAsync(context, cancellationToken).ConfigureAwait(false),
|
||||
cancellationToken: cancellationToken);
|
||||
|
||||
List<AgentRunResponseUpdate> updates = [];
|
||||
List<AgentResponseUpdate> updates = [];
|
||||
|
||||
await foreach (AgentRunResponseUpdate update in agentStream.ConfigureAwait(false))
|
||||
await foreach (AgentResponseUpdate update in agentStream.ConfigureAwait(false))
|
||||
{
|
||||
await context.AddEventAsync(new AgentRunUpdateEvent(this.Id, update), cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -72,12 +72,12 @@ internal sealed class AIAgentHostExecutor : ChatProtocolExecutor
|
||||
updates.Add(update);
|
||||
}
|
||||
|
||||
await context.SendMessageAsync(updates.ToAgentRunResponse().Messages, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
await context.SendMessageAsync(updates.ToAgentResponse().Messages, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Otherwise, run the agent in non-streaming mode.
|
||||
AgentRunResponse response = await this._agent.RunAsync(
|
||||
AgentResponse response = await this._agent.RunAsync(
|
||||
messages,
|
||||
await this.EnsureThreadAsync(context, cancellationToken).ConfigureAwait(false),
|
||||
cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
@@ -22,7 +22,7 @@ internal sealed class AgentRunStreamingExecutor(AIAgent agent, bool includeInput
|
||||
{
|
||||
List<ChatMessage>? roleChanged = messages.ChangeAssistantToUserForOtherParticipants(agent.Name ?? agent.Id);
|
||||
|
||||
List<AgentRunResponseUpdate> updates = [];
|
||||
List<AgentResponseUpdate> updates = [];
|
||||
await foreach (var update in agent.RunStreamingAsync(messages, cancellationToken: cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
updates.Add(update);
|
||||
@@ -35,7 +35,7 @@ internal sealed class AgentRunStreamingExecutor(AIAgent agent, bool includeInput
|
||||
roleChanged.ResetUserToAssistantForChangedRoles();
|
||||
|
||||
List<ChatMessage> result = includeInputInOutput ? [.. messages] : [];
|
||||
result.AddRange(updates.ToAgentRunResponse().Messages);
|
||||
result.AddRange(updates.ToAgentResponse().Messages);
|
||||
|
||||
await context.SendMessageAsync(result, cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ internal sealed class HandoffAgentExecutor(
|
||||
routeBuilder.AddHandler<HandoffState>(async (handoffState, context, cancellationToken) =>
|
||||
{
|
||||
string? requestedHandoff = null;
|
||||
List<AgentRunResponseUpdate> updates = [];
|
||||
List<AgentResponseUpdate> updates = [];
|
||||
List<ChatMessage> allMessages = handoffState.Messages;
|
||||
|
||||
List<ChatMessage>? roleChanges = allMessages.ChangeAssistantToUserForOtherParticipants(this._agent.Name ?? this._agent.Id);
|
||||
@@ -82,7 +82,7 @@ internal sealed class HandoffAgentExecutor(
|
||||
{
|
||||
requestedHandoff = fcc.Name;
|
||||
await AddUpdateAsync(
|
||||
new AgentRunResponseUpdate
|
||||
new AgentResponseUpdate
|
||||
{
|
||||
AgentId = this._agent.Id,
|
||||
AuthorName = this._agent.Name ?? this._agent.Id,
|
||||
@@ -98,13 +98,13 @@ internal sealed class HandoffAgentExecutor(
|
||||
}
|
||||
}
|
||||
|
||||
allMessages.AddRange(updates.ToAgentRunResponse().Messages);
|
||||
allMessages.AddRange(updates.ToAgentResponse().Messages);
|
||||
|
||||
roleChanges.ResetUserToAssistantForChangedRoles();
|
||||
|
||||
await context.SendMessageAsync(new HandoffState(handoffState.TurnToken, requestedHandoff, allMessages), cancellationToken: cancellationToken).ConfigureAwait(false);
|
||||
|
||||
async Task AddUpdateAsync(AgentRunResponseUpdate update, CancellationToken cancellationToken)
|
||||
async Task AddUpdateAsync(AgentResponseUpdate update, CancellationToken cancellationToken)
|
||||
{
|
||||
updates.Add(update);
|
||||
if (handoffState.TurnToken.EmitEvents is true)
|
||||
|
||||
@@ -85,7 +85,7 @@ internal sealed class WorkflowHostAgent : AIAgent
|
||||
}
|
||||
|
||||
protected override async
|
||||
Task<AgentRunResponse> RunCoreAsync(
|
||||
Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -96,7 +96,7 @@ internal sealed class WorkflowHostAgent : AIAgent
|
||||
WorkflowThread workflowThread = await this.UpdateThreadAsync(messages, thread, cancellationToken).ConfigureAwait(false);
|
||||
MessageMerger merger = new();
|
||||
|
||||
await foreach (AgentRunResponseUpdate update in workflowThread.InvokeStageAsync(cancellationToken)
|
||||
await foreach (AgentResponseUpdate update in workflowThread.InvokeStageAsync(cancellationToken)
|
||||
.ConfigureAwait(false)
|
||||
.WithCancellation(cancellationToken))
|
||||
{
|
||||
@@ -107,7 +107,7 @@ internal sealed class WorkflowHostAgent : AIAgent
|
||||
}
|
||||
|
||||
protected override async
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -116,7 +116,7 @@ internal sealed class WorkflowHostAgent : AIAgent
|
||||
await this.ValidateWorkflowAsync().ConfigureAwait(false);
|
||||
|
||||
WorkflowThread workflowThread = await this.UpdateThreadAsync(messages, thread, cancellationToken).ConfigureAwait(false);
|
||||
await foreach (AgentRunResponseUpdate update in workflowThread.InvokeStageAsync(cancellationToken)
|
||||
await foreach (AgentResponseUpdate update in workflowThread.InvokeStageAsync(cancellationToken)
|
||||
.ConfigureAwait(false)
|
||||
.WithCancellation(cancellationToken))
|
||||
{
|
||||
|
||||
@@ -83,11 +83,11 @@ internal sealed class WorkflowThread : AgentThread
|
||||
return marshaller.Marshal(info);
|
||||
}
|
||||
|
||||
public AgentRunResponseUpdate CreateUpdate(string responseId, object raw, params AIContent[] parts)
|
||||
public AgentResponseUpdate CreateUpdate(string responseId, object raw, params AIContent[] parts)
|
||||
{
|
||||
Throw.IfNullOrEmpty(parts);
|
||||
|
||||
AgentRunResponseUpdate update = new(ChatRole.Assistant, parts)
|
||||
AgentResponseUpdate update = new(ChatRole.Assistant, parts)
|
||||
{
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
MessageId = Guid.NewGuid().ToString("N"),
|
||||
@@ -130,7 +130,7 @@ internal sealed class WorkflowThread : AgentThread
|
||||
}
|
||||
|
||||
internal async
|
||||
IAsyncEnumerable<AgentRunResponseUpdate> InvokeStageAsync(
|
||||
IAsyncEnumerable<AgentResponseUpdate> InvokeStageAsync(
|
||||
[EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
try
|
||||
@@ -157,7 +157,7 @@ internal sealed class WorkflowThread : AgentThread
|
||||
|
||||
case RequestInfoEvent requestInfo:
|
||||
FunctionCallContent fcContent = requestInfo.Request.ToFunctionCall();
|
||||
AgentRunResponseUpdate update = this.CreateUpdate(this.LastResponseId, evt, fcContent);
|
||||
AgentResponseUpdate update = this.CreateUpdate(this.LastResponseId, evt, fcContent);
|
||||
yield return update;
|
||||
break;
|
||||
|
||||
@@ -186,7 +186,7 @@ internal sealed class WorkflowThread : AgentThread
|
||||
|
||||
default:
|
||||
// Emit all other workflow events for observability (DevUI, logging, etc.)
|
||||
yield return new AgentRunResponseUpdate(ChatRole.Assistant, [])
|
||||
yield return new AgentResponseUpdate(ChatRole.Assistant, [])
|
||||
{
|
||||
CreatedAt = DateTimeOffset.UtcNow,
|
||||
MessageId = Guid.NewGuid().ToString("N"),
|
||||
|
||||
@@ -143,8 +143,8 @@ public sealed class AIAgentBuilder
|
||||
/// </remarks>
|
||||
/// <exception cref="ArgumentNullException">Both <paramref name="runFunc"/> and <paramref name="runStreamingFunc"/> are <see langword="null"/>.</exception>
|
||||
public AIAgentBuilder Use(
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, Task<AgentRunResponse>>? runFunc,
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, IAsyncEnumerable<AgentRunResponseUpdate>>? runStreamingFunc)
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, Task<AgentResponse>>? runFunc,
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, IAsyncEnumerable<AgentResponseUpdate>>? runStreamingFunc)
|
||||
{
|
||||
AnonymousDelegatingAIAgent.ThrowIfBothDelegatesNull(runFunc, runStreamingFunc);
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Microsoft.Agents.AI;
|
||||
internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
{
|
||||
/// <summary>The delegate to use as the implementation of <see cref="RunCoreAsync"/>.</summary>
|
||||
private readonly Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, Task<AgentRunResponse>>? _runFunc;
|
||||
private readonly Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, Task<AgentResponse>>? _runFunc;
|
||||
|
||||
/// <summary>The delegate to use as the implementation of <see cref="RunCoreStreamingAsync"/>.</summary>
|
||||
/// <remarks>
|
||||
@@ -26,7 +26,7 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
/// will be invoked with the same arguments as the method itself.
|
||||
/// When <see langword="null"/>, <see cref="RunCoreStreamingAsync"/> will delegate directly to the inner agent.
|
||||
/// </remarks>
|
||||
private readonly Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, IAsyncEnumerable<AgentRunResponseUpdate>>? _runStreamingFunc;
|
||||
private readonly Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, IAsyncEnumerable<AgentResponseUpdate>>? _runStreamingFunc;
|
||||
|
||||
/// <summary>The delegate to use as the implementation of both <see cref="RunCoreAsync"/> and <see cref="RunCoreStreamingAsync"/>.</summary>
|
||||
private readonly Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, CancellationToken, Task>, CancellationToken, Task>? _sharedFunc;
|
||||
@@ -74,8 +74,8 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
/// <exception cref="ArgumentNullException">Both <paramref name="runFunc"/> and <paramref name="runStreamingFunc"/> are <see langword="null"/>.</exception>
|
||||
public AnonymousDelegatingAIAgent(
|
||||
AIAgent innerAgent,
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, Task<AgentRunResponse>>? runFunc,
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, IAsyncEnumerable<AgentRunResponseUpdate>>? runStreamingFunc)
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, Task<AgentResponse>>? runFunc,
|
||||
Func<IEnumerable<ChatMessage>, AgentThread?, AgentRunOptions?, AIAgent, CancellationToken, IAsyncEnumerable<AgentResponseUpdate>>? runStreamingFunc)
|
||||
: base(innerAgent)
|
||||
{
|
||||
ThrowIfBothDelegatesNull(runFunc, runStreamingFunc);
|
||||
@@ -85,7 +85,7 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -97,10 +97,10 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
{
|
||||
return GetRunViaSharedAsync(messages, thread, options, cancellationToken);
|
||||
|
||||
async Task<AgentRunResponse> GetRunViaSharedAsync(
|
||||
async Task<AgentResponse> GetRunViaSharedAsync(
|
||||
IEnumerable<ChatMessage> messages, AgentThread? thread, AgentRunOptions? options, CancellationToken cancellationToken)
|
||||
{
|
||||
AgentRunResponse? response = null;
|
||||
AgentResponse? response = null;
|
||||
|
||||
await this._sharedFunc(
|
||||
messages,
|
||||
@@ -113,7 +113,7 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
|
||||
if (response is null)
|
||||
{
|
||||
Throw.InvalidOperationException("The shared delegate completed successfully without producing an AgentRunResponse.");
|
||||
Throw.InvalidOperationException("The shared delegate completed successfully without producing an AgentResponse.");
|
||||
}
|
||||
|
||||
return response;
|
||||
@@ -127,12 +127,12 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
{
|
||||
Debug.Assert(this._runStreamingFunc is not null, "Expected non-null streaming delegate.");
|
||||
return this._runStreamingFunc!(messages, thread, options, this.InnerAgent, cancellationToken)
|
||||
.ToAgentRunResponseAsync(cancellationToken);
|
||||
.ToAgentResponseAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -142,7 +142,7 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
|
||||
if (this._sharedFunc is not null)
|
||||
{
|
||||
var updates = Channel.CreateBounded<AgentRunResponseUpdate>(1);
|
||||
var updates = Channel.CreateBounded<AgentResponseUpdate>(1);
|
||||
|
||||
_ = ProcessAsync();
|
||||
async Task ProcessAsync()
|
||||
@@ -180,10 +180,10 @@ internal sealed class AnonymousDelegatingAIAgent : DelegatingAIAgent
|
||||
Debug.Assert(this._runFunc is not null, "Expected non-null non-streaming delegate.");
|
||||
return GetStreamingRunAsyncViaRunAsync(this._runFunc!(messages, thread, options, this.InnerAgent, cancellationToken));
|
||||
|
||||
static async IAsyncEnumerable<AgentRunResponseUpdate> GetStreamingRunAsyncViaRunAsync(Task<AgentRunResponse> task)
|
||||
static async IAsyncEnumerable<AgentResponseUpdate> GetStreamingRunAsyncViaRunAsync(Task<AgentResponse> task)
|
||||
{
|
||||
AgentRunResponse response = await task.ConfigureAwait(false);
|
||||
foreach (var update in response.ToAgentRunResponseUpdates())
|
||||
AgentResponse response = await task.ConfigureAwait(false);
|
||||
foreach (var update in response.ToAgentResponseUpdates())
|
||||
{
|
||||
yield return update;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ public sealed partial class ChatClientAgent : AIAgent
|
||||
internal ChatOptions? ChatOptions => this._agentOptions?.ChatOptions;
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -160,9 +160,9 @@ public sealed partial class ChatClientAgent : AIAgent
|
||||
return chatClient.GetResponseAsync(threadMessages, chatOptions, ct);
|
||||
}
|
||||
|
||||
static AgentRunResponse CreateResponse(ChatResponse chatResponse)
|
||||
static AgentResponse CreateResponse(ChatResponse chatResponse)
|
||||
{
|
||||
return new AgentRunResponse(chatResponse)
|
||||
return new AgentResponse(chatResponse)
|
||||
{
|
||||
ContinuationToken = WrapContinuationToken(chatResponse.ContinuationToken)
|
||||
};
|
||||
@@ -196,7 +196,7 @@ public sealed partial class ChatClientAgent : AIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -406,14 +406,14 @@ public sealed partial class ChatClientAgent : AIAgent
|
||||
|
||||
#region Private
|
||||
|
||||
private async Task<TAgentRunResponse> RunCoreAsync<TAgentRunResponse, TChatClientResponse>(
|
||||
private async Task<TAgentResponse> RunCoreAsync<TAgentResponse, TChatClientResponse>(
|
||||
Func<IChatClient, List<ChatMessage>, ChatOptions?, CancellationToken, Task<TChatClientResponse>> chatClientRunFunc,
|
||||
Func<TChatClientResponse, TAgentRunResponse> agentResponseFactoryFunc,
|
||||
Func<TChatClientResponse, TAgentResponse> agentResponseFactoryFunc,
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
AgentRunOptions? options = null,
|
||||
CancellationToken cancellationToken = default)
|
||||
where TAgentRunResponse : AgentRunResponse
|
||||
where TAgentResponse : AgentResponse
|
||||
where TChatClientResponse : ChatResponse
|
||||
{
|
||||
var inputMessages = Throw.IfNull(messages) as IReadOnlyCollection<ChatMessage> ?? messages.ToList();
|
||||
|
||||
@@ -22,8 +22,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentResponse> RunAsync(
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
@@ -39,8 +39,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentResponse> RunAsync(
|
||||
string message,
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -57,8 +57,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentResponse> RunAsync(
|
||||
ChatMessage message,
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -75,8 +75,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentRunResponse> RunAsync(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
public Task<AgentResponse> RunAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -92,8 +92,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
CancellationToken cancellationToken = default) =>
|
||||
@@ -109,8 +109,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
string message,
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -127,8 +127,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
ChatMessage message,
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -145,8 +145,8 @@ public partial class ChatClientAgent
|
||||
/// </param>
|
||||
/// <param name="options">Configuration parameters for controlling the agent's invocation behavior.</param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentRunResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentRunResponseUpdate> RunStreamingAsync(
|
||||
/// <returns>An asynchronous enumerable of <see cref="AgentResponseUpdate"/> instances representing the streaming response.</returns>
|
||||
public IAsyncEnumerable<AgentResponseUpdate> RunStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -167,8 +167,8 @@ public partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentRunResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
AgentThread? thread,
|
||||
JsonSerializerOptions? serializerOptions,
|
||||
ChatClientAgentRunOptions? options,
|
||||
@@ -191,8 +191,8 @@ public partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentRunResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
string message,
|
||||
AgentThread? thread,
|
||||
JsonSerializerOptions? serializerOptions,
|
||||
@@ -216,8 +216,8 @@ public partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentRunResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
ChatMessage message,
|
||||
AgentThread? thread,
|
||||
JsonSerializerOptions? serializerOptions,
|
||||
@@ -241,8 +241,8 @@ public partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentRunResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="ChatClientAgentResponse{T}"/> with the agent's output.</returns>
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread,
|
||||
JsonSerializerOptions? serializerOptions,
|
||||
|
||||
@@ -12,23 +12,23 @@ namespace Microsoft.Agents.AI;
|
||||
/// <typeparam name="T">The type of value expected from the chat response.</typeparam>
|
||||
/// <remarks>
|
||||
/// Language models are not guaranteed to honor the requested schema. If the model's output is not
|
||||
/// parsable as the expected type, you can access the underlying JSON response on the <see cref="AgentRunResponse.Text"/> property.
|
||||
/// parsable as the expected type, you can access the underlying JSON response on the <see cref="AgentResponse.Text"/> property.
|
||||
/// </remarks>
|
||||
public sealed class ChatClientAgentRunResponse<T> : AgentRunResponse<T>
|
||||
public sealed class ChatClientAgentResponse<T> : AgentResponse<T>
|
||||
{
|
||||
private readonly ChatResponse<T> _response;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AgentRunResponse{T}"/> class from an existing <see cref="ChatResponse{T}"/>.
|
||||
/// Initializes a new instance of the <see cref="AgentResponse{T}"/> class from an existing <see cref="ChatResponse{T}"/>.
|
||||
/// </summary>
|
||||
/// <param name="response">The <see cref="ChatResponse{T}"/> from which to populate this <see cref="AgentRunResponse{T}"/>.</param>
|
||||
/// <param name="response">The <see cref="ChatResponse{T}"/> from which to populate this <see cref="AgentResponse{T}"/>.</param>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="response"/> is <see langword="null"/>.</exception>
|
||||
/// <remarks>
|
||||
/// This constructor creates an agent response that wraps an existing <see cref="ChatResponse{T}"/>, preserving all
|
||||
/// metadata and storing the original response in <see cref="ChatResponse.RawRepresentation"/> for access to
|
||||
/// the underlying implementation details.
|
||||
/// </remarks>
|
||||
public ChatClientAgentRunResponse(ChatResponse<T> response) : base(response)
|
||||
public ChatClientAgentResponse(ChatResponse<T> response) : base(response)
|
||||
{
|
||||
_ = Throw.IfNull(response);
|
||||
|
||||
|
||||
@@ -29,12 +29,12 @@ public sealed partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <remarks>
|
||||
/// This overload is useful when the agent has sufficient context from previous messages in the thread
|
||||
/// or from its initial configuration to generate a meaningful response without additional input.
|
||||
/// </remarks>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
AgentThread? thread = null,
|
||||
JsonSerializerOptions? serializerOptions = null,
|
||||
AgentRunOptions? options = null,
|
||||
@@ -57,13 +57,13 @@ public sealed partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <exception cref="ArgumentException"><paramref name="message"/> is <see langword="null"/>, empty, or contains only whitespace.</exception>
|
||||
/// <remarks>
|
||||
/// The provided text will be wrapped in a <see cref="ChatMessage"/> with the <see cref="ChatRole.User"/> role
|
||||
/// before being sent to the agent. This is a convenience method for simple text-based interactions.
|
||||
/// </remarks>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
string message,
|
||||
AgentThread? thread = null,
|
||||
JsonSerializerOptions? serializerOptions = null,
|
||||
@@ -91,9 +91,9 @@ public sealed partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <exception cref="ArgumentNullException"><paramref name="message"/> is <see langword="null"/>.</exception>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
ChatMessage message,
|
||||
AgentThread? thread = null,
|
||||
JsonSerializerOptions? serializerOptions = null,
|
||||
@@ -121,7 +121,7 @@ public sealed partial class ChatClientAgent
|
||||
/// Using a JSON schema improves reliability if the underlying model supports native structured output with a schema, but might cause an error if the model does not support it.
|
||||
/// </param>
|
||||
/// <param name="cancellationToken">The <see cref="CancellationToken"/> to monitor for cancellation requests. The default is <see cref="CancellationToken.None"/>.</param>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentRunResponse"/> with the agent's output.</returns>
|
||||
/// <returns>A task that represents the asynchronous operation. The task result contains an <see cref="AgentResponse"/> with the agent's output.</returns>
|
||||
/// <typeparam name="T">The type of structured output to request.</typeparam>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
@@ -134,7 +134,7 @@ public sealed partial class ChatClientAgent
|
||||
/// The agent's response will also be added to <paramref name="thread"/> if one is provided.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
public Task<ChatClientAgentRunResponse<T>> RunAsync<T>(
|
||||
public Task<ChatClientAgentResponse<T>> RunAsync<T>(
|
||||
IEnumerable<ChatMessage> messages,
|
||||
AgentThread? thread = null,
|
||||
JsonSerializerOptions? serializerOptions = null,
|
||||
@@ -152,9 +152,9 @@ public sealed partial class ChatClientAgent
|
||||
ct).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
static ChatClientAgentRunResponse<T> CreateResponse(ChatResponse<T> chatResponse)
|
||||
static ChatClientAgentResponse<T> CreateResponse(ChatResponse<T> chatResponse)
|
||||
{
|
||||
return new ChatClientAgentRunResponse<T>(chatResponse)
|
||||
return new ChatClientAgentResponse<T>(chatResponse)
|
||||
{
|
||||
ContinuationToken = WrapContinuationToken(chatResponse.ContinuationToken)
|
||||
};
|
||||
|
||||
@@ -21,10 +21,10 @@ internal sealed class FunctionInvocationDelegatingAgent : DelegatingAIAgent
|
||||
this._delegateFunc = delegateFunc;
|
||||
}
|
||||
|
||||
protected override Task<AgentRunResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
protected override Task<AgentResponse> RunCoreAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> this.InnerAgent.RunAsync(messages, thread, this.AgentRunOptionsWithFunctionMiddleware(options), cancellationToken);
|
||||
|
||||
protected override IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
protected override IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
=> this.InnerAgent.RunStreamingAsync(messages, thread, this.AgentRunOptionsWithFunctionMiddleware(options), cancellationToken);
|
||||
|
||||
// Decorate options to add the middleware function
|
||||
|
||||
@@ -55,7 +55,7 @@ public sealed partial class LoggingAgent : DelegatingAIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override async Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (this._logger.IsEnabled(LogLevel.Debug))
|
||||
@@ -72,7 +72,7 @@ public sealed partial class LoggingAgent : DelegatingAIAgent
|
||||
|
||||
try
|
||||
{
|
||||
AgentRunResponse response = await base.RunCoreAsync(messages, thread, options, cancellationToken).ConfigureAwait(false);
|
||||
AgentResponse response = await base.RunCoreAsync(messages, thread, options, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
if (this._logger.IsEnabled(LogLevel.Debug))
|
||||
{
|
||||
@@ -101,7 +101,7 @@ public sealed partial class LoggingAgent : DelegatingAIAgent
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
if (this._logger.IsEnabled(LogLevel.Debug))
|
||||
@@ -116,7 +116,7 @@ public sealed partial class LoggingAgent : DelegatingAIAgent
|
||||
}
|
||||
}
|
||||
|
||||
IAsyncEnumerator<AgentRunResponseUpdate> e;
|
||||
IAsyncEnumerator<AgentResponseUpdate> e;
|
||||
try
|
||||
{
|
||||
e = base.RunCoreStreamingAsync(messages, thread, options, cancellationToken).GetAsyncEnumerator(cancellationToken);
|
||||
@@ -134,7 +134,7 @@ public sealed partial class LoggingAgent : DelegatingAIAgent
|
||||
|
||||
try
|
||||
{
|
||||
AgentRunResponseUpdate? update = null;
|
||||
AgentResponseUpdate? update = null;
|
||||
while (true)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -78,25 +78,25 @@ public sealed class OpenTelemetryAgent : DelegatingAIAgent, IDisposable
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async Task<AgentRunResponse> RunCoreAsync(
|
||||
protected override async Task<AgentResponse> RunCoreAsync(
|
||||
IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatOptions co = new ForwardedOptions(options, thread, Activity.Current);
|
||||
|
||||
var response = await this._otelClient.GetResponseAsync(messages, co, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return response.RawRepresentation as AgentRunResponse ?? new AgentRunResponse(response);
|
||||
return response.RawRepresentation as AgentResponse ?? new AgentResponse(response);
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
protected override async IAsyncEnumerable<AgentRunResponseUpdate> RunCoreStreamingAsync(
|
||||
protected override async IAsyncEnumerable<AgentResponseUpdate> RunCoreStreamingAsync(
|
||||
IEnumerable<ChatMessage> messages, AgentThread? thread = null, AgentRunOptions? options = null, [EnumeratorCancellation] CancellationToken cancellationToken = default)
|
||||
{
|
||||
ChatOptions co = new ForwardedOptions(options, thread, Activity.Current);
|
||||
|
||||
await foreach (var update in this._otelClient.GetStreamingResponseAsync(messages, co, cancellationToken).ConfigureAwait(false))
|
||||
{
|
||||
yield return update.RawRepresentation as AgentRunResponseUpdate ?? new AgentRunResponseUpdate(update);
|
||||
yield return update.RawRepresentation as AgentResponseUpdate ?? new AgentResponseUpdate(update);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,12 +86,12 @@ public abstract class BaseSample : TextWriter
|
||||
/// Processes and writes the latest agent chat response to the console, including metadata and content details.
|
||||
/// </summary>
|
||||
/// <remarks>This method formats and outputs the most recent message from the provided <see
|
||||
/// cref="AgentRunResponse"/> object. It includes the message role, author name (if available), text content, and
|
||||
/// cref="AgentResponse"/> object. It includes the message role, author name (if available), text content, and
|
||||
/// additional content such as images, function calls, and function results. Usage statistics, including token
|
||||
/// counts, are also displayed.</remarks>
|
||||
/// <param name="response">The <see cref="AgentRunResponse"/> object containing the chat messages and usage data.</param>
|
||||
/// <param name="response">The <see cref="AgentResponse"/> object containing the chat messages and usage data.</param>
|
||||
/// <param name="printUsage">The flag to indicate whether to print usage information. Defaults to <see langword="true"/>.</param>
|
||||
protected void WriteResponseOutput(AgentRunResponse response, bool? printUsage = true)
|
||||
protected void WriteResponseOutput(AgentResponse response, bool? printUsage = true)
|
||||
{
|
||||
if (response.Messages.Count == 0)
|
||||
{
|
||||
@@ -150,11 +150,11 @@ public abstract class BaseSample : TextWriter
|
||||
/// Writes the streaming agent response updates to the console.
|
||||
/// </summary>
|
||||
/// <remarks>This method formats and outputs the most recent message from the provided <see
|
||||
/// cref="AgentRunResponseUpdate"/> object. It includes the message role, author name (if available), text content, and
|
||||
/// cref="AgentResponseUpdate"/> object. It includes the message role, author name (if available), text content, and
|
||||
/// additional content such as images, function calls, and function results. Usage statistics, including token
|
||||
/// counts, are also displayed.</remarks>
|
||||
/// <param name="update">The <see cref="AgentRunResponseUpdate"/> object containing the chat messages and usage data.</param>
|
||||
protected void WriteAgentOutput(AgentRunResponseUpdate update)
|
||||
/// <param name="update">The <see cref="AgentResponseUpdate"/> object containing the chat messages and usage data.</param>
|
||||
protected void WriteAgentOutput(AgentResponseUpdate update)
|
||||
{
|
||||
if (update.Contents.Count == 0)
|
||||
{
|
||||
|
||||
@@ -75,13 +75,13 @@ public abstract class OrchestrationSample : BaseSample
|
||||
/// <summary>
|
||||
/// Writes the streamed agent run response updates to the console or test output, including role and author information.
|
||||
/// </summary>
|
||||
/// <param name="streamedResponses">An enumerable of <see cref="AgentRunResponseUpdate"/> objects representing streamed responses.</param>
|
||||
protected static void WriteStreamedResponse(IEnumerable<AgentRunResponseUpdate> streamedResponses)
|
||||
/// <param name="streamedResponses">An enumerable of <see cref="AgentResponseUpdate"/> objects representing streamed responses.</param>
|
||||
protected static void WriteStreamedResponse(IEnumerable<AgentResponseUpdate> streamedResponses)
|
||||
{
|
||||
string? authorName = null;
|
||||
ChatRole? authorRole = null;
|
||||
StringBuilder builder = new();
|
||||
foreach (AgentRunResponseUpdate response in streamedResponses)
|
||||
foreach (AgentResponseUpdate response in streamedResponses)
|
||||
{
|
||||
authorName ??= response.AuthorName;
|
||||
authorRole ??= response.Role;
|
||||
@@ -106,7 +106,7 @@ public abstract class OrchestrationSample : BaseSample
|
||||
/// <summary>
|
||||
/// Gets the list of streamed response updates received so far.
|
||||
/// </summary>
|
||||
public List<AgentRunResponseUpdate> StreamedResponses { get; } = [];
|
||||
public List<AgentResponseUpdate> StreamedResponses { get; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// Gets the list of chat messages representing the conversation history.
|
||||
@@ -131,9 +131,9 @@ public abstract class OrchestrationSample : BaseSample
|
||||
/// <summary>
|
||||
/// Callback to handle a streamed agent run response update, adding it to the list and writing output if final.
|
||||
/// </summary>
|
||||
/// <param name="streamedResponse">The <see cref="AgentRunResponseUpdate"/> to process.</param>
|
||||
/// <param name="streamedResponse">The <see cref="AgentResponseUpdate"/> to process.</param>
|
||||
/// <returns>A <see cref="ValueTask"/> representing the asynchronous operation.</returns>
|
||||
public ValueTask StreamingResultCallbackAsync(AgentRunResponseUpdate streamedResponse)
|
||||
public ValueTask StreamingResultCallbackAsync(AgentResponseUpdate streamedResponse)
|
||||
{
|
||||
this.StreamedResponses.Add(streamedResponse);
|
||||
return default;
|
||||
|
||||
Reference in New Issue
Block a user