Preserve IsStalled on stall-triggered plan review requests

Agent-Logs-Url: https://github.com/microsoft/agent-framework/sessions/1b9e74e8-69e1-43f2-8467-c5ba963c2622

Co-authored-by: lokitoth <6936551+lokitoth@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-05-13 23:10:45 +00:00
committed by GitHub
Unverified
parent 1c8e16b332
commit c46ce45fdb
2 changed files with 8 additions and 5 deletions
@@ -110,7 +110,7 @@ internal class MagenticOrchestrator(AIAgent managerAgent, List<AIAgent> team, Ta
out this._planReviewPort);
}
private ValueTask SubmitPlanReviewRequestAsync(MagenticTaskContext taskContext, IWorkflowContext workflowContext)
private ValueTask SubmitPlanReviewRequestAsync(MagenticTaskContext taskContext, IWorkflowContext workflowContext, bool isStalled = false)
{
MagenticProgressLedger? progressLedger = taskContext.ProgressLedger;
if (progressLedger?.IsStarted is not true)
@@ -118,7 +118,7 @@ internal class MagenticOrchestrator(AIAgent managerAgent, List<AIAgent> team, Ta
progressLedger = null;
}
MagenticPlanReviewRequest request = new(taskContext.TaskLedger!.CurrentPlan, progressLedger, taskContext.IsStalled);
MagenticPlanReviewRequest request = new(taskContext.TaskLedger!.CurrentPlan, progressLedger, isStalled);
return this._planReviewPort!.PostRequestAsync(request);
}
@@ -162,7 +162,7 @@ internal class MagenticOrchestrator(AIAgent managerAgent, List<AIAgent> team, Ta
}
}
private async ValueTask UpdatePlanAndDelegateAsync(MagenticTaskContext taskContext, IWorkflowContext context, CancellationToken cancellationToken)
private async ValueTask UpdatePlanAndDelegateAsync(MagenticTaskContext taskContext, IWorkflowContext context, CancellationToken cancellationToken, bool isStalled = false)
{
bool isReplan = taskContext.TaskLedger != null;
@@ -178,7 +178,7 @@ internal class MagenticOrchestrator(AIAgent managerAgent, List<AIAgent> team, Ta
if (requirePlanSignoff)
{
await this.SubmitPlanReviewRequestAsync(taskContext, context).ConfigureAwait(false);
await this.SubmitPlanReviewRequestAsync(taskContext, context, isStalled).ConfigureAwait(false);
}
else
{
@@ -289,10 +289,11 @@ internal class MagenticOrchestrator(AIAgent managerAgent, List<AIAgent> team, Ta
private async ValueTask ResetAndReplanAsync(MagenticTaskContext taskContext, IWorkflowContext context, CancellationToken cancellationToken)
{
bool wasStalled = taskContext.IsStalled;
taskContext.Reset();
await context.SendMessageAsync(new ResetChatSignal(), cancellationToken: cancellationToken).ConfigureAwait(false);
await this.UpdatePlanAndDelegateAsync(taskContext, context, cancellationToken).ConfigureAwait(false);
await this.UpdatePlanAndDelegateAsync(taskContext, context, cancellationToken, isStalled: wasStalled).ConfigureAwait(false);
}
private async ValueTask PrepareFinalAnswerAsync(MagenticTaskContext taskContext, IWorkflowContext context, CancellationToken cancellationToken)
@@ -641,6 +641,7 @@ public class MagenticOrchestrationTests
MagenticPlanReviewRequest? reviewRequest1 = request1.Data.As<MagenticPlanReviewRequest>();
reviewRequest1.Should().NotBeNull();
reviewRequest1!.Plan.Text.Should().Contain("Initial plan");
reviewRequest1.IsStalled.Should().BeFalse("the initial plan review is not stall-triggered");
// Act 2: Approve initial plan → stall occurs → reset → replan → new plan review
MagenticPlanReviewResponse approval1 = reviewRequest1.Approve();
@@ -658,6 +659,7 @@ public class MagenticOrchestrationTests
MagenticPlanReviewRequest? reviewRequest2 = request2.Data.As<MagenticPlanReviewRequest>();
reviewRequest2.Should().NotBeNull();
reviewRequest2!.Plan.Text.Should().Contain("Fresh plan after stall reset");
reviewRequest2.IsStalled.Should().BeTrue("the replan was triggered by a stall");
// Act 3: Approve the revised plan → satisfied → final answer
MagenticPlanReviewResponse approval2 = reviewRequest2.Approve();