From 170ac22e3c3c71d82df56ac2523bbd083af8c443 Mon Sep 17 00:00:00 2001 From: leonardotrapani Date: Sun, 1 Feb 2026 13:34:50 +0100 Subject: [PATCH] improve language-model compatibility error messages with docs URL --- internal/config/config_test.go | 4 ++-- internal/config/validate.go | 17 ++++++++++++----- internal/provider/provider.go | 18 ++++++++++++++---- internal/provider/provider_test.go | 30 ++++++++++++++++++++++++++++++ progress.txt | 11 +++++++++++ tasks/prd.jsonc | 2 +- 6 files changed, 70 insertions(+), 12 deletions(-) diff --git a/internal/config/config_test.go b/internal/config/config_test.go index 6f16408..253ac23 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -707,7 +707,7 @@ func TestValidateModelLanguageCompatibility(t *testing.T) { model: "distil-whisper-large-v3-en", langCode: "es", wantErr: true, - errContains: "does not support language 'es'", + errContains: "does not support Spanish (es)", }, { name: "multilingual model supports spanish", @@ -722,7 +722,7 @@ func TestValidateModelLanguageCompatibility(t *testing.T) { model: "base.en", langCode: "fr", wantErr: true, - errContains: "does not support language 'fr'", + errContains: "does not support French (fr)", }, { name: "whisper-cpp multilingual supports french", diff --git a/internal/config/validate.go b/internal/config/validate.go index ef402f1..6805b3b 100644 --- a/internal/config/validate.go +++ b/internal/config/validate.go @@ -212,16 +212,23 @@ func ValidateModelLanguageCompatibility(registryProvider, modelID, langCode stri // truncate supported languages for error message supported := model.SupportedLanguages suffix := "" - if len(supported) > 10 { - supported = supported[:10] + if len(supported) > 5 { + supported = supported[:5] suffix = "..." } + // build error with docs URL if available + docsHint := "" + if model.DocsURL != "" { + docsHint = fmt.Sprintf(" See %s for full list.", model.DocsURL) + } + return fmt.Errorf( - "model %s does not support language '%s' (%s). Either change model, select auto-detect, or choose a supported language: %s%s", - modelID, - langCode, + "model %s does not support %s (%s).%s Supported: %s%s", + model.Name, langName, + langCode, + docsHint, strings.Join(supported, ", "), suffix, ) diff --git a/internal/provider/provider.go b/internal/provider/provider.go index 0dd1a02..a7f1d81 100644 --- a/internal/provider/provider.go +++ b/internal/provider/provider.go @@ -151,15 +151,25 @@ func ValidateModelLanguage(providerName, modelID, langCode string) error { // truncate supported languages list for error message supported := model.SupportedLanguages - if len(supported) > 10 { - supported = append(supported[:10], "...") + suffix := "" + if len(supported) > 5 { + supported = supported[:5] + suffix = "..." + } + + // build error with docs URL if available + docsHint := "" + if model.DocsURL != "" { + docsHint = fmt.Sprintf(" See %s for full list.", model.DocsURL) } return fmt.Errorf( - "model %s does not support language '%s'. Supported: %s", - modelID, + "model %s does not support language '%s'.%s Supported: %s%s", + model.Name, langCode, + docsHint, strings.Join(supported, ", "), + suffix, ) } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 6e8a454..50ae22f 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -2,6 +2,7 @@ package provider import ( "slices" + "strings" "testing" ) @@ -263,6 +264,35 @@ func TestValidateModelLanguage(t *testing.T) { } } +func TestValidateModelLanguage_ErrorFormat(t *testing.T) { + // verify error includes model name, not ID + err := ValidateModelLanguage("groq", "distil-whisper-large-v3-en", "es") + if err == nil { + t.Fatal("expected error for unsupported language") + } + errMsg := err.Error() + + // should contain model name (from Model.Name) + if !strings.Contains(errMsg, "Distil Whisper Large v3 EN") { + t.Errorf("error should contain model name, got: %s", errMsg) + } + + // should contain docs URL + if !strings.Contains(errMsg, "https://console.groq.com/docs/speech-to-text#supported-languages") { + t.Errorf("error should contain docs URL, got: %s", errMsg) + } + + // should contain language code + if !strings.Contains(errMsg, "'es'") { + t.Errorf("error should contain language code, got: %s", errMsg) + } + + // should have truncated language list (only 5 supported langs, English-only has 1) + if !strings.Contains(errMsg, "en") { + t.Errorf("error should contain supported languages, got: %s", errMsg) + } +} + func TestOpenAIRealtimeModel(t *testing.T) { m, err := GetModel("openai", "gpt-4o-realtime-preview") if err != nil { diff --git a/progress.txt b/progress.txt index 79ef6ab..53925d6 100644 --- a/progress.txt +++ b/progress.txt @@ -584,4 +584,15 @@ Started: Sun Feb 1 12:22:47 AM CET 2026 - whisper-cpp: https://github.com/openai/whisper#available-models-and-languages - LLM models don't have DocsURL (not needed - no language restrictions) - Added TestAllTranscriptionModels_HaveDocsURL test verifying all transcription models have correct URLs +- All tests passing, typecheck passes + +### Task 10: Improve language-model compatibility error messages +- Updated `ValidateModelLanguageCompatibility` in internal/config/validate.go +- Updated `ValidateModelLanguage` in internal/provider/provider.go +- Error now includes: model Name (not ID), language Name (not just code), DocsURL, first 5 supported languages +- Format: "model {Name} does not support {LanguageName} ({code}). See {DocsURL} for full list. Supported: {langs}..." +- Truncated languages list from 10 to 5 for more concise errors +- TUI already displays err.Error() so improvements propagate automatically +- Added TestValidateModelLanguage_ErrorFormat test verifying error includes model name, docs URL, and language +- Updated test expectations in config_test.go for new error format - All tests passing, typecheck passes \ No newline at end of file diff --git a/tasks/prd.jsonc b/tasks/prd.jsonc index 9406721..3ffdbee 100644 --- a/tasks/prd.jsonc +++ b/tasks/prd.jsonc @@ -168,7 +168,7 @@ "Error is actionable and clear", "Typecheck passes" ], - "passes": false + "passes": true }, { "title": "Update config validation for general language",