diff --git a/apps/SKonsole/Commands/ExecuteCommand.cs b/apps/SKonsole/Commands/ExecuteCommand.cs new file mode 100644 index 0000000..ede547e --- /dev/null +++ b/apps/SKonsole/Commands/ExecuteCommand.cs @@ -0,0 +1,88 @@ +using System.CommandLine; +using Microsoft.Extensions.Logging; +using Microsoft.SemanticKernel; +using SKonsole.Utils; + +namespace SKonsole.Commands; +internal sealed class ExecuteCommand : Command +{ + private ILogger _logger; + + public ExecuteCommand(ConfigurationProvider config, ILogger? logger = null) : base("exec", "Execute semantic function.") + { + if (logger is null) + { + using var loggerFactory = Logging.GetFactory(); + this._logger = loggerFactory.CreateLogger(this.GetType()); + } + else + { + this._logger = logger; + } + + var promptArgument = new Argument + ("prompt", "The semantic function prompt or input for direct execution"); + + this.AddArgument(promptArgument); + + var templateOption = new Option( + new string[] { "--template", "-t" }, + () => { return "{{$input}}"; }, + "The template (file) to use for the semantic function."); + + this.AddOption(templateOption); + + var outputOption = new Option( + new string[] { "--outputFile", "-o" }, + description: "Output the result to the specified file."); + this.AddOption(outputOption); + + this.SetHandler(async context => await RunExecuteAsync(context.GetCancellationToken(), + context.BindingContext.ParseResult.GetValueForArgument(promptArgument), + context.BindingContext.ParseResult.GetValueForOption(templateOption), + context.BindingContext.ParseResult.GetValueForOption(outputOption), + this._logger)); + } + + private static async Task RunExecuteAsync(CancellationToken cancellationToken, + string prompt, + string? template = null, + string? outputFile = null, + ILogger? logger = null) + { + var kernel = KernelProvider.Instance.Get(); + + if (string.IsNullOrWhiteSpace(template)) + { + template = "{{$input}}"; + } + else if (Path.Exists(template)) + { + template = await File.ReadAllTextAsync(template, cancellationToken); + } + else if (Path.Exists(Path.Combine(template, "skprompt.txt"))) + { + template = await File.ReadAllTextAsync(Path.Combine(template, "skprompt.txt"), cancellationToken); + } + + var func = kernel.CreateSemanticFunction(template); + + var output = await kernel.RunAsync(prompt, func); + + var result = output.GetValue(); + + if (!string.IsNullOrWhiteSpace(outputFile)) + { + var directory = Path.GetDirectoryName(outputFile); + if (!string.IsNullOrEmpty(directory)) + { + Directory.CreateDirectory(directory); + } + System.IO.File.WriteAllText(outputFile, result); + } + else + { + Console.WriteLine(result); + } + } +} diff --git a/apps/SKonsole/Program.cs b/apps/SKonsole/Program.cs index d9e5f68..4376e39 100644 --- a/apps/SKonsole/Program.cs +++ b/apps/SKonsole/Program.cs @@ -13,7 +13,8 @@ new PRCommand(ConfigurationProvider.Instance), new PlannerCommand(ConfigurationProvider.Instance), new StepwisePlannerCommand(ConfigurationProvider.Instance), - new PromptChatCommand(ConfigurationProvider.Instance) + new PromptChatCommand(ConfigurationProvider.Instance), + new ExecuteCommand(ConfigurationProvider.Instance), }; return await rootCommand.InvokeAsync(args);