diff --git a/internal/provider/elevenlabs.go b/internal/provider/elevenlabs.go index fe7aed8..a3e6d42 100644 --- a/internal/provider/elevenlabs.go +++ b/internal/provider/elevenlabs.go @@ -23,13 +23,16 @@ func (p *ElevenLabsProvider) IsLocal() bool { } func (p *ElevenLabsProvider) Models() []Model { + // ElevenLabs Scribe supports 90+ languages, including all 57 from our master list + // See: https://elevenlabs.io/speech-to-text allLangs := language.AllLanguageCodes() return []Model{ + // batch models { ID: "scribe_v1", Name: "Scribe v1", - Description: "99 languages, best accuracy", + Description: "90+ languages, best accuracy", Type: Transcription, Streaming: false, Local: false, @@ -48,6 +51,29 @@ func (p *ElevenLabsProvider) Models() []Model { SupportedLanguages: allLangs, Endpoint: &EndpointConfig{BaseURL: "https://api.elevenlabs.io", Path: "/v1/speech-to-text"}, }, + // streaming models + { + ID: "scribe_v1-streaming", + Name: "Scribe v1 Streaming", + Description: "Real-time transcription, 90+ languages", + Type: Transcription, + Streaming: true, + Local: false, + AdapterType: "elevenlabs-streaming", + SupportedLanguages: allLangs, + Endpoint: &EndpointConfig{BaseURL: "wss://api.elevenlabs.io", Path: "/v1/speech-to-text/realtime"}, + }, + { + ID: "scribe_v2-streaming", + Name: "Scribe v2 Streaming", + Description: "Real-time with <150ms latency", + Type: Transcription, + Streaming: true, + Local: false, + AdapterType: "elevenlabs-streaming", + SupportedLanguages: allLangs, + Endpoint: &EndpointConfig{BaseURL: "wss://api.elevenlabs.io", Path: "/v1/speech-to-text/realtime"}, + }, } } diff --git a/internal/provider/provider_test.go b/internal/provider/provider_test.go index 3492364..6920049 100644 --- a/internal/provider/provider_test.go +++ b/internal/provider/provider_test.go @@ -262,3 +262,70 @@ func TestValidateModelLanguage(t *testing.T) { t.Error("ValidateModelLanguage with unknown model should return error") } } + +func TestElevenLabsProvider(t *testing.T) { + p := GetProvider("elevenlabs") + if p == nil { + t.Fatal("GetProvider('elevenlabs') returned nil") + } + + models := p.Models() + + // ElevenLabsProvider.Models() returns 4 models + if len(models) != 4 { + t.Errorf("ElevenLabsProvider.Models() = %d models, want 4", len(models)) + } + + // Check batch models + scribeV1, err := GetModel("elevenlabs", "scribe_v1") + if err != nil { + t.Fatalf("GetModel('elevenlabs', 'scribe_v1') error: %v", err) + } + if scribeV1.Streaming { + t.Error("scribe_v1 should have Streaming=false") + } + if scribeV1.AdapterType != "elevenlabs" { + t.Errorf("scribe_v1 AdapterType=%q, want 'elevenlabs'", scribeV1.AdapterType) + } + + scribeV2, err := GetModel("elevenlabs", "scribe_v2") + if err != nil { + t.Fatalf("GetModel('elevenlabs', 'scribe_v2') error: %v", err) + } + if scribeV2.Streaming { + t.Error("scribe_v2 should have Streaming=false") + } + if scribeV2.AdapterType != "elevenlabs" { + t.Errorf("scribe_v2 AdapterType=%q, want 'elevenlabs'", scribeV2.AdapterType) + } + + // Check streaming models + scribeV1S, err := GetModel("elevenlabs", "scribe_v1-streaming") + if err != nil { + t.Fatalf("GetModel('elevenlabs', 'scribe_v1-streaming') error: %v", err) + } + if !scribeV1S.Streaming { + t.Error("scribe_v1-streaming should have Streaming=true") + } + if scribeV1S.AdapterType != "elevenlabs-streaming" { + t.Errorf("scribe_v1-streaming AdapterType=%q, want 'elevenlabs-streaming'", scribeV1S.AdapterType) + } + + scribeV2S, err := GetModel("elevenlabs", "scribe_v2-streaming") + if err != nil { + t.Fatalf("GetModel('elevenlabs', 'scribe_v2-streaming') error: %v", err) + } + if !scribeV2S.Streaming { + t.Error("scribe_v2-streaming should have Streaming=true") + } + if scribeV2S.AdapterType != "elevenlabs-streaming" { + t.Errorf("scribe_v2-streaming AdapterType=%q, want 'elevenlabs-streaming'", scribeV2S.AdapterType) + } + + // All models have explicit SupportedLanguages from docs (subset of our 57) + for _, m := range models { + if len(m.SupportedLanguages) != 57 { + t.Errorf("model %q has %d languages, want 57", m.ID, len(m.SupportedLanguages)) + } + } +} diff --git a/progress.txt b/progress.txt index 1025cdb..aad1a8a 100644 --- a/progress.txt +++ b/progress.txt @@ -95,3 +95,12 @@ Started: Sun Feb 1 12:22:47 AM CET 2026 - SupportedLanguages set to all 57 language codes (multilingual per Mistral docs) - Researched Mistral API docs - language parameter is optional, no specific list of restrictions - All tests passing, typecheck passes + +### Task 11: Migrate ElevenLabs provider to new Model structure +- Added 4 models: 2 batch (scribe_v1, scribe_v2) + 2 streaming (scribe_v1-streaming, scribe_v2-streaming) +- Batch models: AdapterType='elevenlabs', Streaming=false, Endpoint.BaseURL='https://api.elevenlabs.io' +- Streaming models: AdapterType='elevenlabs-streaming', Streaming=true, Endpoint.BaseURL='wss://api.elevenlabs.io' +- Researched ElevenLabs docs: Scribe supports 90+ languages, including all 57 from our master list +- SupportedLanguages set to all 57 language codes +- Added TestElevenLabsProvider test verifying all requirements +- All tests passing, typecheck passes diff --git a/tasks/prd.jsonc b/tasks/prd.jsonc index 7c83f69..c79de61 100644 --- a/tasks/prd.jsonc +++ b/tasks/prd.jsonc @@ -288,7 +288,7 @@ "All models have explicit SupportedLanguages list from docs (subset of our 57)", "Typecheck passes" ], - "passes": false + "passes": true }, // ============================================================================ // PHASE 3: CONSOLIDATE BATCH ADAPTER IMPLEMENTATIONS