Merge from main

This commit is contained in:
Dmytro Struk
2025-11-11 18:28:38 -08:00
parent 519bc9da0a
commit b8206a85d7
231 changed files with 19655 additions and 4139 deletions
@@ -16,7 +16,7 @@ internal static class WorkflowFactory
internal static Workflow BuildWorkflow(IChatClient chatClient)
{
// Create executors
var startExecutor = new ConcurrentStartExecutor();
var startExecutor = new ChatForwardingExecutor("Start");
var aggregationExecutor = new ConcurrentAggregationExecutor();
AIAgent frenchAgent = GetLanguageAgent("French", chatClient);
AIAgent englishAgent = GetLanguageAgent("English", chatClient);
@@ -38,33 +38,11 @@ internal static class WorkflowFactory
private static ChatClientAgent GetLanguageAgent(string targetLanguage, IChatClient chatClient) =>
new(chatClient, instructions: $"You're a helpful assistant who always responds in {targetLanguage}.", name: $"{targetLanguage}Agent");
/// <summary>
/// Executor that starts the concurrent processing by sending messages to the agents.
/// </summary>
private sealed class ConcurrentStartExecutor() : Executor("ConcurrentStartExecutor")
{
protected override RouteBuilder ConfigureRoutes(RouteBuilder routeBuilder)
{
return routeBuilder
.AddHandler<List<ChatMessage>>(this.RouteMessages)
.AddHandler<TurnToken>(this.RouteTurnTokenAsync);
}
private ValueTask RouteMessages(List<ChatMessage> messages, IWorkflowContext context, CancellationToken cancellationToken)
{
return context.SendMessageAsync(messages, cancellationToken: cancellationToken);
}
private ValueTask RouteTurnTokenAsync(TurnToken token, IWorkflowContext context, CancellationToken cancellationToken)
{
return context.SendMessageAsync(token, cancellationToken: cancellationToken);
}
}
/// <summary>
/// Executor that aggregates the results from the concurrent agents.
/// </summary>
private sealed class ConcurrentAggregationExecutor() : Executor<List<ChatMessage>>("ConcurrentAggregationExecutor")
private sealed class ConcurrentAggregationExecutor() :
Executor<List<ChatMessage>>("ConcurrentAggregationExecutor"), IResettableExecutor
{
private readonly List<ChatMessage> _messages = [];
@@ -85,5 +63,12 @@ internal static class WorkflowFactory
await context.YieldOutputAsync(formattedMessages, cancellationToken);
}
}
/// <inheritdoc/>
public ValueTask ResetAsync()
{
this._messages.Clear();
return default;
}
}
}
@@ -42,7 +42,7 @@ internal sealed class Program
Console.WriteLine(code);
}
private const string DefaultWorkflow = "HelloWorld.yaml";
private const string DefaultWorkflow = "Marketing.yaml";
private string WorkflowFile { get; }
@@ -92,11 +92,11 @@ The repository has example workflows available in the root [`/workflow-samples`]
2. Run the demo referencing a sample workflow by name:
```sh
dotnet run HelloWorld
dotnet run Marketing
```
3. Run the demo with a path to any workflow file:
```sh
dotnet run c:/myworkflows/HelloWorld.yaml
dotnet run c:/myworkflows/Marketing.yaml
```