mirror of
https://github.com/openclaw/openclaw.git
synced 2026-08-26 12:26:38 -06:00
refactor(tts): consolidate speech provider ordering (#129508)
Amp-Thread-ID: https://ampcode.com/threads/T-01a037b7-785b-75eb-8426-ad67094e61d4 Co-authored-by: Amp <amp@ampcode.com>
This commit is contained in:
committed by
GitHub
parent
43ffe41a4b
commit
73294a85f2
+3
-13
@@ -4,6 +4,7 @@ import type { OpenClawConfig } from "../config/types.js";
|
||||
import type { AssistantDeliveryTtsFacts } from "../llm/types.js";
|
||||
import type { SpeechProviderPlugin } from "../plugins/types.js";
|
||||
import { extractTtsDirectiveFacts } from "./directive-facts.js";
|
||||
import { compareSpeechProviderOrder } from "./provider-registry-core.js";
|
||||
import { listSpeechProviders } from "./provider-registry.js";
|
||||
import type {
|
||||
SpeechModelOverridePolicy,
|
||||
@@ -31,20 +32,9 @@ type TtsDirectiveTextStreamCleaner = {
|
||||
hasBufferedDirectiveText: () => boolean;
|
||||
};
|
||||
|
||||
function buildProviderOrder(left: SpeechProviderPlugin, right: SpeechProviderPlugin): number {
|
||||
const leftOrder = left.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = right.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
return left.id.localeCompare(right.id);
|
||||
}
|
||||
|
||||
function resolveDirectiveProviders(options?: ParseTtsDirectiveOptions): SpeechProviderPlugin[] {
|
||||
if (options?.providers) {
|
||||
return [...options.providers].toSorted(buildProviderOrder);
|
||||
}
|
||||
return listSpeechProviders(options?.cfg).toSorted(buildProviderOrder);
|
||||
const providers = options?.providers ?? listSpeechProviders(options?.cfg);
|
||||
return providers.toSorted(compareSpeechProviderOrder);
|
||||
}
|
||||
|
||||
function resolveDirectiveProviderConfig(
|
||||
|
||||
@@ -20,6 +20,19 @@ export function normalizeSpeechProviderId(
|
||||
return normalizeCapabilityProviderId(providerId);
|
||||
}
|
||||
|
||||
/** Order speech providers by priority and provider ID for deterministic equal-priority fallback. */
|
||||
export function compareSpeechProviderOrder(
|
||||
left: SpeechProviderPlugin,
|
||||
right: SpeechProviderPlugin,
|
||||
): number {
|
||||
const leftOrder = left.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = right.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
return left.id.localeCompare(right.id);
|
||||
}
|
||||
|
||||
/** Create a registry facade with canonical listing, alias lookup, and ID canonicalization. */
|
||||
export function createSpeechProviderRegistry(resolver: SpeechProviderRegistryResolver) {
|
||||
const buildResolvedProviderMaps = (cfg?: OpenClawConfig) =>
|
||||
|
||||
@@ -96,10 +96,11 @@ describe("speech provider registry", () => {
|
||||
expect(registry.canonicalizeSpeechProviderId("edge")).toBe("microsoft");
|
||||
});
|
||||
|
||||
it("resolves fallback order and aliases from a supplied provider inventory", () => {
|
||||
it("resolves deterministic fallback order and aliases from a supplied provider inventory", () => {
|
||||
const inventory = [
|
||||
{ ...createSpeechProvider("openai", ["oai"]), autoSelectOrder: 5 },
|
||||
{ ...createSpeechProvider("google"), autoSelectOrder: 1 },
|
||||
{ ...createSpeechProvider("azure"), autoSelectOrder: 1 },
|
||||
{ ...createSpeechProvider("elevenlabs"), autoSelectOrder: 3 },
|
||||
];
|
||||
|
||||
@@ -109,7 +110,7 @@ describe("speech provider registry", () => {
|
||||
undefined,
|
||||
inventory,
|
||||
),
|
||||
).toEqual(["openai", "google", "elevenlabs"]);
|
||||
).toEqual(["openai", "azure", "google", "elevenlabs"]);
|
||||
});
|
||||
|
||||
it("selects the first configured provider entirely from prepared facts", () => {
|
||||
|
||||
@@ -10,6 +10,7 @@ import type {
|
||||
TtsProvider,
|
||||
} from "../config/types.js";
|
||||
import type { SpeechProviderPlugin } from "../plugins/types.js";
|
||||
import { compareSpeechProviderOrder } from "./provider-registry-core.js";
|
||||
import {
|
||||
canonicalizeSpeechProviderId,
|
||||
getSpeechProvider,
|
||||
@@ -64,14 +65,7 @@ function sortSpeechProvidersForAutoSelection(
|
||||
cfg?: OpenClawConfig,
|
||||
providers?: readonly SpeechProviderPlugin[],
|
||||
) {
|
||||
return [...(providers ?? listSpeechProviders(cfg))].toSorted((left, right) => {
|
||||
const leftOrder = left.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
const rightOrder = right.autoSelectOrder ?? Number.MAX_SAFE_INTEGER;
|
||||
if (leftOrder !== rightOrder) {
|
||||
return leftOrder - rightOrder;
|
||||
}
|
||||
return left.id.localeCompare(right.id);
|
||||
});
|
||||
return [...(providers ?? listSpeechProviders(cfg))].toSorted(compareSpeechProviderOrder);
|
||||
}
|
||||
|
||||
function canonicalizeSpeechProviderIdFromInventory(
|
||||
|
||||
Reference in New Issue
Block a user