146 lines
5.7 KiB
C#
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.[/]");
|
|
}
|
|
}
|