diff --git a/Commands/OnboardCommand.cs b/Commands/OnboardCommand.cs index f1713a9..547ace8 100644 --- a/Commands/OnboardCommand.cs +++ b/Commands/OnboardCommand.cs @@ -17,16 +17,11 @@ public static class OnboardCommand AnsiConsole.MarkupLine("[grey]Welcome to the Toak configuration wizard.[/]"); AnsiConsole.WriteLine(); - config.GroqApiKey = AnsiConsole.Prompt( - new TextPrompt("Groq API Key (required for Whisper):") - .DefaultValue(string.IsNullOrWhiteSpace(config.GroqApiKey) ? "" : config.GroqApiKey) - .AllowEmpty()); - config.LlmProvider = AnsiConsole.Prompt( new SelectionPrompt() .Title("Select [green]LLM Provider[/]:") - .AddChoices(new[] { "groq", "together" }) - .UseConverter(c => c == "groq" ? "Groq (Default)" : "Together AI")); + .AddChoices(new[] { "groq", "together", "cerebras", "fireworks" }) + .UseConverter(c => c == "groq" ? "Groq (Default)" : c == "together" ? "Together AI" : c == "cerebras" ? "Cerebras" : "Fireworks AI")); if (config.LlmProvider == "together") { @@ -40,8 +35,38 @@ public static class OnboardCommand .Title("Select [green]LLM Model[/]:") .AddChoices(new[] { "meta-llama/Llama-3.3-70B-Instruct-Turbo", "meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo", "openai/gpt-oss-20b" })); } + else if (config.LlmProvider == "cerebras") + { + config.CerebrasApiKey = AnsiConsole.Prompt( + new TextPrompt("Cerebras API Key:") + .DefaultValue(string.IsNullOrWhiteSpace(config.CerebrasApiKey) ? "" : config.CerebrasApiKey) + .AllowEmpty()); + + config.LlmModel = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select [green]LLM Model[/]:") + .AddChoices(new[] { "llama3.1-8b", "gpt-oss-120b" })); + } + else if (config.LlmProvider == "fireworks") + { + config.FireworksApiKey = AnsiConsole.Prompt( + new TextPrompt("Fireworks API Key:") + .DefaultValue(string.IsNullOrWhiteSpace(config.FireworksApiKey) ? "" : config.FireworksApiKey) + .AllowEmpty()); + + config.LlmModel = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select [green]LLM Model[/]:") + .AddChoices(new[] { "accounts/fireworks/models/deepseek-v3p1", "fireworks/gpt-oss-120b", "fireworks/deepseek-v3p2", "fireworks/qwen3-8b", "fireworks/minimax-m2p5" }) + .UseConverter(c => c.Split('/').Last())); + } else { + config.GroqApiKey = AnsiConsole.Prompt( + new TextPrompt("Groq API Key:") + .DefaultValue(string.IsNullOrWhiteSpace(config.GroqApiKey) ? "" : config.GroqApiKey) + .AllowEmpty()); + config.LlmModel = AnsiConsole.Prompt( new SelectionPrompt() .Title("Select [green]LLM Model[/]:") @@ -57,11 +82,43 @@ public static class OnboardCommand .AddChoices(new[] { "none", "low" }) .UseConverter(c => c == "none" ? "None (Standard)" : "Low (Moderate Reasoning)")); - config.WhisperModel = AnsiConsole.Prompt( + config.WhisperProvider = AnsiConsole.Prompt( new SelectionPrompt() - .Title("Select [green]Whisper Model[/]:") - .AddChoices(new[] { "whisper-large-v3", "whisper-large-v3-turbo" }) - .UseConverter(c => c == "whisper-large-v3" ? "whisper-large-v3 (Accurate)" : "whisper-large-v3-turbo (Fast)")); + .Title("Select [green]Whisper Provider[/]:") + .AddChoices(new[] { "groq", "fireworks" }) + .UseConverter(c => c == "groq" ? "Groq (Default)" : "Fireworks AI")); + + if (config.WhisperProvider == "fireworks") + { + if (string.IsNullOrWhiteSpace(config.FireworksApiKey)) + { + config.FireworksApiKey = AnsiConsole.Prompt( + new TextPrompt("Fireworks API Key (required for Whisper):") + .DefaultValue("") + .AllowEmpty()); + } + + config.WhisperModel = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select [green]Whisper Model[/]:") + .AddChoices(new[] { "fireworks/whisper-v3", "fireworks/whisper-v3-turbo" })); + } + else + { + if (string.IsNullOrWhiteSpace(config.GroqApiKey)) + { + config.GroqApiKey = AnsiConsole.Prompt( + new TextPrompt("Groq API Key (required for Whisper):") + .DefaultValue("") + .AllowEmpty()); + } + + config.WhisperModel = AnsiConsole.Prompt( + new SelectionPrompt() + .Title("Select [green]Whisper Model[/]:") + .AddChoices(new[] { "whisper-large-v3", "whisper-large-v3-turbo" }) + .UseConverter(c => c == "whisper-large-v3" ? "whisper-large-v3 (Accurate)" : "whisper-large-v3-turbo (Fast)")); + } config.WhisperLanguage = AnsiConsole.Prompt( new TextPrompt("Microphone Spoken Language (e.g. en, es, zh):") diff --git a/Configuration/ToakConfig.cs b/Configuration/ToakConfig.cs index 60ab6cc..612811d 100644 --- a/Configuration/ToakConfig.cs +++ b/Configuration/ToakConfig.cs @@ -4,7 +4,10 @@ public class ToakConfig { public string GroqApiKey { get; set; } = string.Empty; public string TogetherApiKey { get; set; } = string.Empty; - public string LlmProvider { get; set; } = "groq"; // groq or together + public string CerebrasApiKey { get; set; } = string.Empty; + public string FireworksApiKey { get; set; } = string.Empty; + public string LlmProvider { get; set; } = "groq"; // groq, together, cerebras, or fireworks + public string WhisperProvider { get; set; } = "groq"; // groq or fireworks public string TypingBackend { get; set; } = "xdotool"; // wtype or xdotool public string AudioBackend { get; set; } = "pw-record"; // pw-record or ffmpeg public bool ModulePunctuation { get; set; } = true; diff --git a/Core/DaemonService.cs b/Core/DaemonService.cs index 204b898..6f5c55f 100644 --- a/Core/DaemonService.cs +++ b/Core/DaemonService.cs @@ -40,19 +40,31 @@ public static class DaemonService var configManager = new ConfigManager(); var config = configManager.LoadConfig(); - if (string.IsNullOrWhiteSpace(config.GroqApiKey)) + if (config.WhisperProvider == "groq" && string.IsNullOrWhiteSpace(config.GroqApiKey)) { - Console.WriteLine("Groq API Key is not configured. Run 'toak onboard'."); + Console.WriteLine("Groq API Key is not configured for Whisper. Run 'toak onboard'."); + return; + } + if (config.WhisperProvider == "fireworks" && string.IsNullOrWhiteSpace(config.FireworksApiKey)) + { + Console.WriteLine("Fireworks API Key is not configured for Whisper. Run 'toak onboard'."); return; } var stateTracker = new StateTracker(); var notifications = new Notifications(); - var speechClient = new OpenAiCompatibleClient(config.GroqApiKey); - ILlmClient llmClient = config.LlmProvider == "together" - ? new OpenAiCompatibleClient(config.TogetherApiKey, "https://api.together.xyz/v1/", config.ReasoningEffort) - : new OpenAiCompatibleClient(config.GroqApiKey, "https://api.groq.com/openai/v1/", config.ReasoningEffort); + ISpeechClient speechClient = config.WhisperProvider == "fireworks" + ? new OpenAiCompatibleClient(config.FireworksApiKey, "https://api.fireworks.ai/inference/v1/") + : new OpenAiCompatibleClient(config.GroqApiKey); + + ILlmClient llmClient = config.LlmProvider switch + { + "together" => new OpenAiCompatibleClient(config.TogetherApiKey, "https://api.together.xyz/v1/", config.ReasoningEffort), + "cerebras" => new OpenAiCompatibleClient(config.CerebrasApiKey, "https://api.cerebras.ai/v1/", config.ReasoningEffort), + "fireworks" => new OpenAiCompatibleClient(config.FireworksApiKey, "https://api.fireworks.ai/inference/v1/", config.ReasoningEffort), + _ => new OpenAiCompatibleClient(config.GroqApiKey, "https://api.groq.com/openai/v1/", config.ReasoningEffort) + }; IAudioRecorder recorder = config.AudioBackend == "ffmpeg" ? new FfmpegAudioRecorder(stateTracker, notifications)