80 lines
2.9 KiB
TypeScript
80 lines
2.9 KiB
TypeScript
/**
|
|
* Per-agent voice overrides (persisted in settings) take precedence over the
|
|
* agent's registry voiceConfig and the deterministic fallback, with the same
|
|
* enablement validation as voiceConfig.
|
|
*/
|
|
import { describe, it, expect } from 'vitest';
|
|
import type { AgentConfig } from '@/lib/orchestration/registry/types';
|
|
import { resolveAgentVoice, type ProviderWithVoices } from '@/lib/audio/voice-resolver';
|
|
|
|
const agent = (id: string, voiceConfig?: AgentConfig['voiceConfig']) =>
|
|
({ id, voiceConfig }) as AgentConfig;
|
|
|
|
const qwen: ProviderWithVoices = {
|
|
providerId: 'qwen-tts',
|
|
providerName: 'Qwen TTS',
|
|
voices: [
|
|
{ id: 'Cherry', name: 'Cherry' },
|
|
{ id: 'Dylan', name: 'Dylan' },
|
|
],
|
|
modelGroups: [],
|
|
};
|
|
|
|
describe('resolveAgentVoice with overrides', () => {
|
|
it('prefers the override over voiceConfig and fallback', () => {
|
|
const resolved = resolveAgentVoice(
|
|
agent('default-2', { providerId: 'qwen-tts', voiceId: 'Cherry' }),
|
|
0,
|
|
[qwen],
|
|
{ 'default-2': { providerId: 'qwen-tts', voiceId: 'Dylan' } },
|
|
);
|
|
expect(resolved).toEqual({ providerId: 'qwen-tts', modelId: undefined, voiceId: 'Dylan' });
|
|
});
|
|
|
|
it('ignores an override whose provider is not enabled, falling back to voiceConfig', () => {
|
|
const resolved = resolveAgentVoice(
|
|
agent('default-2', { providerId: 'qwen-tts', voiceId: 'Cherry' }),
|
|
0,
|
|
[qwen],
|
|
{ 'default-2': { providerId: 'openai-tts', voiceId: 'alloy' } },
|
|
);
|
|
expect(resolved).toEqual({ providerId: 'qwen-tts', modelId: undefined, voiceId: 'Cherry' });
|
|
});
|
|
|
|
it('ignores an override whose voice is unknown to the provider', () => {
|
|
const resolved = resolveAgentVoice(agent('default-2'), 1, [qwen], {
|
|
'default-2': { providerId: 'qwen-tts', voiceId: 'NotAVoice' },
|
|
});
|
|
// falls through to deterministic fallback: voices[1 % 2] = Dylan
|
|
expect(resolved).toEqual({ providerId: 'qwen-tts', voiceId: 'Dylan' });
|
|
});
|
|
|
|
it('only applies the override of the matching agent id', () => {
|
|
const resolved = resolveAgentVoice(agent('default-3'), 0, [qwen], {
|
|
'default-2': { providerId: 'qwen-tts', voiceId: 'Dylan' },
|
|
});
|
|
expect(resolved).toEqual({ providerId: 'qwen-tts', voiceId: 'Cherry' });
|
|
});
|
|
|
|
it('honors a browser-native override only when browser-native is selectable', () => {
|
|
const browserNative: ProviderWithVoices = {
|
|
providerId: 'browser-native-tts',
|
|
providerName: 'Browser',
|
|
voices: [{ id: 'Anna', name: 'Anna' }],
|
|
modelGroups: [],
|
|
};
|
|
const override = {
|
|
'default-2': { providerId: 'browser-native-tts' as const, voiceId: 'Anna' },
|
|
};
|
|
expect(resolveAgentVoice(agent('default-2'), 0, [qwen], override)).toEqual({
|
|
providerId: 'qwen-tts',
|
|
voiceId: 'Cherry',
|
|
});
|
|
expect(resolveAgentVoice(agent('default-2'), 0, [qwen, browserNative], override)).toEqual({
|
|
providerId: 'browser-native-tts',
|
|
modelId: undefined,
|
|
voiceId: 'Anna',
|
|
});
|
|
});
|
|
});
|