diff --git a/README.md b/README.md index 8283d9d3..b74476ed 100644 --- a/README.md +++ b/README.md @@ -72,8 +72,14 @@ Agent README files: - [`interpreter`][07] - [`azure`][17] (shipped with AI Shell) -When you run `aish`, you are prompted to choose an agent. For more details about each agent, see the -README in the each agent folder. +When you run `aish`, you are prompted to choose an agent. You can also specify an agent directly using the `--agent` or `-a` parameter: + +```bash +aish --agent openai-gpt +aish -a azure +``` + +For more details about each agent, see the README in the each agent folder. To learn more about how to create an agent for yourself please see, [Creating an Agent][03]. @@ -120,9 +126,18 @@ key bindings will be supported in future releases. ### Configuration -Currently, AI Shell supports very basic configuration. One can creates a file named `config.json` -under `~/.aish` to configure AI Shell, but it only supports declaring the default agent to use at -startup. This way you do not need to select agents every time you run `aish.exe` +Currently, AI Shell supports very basic configuration. You can specify which agent to use in several ways: + +1. **Command line parameter** (highest priority): `aish --agent openai-gpt` or `aish -a azure` +2. **Configuration file**: Create a file named `config.json` under `~/.aish` to declare the default agent: + +```json +{ + "DefaultAgent": "openai-gpt" +} +``` + +This way you do not need to select agents every time you run `aish.exe` Configuration of AI Shell will be improved in future releases to support custom key bindings, color themes and more. diff --git a/global.json b/global.json index 67c8b3bd..f61fa353 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "8.0.409" + "version": "8.0.116" } } diff --git a/shell/AIShell.App/Program.cs b/shell/AIShell.App/Program.cs index 2728fd1a..b5ba9862 100644 --- a/shell/AIShell.App/Program.cs +++ b/shell/AIShell.App/Program.cs @@ -27,6 +27,7 @@ static int Main(string[] args) Argument query = new("query", getDefaultValue: () => null, "The query term used to get response from AI."); Option channel = new("--channel", "A named pipe used to setup communication between aish and the command-line shell."); Option shellWrapper = new("--shell-wrapper", "Path to the configuration file to wrap AIShell as a different application."); + Option agent = new(["--agent", "-a"], "The AI agent to use for this session."); query.AddValidator(result => { @@ -38,12 +39,12 @@ static int Main(string[] args) } }); - RootCommand rootCommand = new("AI for the command line.") { query, channel, shellWrapper }; - rootCommand.SetHandler(StartShellAsync, query, channel, shellWrapper); + RootCommand rootCommand = new("AI for the command line.") { query, channel, shellWrapper, agent }; + rootCommand.SetHandler(StartShellAsync, query, channel, shellWrapper, agent); return rootCommand.Invoke(args); } - private async static Task StartShellAsync(string query, string channel, FileInfo shellWrapperConfigFile) + private async static Task StartShellAsync(string query, string channel, FileInfo shellWrapperConfigFile, string agent) { if (!ReadShellWrapperConfig(shellWrapperConfigFile, out ShellWrapper shellWrapper)) { @@ -51,7 +52,7 @@ private async static Task StartShellAsync(string query, string channel, FileInfo } Utils.Setup(shellWrapper?.Name); - ShellArgs args = new(shellWrapper, channel); + ShellArgs args = new(shellWrapper, channel, agent); Shell shell; if (query is not null) diff --git a/shell/AIShell.Kernel/Shell.cs b/shell/AIShell.Kernel/Shell.cs index c353ee4c..613d44f7 100644 --- a/shell/AIShell.Kernel/Shell.cs +++ b/shell/AIShell.Kernel/Shell.cs @@ -14,6 +14,7 @@ internal sealed class Shell : IShell private readonly ShellWrapper _wrapper; private readonly HashSet _textToIgnore; private readonly Setting _setting; + private readonly string _commandLineAgent; private bool _shouldRefresh; private LLMAgent _activeAgent; @@ -90,6 +91,7 @@ internal Shell(bool interactive, ShellArgs args) { _isInteractive = interactive; _wrapper = args.ShellWrapper; + _commandLineAgent = args.Agent; // Create the channel if the args is specified. // The channel object starts the connection initialization on a background thread, @@ -261,7 +263,7 @@ private void LoadAvailableAgents() try { LLMAgent chosenAgent = null; - string active = _wrapper?.Agent ?? _setting.DefaultAgent; + string active = _commandLineAgent ?? _wrapper?.Agent ?? _setting.DefaultAgent; if (!string.IsNullOrEmpty(active)) { foreach (LLMAgent agent in _agents) @@ -275,7 +277,9 @@ private void LoadAvailableAgents() if (chosenAgent is null) { - Host.MarkupWarningLine($"The configured active agent '{active}' is not available.\n"); + string source = !string.IsNullOrEmpty(_commandLineAgent) ? "command line" : + !string.IsNullOrEmpty(_wrapper?.Agent) ? "wrapper configuration" : "default configuration"; + Host.MarkupWarningLine($"The {source} agent '{active}' is not available.\n"); } else if (_wrapper?.Prompt is not null) { diff --git a/shell/AIShell.Kernel/Utility/ShellArgs.cs b/shell/AIShell.Kernel/Utility/ShellArgs.cs index 20b39d62..aab9042f 100644 --- a/shell/AIShell.Kernel/Utility/ShellArgs.cs +++ b/shell/AIShell.Kernel/Utility/ShellArgs.cs @@ -5,7 +5,7 @@ namespace AIShell.Kernel; /// /// Arguments for the AI shell. /// -public sealed class ShellArgs(ShellWrapper shellWrapper, string channel) +public sealed class ShellArgs(ShellWrapper shellWrapper, string channel, string agent) { /// /// Gets the named pipe used to setup communication between aish and the command-line shell. @@ -16,4 +16,9 @@ public sealed class ShellArgs(ShellWrapper shellWrapper, string channel) /// Gets the shell wrapper configuration. /// public ShellWrapper ShellWrapper { get; } = shellWrapper; + + /// + /// Gets the AI agent name to use for this session. + /// + public string Agent { get; } = string.IsNullOrEmpty(agent) ? null : agent; }