feat: Implement a user-approved shell command execution tool and a Windows installer script.
This commit is contained in:
@@ -12,6 +12,12 @@
|
|||||||
<AssemblyName>anchor</AssemblyName>
|
<AssemblyName>anchor</AssemblyName>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
|
||||||
|
<DefineConstants>$(DefineConstants);WINDOWS</DefineConstants>
|
||||||
|
<!-- Windows requires Desktop C++ Workload for NativeAOT, so we compile a standard self-contained portable executable instead -->
|
||||||
|
<PublishAot>false</PublishAot>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.AI" Version="10.3.0" />
|
<PackageReference Include="Microsoft.Extensions.AI" Version="10.3.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="10.3.0" />
|
<PackageReference Include="Microsoft.Extensions.AI.OpenAI" Version="10.3.0" />
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ if (modelInfo != null)
|
|||||||
// ── Chat history with system prompt ─────────────────────────────────────
|
// ── Chat history with system prompt ─────────────────────────────────────
|
||||||
List<ChatMessage> history =
|
List<ChatMessage> history =
|
||||||
[
|
[
|
||||||
new(ChatRole.System, """
|
new(ChatRole.System, $$"""
|
||||||
You are anchor, a coding assistant that edits files using the Hashline technique.
|
You are anchor, a coding assistant that edits files using the Hashline technique.
|
||||||
|
|
||||||
## Reading files
|
## Reading files
|
||||||
@@ -166,6 +166,7 @@ List<ChatMessage> history =
|
|||||||
4. If an anchor fails validation, re-read the file to get fresh anchors.
|
4. If an anchor fails validation, re-read the file to get fresh anchors.
|
||||||
|
|
||||||
Keep responses concise. You have access to the current working directory.
|
Keep responses concise. You have access to the current working directory.
|
||||||
|
You are running on: {{System.Runtime.InteropServices.RuntimeInformation.OSDescription}}
|
||||||
""")
|
""")
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,11 @@ internal static class CommandTool
|
|||||||
{
|
{
|
||||||
public static Action<string> Log { get; set; } = Console.WriteLine;
|
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.")]
|
#if WINDOWS
|
||||||
|
[Description("Execute a PowerShell 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.")]
|
||||||
|
#else
|
||||||
|
[Description("Execute a Bash 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.")]
|
||||||
|
#endif
|
||||||
public static string ExecuteCommand(
|
public static string ExecuteCommand(
|
||||||
[Description("The shell command to execute.")] string command)
|
[Description("The shell command to execute.")] string command)
|
||||||
{
|
{
|
||||||
@@ -41,8 +45,13 @@ internal static class CommandTool
|
|||||||
{
|
{
|
||||||
var startInfo = new ProcessStartInfo
|
var startInfo = new ProcessStartInfo
|
||||||
{
|
{
|
||||||
|
#if WINDOWS
|
||||||
|
FileName = "powershell.exe",
|
||||||
|
Arguments = $"-NoProfile -Command \"{command}\"",
|
||||||
|
#else
|
||||||
FileName = "/bin/bash",
|
FileName = "/bin/bash",
|
||||||
Arguments = $"-c \"{command}\"",
|
Arguments = $"-c \"{command}\"",
|
||||||
|
#endif
|
||||||
UseShellExecute = false,
|
UseShellExecute = false,
|
||||||
RedirectStandardOutput = true,
|
RedirectStandardOutput = true,
|
||||||
RedirectStandardError = true,
|
RedirectStandardError = true,
|
||||||
|
|||||||
39
installer.ps1
Normal file
39
installer.ps1
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
$ErrorActionPreference = "Stop"
|
||||||
|
|
||||||
|
Write-Host "Publishing project..."
|
||||||
|
dotnet publish -c Release -r win-x64 -p:PublishSingleFile=true -o ./publish
|
||||||
|
|
||||||
|
Write-Host "Finding binary..."
|
||||||
|
$binary = Get-ChildItem -Path ./publish -Filter "anchor.exe" -File | Select-Object -First 1
|
||||||
|
|
||||||
|
if (-not $binary) {
|
||||||
|
Write-Host "Error: Could not find anchor.exe in ./publish" -ForegroundColor Red
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Found binary: $($binary.FullName)"
|
||||||
|
|
||||||
|
# Define the installation directory in the user's profile
|
||||||
|
$installDir = Join-Path $env:USERPROFILE ".anchor\bin"
|
||||||
|
|
||||||
|
if (-not (Test-Path $installDir)) {
|
||||||
|
Write-Host "Creating installation directory: $installDir"
|
||||||
|
New-Item -ItemType Directory -Path $installDir | Out-Null
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Copying to $installDir..."
|
||||||
|
Copy-Item -Path $binary.FullName -Destination $installDir -Force
|
||||||
|
|
||||||
|
# Check if the installation directory is in the User PATH
|
||||||
|
$userPath = [Environment]::GetEnvironmentVariable("PATH", "User")
|
||||||
|
if ($userPath -split ';' -notcontains $installDir) {
|
||||||
|
Write-Host "Adding $installDir to User PATH..."
|
||||||
|
$newPath = if ($userPath) { "$userPath;$installDir" } else { $installDir }
|
||||||
|
[Environment]::SetEnvironmentVariable("PATH", $newPath, "User")
|
||||||
|
Write-Host "PATH updated. You may need to restart your terminal for changes to take effect." -ForegroundColor Yellow
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Write-Host "$installDir is already in the PATH."
|
||||||
|
}
|
||||||
|
|
||||||
|
Write-Host "Installation complete!" -ForegroundColor Green
|
||||||
Reference in New Issue
Block a user