mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET Workflows - Add unit tests for ForeachExecutor (Declarative Workflows) (#3835)
* Initial plan * Add comprehensive unit tests for ForeachExecutor Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> * Formatting * Checkpoint * Checkpoint * Updated test capabilities for non-discrete * Update dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/ObjectModel/ForeachExecutorTest.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Update dotnet/tests/Microsoft.Agents.AI.Workflows.Declarative.UnitTests/ObjectModel/ForeachExecutorTest.cs Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Consistency * Cleanup test * Fixed --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: crickman <66376200+crickman@users.noreply.github.com> Co-authored-by: Chris Rickman <crickman@microsoft.com> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
co-authored by
crickman
Copilot
copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Chris Rickman
parent
be7b55f99b
commit
69dcfe31ee
@@ -65,7 +65,7 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
this._values = [evaluatedValue];
|
||||
}
|
||||
|
||||
await this.ResetAsync(context, null, cancellationToken).ConfigureAwait(false);
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
@@ -84,9 +84,19 @@ namespace Microsoft.Agents.AI.Workflows.Declarative.CodeGen
|
||||
AssignVariable(this.Index, "this._index", tightFormat: true);
|
||||
}
|
||||
|
||||
this.Write("\n\n this._index++;\n }\n }\n\n public async ValueTask ResetAsy" +
|
||||
"nc(IWorkflowContext context, object? _, CancellationToken cancellationToken)\n " +
|
||||
" {");
|
||||
this.Write(@"
|
||||
|
||||
this._index++;
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask CompleteAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask ResetAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{");
|
||||
|
||||
AssignVariable(this.Value, "UnassignedValue.Instance", tightFormat: true);
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionE
|
||||
this._values = [evaluatedValue];
|
||||
}
|
||||
|
||||
await this.ResetAsync(context, null, cancellationToken).ConfigureAwait(false);
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
@@ -59,7 +59,12 @@ internal sealed class <#= this.Name #>Executor(FormulaSession session) : ActionE
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask ResetAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
public async ValueTask CompleteAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
await this.ResetAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
private async ValueTask ResetAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{<#
|
||||
AssignVariable(this.Value, "UnassignedValue.Instance", tightFormat: true);
|
||||
|
||||
|
||||
+1
-1
@@ -201,7 +201,7 @@ internal sealed class WorkflowActionVisitor : DialogActionVisitor
|
||||
{
|
||||
// Transition to end of inner actions
|
||||
string endActionsId = ForeachExecutor.Steps.End(action.Id);
|
||||
this.ContinueWith(new DelegateActionExecutor(endActionsId, this._workflowState, action.ResetAsync), action.Id);
|
||||
this.ContinueWith(new DelegateActionExecutor(endActionsId, this._workflowState, action.CompleteAsync), action.Id);
|
||||
// Transition to select the next item
|
||||
this._workflowModel.AddLink(endActionsId, loopId);
|
||||
}
|
||||
|
||||
+1
-1
@@ -163,7 +163,7 @@ internal sealed class WorkflowTemplateVisitor : DialogActionVisitor
|
||||
{
|
||||
// Transition to end of inner actions
|
||||
string endActionsId = ForeachExecutor.Steps.End(action.Id); // Loop continuation
|
||||
this.ContinueWith(new EmptyTemplate(endActionsId, this._rootId, $"{action.Id.FormatName()}.{nameof(ForeachExecutor.ResetAsync)}"), action.Id);
|
||||
this.ContinueWith(new EmptyTemplate(endActionsId, this._rootId, $"{action.Id.FormatName()}.{nameof(ForeachExecutor.CompleteAsync)}"), action.Id);
|
||||
// Transition to select the next item
|
||||
this._workflowModel.AddLink(endActionsId, loopId);
|
||||
}
|
||||
|
||||
+18
-19
@@ -37,27 +37,21 @@ internal sealed class ForeachExecutor : DeclarativeActionExecutor<Foreach>
|
||||
|
||||
protected override async ValueTask<object?> ExecuteAsync(IWorkflowContext context, CancellationToken cancellationToken = default)
|
||||
{
|
||||
Throw.IfNull(this.Model.Items, $"{nameof(this.Model)}.{nameof(this.Model.Items)}");
|
||||
|
||||
this._index = 0;
|
||||
|
||||
if (this.Model.Items is null)
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Items);
|
||||
if (expressionResult.Value is TableDataValue tableValue)
|
||||
{
|
||||
this._values = [];
|
||||
this.HasValue = false;
|
||||
this._values = [.. tableValue.Values.Select(value => value.Properties.Values.First().ToFormula())];
|
||||
}
|
||||
else
|
||||
{
|
||||
EvaluationResult<DataValue> expressionResult = this.Evaluator.GetValue(this.Model.Items);
|
||||
if (expressionResult.Value is TableDataValue tableValue)
|
||||
{
|
||||
this._values = [.. tableValue.Values.Select(value => value.Properties.Values.First().ToFormula())];
|
||||
}
|
||||
else
|
||||
{
|
||||
this._values = [expressionResult.Value.ToFormula()];
|
||||
}
|
||||
this._values = [expressionResult.Value.ToFormula()];
|
||||
}
|
||||
|
||||
await this.ResetAsync(context, null, cancellationToken).ConfigureAwait(false);
|
||||
await this.ResetStateAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
return default;
|
||||
}
|
||||
@@ -79,19 +73,24 @@ internal sealed class ForeachExecutor : DeclarativeActionExecutor<Foreach>
|
||||
}
|
||||
}
|
||||
|
||||
public async ValueTask ResetAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
public async ValueTask CompleteAsync(IWorkflowContext context, object? _, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
await context.QueueStateResetAsync(Throw.IfNull(this.Model.Value), cancellationToken).ConfigureAwait(false);
|
||||
if (this.Model.Index is not null)
|
||||
{
|
||||
await context.QueueStateResetAsync(this.Model.Index, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
await this.ResetStateAsync(context, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
finally
|
||||
{
|
||||
await context.RaiseCompletionEventAsync(this.Model, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task ResetStateAsync(IWorkflowContext context, CancellationToken cancellationToken)
|
||||
{
|
||||
await context.QueueStateResetAsync(Throw.IfNull(this.Model.Value), cancellationToken).ConfigureAwait(false);
|
||||
if (this.Model.Index is not null)
|
||||
{
|
||||
await context.QueueStateResetAsync(this.Model.Index, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user