// Copyright (c) Microsoft. All rights reserved. using Events; using Microsoft.SemanticKernel; namespace SharedSteps; /// /// A step that elicits user input. /// /// Step used in the Processes Samples: /// - Step01_Processes.cs /// - Step02_AccountOpening.cs /// - Step04_AgentOrchestration /// public class ScriptedUserInputStep : KernelProcessStep { public static class ProcessStepFunctions { public const string GetUserInput = nameof(GetUserInput); } protected bool SuppressOutput { get; init; } /// /// The state object for the user input step. This object holds the user inputs and the current input index. /// private UserInputState? _state; /// /// Method to be overridden by the user to populate with custom user messages /// /// The initialized state object for the step. public virtual void PopulateUserInputs(UserInputState state) { return; } /// /// Activates the user input step by initializing the state object. This method is called when the process is started /// and before any of the KernelFunctions are invoked. /// /// The state object for the step. /// A public override ValueTask ActivateAsync(KernelProcessStepState state) { _state = state.State; PopulateUserInputs(_state!); return ValueTask.CompletedTask; } internal string GetNextUserMessage() { if (_state != null && _state.CurrentInputIndex >= 0 && _state.CurrentInputIndex < this._state.UserInputs.Count) { var userMessage = this._state!.UserInputs[_state.CurrentInputIndex]; _state.CurrentInputIndex++; Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"USER: {userMessage}"); Console.ResetColor(); return userMessage; } Console.WriteLine("SCRIPTED_USER_INPUT: No more scripted user messages defined, returning empty string as user message"); return string.Empty; } /// /// Gets the user input. /// Could be overridden to customize the output events to be emitted /// /// An instance of which can be /// used to emit events from within a KernelFunction. /// A [KernelFunction(ProcessStepFunctions.GetUserInput)] public virtual async ValueTask GetUserInputAsync(KernelProcessStepContext context) { var userMessage = this.GetNextUserMessage(); // Emit the user input if (string.IsNullOrEmpty(userMessage)) { await context.EmitEventAsync(new() { Id = CommonEvents.Exit }); return; } await context.EmitEventAsync(new() { Id = CommonEvents.UserInputReceived, Data = userMessage }); } } /// /// The state object for the /// public record UserInputState { public List UserInputs { get; init; } = []; public int CurrentInputIndex { get; set; } = 0; }