98 lines
3.1 KiB
C#
98 lines
3.1 KiB
C#
using System.ComponentModel;
|
|
using System.Diagnostics;
|
|
using Spectre.Console;
|
|
|
|
namespace AnchorCli.Tools;
|
|
|
|
/// <summary>
|
|
/// Command execution tool with user approval.
|
|
/// </summary>
|
|
internal static class CommandTool
|
|
{
|
|
public static Action<string> Log { get; set; } = Console.WriteLine;
|
|
|
|
[Description("Execute a shell command after user approval. Prompts with [Y/n] before running. Note: For file editing and operations, use the built-in file tools (ReadFile, ReplaceLines, InsertAfter, DeleteRange, CreateFile, etc.) instead of shell commands.")]
|
|
public static string ExecuteCommand(
|
|
[Description("The shell command to execute.")] string command)
|
|
{
|
|
Log($"Command request: {command}");
|
|
|
|
// Prompt for user approval
|
|
AnsiConsole.WriteLine();
|
|
AnsiConsole.Write(
|
|
new Panel($"[yellow]{Markup.Escape(command)}[/]")
|
|
.Header("[bold yellow] Run command? [/]")
|
|
.BorderColor(Color.Yellow)
|
|
.RoundedBorder()
|
|
.Padding(1, 0));
|
|
|
|
// Drain any buffered keystrokes so stale input doesn't auto-answer
|
|
while (Console.KeyAvailable)
|
|
Console.ReadKey(intercept: true);
|
|
|
|
if (!AnsiConsole.Confirm("Execute?", defaultValue: true))
|
|
{
|
|
AnsiConsole.MarkupLine("[dim grey] ✗ Cancelled by user[/]");
|
|
return "ERROR: Command execution cancelled by user";
|
|
}
|
|
|
|
// Execute the command
|
|
try
|
|
{
|
|
var startInfo = new ProcessStartInfo
|
|
{
|
|
FileName = "/bin/bash",
|
|
Arguments = $"-c \"{command}\"",
|
|
UseShellExecute = false,
|
|
RedirectStandardOutput = true,
|
|
RedirectStandardError = true,
|
|
CreateNoWindow = true,
|
|
};
|
|
|
|
using var process = Process.Start(startInfo);
|
|
if (process == null)
|
|
{
|
|
return "ERROR: Failed to start process";
|
|
}
|
|
|
|
string output = process.StandardOutput.ReadToEnd();
|
|
string error = process.StandardError.ReadToEnd();
|
|
process.WaitForExit();
|
|
|
|
// Log the output and error
|
|
if (!string.IsNullOrWhiteSpace(output))
|
|
{
|
|
Log("Output:");
|
|
Log(output);
|
|
}
|
|
if (!string.IsNullOrWhiteSpace(error))
|
|
{
|
|
Log("Error:");
|
|
Log(error);
|
|
}
|
|
|
|
var sb = new System.Text.StringBuilder();
|
|
sb.AppendLine($"Command: {command}");
|
|
sb.AppendLine($"Exit code: {process.ExitCode}");
|
|
|
|
if (!string.IsNullOrWhiteSpace(output))
|
|
{
|
|
sb.AppendLine("Output:");
|
|
sb.AppendLine(output);
|
|
}
|
|
|
|
if (!string.IsNullOrWhiteSpace(error))
|
|
{
|
|
sb.AppendLine("Error:");
|
|
sb.AppendLine(error);
|
|
}
|
|
|
|
return sb.ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
return $"ERROR executing command: {ex.Message}";
|
|
}
|
|
}
|
|
}
|