feat: better language selection

This commit is contained in:
leonardotrapani
2026-02-01 18:53:44 +01:00
parent 0025bf97b6
commit 3ae86f7bae
40 changed files with 452 additions and 852 deletions
+1 -1
View File
@@ -37,7 +37,7 @@ func editLLM(cfg *config.Config, configuredProviders []string) ([]string, error)
enableLLM := cfg.LLM.Enabled
enableDesc := "LLM improves transcription by fixing grammar, removing stutters, and cleaning up text"
enableDesc := "LLM improves transcription by fixing grammar, removing stutters, and cleaning up text. Recommended for weak voice models"
if cfg.LLM.Enabled {
enableDesc = fmt.Sprintf("Currently: enabled (%s/%s). %s", cfg.LLM.Provider, cfg.LLM.Model, enableDesc)
} else {
+28 -1
View File
@@ -47,6 +47,7 @@ func editProviders(cfg *config.Config, onboarding bool) error {
for {
var options []huh.Option[string]
options = append(options, huh.NewOption("Local", "local"))
for _, name := range AllProviders {
options = append(options, huh.NewOption(formatProviderOption(cfg, name), name))
}
@@ -75,6 +76,13 @@ func editProviders(cfg *config.Config, onboarding bool) error {
return nil
}
if selected == "local" {
if err := showLocalProviderInfo(); err != nil {
continue
}
return nil
}
apiKey, err := configureSingleProvider(cfg, selected)
if err != nil {
continue
@@ -90,6 +98,25 @@ func editProviders(cfg *config.Config, onboarding bool) error {
}
}
func showLocalProviderInfo() error {
selected := "done"
form := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("Local Models").
Description("No need to configure any API keys for local models, go to the next step.").
Options(huh.NewOption("Done", "done")).
Value(&selected),
),
).WithTheme(getTheme())
if err := form.Run(); err != nil {
return err
}
return nil
}
// formatProviderOption formats a provider menu option with status
func formatProviderOption(cfg *config.Config, name string) string {
var status string
@@ -190,7 +217,7 @@ func inputAPIKey(providerName string) (string, error) {
func ensureProviderConfigured(cfg *config.Config, selectedProvider string, configuredProviders []string) []string {
providerName := selectedProvider
switch selectedProvider {
case "groq-transcription", "groq-translation":
case "groq-transcription":
providerName = "groq"
case "mistral-transcription":
providerName = "mistral"
+32 -29
View File
@@ -35,8 +35,7 @@ func editTranscription(cfg *config.Config, configuredProviders []string) ([]stri
huh.NewOption("OpenAI Whisper", "openai"))
case "groq":
transcriptionOptions = append(transcriptionOptions,
huh.NewOption("Groq Whisper (transcription)", "groq-transcription"),
huh.NewOption("Groq Whisper (translate to English)", "groq-translation"))
huh.NewOption("Groq Whisper", "groq-transcription"))
case "mistral":
transcriptionOptions = append(transcriptionOptions,
huh.NewOption("Mistral Voxtral", "mistral-transcription"))
@@ -210,25 +209,37 @@ func editTranscription(cfg *config.Config, configuredProviders []string) ([]stri
return configuredProviders, err
}
languageOptions := getModelLanguageOptions(model, cfg.Transcription.Language)
selectedLanguage := cfg.Transcription.Language
languageForm := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("Language").
Description("Select language for transcription").
Options(languageOptions...).
Filtering(true).
Value(&selectedLanguage),
),
).WithTheme(getTheme())
if err := languageForm.Run(); err != nil {
return configuredProviders, err
if cfg.Transcription.Language != "" && !model.SupportsLanguage(cfg.Transcription.Language) {
cfg.Transcription.Language = ""
}
cfg.Transcription.Language = selectedLanguage
if len(model.SupportedLanguages) <= 1 {
if len(model.SupportedLanguages) == 1 {
cfg.Transcription.Language = model.SupportedLanguages[0]
} else {
cfg.Transcription.Language = ""
}
} else {
languageOptions := getModelLanguageOptions(model, cfg.Transcription.Language)
selectedLanguage := cfg.Transcription.Language
languageForm := huh.NewForm(
huh.NewGroup(
huh.NewSelect[string]().
Title("Language").
Description("Select language for transcription").
Options(languageOptions...).
Filtering(true).
Value(&selectedLanguage),
),
).WithTheme(getTheme())
if err := languageForm.Run(); err != nil {
return configuredProviders, err
}
cfg.Transcription.Language = selectedLanguage
}
// set streaming mode based on model capabilities
if model.SupportsBothModes() {
@@ -271,8 +282,7 @@ func getUnconfiguredTranscriptionOptions(configuredProviders []string) []huh.Opt
}
if !configured["groq"] {
options = append(options,
huh.NewOption("Groq Whisper transcription (not configured)", "groq-transcription"),
huh.NewOption("Groq Whisper translation (not configured)", "groq-translation"))
huh.NewOption("Groq Whisper (not configured)", "groq-transcription"))
}
if !configured["mistral"] {
options = append(options, huh.NewOption("Mistral Voxtral (not configured)", "mistral-transcription"))
@@ -284,13 +294,6 @@ func getUnconfiguredTranscriptionOptions(configuredProviders []string) []huh.Opt
}
func getTranscriptionModelOptions(configProvider string) []huh.Option[string] {
// special case: groq-translation only supports whisper-large-v3
if configProvider == "groq-translation" {
return []huh.Option[string]{
huh.NewOption("whisper-large-v3 (only option)", "whisper-large-v3"),
}
}
// map config provider name to registry provider name
registryName := mapConfigProviderToRegistry(configProvider)
p := provider.GetProvider(registryName)
@@ -319,7 +322,7 @@ func getTranscriptionModelOptions(configProvider string) []huh.Option[string] {
// mapConfigProviderToRegistry maps config provider names to registry provider names
func mapConfigProviderToRegistry(configProvider string) string {
switch configProvider {
case "groq-transcription", "groq-translation":
case "groq-transcription":
return "groq"
case "mistral-transcription":
return "mistral"
+8 -21
View File
@@ -1,10 +1,7 @@
package tui
import (
"fmt"
"github.com/charmbracelet/huh"
"github.com/leonardotrapani/hyprvoice/internal/language"
"github.com/leonardotrapani/hyprvoice/internal/provider"
)
@@ -13,33 +10,23 @@ func getModelLanguageOptions(model *provider.Model, currentLang string) []huh.Op
var options []huh.Option[string]
// auto-detect is always first
autoLabel := "Auto-detect"
autoLabel := "Auto-detect (recommended)"
if currentLang == "" {
autoLabel += " (current)"
}
options = append(options, huh.NewOption(autoLabel, ""))
// only show languages supported by the model
for _, lang := range language.List() {
if model != nil && !model.SupportsLanguage(lang.Code) {
continue
}
if model == nil {
return options
}
label := formatLanguageLabel(lang)
if lang.Code == currentLang {
for _, code := range model.SupportedLanguages {
label := code
if code == currentLang {
label += " (current)"
}
options = append(options, huh.NewOption(label, lang.Code))
options = append(options, huh.NewOption(label, code))
}
return options
}
// formatLanguageLabel formats a language for display
func formatLanguageLabel(lang language.Language) string {
if lang.Name == lang.NativeName || lang.NativeName == "" {
return fmt.Sprintf("%s (%s)", lang.Name, lang.Code)
}
return fmt.Sprintf("%s - %s (%s)", lang.Name, lang.NativeName, lang.Code)
}