// Copyright (c) Microsoft. All rights reserved.
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.AI;
namespace Microsoft.Agents.AI.Workflows.Specialized;
///
/// Executor that runs the agent and forwards all messages, input and output, to the next executor.
///
internal sealed class AgentRunStreamingExecutor(AIAgent agent, bool includeInputInOutput)
: ChatProtocolExecutor(agent.GetDescriptiveId(), DefaultOptions, declareCrossRunShareable: true), IResettableExecutor
{
private static ChatProtocolExecutorOptions DefaultOptions => new()
{
StringMessageChatRole = ChatRole.User
};
protected override async ValueTask TakeTurnAsync(List messages, IWorkflowContext context, bool? emitEvents, CancellationToken cancellationToken = default)
{
List? roleChanged = messages.ChangeAssistantToUserForOtherParticipants(agent.DisplayName);
List updates = [];
await foreach (var update in agent.RunStreamingAsync(messages, cancellationToken: cancellationToken).ConfigureAwait(false))
{
updates.Add(update);
if (emitEvents is true)
{
await context.AddEventAsync(new AgentRunUpdateEvent(this.Id, update), cancellationToken).ConfigureAwait(false);
}
}
roleChanged.ResetUserToAssistantForChangedRoles();
List result = includeInputInOutput ? [.. messages] : [];
result.AddRange(updates.ToAgentRunResponse().Messages);
await context.SendMessageAsync(result, cancellationToken: cancellationToken).ConfigureAwait(false);
}
public new ValueTask ResetAsync() => base.ResetAsync();
}