initial commit
This commit is contained in:
97
Tools/CommandTool.cs
Normal file
97
Tools/CommandTool.cs
Normal file
@@ -0,0 +1,97 @@
|
||||
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}";
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user