summaryrefslogtreecommitdiff
path: root/src/Agent.App/Cli
diff options
context:
space:
mode:
Diffstat (limited to 'src/Agent.App/Cli')
-rw-r--r--src/Agent.App/Cli/CommandLine.cs102
1 files changed, 84 insertions, 18 deletions
diff --git a/src/Agent.App/Cli/CommandLine.cs b/src/Agent.App/Cli/CommandLine.cs
index 3fdac9f..3b3fde1 100644
--- a/src/Agent.App/Cli/CommandLine.cs
+++ b/src/Agent.App/Cli/CommandLine.cs
@@ -1,38 +1,104 @@
namespace Agent.App.Cli;
-public enum AppCommand { Serve, Check }
+public enum AppCommand
+{
+ Serve,
+ Check,
+ ExecutableResolve,
+ ExecutableApprove,
+ ExecutableList,
+ ExecutableRevoke,
+ SandboxResolve,
+ SandboxConfirm,
+ SandboxShow
+}
-public sealed record CommandLine(AppCommand Command, string? ConfigPath, string? Language, string? Transport)
+public sealed record CommandLine(
+ AppCommand Command,
+ string? ConfigPath,
+ string? Language,
+ string? Transport,
+ string? Alias = null,
+ string? ExecutablePath = null,
+ string? RuntimeRoot = null,
+ bool NoRuntime = false,
+ bool Yes = false,
+ string Format = "text")
{
public static CommandLine Parse(string[] args)
{
bool implicitServe = args.Length == 0 || args[0].StartsWith("--", StringComparison.Ordinal);
- AppCommand command = implicitServe ? AppCommand.Serve : args[0] switch
+ int index = implicitServe ? 0 : 1;
+ AppCommand command;
+ string? alias = null;
+ if (implicitServe) command = AppCommand.Serve;
+ else if (args[0] == "serve") command = AppCommand.Serve;
+ else if (args[0] == "check") command = AppCommand.Check;
+ else if (args[0] is "executable" or "sandbox")
{
- "serve" => AppCommand.Serve,
- "check" => AppCommand.Check,
- _ => throw new CommandLineException("Expected 'serve' or 'check'.")
- };
+ if (index >= args.Length) throw new CommandLineException($"Expected a subcommand after '{args[0]}'.");
+ string subcommand = args[index++];
+ command = (args[0], subcommand) switch
+ {
+ ("executable", "resolve") => AppCommand.ExecutableResolve,
+ ("executable", "approve") => AppCommand.ExecutableApprove,
+ ("executable", "list") => AppCommand.ExecutableList,
+ ("executable", "revoke") => AppCommand.ExecutableRevoke,
+ ("sandbox", "resolve") => AppCommand.SandboxResolve,
+ ("sandbox", "confirm") => AppCommand.SandboxConfirm,
+ ("sandbox", "show") => AppCommand.SandboxShow,
+ _ => throw new CommandLineException($"Unknown subcommand '{args[0]} {subcommand}'.")
+ };
+ if (command is AppCommand.ExecutableResolve or AppCommand.ExecutableApprove or AppCommand.ExecutableRevoke)
+ {
+ if (index >= args.Length || args[index].StartsWith("--", StringComparison.Ordinal))
+ throw new CommandLineException($"Executable Alias is required for '{args[0]} {subcommand}'.");
+ alias = args[index++];
+ }
+ }
+ else throw new CommandLineException("Expected 'serve', 'check', 'executable', or 'sandbox'.");
string? config = null;
string? language = null;
string? transport = null;
- for (int i = implicitServe ? 0 : 1; i < args.Length; i++)
+ string? executablePath = null;
+ string? runtimeRoot = null;
+ bool noRuntime = false;
+ bool yes = false;
+ string format = "text";
+ while (index < args.Length)
{
- string option = args[i];
- if (i + 1 >= args.Length) throw new CommandLineException($"Missing value for '{option}'.");
- string value = args[++i];
+ string option = args[index++];
switch (option)
{
- case "--config" when config is null: config = value; break;
- case "--lang" when language is null: language = value; break;
- case "--transport" when command == AppCommand.Serve && transport is null && value is "stdio" or "http": transport = value; break;
- case "--transport" when command == AppCommand.Check: throw new CommandLineException("--transport is only valid for serve.");
- case "--transport": throw new CommandLineException("Transport must be stdio or http.");
- default: throw new CommandLineException($"Unknown or duplicate option '{option}'.");
+ case "--yes" when !yes: yes = true; break;
+ case "--no-runtime" when !noRuntime && runtimeRoot is null: noRuntime = true; break;
+ case "--config" when config is null: config = Value(option); break;
+ case "--lang" when language is null: language = Value(option); break;
+ case "--transport" when command == AppCommand.Serve && transport is null:
+ transport = Value(option);
+ if (transport is not ("stdio" or "http")) throw new CommandLineException("Transport must be stdio or http.");
+ break;
+ case "--path" when executablePath is null: executablePath = Value(option); break;
+ case "--runtime-root" when runtimeRoot is null && !noRuntime: runtimeRoot = Value(option); break;
+ case "--format" when command == AppCommand.SandboxShow:
+ format = Value(option);
+ if (format is not ("text" or "json")) throw new CommandLineException("Format must be text or json.");
+ break;
+ default: throw new CommandLineException($"Unknown, duplicate, or invalid option '{option}' for this command.");
}
}
- return new CommandLine(command, config, language, transport);
+ bool management = command is not (AppCommand.Serve or AppCommand.Check);
+ if (management && config is null) throw new CommandLineException("--config <file> is required for executable and sandbox commands.");
+ if (yes && command is not (AppCommand.ExecutableApprove or AppCommand.ExecutableRevoke or AppCommand.SandboxConfirm))
+ throw new CommandLineException("--yes is valid only for approve, revoke, and confirm.");
+ return new(command, config, language, transport, alias, executablePath, runtimeRoot, noRuntime, yes, format);
+
+ string Value(string optionName)
+ {
+ if (index >= args.Length) throw new CommandLineException($"Missing value for '{optionName}'.");
+ return args[index++];
+ }
}
}