From b15ab00e85013ccc9bf7079a3546b663961eea60 Mon Sep 17 00:00:00 2001 From: Jose Luis Latorre Millas Date: Tue, 17 Dec 2024 15:01:45 +0100 Subject: [PATCH] improved fluent syntax and test --- .../Step00/Step00_Processes.cs | 36 ++-------- .../Process.Core/ProcessBuilder.cs | 72 +++++++++++++++++++ 2 files changed, 79 insertions(+), 29 deletions(-) diff --git a/dotnet/samples/GettingStartedWithProcesses/Step00/Step00_Processes.cs b/dotnet/samples/GettingStartedWithProcesses/Step00/Step00_Processes.cs index 1fce9ca23921..4896586472ac 100644 --- a/dotnet/samples/GettingStartedWithProcesses/Step00/Step00_Processes.cs +++ b/dotnet/samples/GettingStartedWithProcesses/Step00/Step00_Processes.cs @@ -25,43 +25,21 @@ public async Task UseSimplestProcessAsync() { // Create a simple kernel Kernel kernel = Kernel.CreateBuilder() - .Build(); + .Build(); ProcessBuilder processBuilder = new(nameof(Step00_Processes)); - // Create a process that will interact with the chat completion service - ProcessBuilder process = new("ChatBot"); - var startStep = processBuilder.AddStepFromType(); - var doSomeWorkStep = processBuilder.AddStepFromType(); - var doMoreWorkStep = processBuilder.AddStepFromType(); - var lastStep = processBuilder.AddStepFromType(); - - // Define the process flow processBuilder - .OnInputEvent(ProcessEvents.StartProcess) - .SendEventTo(new ProcessFunctionTargetBuilder(startStep)); - - startStep - .OnFunctionResult() - .SendEventTo(new ProcessFunctionTargetBuilder(doSomeWorkStep)); - - doSomeWorkStep - .OnFunctionResult() - .SendEventTo(new ProcessFunctionTargetBuilder(doMoreWorkStep)); - - doMoreWorkStep - .OnFunctionResult() - .SendEventTo(new ProcessFunctionTargetBuilder(lastStep)); - - lastStep - .OnFunctionResult() - .StopProcess(); + .StartWith(ProcessEvents.StartProcess) + .AndThen() + .AndThen() + .AndFinally(); // Build the process to get a handle that can be started - KernelProcess kernelProcess = process.Build(); + KernelProcess kernelProcess = processBuilder.Build(); // Start the process with an initial external event - using var runningProcess = await kernelProcess.StartAsync( + using var runningProcess = await kernelProcess!.StartAsync( kernel, new KernelProcessEvent() { diff --git a/dotnet/src/Experimental/Process.Core/ProcessBuilder.cs b/dotnet/src/Experimental/Process.Core/ProcessBuilder.cs index e475017af6ba..2ed5be73dfbf 100644 --- a/dotnet/src/Experimental/Process.Core/ProcessBuilder.cs +++ b/dotnet/src/Experimental/Process.Core/ProcessBuilder.cs @@ -315,5 +315,77 @@ public ProcessBuilder(string name) { } + /// + /// Starts the process with the specified step and binds it to the given input event. + /// + /// The step type to start the process. + /// The name of the input event that triggers the start. + /// Optional: The name of the step. + /// The current ProcessBuilder instance. + public ProcessBuilder StartWith(string eventName, string? name = null) where TStep : KernelProcessStep + { + Verify.NotNullOrWhiteSpace(eventName, nameof(eventName)); + + // Add the first step + var stepBuilder = this.AddStepFromType(name); + + // Bind the step to the input event + this.OnInputEvent(eventName) + .SendEventTo(new ProcessFunctionTargetBuilder(stepBuilder)); + + return this; + } + + /// + /// Chains the next step in the process using an input event or a function result. + /// + /// The step type to add next. + /// The event name or function name that triggers this transition. + /// Optional: The name of the step. + /// The current ProcessBuilder instance. + public ProcessBuilder AndThen(string? eventOrFunctionName = null, string? name = null) where TStep : KernelProcessStep + { + // Ensure there is a previous step + if (this._steps.Count == 0) + { + throw new InvalidOperationException("AndThen cannot be called before StartWith."); + } + + // Get the previous step + var previousStepBuilder = this._steps.Last(); + + // Add the next step + var nextStepBuilder = this.AddStepFromType(name); + + // Determine the edge builder from the previous step + ProcessStepEdgeBuilder edgeBuilder = string.IsNullOrWhiteSpace(eventOrFunctionName) + ? previousStepBuilder.OnFunctionResult() // Default to OnFunctionResult + : previousStepBuilder.OnEvent(eventOrFunctionName); // Use OnEvent if specified + + // Link the edge to the next step + edgeBuilder.SendEventTo(new ProcessFunctionTargetBuilder(nextStepBuilder)); + + return this; + } + + /// + /// Marks the final step in the process and stops the process automatically. + /// + /// The step type to add as the final step. + /// The event name or function name that triggers this transition. + /// Optional: The name of the step. + /// The current ProcessBuilder instance. + public ProcessBuilder AndFinally(string? eventOrFunctionName = null, string? name = null) where TStep : KernelProcessStep + { + this.AndThen(eventOrFunctionName, name); + + // Get the final step + var finalStepBuilder = this._steps.Last(); + + finalStepBuilder.OnFunctionResult().StopProcess(); + + return this; + } + #endregion }