From cc3d77c2903e2cd4d5b24c24d6589032fa2288d2 Mon Sep 17 00:00:00 2001 From: Gustavo Madeira Santana Date: Sun, 15 Mar 2026 21:13:01 +0000 Subject: [PATCH] TTS: adopt backend catalog order --- .../runtime-backend-catalog.test.ts | 5 +++++ src/extension-host/runtime-backend-catalog.ts | 19 +++++++++++++++++++ src/extension-host/tts-runtime-setup.test.ts | 6 +++++- src/extension-host/tts-runtime-setup.ts | 5 ++--- src/extension-host/tts-status.test.ts | 6 +++++- src/extension-host/tts-status.ts | 6 +++--- src/tts/tts.test.ts | 5 +++++ src/tts/tts.ts | 10 ++++++---- 8 files changed, 50 insertions(+), 12 deletions(-) diff --git a/src/extension-host/runtime-backend-catalog.test.ts b/src/extension-host/runtime-backend-catalog.test.ts index 7f30bc31bfc..c6e6438e17e 100644 --- a/src/extension-host/runtime-backend-catalog.test.ts +++ b/src/extension-host/runtime-backend-catalog.test.ts @@ -117,6 +117,11 @@ describe("runtime-backend-catalog", () => { "elevenlabs", "edge", ]); + expect(catalog.resolveExtensionHostTtsRuntimeBackendOrder("edge")).toEqual([ + "edge", + "openai", + "elevenlabs", + ]); }); it("aggregates runtime-backend catalog entries across subsystem families", async () => { diff --git a/src/extension-host/runtime-backend-catalog.ts b/src/extension-host/runtime-backend-catalog.ts index f1d0e31b878..46e6ccd16df 100644 --- a/src/extension-host/runtime-backend-catalog.ts +++ b/src/extension-host/runtime-backend-catalog.ts @@ -235,12 +235,31 @@ export function listExtensionHostRuntimeBackendIdsForSubsystem( .map((entry) => entry.backendId); } +export function resolveExtensionHostRuntimeBackendOrderForSubsystem( + subsystemId: ExtensionHostRuntimeBackendSubsystemId, + preferredBackendId: string, +): readonly string[] { + const ordered = listExtensionHostRuntimeBackendIdsForSubsystem(subsystemId); + if (!ordered.includes(preferredBackendId)) { + return [preferredBackendId, ...ordered]; + } + return [preferredBackendId, ...ordered.filter((backendId) => backendId !== preferredBackendId)]; +} + export function listExtensionHostMediaRuntimeBackendIds( subsystemId: ExtensionHostMediaRuntimeSubsystemId, ): readonly string[] { return listExtensionHostRuntimeBackendIdsForSubsystem(subsystemId); } +export function resolveExtensionHostTtsRuntimeBackendOrder( + preferredBackendId: TtsProvider, +): readonly TtsProvider[] { + return resolveExtensionHostRuntimeBackendOrderForSubsystem("tts", preferredBackendId).map( + (backendId) => backendId as TtsProvider, + ); +} + export function listExtensionHostRuntimeBackendCatalogEntries(): readonly ExtensionHostRuntimeBackendCatalogEntry[] { return [ ...listExtensionHostEmbeddingRuntimeBackendCatalogEntries(), diff --git a/src/extension-host/tts-runtime-setup.test.ts b/src/extension-host/tts-runtime-setup.test.ts index ba31375b2a7..a96eb8fcc75 100644 --- a/src/extension-host/tts-runtime-setup.test.ts +++ b/src/extension-host/tts-runtime-setup.test.ts @@ -10,7 +10,11 @@ import { } from "./tts-runtime-setup.js"; vi.mock("./runtime-backend-catalog.js", () => ({ - listExtensionHostTtsRuntimeBackendIds: vi.fn(() => ["openai", "elevenlabs", "edge"]), + resolveExtensionHostTtsRuntimeBackendOrder: vi.fn((provider: string) => + [provider, "openai", "elevenlabs", "edge"].filter( + (candidate, index, items) => items.indexOf(candidate) === index, + ), + ), })); const tempDirs: string[] = []; diff --git a/src/extension-host/tts-runtime-setup.ts b/src/extension-host/tts-runtime-setup.ts index 6e15cf7e195..7886011f631 100644 --- a/src/extension-host/tts-runtime-setup.ts +++ b/src/extension-host/tts-runtime-setup.ts @@ -1,6 +1,6 @@ import { existsSync, readFileSync } from "node:fs"; import type { TtsProvider } from "../config/types.tts.js"; -import { listExtensionHostTtsRuntimeBackendIds } from "./runtime-backend-catalog.js"; +import { resolveExtensionHostTtsRuntimeBackendOrder } from "./runtime-backend-catalog.js"; import type { ResolvedTtsConfig } from "./tts-config.js"; import { resolveExtensionHostTtsApiKey } from "./tts-runtime-registry.js"; @@ -65,9 +65,8 @@ export function resolveExtensionHostTtsRequestSetup(params: { const provider = params.providerOverride ?? resolveExtensionHostTtsProvider(params.config, params.prefsPath); - const providerOrder = listExtensionHostTtsRuntimeBackendIds(); return { config: params.config, - providers: [provider, ...providerOrder.filter((candidate) => candidate !== provider)], + providers: [...resolveExtensionHostTtsRuntimeBackendOrder(provider)], }; } diff --git a/src/extension-host/tts-status.test.ts b/src/extension-host/tts-status.test.ts index 5a4e34beaf6..25be50e3993 100644 --- a/src/extension-host/tts-status.test.ts +++ b/src/extension-host/tts-status.test.ts @@ -6,7 +6,11 @@ import { } from "./tts-status.js"; vi.mock("./runtime-backend-catalog.js", () => ({ - listExtensionHostTtsRuntimeBackendIds: vi.fn(() => ["openai", "elevenlabs", "edge"]), + resolveExtensionHostTtsRuntimeBackendOrder: vi.fn((provider: string) => + [provider, "openai", "elevenlabs", "edge"].filter( + (candidate, index, items) => items.indexOf(candidate) === index, + ), + ), })); describe("tts-status", () => { diff --git a/src/extension-host/tts-status.ts b/src/extension-host/tts-status.ts index 41af9ad886f..f86a8ea2c02 100644 --- a/src/extension-host/tts-status.ts +++ b/src/extension-host/tts-status.ts @@ -1,5 +1,5 @@ import type { TtsProvider } from "../config/types.tts.js"; -import { listExtensionHostTtsRuntimeBackendIds } from "./runtime-backend-catalog.js"; +import { resolveExtensionHostTtsRuntimeBackendOrder } from "./runtime-backend-catalog.js"; import type { ResolvedTtsConfig } from "./tts-config.js"; import { getExtensionHostTtsMaxLength, @@ -57,8 +57,8 @@ export function resolveExtensionHostTtsStatusSnapshot(params: { }): ExtensionHostTtsStatusSnapshot { const { config, prefsPath } = params; const provider = resolveExtensionHostTtsProvider(config, prefsPath); - const fallbackProviders = listExtensionHostTtsRuntimeBackendIds() - .filter((candidate) => candidate !== provider) + const fallbackProviders = resolveExtensionHostTtsRuntimeBackendOrder(provider) + .slice(1) .filter((candidate) => isExtensionHostTtsProviderConfigured(config, candidate)); return { enabled: isExtensionHostTtsEnabled(config, prefsPath), diff --git a/src/tts/tts.test.ts b/src/tts/tts.test.ts index 8b232ed034d..ad1bdda1bcb 100644 --- a/src/tts/tts.test.ts +++ b/src/tts/tts.test.ts @@ -124,6 +124,11 @@ describe("tts", () => { ); }); + it("keeps compatibility provider exports aligned with the runtime-backend catalog", () => { + expect(tts.TTS_PROVIDERS).toEqual(["openai", "elevenlabs", "edge"]); + expect(tts.resolveTtsProviderOrder("edge")).toEqual(["edge", "openai", "elevenlabs"]); + }); + describe("isValidVoiceId", () => { it("validates ElevenLabs voice ID length and character rules", () => { const cases = [ diff --git a/src/tts/tts.ts b/src/tts/tts.ts index 1a527718298..51692a9dfcd 100644 --- a/src/tts/tts.ts +++ b/src/tts/tts.ts @@ -1,4 +1,8 @@ import type { TtsProvider } from "../config/types.tts.js"; +import { + listExtensionHostTtsRuntimeBackendIds, + resolveExtensionHostTtsRuntimeBackendOrder, +} from "../extension-host/runtime-backend-catalog.js"; import { applyExtensionHostTtsToPayload, buildExtensionHostTtsSystemPromptHint, @@ -26,10 +30,8 @@ import { setExtensionHostTtsSummarizationEnabled, } from "../extension-host/tts-preferences.js"; import { - EXTENSION_HOST_TTS_PROVIDER_IDS, isExtensionHostTtsProviderConfigured, resolveExtensionHostTtsApiKey, - resolveExtensionHostTtsProviderOrder, } from "../extension-host/tts-runtime-registry.js"; import { resolveExtensionHostTtsProvider } from "../extension-host/tts-runtime-setup.js"; import { @@ -129,11 +131,11 @@ export function setLastTtsAttempt(entry: TtsStatusEntry | undefined): void { setExtensionHostLastTtsAttempt(entry); } -export const TTS_PROVIDERS = EXTENSION_HOST_TTS_PROVIDER_IDS; +export const TTS_PROVIDERS = listExtensionHostTtsRuntimeBackendIds(); export const resolveTtsApiKey = resolveExtensionHostTtsApiKey; -export const resolveTtsProviderOrder = resolveExtensionHostTtsProviderOrder; +export const resolveTtsProviderOrder = resolveExtensionHostTtsRuntimeBackendOrder; export const isTtsProviderConfigured = isExtensionHostTtsProviderConfigured;