diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs b/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs
index d2301c0311..78e582dfc9 100644
--- a/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs
+++ b/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs
@@ -94,11 +94,19 @@ internal sealed class Program
{
if (evt is ExecutorInvokeEvent executorInvoked)
{
- Debug.WriteLine($"STEP ENTER #{executorInvoked.ExecutorId}");
+ Debug.WriteLine($"EXECUTOR ENTER #{executorInvoked.ExecutorId}");
}
else if (evt is ExecutorCompleteEvent executorComplete)
{
- Debug.WriteLine($"STEP EXIT #{executorComplete.ExecutorId}");
+ Debug.WriteLine($"EXECUTOR EXIT #{executorComplete.ExecutorId}");
+ }
+ if (evt is DeclarativeActionInvokeEvent actionInvoked)
+ {
+ Debug.WriteLine($"ACTION ENTER #{actionInvoked.ActionId} [{actionInvoked.ActionType}]");
+ }
+ else if (evt is DeclarativeActionCompleteEvent actionComplete)
+ {
+ Debug.WriteLine($"ACTION EXIT #{actionComplete.ActionId} [{actionComplete.ActionType}]");
}
else if (evt is ExecutorFailureEvent executorFailure)
{
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/ConversationUpdateEvent.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/ConversationUpdateEvent.cs
deleted file mode 100644
index 7984ffcd11..0000000000
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/ConversationUpdateEvent.cs
+++ /dev/null
@@ -1,14 +0,0 @@
-// Copyright (c) Microsoft. All rights reserved.
-
-namespace Microsoft.Agents.Workflows.Declarative;
-
-///
-/// Event that represents a message produced by a declarative workflow.
-///
-public class ConversationUpdateEvent(string executorid, string conversationId) : ExecutorEvent(executorid, conversationId)
-{
- ///
- /// The conversation ID associated with the workflow.
- ///
- public string ConversationId { get; } = conversationId;
-}
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowEvents.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowEvents.cs
new file mode 100644
index 0000000000..74970f62f1
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/DeclarativeWorkflowEvents.cs
@@ -0,0 +1,64 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using Microsoft.Agents.Workflows.Declarative.Extensions;
+using Microsoft.Bot.ObjectModel;
+
+namespace Microsoft.Agents.Workflows.Declarative;
+
+///
+/// Event that broadcasts the conversation identifier.
+///
+public class ConversationUpdateEvent(string executorid, string conversationId) : ExecutorEvent(executorid, conversationId)
+{
+ ///
+ /// The conversation ID associated with the workflow.
+ ///
+ public string ConversationId { get; } = conversationId;
+}
+
+///
+/// Event that indicates a declarative action has been invoked.
+///
+public class DeclarativeActionInvokeEvent(string actionId, DialogAction action, string? priorActionId) : WorkflowEvent(action)
+{
+ ///
+ /// The declarative action id.
+ ///
+ public string ActionId => actionId;
+
+ ///
+ /// The declarative action type name.
+ ///
+ public string ActionType => action.GetType().Name;
+
+ ///
+ /// Identifier of the parent action.
+ ///
+ public string? ParentActionId => action.GetParentId();
+
+ ///
+ /// Identifier of the previous action.
+ ///
+ public string? PriorActionId => priorActionId;
+}
+
+///
+/// Event that indicates a declarative action has completed.
+///
+public class DeclarativeActionCompleteEvent(string actionId, DialogAction action) : WorkflowEvent(action)
+{
+ ///
+ /// The declarative action identifier.
+ ///
+ public string ActionId => actionId;
+
+ ///
+ /// The declarative action type name.
+ ///
+ public string ActionType => action.GetType().Name;
+
+ ///
+ /// Identifier of the parent action.
+ ///
+ public string? ParentActionId => action.GetParentId();
+}
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeActionExecutor.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeActionExecutor.cs
index 0d0138f261..2fa157bcca 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeActionExecutor.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/DeclarativeActionExecutor.cs
@@ -7,7 +7,6 @@ using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Agents.Workflows.Declarative.Extensions;
-using Microsoft.Agents.Workflows.Reflection;
using Microsoft.Bot.ObjectModel;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Abstractions;
@@ -25,9 +24,7 @@ internal abstract class DeclarativeActionExecutor(TAction model, Declar
public new TAction Model => (TAction)base.Model;
}
-internal abstract class WorkflowActionExecutor :
- ReflectingExecutor,
- IMessageHandler
+internal abstract class WorkflowActionExecutor : Executor
{
public const string RootActionId = "(root)";
@@ -60,8 +57,10 @@ internal abstract class WorkflowActionExecutor :
protected DeclarativeWorkflowState State { get; }
+ protected virtual bool IsDiscreteAction => true;
+
///
- public async ValueTask HandleAsync(DeclarativeExecutorResult message, IWorkflowContext context)
+ public override async ValueTask HandleAsync(DeclarativeExecutorResult message, IWorkflowContext context)
{
if (this.Model.Disabled)
{
@@ -69,6 +68,8 @@ internal abstract class WorkflowActionExecutor :
return;
}
+ await this.RaiseInvocationEventAsync(context, message.ExecutorId).ConfigureAwait(false);
+
await this.State.RestoreAsync(context, default).ConfigureAwait(false);
try
@@ -87,6 +88,13 @@ internal abstract class WorkflowActionExecutor :
Debug.WriteLine($"ERROR [{this.Id}] {exception.GetType().Name}\n{exception.Message}");
throw new DeclarativeActionException($"Unhandled workflow failure - #{this.Id} ({this.Model.GetType().Name})", exception);
}
+ finally
+ {
+ if (this.IsDiscreteAction)
+ {
+ await this.RaiseCompletionEventAsync(context).ConfigureAwait(false);
+ }
+ }
}
protected abstract ValueTask