1
0
Files
AnchorCli/SetupTui.cs

146 lines
5.7 KiB
C#

using Spectre.Console;
namespace AnchorCli;
internal static class SetupTui
{
public static void Run()
{
var config = AnchorConfig.Load();
AnsiConsole.Write(new Rule("[cornflowerblue]anchor setup[/]").LeftJustified());
AnsiConsole.WriteLine();
// ── API Key ───────────────────────────────────────────────────
string maskedKey = config.ApiKey.Length > 8
? config.ApiKey[..4] + new string('*', config.ApiKey.Length - 8) + config.ApiKey[^4..]
: config.ApiKey.Length > 0 ? "****" : "[dim](not set)[/]";
AnsiConsole.MarkupLine($" Current API key: [dim]{Markup.Escape(maskedKey)}[/]");
string newKey = AnsiConsole.Prompt(
new TextPrompt<string>(" New API key [dim](Enter to keep)[/]:")
.AllowEmpty()
.Secret('*'));
if (!string.IsNullOrWhiteSpace(newKey))
config.ApiKey = newKey.Trim();
AnsiConsole.WriteLine();
// ── Provider ────────────────────────────────────────────────────
var providers = new List<(string Value, string Description)>
{
("openrouter", "default, pricing support"),
("groq", "high-speed inference"),
("ollama", "local, no auth required"),
("openai", "official OpenAI API"),
("custom", "generic OpenAI-compatible endpoint")
};
string currentProvider = config.Provider ?? "openrouter";
AnsiConsole.MarkupLine($" Current provider: [cyan]{Markup.Escape(currentProvider)}[/]");
var selectedProviderChoice = AnsiConsole.Prompt(
new SelectionPrompt<(string Value, string Description)>()
.Title(" Select a provider:")
.UseConverter(p => p.Value + (string.IsNullOrEmpty(p.Description) ? "" : $" [dim]({p.Description})[/]"))
.AddChoices(providers));
config.Provider = selectedProviderChoice.Value;
if (config.Provider == "custom")
{
string customEndpoint = AnsiConsole.Prompt(
new TextPrompt<string>(" Enter endpoint URL:")
.DefaultValue(config.Endpoint)
.AllowEmpty());
if (!string.IsNullOrWhiteSpace(customEndpoint))
{
config.Endpoint = customEndpoint.Trim();
}
}
else
{
config.Endpoint = config.Provider.ToLowerInvariant() switch
{
"openrouter" => "https://openrouter.ai/api/v1",
"groq" => "https://api.groq.com/openai/v1",
"ollama" => "http://localhost:11434/v1",
"openai" => "https://api.openai.com/v1",
_ => config.Endpoint
};
}
AnsiConsole.WriteLine();
// ── Model ─────────────────────────────────────────────────────
AnsiConsole.MarkupLine($" Current model: [cyan]{Markup.Escape(config.Model)}[/]");
var models = config.Provider.ToLowerInvariant() switch
{
"groq" => new List<(string Value, string Description)>
{
("llama-3.3-70b-versatile", "fast, powerful"),
("llama-3.1-8b-instant", "very fast"),
("mixtral-8x7b-32768", "sparse MoE"),
("gemma2-9b-it", "Google's Gemma"),
("Custom...", "")
},
"ollama" => new List<(string Value, string Description)>
{
("llama3.2", "Meta's Llama 3.2"),
("qwen2.5", "Alibaba Qwen"),
("mistral", "Mistral AI"),
("codellama", "code-focused"),
("Custom...", "")
},
"openai" => new List<(string Value, string Description)>
{
("gpt-4o", "most capable"),
("gpt-4o-mini", "fast, affordable"),
("o1-preview", "reasoning model"),
("Custom...", "")
},
_ => new List<(string Value, string Description)>
{
("qwen/qwen3.5-397b-a17b", "smart, expensive"),
("qwen/qwen3.5-122b-a10b", "faster"),
("qwen/qwen3.5-27b", "fast"),
("qwen/qwen3.5-flash-02-23", "cloud, fast"),
("qwen/qwen3.5-plus-02-15", "cloud, smart"),
("Custom...", "")
}
};
string selectedModel = AnsiConsole.Prompt(
new SelectionPrompt<(string Value, string Description)>()
.Title(" Select a model:")
.UseConverter(m => m.Value + (string.IsNullOrEmpty(m.Description) ? "" : $" [dim]({m.Description})[/]"))
.AddChoices(models))
.Value;
if (selectedModel == "Custom...")
{
string customModel = AnsiConsole.Prompt(
new TextPrompt<string>(" Enter custom model name:")
.AllowEmpty());
if (!string.IsNullOrWhiteSpace(customModel))
config.Model = customModel.Trim();
}
else
{
config.Model = selectedModel;
}
// ── Save ──────────────────────────────────────────────────────
AnsiConsole.WriteLine();
config.Save();
AnsiConsole.MarkupLine("[green]✓ Config saved.[/]");
}
}