diff --git a/internal/tui/configure_transcription.go b/internal/tui/configure_transcription.go index f37c002..b01b0bd 100644 --- a/internal/tui/configure_transcription.go +++ b/internal/tui/configure_transcription.go @@ -156,6 +156,43 @@ func editTranscription(cfg *config.Config, configuredProviders []string) ([]stri return configuredProviders, err } + // validate language-model compatibility before saving + registryName = mapConfigProviderToRegistry(selectedProvider) + if err := provider.ValidateModelLanguage(registryName, selectedModel, selectedLanguage); err != nil { + // show error dialog and let user fix + fmt.Println() + fmt.Println(StyleError.Render("Language-Model Incompatibility")) + fmt.Println(StyleMuted.Render(err.Error())) + fmt.Println() + fmt.Println(StyleMuted.Render("You can:")) + fmt.Println(StyleMuted.Render(" - Change to a different model")) + fmt.Println(StyleMuted.Render(" - Select 'Auto-detect' for language")) + fmt.Println(StyleMuted.Render(" - Choose a supported language")) + fmt.Println() + + var retry bool + retryForm := huh.NewForm( + huh.NewGroup( + huh.NewConfirm(). + Title("Try again?"). + Description("Return to fix the incompatibility"). + Affirmative("Yes, let me fix it"). + Negative("Cancel"). + Value(&retry), + ), + ).WithTheme(getTheme()) + + if err := retryForm.Run(); err != nil { + return configuredProviders, err + } + + if retry { + // recurse to let user fix the issue + return editTranscription(cfg, configuredProviders) + } + return configuredProviders, nil + } + // for whisper-cpp, check if model needs download if selectedProvider == "whisper-cpp" && !whisper.IsInstalled(selectedModel) { modelInfo := whisper.GetModel(selectedModel) diff --git a/progress.txt b/progress.txt index 57f7f06..25a8e39 100644 --- a/progress.txt +++ b/progress.txt @@ -297,4 +297,13 @@ Started: Sun Feb 1 12:22:47 AM CET 2026 - Pass current model to `getLanguageOptions()` for compatibility warnings - Language code saved to config, not display name - All 57 languages + Auto = 58 options total +- All tests passing, typecheck passes + +### Task 30: Add TUI validation for language-model compatibility on save +- Added validation check in `editTranscription()` before saving config +- Uses `provider.ValidateModelLanguage(registryName, selectedModel, selectedLanguage)` +- If validation fails: shows error with message and options (change model, select auto-detect, choose supported language) +- Shows confirm dialog "Try again?" - if yes, recursively calls `editTranscription()` to let user fix +- Config only saved AFTER validation passes (no save on cancel) +- Leverages existing `ValidateModelLanguage` which returns error with supported languages list - All tests passing, typecheck passes \ No newline at end of file diff --git a/tasks/prd.jsonc b/tasks/prd.jsonc index 220e01d..4943e06 100644 --- a/tasks/prd.jsonc +++ b/tasks/prd.jsonc @@ -702,19 +702,19 @@ "User can fix by: changing model, changing language to auto, or changing to supported language", "After showing error, return to the form so user can make changes" ], - "verify": [ - "Selecting English-only model + Spanish language shows error on save", - "Error dialog displays clear message with options", - "Config is not saved when validation fails", - "User can change model and save successfully", - "User can change language to auto and save successfully", - "User can change language to supported language and save successfully", - "Typecheck passes" - ], - "passes": false - }, - // ============================================================================ - // PHASE 7: STREAMING ADAPTER IMPLEMENTATIONS + "verify": [ + "Selecting English-only model + Spanish language shows error on save", + "Error dialog displays clear message with options", + "Config is not saved when validation fails", + "User can change model and save successfully", + "User can change language to auto and save successfully", + "User can change language to supported language and save successfully", + "Typecheck passes" + ], + "passes": true + }, + // ============================================================================ + // PHASE 7: STREAMING ADAPTER IMPLEMENTATIONS // Each adapter is a separate task for right-sizing // ============================================================================ {