{ "project": "Language & Streaming UX Improvements", "description": "Move language to general config section, add Language menu in TUI, enable streaming model selection with clear indicators, and improve error messages", "previous_prd_summary": "Model Architecture Overhaul (46 tasks completed): Created language package with 57 languages + provider format conversion, Model as first-class entity with full metadata, BatchAdapter/StreamingAdapter interfaces, migrated all providers (OpenAI, Groq, Mistral, ElevenLabs, Deepgram, whisper-cpp), consolidated OpenAI-compatible adapters, added local transcription via whisper-cpp with CLI commands, created streaming adapters for ElevenLabs/Deepgram/OpenAI Realtime, added TUI model picker with language warnings, added config validation for language-model compatibility", "tasks": [ { "title": "Add GeneralConfig with Language field to config types", "steps": [ "Add GeneralConfig struct to internal/config/types.go with Language string field", "Add General GeneralConfig field to Config struct with toml tag 'general'", "Keep TranscriptionConfig.Language field for now (will be used as override)" ], "verify": [ "Config struct has General field of type GeneralConfig", "GeneralConfig has Language string field with toml:'language' tag", "Typecheck passes" ], "passes": true }, { "title": "Update config loading to handle general language", "steps": [ "Update internal/config/load.go to read general.language from TOML", "If general.language is set but transcription.language is empty, use general.language as default", "If transcription.language is set, it overrides general.language (provider-specific override)", "Update ToTranscriberConfig() in convert.go to resolve effective language: transcription.language || general.language" ], "verify": [ "Config with only general.language='es' results in effective language 'es' for transcription", "Config with general.language='es' and transcription.language='en' results in effective language 'en'", "Config with neither set results in effective language '' (auto)", "Typecheck passes" ], "passes": true }, { "title": "Update config template to include general section", "steps": [ "Update internal/config/save.go configTemplate to add [general] section at top", "Add language field with comment: '# Language for transcription (ISO 639-1 code, e.g., en, es, de). Empty for auto-detect.'", "Remove language from [transcription] section in template (keep for backwards compat in loading)", "Add comment in transcription section: '# language can be set here to override general.language'" ], "verify": [ "New config files have [general] section with language field", "Template shows language under [general] not [transcription]", "Typecheck passes" ], "passes": true }, { "title": "Add SectionLanguage to TUI configure menu", "steps": [ "Add SectionLanguage ConfigSection constant in internal/tui/configure.go", "Add 'Language' option to selectSection() options list after Providers", "Create formatLanguageLabel(cfg) helper that shows current language or 'Auto-detect'", "Add case SectionLanguage in runEditExisting switch that calls new editLanguage function" ], "verify": [ "'Language' appears in TUI configuration menu", "Menu shows current language setting in label", "Selecting Language enters language edit flow", "Typecheck passes" ], "passes": true }, { "title": "Create editLanguage function in TUI", "steps": [ "Create internal/tui/configure_language.go", "Implement editLanguage(cfg *config.Config) error function", "Use getLanguageOptions(nil) since this is global (no model-specific warnings)", "Show huh.NewSelect with Filtering(true) for language search", "Save selected language to cfg.General.Language", "If language changed and transcription model doesn't support it, show warning with options to change model or keep auto" ], "verify": [ "Language picker shows all 58 options (57 languages + Auto-detect)", "Filtering works (can type to search)", "Selecting a language saves to cfg.General.Language", "Warning shown if current model doesn't support selected language", "Typecheck passes" ], "passes": true }, { "title": "Remove language from transcription edit flow", "steps": [ "Update internal/tui/configure_transcription.go editTranscription()", "Remove the language input field from the transcription form", "Keep language validation on save but use effective language from config", "Update any references to selectedLanguage to use cfg.General.Language as fallback" ], "verify": [ "Transcription edit no longer shows language field", "Model selection still works", "Language validation still occurs using effective language", "Typecheck passes" ], "passes": true }, { "title": "Enable streaming models in TUI model picker", "steps": [ "Update internal/tui/configure_transcription.go getTranscriptionModelOptions()", "Remove the 'if m.Streaming { continue }' filter that skips streaming models", "Ensure buildModelLabel already adds [streaming] tag (verify it does)", "Streaming models should now appear in the list with [streaming] indicator" ], "verify": [ "scribe_v1-streaming, scribe_v2-streaming appear for ElevenLabs", "nova-3, nova-2 appear for Deepgram (streaming-only)", "gpt-4o-realtime-preview appears for OpenAI", "All streaming models show [streaming] tag in label", "Typecheck passes" ], "passes": true }, { "title": "Add streaming section header in model picker", "steps": [ "Update getTranscriptionModelOptions() to group models into batch and streaming", "Add visual separator or section headers: 'Batch Models' and 'Streaming Models'", "List batch models first, then streaming models", "Use huh.NewOption with description to show streaming info" ], "verify": [ "Model picker shows batch models grouped together", "Model picker shows streaming models grouped together", "Clear visual distinction between batch and streaming sections", "Typecheck passes" ], "passes": true }, { "title": "Add docs URLs to provider models", "steps": [ "Add DocsURL string field to Model struct in internal/provider/model.go", "Update each provider to set DocsURL for models pointing to language support docs:", " - OpenAI: 'https://platform.openai.com/docs/guides/speech-to-text#supported-languages'", " - Groq: 'https://console.groq.com/docs/speech-to-text#supported-languages'", " - ElevenLabs: 'https://elevenlabs.io/docs/capabilities/speech-to-text#supported-languages'", " - Deepgram: 'https://developers.deepgram.com/docs/language'", " - whisper-cpp: 'https://github.com/openai/whisper#available-models-and-languages'", " - Mistral: 'https://docs.mistral.ai/capabilities/speech/'" ], "verify": [ "Model struct has DocsURL field", "All transcription models have DocsURL set", "URLs point to correct language support documentation", "Typecheck passes" ], "passes": true }, { "title": "Improve language-model compatibility error messages", "steps": [ "Update ValidateModelLanguageCompatibility in internal/config/validate.go", "Error message format: 'Model {name} does not support {language}. See {docsURL} for supported languages. Supported: {first 5 languages}...'", "Lookup model to get DocsURL using provider.GetModel()", "Include both the docs URL and a truncated list of supported languages", "Update error in internal/tui/configure_transcription.go to show this improved message" ], "verify": [ "Error includes model name and language name (not just code)", "Error includes docs URL", "Error includes first few supported languages", "Error is actionable and clear", "Typecheck passes" ], "passes": true }, { "title": "Update config validation for general language", "steps": [ "Update internal/config/validate.go to validate general.language if set", "Use language.IsValidCode() for validation", "Validate that effective language (general or transcription override) is compatible with selected model", "Add clear error when general language set but overridden by transcription language" ], "verify": [ "Invalid general.language code warns user", "Effective language validated against model", "Config with general.language='invalid' warns but doesn't hard fail", "Typecheck passes" ], "passes": true }, { "title": "Update README and docs for general language setting", "steps": [ "Update README.md to show language in [general] section in example config", "Update docs/config.md to document [general] section and language field", "Add note that transcription.language can override general.language", "Update any references to transcription.language to point to general.language" ], "verify": [ "README shows language under [general]", "docs/config.md documents general section", "Override behavior documented", "Typecheck passes" ], "passes": true }, { "title": "Add migration for existing configs", "steps": [ "Update internal/config/load.go to migrate old configs", "If transcription.language is set but general.language is not, copy to general.language", "Log info message about migration: 'Migrated language setting to [general] section'", "Only migrate on load, don't modify file until user saves" ], "verify": [ "Old config with transcription.language='es' loads with general.language='es'", "Migration logged when it occurs", "Original file not modified until explicit save", "Typecheck passes" ], "passes": false } ] }