mirror of
https://github.com/microsoft/agent-framework.git
synced 2026-06-16 21:04:09 +08:00
.NET: Fix to emit WorkflowStartedEvent during workflow execution (#4514)
* Fix bug to emit WorkflowStartedEvent during workflow execution * Updated based on PR comments
This commit is contained in:
committed by
GitHub
Unverified
parent
bcb55b4a98
commit
aa2ff672fb
@@ -72,6 +72,9 @@ internal sealed class LockstepRunEventStream : IRunEventStream
|
||||
this.RunStatus = RunStatus.Running;
|
||||
runActivity?.AddEvent(new ActivityEvent(EventNames.WorkflowStarted));
|
||||
|
||||
// Emit WorkflowStartedEvent to the event stream for consumers
|
||||
eventSink.Enqueue(new WorkflowStartedEvent());
|
||||
|
||||
do
|
||||
{
|
||||
while (this._stepRunner.HasUnprocessedMessages &&
|
||||
|
||||
@@ -88,9 +88,16 @@ internal sealed class StreamingRunEventStream : IRunEventStream
|
||||
|
||||
// Run all available supersteps continuously
|
||||
// Events are streamed out in real-time as they happen via the event handler
|
||||
while (this._stepRunner.HasUnprocessedMessages && !linkedSource.Token.IsCancellationRequested)
|
||||
if (this._stepRunner.HasUnprocessedMessages)
|
||||
{
|
||||
await this._stepRunner.RunSuperStepAsync(linkedSource.Token).ConfigureAwait(false);
|
||||
// Emit WorkflowStartedEvent only when there's actual work to process
|
||||
// This avoids spurious events on timeout-only loop iterations
|
||||
await this._eventChannel.Writer.WriteAsync(new WorkflowStartedEvent(), linkedSource.Token).ConfigureAwait(false);
|
||||
|
||||
while (this._stepRunner.HasUnprocessedMessages && !linkedSource.Token.IsCancellationRequested)
|
||||
{
|
||||
await this._stepRunner.RunSuperStepAsync(linkedSource.Token).ConfigureAwait(false);
|
||||
}
|
||||
}
|
||||
|
||||
// Update status based on what's waiting
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.AI;
|
||||
|
||||
namespace Microsoft.Agents.AI.Workflows.UnitTests;
|
||||
@@ -88,4 +90,69 @@ public class AgentEventsTests
|
||||
Assert.Same(response, evt.Response);
|
||||
Assert.Same(response, evt.Data);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that WorkflowStartedEvent is emitted first before any SuperStepStartedEvent.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task StreamingRun_WorkflowStartedEvent_ShouldBeEmittedBefore_SuperStepStartedAsync()
|
||||
{
|
||||
// Arrange
|
||||
TestEchoAgent agent = new("test-agent");
|
||||
Workflow workflow = AgentWorkflowBuilder.BuildSequential(agent);
|
||||
ChatMessage inputMessage = new(ChatRole.User, "Hello");
|
||||
|
||||
// Act
|
||||
await using StreamingRun run = await InProcessExecution.RunStreamingAsync(workflow, new List<ChatMessage> { inputMessage });
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
List<WorkflowEvent> events = [];
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
|
||||
{
|
||||
events.Add(evt);
|
||||
}
|
||||
|
||||
// Assert
|
||||
events.Should().NotBeEmpty();
|
||||
|
||||
List<WorkflowStartedEvent> startedEvents = events.OfType<WorkflowStartedEvent>().ToList();
|
||||
startedEvents.Should().NotBeEmpty();
|
||||
|
||||
WorkflowStartedEvent? firstStartedEvent = startedEvents.FirstOrDefault();
|
||||
SuperStepStartedEvent? firstSuperStepEvent = events.OfType<SuperStepStartedEvent>().FirstOrDefault();
|
||||
firstSuperStepEvent.Should().NotBeNull();
|
||||
|
||||
int startedIndex = events.IndexOf(firstStartedEvent!);
|
||||
int superStepIndex = events.IndexOf(firstSuperStepEvent!);
|
||||
|
||||
startedIndex.Should().BeLessThan(superStepIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Verifies that WorkflowStartedEvent is emitted using Lockstep execution mode.
|
||||
/// </summary>
|
||||
[Fact]
|
||||
public async Task StreamingRun_LockstepExecution_ShouldEmit_WorkflowStartedEventAsync()
|
||||
{
|
||||
// Arrange
|
||||
TestEchoAgent agent = new("test-agent");
|
||||
Workflow workflow = AgentWorkflowBuilder.BuildSequential(agent);
|
||||
ChatMessage inputMessage = new(ChatRole.User, "Hello");
|
||||
|
||||
// Act: Use Lockstep execution mode
|
||||
await using StreamingRun run = await InProcessExecution.Lockstep.RunStreamingAsync(workflow, new List<ChatMessage> { inputMessage });
|
||||
await run.TrySendMessageAsync(new TurnToken(emitEvents: true));
|
||||
|
||||
List<WorkflowEvent> events = [];
|
||||
await foreach (WorkflowEvent evt in run.WatchStreamAsync())
|
||||
{
|
||||
events.Add(evt);
|
||||
}
|
||||
|
||||
// Assert
|
||||
events.Should().NotBeEmpty();
|
||||
|
||||
List<WorkflowStartedEvent> startedEvents = events.OfType<WorkflowStartedEvent>().ToList();
|
||||
startedEvents.Should().NotBeEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user