2026-03-01 08:31:04 +00:00
|
|
|
package voice
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"testing"
|
2026-03-01 21:02:16 +00:00
|
|
|
|
|
|
|
|
"github.com/sipeed/picoclaw/pkg/config"
|
2026-03-01 08:31:04 +00:00
|
|
|
)
|
|
|
|
|
|
2026-03-01 21:02:16 +00:00
|
|
|
func TestDetectTranscriber(t *testing.T) {
|
2026-03-01 08:31:04 +00:00
|
|
|
tests := []struct {
|
2026-03-04 10:21:59 +00:00
|
|
|
name string
|
|
|
|
|
cfg *config.Config
|
|
|
|
|
wantNil bool
|
|
|
|
|
wantName string
|
2026-03-01 08:31:04 +00:00
|
|
|
}{
|
2026-03-01 21:02:16 +00:00
|
|
|
{
|
|
|
|
|
name: "no config",
|
|
|
|
|
cfg: &config.Config{},
|
|
|
|
|
wantNil: true,
|
|
|
|
|
},
|
2026-03-22 11:51:32 +00:00
|
|
|
{
|
|
|
|
|
name: "voice model name selects audio model transcriber",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-22 11:51:32 +00:00
|
|
|
Voice: config.VoiceConfig{ModelName: "voice-gemini"},
|
2026-03-23 02:54:08 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "voice-gemini",
|
|
|
|
|
Model: "gemini/gemini-2.5-flash",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-gemini-model"),
|
2026-03-23 02:54:08 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-22 11:51:32 +00:00
|
|
|
wantName: "audio-model",
|
|
|
|
|
},
|
2026-03-01 21:02:16 +00:00
|
|
|
{
|
|
|
|
|
name: "groq via model list",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-21 17:55:00 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{ModelName: "openai", Model: "openai/gpt-4o", APIKeys: config.SimpleSecureStrings("sk-openai")},
|
|
|
|
|
{
|
|
|
|
|
ModelName: "groq",
|
|
|
|
|
Model: "groq/llama-3.3-70b",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-groq-model"),
|
2026-03-21 17:55:00 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-01 21:02:16 +00:00
|
|
|
wantName: "groq",
|
|
|
|
|
},
|
2026-03-22 11:51:32 +00:00
|
|
|
{
|
|
|
|
|
name: "voice model name selects non-gemini audio model transcriber",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-22 11:51:32 +00:00
|
|
|
Voice: config.VoiceConfig{ModelName: "voice-openai-audio"},
|
2026-03-23 02:54:08 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "voice-openai-audio",
|
|
|
|
|
Model: "openai/gpt-4o-audio-preview",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-openai"),
|
2026-03-23 02:54:08 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-22 11:51:32 +00:00
|
|
|
wantName: "audio-model",
|
|
|
|
|
},
|
2026-03-22 15:40:13 +00:00
|
|
|
{
|
|
|
|
|
name: "voice model name selects azure audio model transcriber",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-22 15:40:13 +00:00
|
|
|
Voice: config.VoiceConfig{ModelName: "voice-azure-audio"},
|
2026-03-23 02:54:08 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-22 15:40:13 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "voice-azure-audio",
|
2026-03-27 16:03:34 +00:00
|
|
|
Model: "azure/my-audio-deployment", APIKeys: config.SimpleSecureStrings("sk-azure"),
|
|
|
|
|
APIBase: "https://example.openai.azure.com",
|
2026-03-22 15:40:13 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-22 15:40:13 +00:00
|
|
|
wantName: "audio-model",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "voice model name with non openai compatible protocol does not select audio model transcriber",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-22 15:40:13 +00:00
|
|
|
Voice: config.VoiceConfig{ModelName: "voice-anthropic"},
|
2026-03-23 02:54:08 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "voice-anthropic",
|
|
|
|
|
Model: "anthropic/claude-sonnet-4.6",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-anthropic"),
|
2026-03-23 02:54:08 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-22 15:40:13 +00:00
|
|
|
wantNil: true,
|
|
|
|
|
},
|
2026-03-01 21:02:16 +00:00
|
|
|
{
|
|
|
|
|
name: "groq model list entry without key is skipped",
|
|
|
|
|
cfg: &config.Config{
|
2026-03-21 17:55:00 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
|
|
|
|
{Model: "groq/llama-3.3-70b"},
|
2026-03-01 21:02:16 +00:00
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
wantNil: true,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "provider key takes priority over model list",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-21 17:55:00 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "groq",
|
|
|
|
|
Model: "groq/llama-3.3-70b",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-groq-model"),
|
2026-03-21 17:55:00 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-01 21:02:16 +00:00
|
|
|
wantName: "groq",
|
|
|
|
|
},
|
2026-03-22 11:51:32 +00:00
|
|
|
{
|
|
|
|
|
name: "missing voice model name config returns nil",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-22 11:51:32 +00:00
|
|
|
Voice: config.VoiceConfig{ModelName: "missing"},
|
2026-03-23 02:54:08 +00:00
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "other",
|
|
|
|
|
Model: "gemini/gemini-2.5-flash",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-other-model"),
|
2026-03-23 02:54:08 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-22 11:51:32 +00:00
|
|
|
wantNil: true,
|
|
|
|
|
},
|
2026-03-23 21:11:10 +00:00
|
|
|
{
|
|
|
|
|
name: "elevenlabs voice config key",
|
|
|
|
|
cfg: &config.Config{
|
|
|
|
|
Voice: config.VoiceConfig{ElevenLabsAPIKey: "sk_elevenlabs_test"},
|
|
|
|
|
},
|
|
|
|
|
wantName: "elevenlabs",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "elevenlabs takes priority over groq model list",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-23 21:11:10 +00:00
|
|
|
Voice: config.VoiceConfig{ElevenLabsAPIKey: "sk_elevenlabs_test"},
|
|
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "groq",
|
|
|
|
|
Model: "groq/llama-3.3-70b",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-groq-model"),
|
2026-03-23 21:11:10 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-23 21:11:10 +00:00
|
|
|
wantName: "elevenlabs",
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "voice model name takes priority over elevenlabs",
|
2026-03-27 16:03:34 +00:00
|
|
|
cfg: &config.Config{
|
2026-03-23 21:11:10 +00:00
|
|
|
Voice: config.VoiceConfig{
|
|
|
|
|
ModelName: "voice-gemini",
|
|
|
|
|
ElevenLabsAPIKey: "sk_elevenlabs_test",
|
|
|
|
|
},
|
|
|
|
|
ModelList: []*config.ModelConfig{
|
2026-03-27 16:03:34 +00:00
|
|
|
{
|
|
|
|
|
ModelName: "voice-gemini",
|
|
|
|
|
Model: "gemini/gemini-2.5-flash",
|
|
|
|
|
APIKeys: config.SimpleSecureStrings("sk-gemini-model"),
|
2026-03-23 21:11:10 +00:00
|
|
|
},
|
|
|
|
|
},
|
2026-03-27 16:03:34 +00:00
|
|
|
},
|
2026-03-23 21:11:10 +00:00
|
|
|
wantName: "audio-model",
|
|
|
|
|
},
|
2026-03-01 08:31:04 +00:00
|
|
|
}
|
2026-03-01 21:02:16 +00:00
|
|
|
|
2026-03-01 08:31:04 +00:00
|
|
|
for _, tc := range tests {
|
|
|
|
|
t.Run(tc.name, func(t *testing.T) {
|
2026-03-01 21:02:16 +00:00
|
|
|
tr := DetectTranscriber(tc.cfg)
|
|
|
|
|
if tc.wantNil {
|
|
|
|
|
if tr != nil {
|
|
|
|
|
t.Errorf("DetectTranscriber() = %v, want nil", tr)
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if tr == nil {
|
|
|
|
|
t.Fatal("DetectTranscriber() = nil, want non-nil")
|
|
|
|
|
}
|
|
|
|
|
if got := tr.Name(); got != tc.wantName {
|
|
|
|
|
t.Errorf("Name() = %q, want %q", got, tc.wantName)
|
2026-03-01 08:31:04 +00:00
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|