// Copyright (c) Microsoft. All rights reserved.
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Agents.AI.Workflows.Declarative.Extensions;
using Microsoft.Agents.AI.Workflows.Declarative.Interpreter;
namespace Microsoft.Agents.AI.Workflows.Declarative.Kit;
///
/// Base class for action executors that do not consume the input message (most).
///
/// The executor id
/// Session to support formula expressions.
public abstract class ActionExecutor(string id, FormulaSession session) : ActionExecutor(id, session)
{
///
protected override ValueTask ExecuteAsync(IWorkflowContext context, ActionExecutorResult message, CancellationToken cancellationToken = default) =>
this.ExecuteAsync(context, cancellationToken);
///
/// Executes the core logic of the action.
///
/// The workflow execution context providing messaging and state services.
/// A token that can be used to observe cancellation.
/// A representing the asynchronous execution operation.
protected abstract ValueTask ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default);
///
/// Test wether the provided value matches the value returned by the prior executor.
///
/// The value to test against the message result.
/// The message containing the prior executor result.
/// True if the value matches the message result
public static bool IsMatch(TValue value, object? message) where TValue : class
{
ActionExecutorResult executorMessage = ActionExecutorResult.ThrowIfNot(message);
object? result = executorMessage.Result;
if (result is TValue resultValue)
{
return value.Equals(resultValue);
}
return false;
}
}
///
/// Base class for an action executor that receives the initial trigger message.
///
/// The type of message being handled
public abstract class ActionExecutor : Executor, IResettableExecutor where TMessage : notnull
{
private readonly FormulaSession _session;
///
/// Initializes a new instance of the class.
///
/// The executor id
/// Session to support formula expressions.
protected ActionExecutor(string id, FormulaSession session)
: base(id)
{
this._session = session;
}
///
public ValueTask ResetAsync()
{
return default;
}
///
[SendsMessage(typeof(ActionExecutorResult))]
public override async ValueTask HandleAsync(TMessage message, IWorkflowContext context, CancellationToken cancellationToken)
{
object? result = await this.ExecuteAsync(new DeclarativeWorkflowContext(context, this._session.State), message, cancellationToken).ConfigureAwait(false);
Debug.WriteLine($"RESULT #{this.Id} - {result ?? "(null)"}");
await context.SendResultMessageAsync(this.Id, result, cancellationToken).ConfigureAwait(false);
}
///
/// Executes the core logic of the action.
///
/// The workflow execution context providing messaging and state services.
/// The the message handled by this executor.
/// A token that can be used to observe cancellation.
/// A representing the asynchronous execution operation.
protected abstract ValueTask ExecuteAsync(IWorkflowContext context, TMessage message, CancellationToken cancellationToken = default);
}