From f690c107d7cb540aa8a68d7e6dfc9e3a3ac3758e Mon Sep 17 00:00:00 2001 From: Amp Date: Wed, 12 Aug 2026 05:20:56 +0000 Subject: [PATCH] refactor(inworld): consolidate speech requests Amp-Thread-ID: https://ampcode.com/threads/T-019ff438-3b93-77b8-9828-1d3c586cb127 --- extensions/inworld/speech-provider.ts | 80 ++++++++++++--------------- 1 file changed, 36 insertions(+), 44 deletions(-) diff --git a/extensions/inworld/speech-provider.ts b/extensions/inworld/speech-provider.ts index 9886aa962d04..79674a70b495 100644 --- a/extensions/inworld/speech-provider.ts +++ b/extensions/inworld/speech-provider.ts @@ -30,10 +30,13 @@ type InworldProviderConfig = { temperature?: number; }; -type InworldProviderOverrides = { - voiceId?: string; - modelId?: string; - temperature?: number; +type InworldSynthesisRequest = { + text: string; + providerConfig: SpeechProviderConfig; + providerOverrides?: SpeechProviderOverrides; + timeoutMs: number; + audioEncoding: InworldAudioEncoding; + sampleRateHertz?: number; }; function normalizeInworldTemperature(value: unknown): number | undefined { @@ -70,19 +73,35 @@ function resolveInworldApiKey(primary?: string, fallback?: string): string | und return resolveSpeechProviderApiKey(primary, fallback, process.env.INWORLD_API_KEY); } -function readInworldOverrides( - overrides: SpeechProviderOverrides | undefined, -): InworldProviderOverrides { - if (!overrides) { - return {}; - } +function readInworldOverrides(overrides: SpeechProviderOverrides | undefined) { return { - voiceId: trimToUndefined(overrides.voiceId ?? overrides.voice), - modelId: trimToUndefined(overrides.modelId ?? overrides.model), - temperature: normalizeInworldTemperature(overrides.temperature), + voiceId: trimToUndefined(overrides?.voiceId ?? overrides?.voice), + modelId: trimToUndefined(overrides?.modelId ?? overrides?.model), + temperature: normalizeInworldTemperature(overrides?.temperature), }; } +async function synthesizeInworld(req: InworldSynthesisRequest): Promise { + const config = readInworldProviderConfig(req.providerConfig); + const overrides = readInworldOverrides(req.providerOverrides); + const apiKey = resolveInworldApiKey(config.apiKey); + if (!apiKey) { + throw new Error("Inworld API key missing"); + } + + return inworldTTS({ + text: req.text, + apiKey, + baseUrl: config.baseUrl, + voiceId: overrides.voiceId ?? config.voiceId, + modelId: overrides.modelId ?? config.modelId, + audioEncoding: req.audioEncoding, + ...(req.sampleRateHertz === undefined ? {} : { sampleRateHertz: req.sampleRateHertz }), + temperature: overrides.temperature ?? config.temperature, + timeoutMs: req.timeoutMs, + }); +} + function parseDirectiveToken(ctx: SpeechDirectiveTokenParseContext): { handled: boolean; overrides?: SpeechProviderOverrides; @@ -181,25 +200,11 @@ export function buildInworldSpeechProvider(): SpeechProviderPlugin { isConfigured: ({ providerConfig }) => Boolean(resolveInworldApiKey(readInworldProviderConfig(providerConfig).apiKey)), synthesize: async (req) => { - const config = readInworldProviderConfig(req.providerConfig); - const overrides = readInworldOverrides(req.providerOverrides); - const apiKey = resolveInworldApiKey(config.apiKey); - if (!apiKey) { - throw new Error("Inworld API key missing"); - } - const useOpus = req.target === "voice-note"; const audioEncoding: InworldAudioEncoding = useOpus ? "OGG_OPUS" : "MP3"; - - const audioBuffer = await inworldTTS({ - text: req.text, - apiKey, - baseUrl: config.baseUrl, - voiceId: overrides.voiceId ?? config.voiceId, - modelId: overrides.modelId ?? config.modelId, + const audioBuffer = await synthesizeInworld({ + ...req, audioEncoding, - temperature: overrides.temperature ?? config.temperature, - timeoutMs: req.timeoutMs, }); return { @@ -210,24 +215,11 @@ export function buildInworldSpeechProvider(): SpeechProviderPlugin { }; }, synthesizeTelephony: async (req) => { - const config = readInworldProviderConfig(req.providerConfig); - const overrides = readInworldOverrides(req.providerOverrides); - const apiKey = resolveInworldApiKey(config.apiKey); - if (!apiKey) { - throw new Error("Inworld API key missing"); - } - const sampleRate = 22_050; - const audioBuffer = await inworldTTS({ - text: req.text, - apiKey, - baseUrl: config.baseUrl, - voiceId: overrides.voiceId ?? config.voiceId, - modelId: overrides.modelId ?? config.modelId, + const audioBuffer = await synthesizeInworld({ + ...req, audioEncoding: "PCM", sampleRateHertz: sampleRate, - temperature: overrides.temperature ?? config.temperature, - timeoutMs: req.timeoutMs, }); return { audioBuffer, outputFormat: "pcm", sampleRate };