fix(tts): treat Add-dialog default URL as a configured credential path (#1482)

addCustomTTSProvider stores the dialog Base URL in customDefaultBaseUrl and leaves baseUrl empty. isTTSProviderConfigured ignored that field, so generation silently skipped narration even after Test TTS succeeded. Accept the dialog URL so already-saved custom providers start working without retyping the field.

Fixes #1471

Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn>
This commit is contained in:
DDL
2026-09-15 16:20:36 +08:00
committed by GitHub
co-authored by wyuc
parent 1da720377c
commit 1271cba69e
2 changed files with 30 additions and 1 deletions
+9 -1
View File
@@ -31,6 +31,11 @@ export const BROWSER_NATIVE_TTS_PROVIDER_ID = 'browser-native-tts' as const;
export interface TTSEnablementConfig {
apiKey?: string;
baseUrl?: string;
/**
* Dialog-supplied default URL for custom providers. `addCustomTTSProvider`
* writes this and leaves `baseUrl` empty; Test TTS already falls back to it.
*/
customDefaultBaseUrl?: string;
/** User-level per-provider toggle. Absent / true ⇒ allowed; false ⇒ hidden. */
enabled?: boolean;
isServerConfigured?: boolean;
@@ -69,7 +74,10 @@ export function isTTSProviderConfigured(
// A custom provider is usable once it has a credential path or any voices
// the user defined for it (its existing visibility rule).
return (
hasText(config.apiKey) || hasText(config.baseUrl) || (config.customVoices?.length ?? 0) > 0
hasText(config.apiKey) ||
hasText(config.baseUrl) ||
hasText(config.customDefaultBaseUrl) ||
(config.customVoices?.length ?? 0) > 0
);
}
+21
View File
@@ -50,10 +50,31 @@ describe('isTTSProviderConfigured', () => {
it('custom provider is configured once it has a credential path or voices', () => {
expect(isTTSProviderConfigured('custom-tts-foo', {})).toBe(false);
expect(isTTSProviderConfigured('custom-tts-foo', { apiKey: 'k' })).toBe(true);
expect(isTTSProviderConfigured('custom-tts-foo', { baseUrl: 'http://127.0.0.1:8020/v1' })).toBe(
true,
);
expect(
isTTSProviderConfigured('custom-tts-foo', { customVoices: [{ id: 'v', name: 'V' }] }),
).toBe(true);
});
it('treats the Add-dialog default base URL as a credential path', () => {
// addCustomTTSProvider persists the dialog URL on customDefaultBaseUrl and
// leaves baseUrl empty. Test TTS already honours that fallback; generation
// must too, or isTTSProviderEnabled stays false and narration is skipped.
expect(
isTTSProviderConfigured('custom-tts-foo', {
customDefaultBaseUrl: 'http://127.0.0.1:8020/v1',
}),
).toBe(true);
expect(
isTTSProviderEnabled('custom-tts-foo', {
customDefaultBaseUrl: 'http://127.0.0.1:8020/v1',
enabled: true,
}),
).toBe(true);
expect(isTTSProviderConfigured('custom-tts-foo', { customDefaultBaseUrl: ' ' })).toBe(false);
});
});
describe('isTTSProviderEnabled', () => {