initial commit
This commit is contained in:
14
Commands/ClearCommand.cs
Normal file
14
Commands/ClearCommand.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using Spectre.Console;
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public class ClearCommand : ICommand
|
||||
{
|
||||
public string Name => "clear";
|
||||
public string Description => "Clear the terminal screen";
|
||||
|
||||
public Task ExecuteAsync(string[] args, CancellationToken ct)
|
||||
{
|
||||
AnsiConsole.Clear();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
31
Commands/CommandDispatcher.cs
Normal file
31
Commands/CommandDispatcher.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using Spectre.Console;
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public class CommandDispatcher
|
||||
{
|
||||
private readonly CommandRegistry _registry;
|
||||
|
||||
public CommandDispatcher(CommandRegistry registry)
|
||||
{
|
||||
_registry = registry;
|
||||
}
|
||||
|
||||
public async Task<bool> TryExecuteAsync(string input, CancellationToken ct)
|
||||
{
|
||||
if (!input.StartsWith('/')) return false;
|
||||
|
||||
var parts = input[1..].Split(' ', 2);
|
||||
var commandName = parts[0];
|
||||
var args = parts.Length > 1 ? new[] { parts[1] } : Array.Empty<string>();
|
||||
|
||||
var command = _registry.GetCommand(commandName);
|
||||
if (command == null)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]Unknown command: /{commandName}[/]");
|
||||
return true;
|
||||
}
|
||||
|
||||
await command.ExecuteAsync(args, ct);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
18
Commands/CommandRegistry.cs
Normal file
18
Commands/CommandRegistry.cs
Normal file
@@ -0,0 +1,18 @@
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public class CommandRegistry
|
||||
{
|
||||
private readonly Dictionary<string, ICommand> _commands = new(StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public void Register(ICommand command)
|
||||
{
|
||||
_commands[command.Name] = command;
|
||||
}
|
||||
|
||||
public ICommand? GetCommand(string name)
|
||||
{
|
||||
return _commands.TryGetValue(name, out var cmd) ? cmd : null;
|
||||
}
|
||||
|
||||
public IEnumerable<ICommand> GetAllCommands() => _commands.Values;
|
||||
}
|
||||
38
Commands/CompactCommand.cs
Normal file
38
Commands/CompactCommand.cs
Normal file
@@ -0,0 +1,38 @@
|
||||
using Microsoft.Extensions.AI;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
internal class CompactCommand(ContextCompactor compactor, List<ChatMessage> history) : ICommand
|
||||
{
|
||||
public string Name => "compact";
|
||||
public string Description => "Manually compact conversation history via LLM summarization";
|
||||
|
||||
public async Task ExecuteAsync(string[] args, CancellationToken ct)
|
||||
{
|
||||
if (history.Count < 5)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[dim grey]Nothing to compact (too few messages).[/]");
|
||||
return;
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine("[yellow]⚠ Manually compacting conversation history...[/]");
|
||||
|
||||
bool compacted = await AnsiConsole.Status()
|
||||
.Spinner(Spinner.Known.BouncingBar)
|
||||
.SpinnerStyle(Style.Parse("yellow"))
|
||||
.StartAsync("Compacting context...", async ctx =>
|
||||
await compactor.TryCompactAsync(history, ct));
|
||||
|
||||
if (compacted)
|
||||
{
|
||||
AnsiConsole.MarkupLine(
|
||||
$"[green]✓ Context compacted ({history.Count} messages remaining)[/]");
|
||||
}
|
||||
else
|
||||
{
|
||||
AnsiConsole.MarkupLine(
|
||||
"[dim grey] (compaction skipped — not enough history to compress)[/]");
|
||||
}
|
||||
}
|
||||
}
|
||||
15
Commands/ExitCommand.cs
Normal file
15
Commands/ExitCommand.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
using Spectre.Console;
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public class ExitCommand : ICommand
|
||||
{
|
||||
public string Name => "exit";
|
||||
public string Description => "Exit the application";
|
||||
|
||||
public Task ExecuteAsync(string[] args, CancellationToken ct)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[green]Goodbye![/]");
|
||||
Environment.Exit(0);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
33
Commands/HelpCommand.cs
Normal file
33
Commands/HelpCommand.cs
Normal file
@@ -0,0 +1,33 @@
|
||||
using Spectre.Console;
|
||||
using System.Linq;
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public class HelpCommand : ICommand
|
||||
{
|
||||
private readonly CommandRegistry _registry;
|
||||
|
||||
public string Name => "help";
|
||||
public string Description => "Show available commands";
|
||||
|
||||
public HelpCommand(CommandRegistry registry)
|
||||
{
|
||||
_registry = registry;
|
||||
}
|
||||
|
||||
public Task ExecuteAsync(string[] args, CancellationToken ct)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[cyan]Available commands:[/]");
|
||||
|
||||
var table = new Table();
|
||||
table.AddColumn("Command");
|
||||
table.AddColumn("Description");
|
||||
|
||||
foreach (var cmd in _registry.GetAllCommands().OrderBy(c => c.Name))
|
||||
{
|
||||
table.AddRow($"[bold]{cmd.Name}[/]", cmd.Description);
|
||||
}
|
||||
|
||||
AnsiConsole.Write(table);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
8
Commands/ICommand.cs
Normal file
8
Commands/ICommand.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public interface ICommand
|
||||
{
|
||||
string Name { get; }
|
||||
string Description { get; }
|
||||
Task ExecuteAsync(string[] args, CancellationToken ct);
|
||||
}
|
||||
34
Commands/StatusCommand.cs
Normal file
34
Commands/StatusCommand.cs
Normal file
@@ -0,0 +1,34 @@
|
||||
using Spectre.Console;
|
||||
namespace AnchorCli.Commands;
|
||||
|
||||
public class StatusCommand : ICommand
|
||||
{
|
||||
private readonly string _model;
|
||||
private readonly string _endpoint;
|
||||
|
||||
public StatusCommand(string model, string endpoint)
|
||||
{
|
||||
_model = model;
|
||||
_endpoint = endpoint;
|
||||
}
|
||||
|
||||
public string Name => "status";
|
||||
public string Description => "Show current settings (model, endpoint, working directory)";
|
||||
|
||||
public Task ExecuteAsync(string[] args, CancellationToken ct)
|
||||
{
|
||||
var table = new Table()
|
||||
.Border(TableBorder.Rounded)
|
||||
.BorderColor(Color.Grey)
|
||||
.AddColumn(new TableColumn("[dim]Setting[/]").NoWrap())
|
||||
.AddColumn(new TableColumn("[dim]Value[/]"));
|
||||
|
||||
table.AddRow("[grey]Model[/]", $"[cyan]{Markup.Escape(_model)}[/]");
|
||||
table.AddRow("[grey]Endpoint[/]", $"[blue]{Markup.Escape(_endpoint)}[/]");
|
||||
table.AddRow("[grey]CWD[/]", $"[green]{Markup.Escape(Environment.CurrentDirectory)}[/]");
|
||||
|
||||
AnsiConsole.Write(table);
|
||||
AnsiConsole.WriteLine();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user