From 29215c03a557b6e7163ef952ad5ea4200deb9cf1 Mon Sep 17 00:00:00 2001 From: ayaangazali Date: Sat, 1 Aug 2026 00:53:13 -0700 Subject: [PATCH] fix(kotlin): gate synthesizeStream on ensureServicesReady before the voice lookup synthesizeStream() queried the model lifecycle for a loaded speech synthesis voice without first waiting for phase 2 initialisation. If a caller starts streaming before phase 2 finishes, currentModel reports found = false and the Flow closes without emitting, so a voice that is actually present looks like no voice at all. Every sibling already gates on this: synthesize() calls ensureServicesReady() before the same lifecycle query, transcribeStream() calls it before its own, and Swift's synthesizeStream awaits it before reading loadedModelSnapshot. Add the missing call. Signed-off-by: ayaangazali --- .../runanywhere/sdk/public/extensions/TTS/RunAnywhereTTS.kt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sdk/runanywhere-kotlin/src/main/kotlin/com/runanywhere/sdk/public/extensions/TTS/RunAnywhereTTS.kt b/sdk/runanywhere-kotlin/src/main/kotlin/com/runanywhere/sdk/public/extensions/TTS/RunAnywhereTTS.kt index b689e6c11b..5f26231273 100644 --- a/sdk/runanywhere-kotlin/src/main/kotlin/com/runanywhere/sdk/public/extensions/TTS/RunAnywhereTTS.kt +++ b/sdk/runanywhere-kotlin/src/main/kotlin/com/runanywhere/sdk/public/extensions/TTS/RunAnywhereTTS.kt @@ -94,6 +94,11 @@ fun RunAnywhere.synthesizeStream( close() return@callbackFlow } + // Phase 2 must have completed before the lifecycle query below, or a + // voice that is present is reported as missing. synthesize() and + // transcribeStream() already gate on this, as does Swift's + // synthesizeStream. + ensureServicesReady() // Mirror synthesize(): query ModelLifecycle (the canonical source of // truth) instead of CppBridgeTTS's own handle. Swift's