diff --git a/.github/workflows/dotnet-build-and-test.yml b/.github/workflows/dotnet-build-and-test.yml
index 237c52cf46..db26cbe061 100644
--- a/.github/workflows/dotnet-build-and-test.yml
+++ b/.github/workflows/dotnet-build-and-test.yml
@@ -55,7 +55,7 @@ jobs:
.github
dotnet
- name: Setup dotnet
- uses: actions/setup-dotnet@v4.3.1
+ uses: actions/setup-dotnet@v5.0.0
with:
global-json-file: ${{ github.workspace }}/dotnet/global.json
- name: Build dotnet solutions
@@ -139,7 +139,7 @@ jobs:
# Generate test reports and check coverage
- name: Generate test reports
- uses: danielpalme/ReportGenerator-GitHub-Action@5.4.11
+ uses: danielpalme/ReportGenerator-GitHub-Action@5.4.13
with:
reports: "./TestResults/Coverage/**/coverage.cobertura.xml"
targetdir: "./TestResults/Reports"
@@ -187,13 +187,13 @@ jobs:
- name: Fail workflow if tests failed
id: check_tests_failed
if: contains(join(needs.*.result, ','), 'failure')
- uses: actions/github-script@v7
+ uses: actions/github-script@v8
with:
script: core.setFailed('Integration Tests Failed!')
- name: Fail workflow if tests cancelled
id: check_tests_cancelled
if: contains(join(needs.*.result, ','), 'cancelled')
- uses: actions/github-script@v7
+ uses: actions/github-script@v8
with:
script: core.setFailed('Integration Tests Cancelled!')
diff --git a/.github/workflows/dotnet-cosmosdb-integration-tests.yml b/.github/workflows/dotnet-cosmosdb-integration-tests.yml
index c947097762..2e0e420b1b 100644
--- a/.github/workflows/dotnet-cosmosdb-integration-tests.yml
+++ b/.github/workflows/dotnet-cosmosdb-integration-tests.yml
@@ -47,7 +47,7 @@ jobs:
AZURE_COSMOS_EMULATOR_PARTITION_COUNT: "20" # the more the better for stable tests
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v5
with:
persist-credentials: false
sparse-checkout: |
@@ -55,7 +55,7 @@ jobs:
.github
dotnet
- name: Setup dotnet
- uses: actions/setup-dotnet@v4.3.1
+ uses: actions/setup-dotnet@v5.0.0
with:
global-json-file: ${{ github.workspace }}/dotnet/global.json
- name: Build dotnet solutions
@@ -145,7 +145,7 @@ jobs:
# Generate test reports and check coverage
- name: Generate test reports
- uses: danielpalme/ReportGenerator-GitHub-Action@5.4.11
+ uses: danielpalme/ReportGenerator-GitHub-Action@5.4.13
with:
reports: "./TestResults/Coverage/**/coverage.cobertura.xml"
targetdir: "./TestResults/Reports"
diff --git a/.github/workflows/label-issues.yml b/.github/workflows/label-issues.yml
index 9cc258ba89..231ee6833d 100644
--- a/.github/workflows/label-issues.yml
+++ b/.github/workflows/label-issues.yml
@@ -13,7 +13,7 @@ jobs:
permissions:
issues: write
steps:
- - uses: actions/github-script@v7
+ - uses: actions/github-script@v8
with:
github-token: ${{ secrets.GH_ACTIONS_PR_WRITE }}
script: |
diff --git a/.github/workflows/label-title-prefix.yml b/.github/workflows/label-title-prefix.yml
index d231fa9640..b8d5b762a7 100644
--- a/.github/workflows/label-title-prefix.yml
+++ b/.github/workflows/label-title-prefix.yml
@@ -15,7 +15,7 @@ jobs:
pull-requests: write
steps:
- - uses: actions/github-script@v7
+ - uses: actions/github-script@v8
name: "Issue/PR: update title"
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/python-merge-tests.yml b/.github/workflows/python-merge-tests.yml
index c0d967ab31..fd18a60836 100644
--- a/.github/workflows/python-merge-tests.yml
+++ b/.github/workflows/python-merge-tests.yml
@@ -251,13 +251,13 @@ jobs:
- name: Fail workflow if tests failed
id: check_tests_failed
if: contains(join(needs.*.result, ','), 'failure')
- uses: actions/github-script@v7
+ uses: actions/github-script@v8
with:
script: core.setFailed('Integration Tests Failed!')
- name: Fail workflow if tests cancelled
id: check_tests_cancelled
if: contains(join(needs.*.result, ','), 'cancelled')
- uses: actions/github-script@v7
+ uses: actions/github-script@v8
with:
script: core.setFailed('Integration Tests Cancelled!')
diff --git a/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs b/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs
index 914365b779..478331efba 100644
--- a/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs
+++ b/dotnet/samples/GettingStarted/Workflows/Declarative/Program.cs
@@ -143,11 +143,11 @@ internal sealed class Program
Debug.WriteLine($"EXECUTOR EXIT #{executorCompleted.ExecutorId}");
break;
- case DeclarativeActionInvokeEvent actionInvoked:
+ case DeclarativeActionInvokedEvent actionInvoked:
Debug.WriteLine($"ACTION ENTER #{actionInvoked.ActionId} [{actionInvoked.ActionType}]");
break;
- case DeclarativeActionCompleteEvent actionComplete:
+ case DeclarativeActionCompletedEvent actionComplete:
Debug.WriteLine($"ACTION EXIT #{actionComplete.ActionId} [{actionComplete.ActionType}]");
break;
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionCompleteEvent.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionCompletedEvent.cs
similarity index 85%
rename from dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionCompleteEvent.cs
rename to dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionCompletedEvent.cs
index b574be1621..349028c96b 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionCompleteEvent.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionCompletedEvent.cs
@@ -8,7 +8,7 @@ namespace Microsoft.Agents.Workflows.Declarative;
///
/// Event that indicates a declarative action has been invoked.
///
-public sealed class DeclarativeActionInvokeEvent : WorkflowEvent
+public sealed class DeclarativeActionInvokedEvent : WorkflowEvent
{
///
/// The declarative action id.
@@ -30,7 +30,7 @@ public sealed class DeclarativeActionInvokeEvent : WorkflowEvent
///
public string? PriorActionId { get; }
- internal DeclarativeActionInvokeEvent(DialogAction action, string? priorActionId) : base(action)
+ internal DeclarativeActionInvokedEvent(DialogAction action, string? priorActionId) : base(action)
{
this.ActionId = action.GetId();
this.ActionType = action.GetType().Name;
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionInvokeEvent.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionInvokedEvent.cs
similarity index 84%
rename from dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionInvokeEvent.cs
rename to dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionInvokedEvent.cs
index bb9f676635..16845124b6 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionInvokeEvent.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Events/DeclarativeActionInvokedEvent.cs
@@ -8,7 +8,7 @@ namespace Microsoft.Agents.Workflows.Declarative;
///
/// Event that indicates a declarative action has completed.
///
-public sealed class DeclarativeActionCompleteEvent : WorkflowEvent
+public sealed class DeclarativeActionCompletedEvent : WorkflowEvent
{
///
/// The declarative action identifier.
@@ -25,7 +25,7 @@ public sealed class DeclarativeActionCompleteEvent : WorkflowEvent
///
public string? ParentActionId { get; }
- internal DeclarativeActionCompleteEvent(DialogAction action) : base(action)
+ internal DeclarativeActionCompletedEvent(DialogAction action) : base(action)
{
this.ActionId = action.GetId();
this.ActionType = action.GetType().Name;
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs
index aa6fc18a98..dce481d5d0 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Extensions/IWorkflowContextExtensions.cs
@@ -12,10 +12,10 @@ namespace Microsoft.Agents.Workflows.Declarative.Extensions;
internal static class IWorkflowContextExtensions
{
public static ValueTask RaiseInvocationEventAsync(this IWorkflowContext context, DialogAction action, string? priorEventId = null) =>
- context.AddEventAsync(new DeclarativeActionInvokeEvent(action, priorEventId));
+ context.AddEventAsync(new DeclarativeActionInvokedEvent(action, priorEventId));
public static ValueTask RaiseCompletionEventAsync(this IWorkflowContext context, DialogAction action) =>
- context.AddEventAsync(new DeclarativeActionCompleteEvent(action));
+ context.AddEventAsync(new DeclarativeActionCompletedEvent(action));
public static ValueTask SendResultMessageAsync(this IWorkflowContext context, string id, object? result = null, CancellationToken cancellationToken = default) =>
context.SendMessageAsync(new ExecutorResultMessage(id, result));
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs
index 7b573c69e2..61f00a5b50 100644
--- a/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/Interpreter/WorkflowActionVisitor.cs
@@ -68,7 +68,13 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
{
if (this._workflowModel.GetDepth(item.Id.Value) > 1)
{
- string completionId = this.ContinuationFor(item.Id.Value); // End scope
+ DelegateAction? action = null;
+ ConditionGroupExecutor? conditionGroup = this._workflowModel.LocateParent(parentId);
+ if (conditionGroup is not null)
+ {
+ action = conditionGroup.DoneAsync;
+ }
+ string completionId = this.ContinuationFor(item.Id.Value, action); // End scope
this._workflowModel.AddLinkFromPeer(item.Id.Value, completionId); // Connect with final action
this._workflowModel.AddLink(completionId, Steps.Post(parentId)); // Merge with parent scope
}
@@ -175,10 +181,10 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
ForeachExecutor? loopExecutor = this._workflowModel.LocateParent(item.GetParentId());
if (loopExecutor is not null)
{
- string parentId = GetParentId(item);
- this.ContinueWith(new DelegateActionExecutor(item.Id.Value, this._workflowState), parentId);
- this._workflowModel.AddLink(item.Id.Value, Steps.Post(loopExecutor.Id));
- this.RestartAfter(item.Id.Value, parentId);
+ DefaultActionExecutor breakLoopExecutor = new(item, this._workflowState);
+ this.ContinueWith(breakLoopExecutor);
+ this._workflowModel.AddLink(breakLoopExecutor.Id, Steps.Post(loopExecutor.Id));
+ this.RestartAfter(breakLoopExecutor.Id, breakLoopExecutor.ParentId);
}
}
@@ -189,10 +195,10 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
ForeachExecutor? loopExecutor = this._workflowModel.LocateParent(item.GetParentId());
if (loopExecutor is not null)
{
- string parentId = GetParentId(item);
- this.ContinueWith(new DelegateActionExecutor(item.Id.Value, this._workflowState), parentId);
- this._workflowModel.AddLink(item.Id.Value, ForeachExecutor.Steps.Next(loopExecutor.Id));
- this.RestartAfter(item.Id.Value, parentId);
+ DefaultActionExecutor continueLoopExecutor = new(item, this._workflowState);
+ this.ContinueWith(continueLoopExecutor);
+ this._workflowModel.AddLink(continueLoopExecutor.Id, Steps.Post(loopExecutor.Id));
+ this.RestartAfter(continueLoopExecutor.Id, continueLoopExecutor.ParentId);
}
}
@@ -200,9 +206,9 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
{
this.Trace(item);
- string parentId = GetParentId(item);
- this.ContinueWith(new DelegateActionExecutor(item.Id.Value, this._workflowState), parentId);
- this.RestartAfter(item.Id.Value, parentId);
+ DefaultActionExecutor endExecutor = new(item, this._workflowState);
+ this.ContinueWith(endExecutor);
+ this.RestartAfter(item.Id.Value, endExecutor.ParentId);
}
protected override void Visit(Question item)
diff --git a/dotnet/src/Microsoft.Agents.Workflows.Declarative/ObjectModel/DefaultActionExecutor.cs b/dotnet/src/Microsoft.Agents.Workflows.Declarative/ObjectModel/DefaultActionExecutor.cs
new file mode 100644
index 0000000000..b09c2b3b18
--- /dev/null
+++ b/dotnet/src/Microsoft.Agents.Workflows.Declarative/ObjectModel/DefaultActionExecutor.cs
@@ -0,0 +1,19 @@
+// Copyright (c) Microsoft. All rights reserved.
+
+using System.Threading;
+using System.Threading.Tasks;
+using Microsoft.Agents.Workflows.Declarative.Interpreter;
+using Microsoft.Agents.Workflows.Declarative.PowerFx;
+using Microsoft.Bot.ObjectModel;
+
+namespace Microsoft.Agents.Workflows.Declarative.ObjectModel;
+
+internal sealed class DefaultActionExecutor(DialogAction model, WorkflowFormulaState state) :
+ DeclarativeActionExecutor(model, state)
+{
+ protected override ValueTask