refactor provider interface to return models with metadata

- replaced old TranscriptionModels/LLMModels/SupportsX methods with Models() []Model
- added DefaultModel(t ModelType), IsLocal() to interface
- added helpers: GetModel, ModelsOfType, FindModelByID, ModelsForLanguage, ValidateModelLanguage
- all providers now return full Model metadata with SupportedLanguages, AdapterType, Endpoint
- groq distil-whisper-large-v3-en marked as english-only
- updated TUI to use new interface
This commit is contained in:
leonardotrapani
2026-02-01 00:33:20 +01:00
parent 51aba743f8
commit c23ac60b8f
10 changed files with 498 additions and 98 deletions
+106 -8
View File
@@ -1,16 +1,19 @@
package provider
import (
"errors"
"fmt"
"strings"
)
// Provider defines the interface for a transcription/LLM service provider
type Provider interface {
Name() string
RequiresAPIKey() bool
ValidateAPIKey(key string) bool
SupportsTranscription() bool
SupportsLLM() bool
DefaultTranscriptionModel() string
DefaultLLMModel() string
TranscriptionModels() []string
LLMModels() []string
IsLocal() bool
Models() []Model
DefaultModel(t ModelType) string
}
// ProviderConfig holds configuration for a single provider
@@ -50,7 +53,7 @@ func ListProviders() []string {
func ListProvidersWithTranscription() []string {
var names []string
for name, p := range registry {
if p.SupportsTranscription() {
if hasModelsOfType(p, Transcription) {
names = append(names, name)
}
}
@@ -61,9 +64,104 @@ func ListProvidersWithTranscription() []string {
func ListProvidersWithLLM() []string {
var names []string
for name, p := range registry {
if p.SupportsLLM() {
if hasModelsOfType(p, LLM) {
names = append(names, name)
}
}
return names
}
// hasModelsOfType returns true if provider has any models of the given type
func hasModelsOfType(p Provider, t ModelType) bool {
for _, m := range p.Models() {
if m.Type == t {
return true
}
}
return false
}
// GetModel returns a model from a specific provider, or error if not found
func GetModel(providerName, modelID string) (*Model, error) {
p := GetProvider(providerName)
if p == nil {
return nil, fmt.Errorf("unknown provider: %s", providerName)
}
for _, m := range p.Models() {
if m.ID == modelID {
return &m, nil
}
}
return nil, fmt.Errorf("model %s not found in provider %s", modelID, providerName)
}
// ModelsOfType returns all models of the given type from a provider
func ModelsOfType(p Provider, t ModelType) []Model {
var result []Model
for _, m := range p.Models() {
if m.Type == t {
result = append(result, m)
}
}
return result
}
// FindModelByID searches all providers for a model with the given ID
func FindModelByID(modelID string) (*Model, Provider, error) {
for _, p := range registry {
for _, m := range p.Models() {
if m.ID == modelID {
return &m, p, nil
}
}
}
return nil, nil, fmt.Errorf("model %s not found in any provider", modelID)
}
// ModelsForLanguage returns models from a provider that support the given language
func ModelsForLanguage(p Provider, t ModelType, langCode string) []Model {
var result []Model
for _, m := range p.Models() {
if m.Type == t && m.SupportsLanguage(langCode) {
result = append(result, m)
}
}
return result
}
// ValidateModelLanguage checks if a model supports the given language.
// Returns error with list of supported languages if not supported.
// Returns nil if langCode is "" (auto) - auto is always supported.
func ValidateModelLanguage(providerName, modelID, langCode string) error {
if langCode == "" {
return nil // auto always supported
}
model, err := GetModel(providerName, modelID)
if err != nil {
return err
}
if model.SupportsLanguage(langCode) {
return nil
}
// truncate supported languages list for error message
supported := model.SupportedLanguages
if len(supported) > 10 {
supported = append(supported[:10], "...")
}
return fmt.Errorf(
"model %s does not support language '%s'. Supported: %s",
modelID,
langCode,
strings.Join(supported, ", "),
)
}
var (
ErrProviderNotFound = errors.New("provider not found")
ErrModelNotFound = errors.New("model not found")
)