From e179a3291bde494c85a8d0147b3397a7c23b1dbd Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 08:02:49 -0300 Subject: [PATCH 01/17] improve: add empty-text guard and retry for Edge TTS Follow-up to PR #43385 Implements reviewer suggestions: - Add pre-check for empty or whitespace-only text - Retry once if Edge TTS produces a zero-byte file - Include file size in error message for debugging --- src/tts/tts-core.ts | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 5d3000d7ad3..da464d828a8 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -703,6 +703,7 @@ export async function edgeTTS(params: { timeoutMs: number; }): Promise { const { text, outputPath, config, timeoutMs } = params; + const tts = new EdgeTTS({ voice: config.voice, lang: config.lang, @@ -714,11 +715,23 @@ export async function edgeTTS(params: { volume: config.volume, timeout: config.timeoutMs ?? timeoutMs, }); + + + if (!text || text.trim().length === 0) { + throw new Error("TTS text cannot be empty"); + } + await tts.ttsPromise(text, outputPath); - const { size } = statSync(outputPath); + let { size } = statSync(outputPath); if (size === 0) { - throw new Error("Edge TTS produced empty audio file"); + + await tts.ttsPromise(text, outputPath); + ({ size } = statSync(outputPath)); + + if (size === 0) { + throw new Error(`Edge TTS produced empty audio file (size=${size})`); + } } } From 729ef4f2679ee293567d2ce0cbdee9ac22c8f969 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 08:27:42 -0300 Subject: [PATCH 02/17] fix: address review comments (guard order + error message) --- src/tts/tts-core.ts | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index da464d828a8..a0c112d82bb 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -681,6 +681,7 @@ export async function openaiTTS(params: { export function inferEdgeExtension(outputFormat: string): string { const normalized = outputFormat.toLowerCase(); + if (normalized.includes("webm")) { return ".webm"; } @@ -690,9 +691,14 @@ export function inferEdgeExtension(outputFormat: string): string { if (normalized.includes("opus")) { return ".opus"; } - if (normalized.includes("wav") || normalized.includes("riff") || normalized.includes("pcm")) { + if ( + normalized.includes("wav") || + normalized.includes("riff") || + normalized.includes("pcm") + ) { return ".wav"; } + return ".mp3"; } @@ -704,6 +710,11 @@ export async function edgeTTS(params: { }): Promise { const { text, outputPath, config, timeoutMs } = params; + + if (!text || text.trim().length === 0) { + throw new Error("TTS text cannot be empty"); + } + const tts = new EdgeTTS({ voice: config.voice, lang: config.lang, @@ -716,11 +727,6 @@ export async function edgeTTS(params: { timeout: config.timeoutMs ?? timeoutMs, }); - - if (!text || text.trim().length === 0) { - throw new Error("TTS text cannot be empty"); - } - await tts.ttsPromise(text, outputPath); let { size } = statSync(outputPath); @@ -731,7 +737,7 @@ export async function edgeTTS(params: { ({ size } = statSync(outputPath)); if (size === 0) { - throw new Error(`Edge TTS produced empty audio file (size=${size})`); + throw new Error("Edge TTS produced empty audio file after retry"); } } } From 8f48af6ab881705c752bd19fcfe9a01abaa80be2 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 08:33:14 -0300 Subject: [PATCH 03/17] style: fix formatter issues From bb506c4db1c0aa741f7dadd3f9b32a4195c29da8 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 08:42:39 -0300 Subject: [PATCH 04/17] style: fix formatter issues --- src/tts/tts-core.ts | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index a0c112d82bb..4472b1e38af 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -681,7 +681,6 @@ export async function openaiTTS(params: { export function inferEdgeExtension(outputFormat: string): string { const normalized = outputFormat.toLowerCase(); - if (normalized.includes("webm")) { return ".webm"; } @@ -691,14 +690,9 @@ export function inferEdgeExtension(outputFormat: string): string { if (normalized.includes("opus")) { return ".opus"; } - if ( - normalized.includes("wav") || - normalized.includes("riff") || - normalized.includes("pcm") - ) { + if (normalized.includes("wav") || normalized.includes("riff") || normalized.includes("pcm")) { return ".wav"; } - return ".mp3"; } @@ -710,7 +704,6 @@ export async function edgeTTS(params: { }): Promise { const { text, outputPath, config, timeoutMs } = params; - if (!text || text.trim().length === 0) { throw new Error("TTS text cannot be empty"); } @@ -732,7 +725,6 @@ export async function edgeTTS(params: { let { size } = statSync(outputPath); if (size === 0) { - await tts.ttsPromise(text, outputPath); ({ size } = statSync(outputPath)); From d2515519987245f161b0516a230529202f016850 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 08:52:05 -0300 Subject: [PATCH 05/17] fix: avoid breaking behavior for empty text --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 4472b1e38af..a21964a46cc 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -705,7 +705,7 @@ export async function edgeTTS(params: { const { text, outputPath, config, timeoutMs } = params; if (!text || text.trim().length === 0) { - throw new Error("TTS text cannot be empty"); + throw new Error("Edge TTS requires non-empty text"); } const tts = new EdgeTTS({ From 91d96821b0abf2e1c3ede15baf8769b03005c626 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 08:56:36 -0300 Subject: [PATCH 06/17] style: fix formatter issues --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index a21964a46cc..ea449e4fcef 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -705,7 +705,7 @@ export async function edgeTTS(params: { const { text, outputPath, config, timeoutMs } = params; if (!text || text.trim().length === 0) { - throw new Error("Edge TTS requires non-empty text"); + throw new Error("Edge TTS requires non-empty text"); } const tts = new EdgeTTS({ From 133fb1a3005f35183ca0ff2400474fe9866c5588 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 11:40:30 -0300 Subject: [PATCH 07/17] style: fix indentation --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index ea449e4fcef..82276f8d356 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -729,7 +729,7 @@ export async function edgeTTS(params: { ({ size } = statSync(outputPath)); if (size === 0) { - throw new Error("Edge TTS produced empty audio file after retry"); + throw new Error("Edge TTS produced empty audio file after retry."); } } } From 07307a7973e681e86cc6beaa0fc6d8eb5ff0599d Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 12:50:28 -0300 Subject: [PATCH 08/17] style: fix indentation --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 82276f8d356..ea449e4fcef 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -729,7 +729,7 @@ export async function edgeTTS(params: { ({ size } = statSync(outputPath)); if (size === 0) { - throw new Error("Edge TTS produced empty audio file after retry."); + throw new Error("Edge TTS produced empty audio file after retry"); } } } From dfc5d6a876a98d10e9b44b714a581a1482cb61b6 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 12:58:44 -0300 Subject: [PATCH 09/17] fix: no-op for empty text to preserve existing behavior --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index ea449e4fcef..fd7a8c861c3 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -705,7 +705,7 @@ export async function edgeTTS(params: { const { text, outputPath, config, timeoutMs } = params; if (!text || text.trim().length === 0) { - throw new Error("Edge TTS requires non-empty text"); + return; } const tts = new EdgeTTS({ From ca17273b938700358994657d2529f1f7108d874b Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 13:03:18 -0300 Subject: [PATCH 10/17] fix: no-op for empty text to preserve existing behavior --- src/tts/tts-core.ts | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index fd7a8c861c3..d8aff2d3694 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -704,9 +704,8 @@ export async function edgeTTS(params: { }): Promise { const { text, outputPath, config, timeoutMs } = params; - if (!text || text.trim().length === 0) { - return; - } + const safeText = + text && text.trim().length > 0 ? text : " "; const tts = new EdgeTTS({ voice: config.voice, @@ -720,12 +719,12 @@ export async function edgeTTS(params: { timeout: config.timeoutMs ?? timeoutMs, }); - await tts.ttsPromise(text, outputPath); + await tts.ttsPromise(safeText, outputPath); let { size } = statSync(outputPath); if (size === 0) { - await tts.ttsPromise(text, outputPath); + await tts.ttsPromise(safeText, outputPath); ({ size } = statSync(outputPath)); if (size === 0) { From 75e314f6b0546aa5dbfaaf8a05d57afcf50d5476 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:30:14 -0300 Subject: [PATCH 11/17] style: fix formatter issues --- src/tts/tts-core.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index d8aff2d3694..4472b1e38af 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -704,8 +704,9 @@ export async function edgeTTS(params: { }): Promise { const { text, outputPath, config, timeoutMs } = params; - const safeText = - text && text.trim().length > 0 ? text : " "; + if (!text || text.trim().length === 0) { + throw new Error("TTS text cannot be empty"); + } const tts = new EdgeTTS({ voice: config.voice, @@ -719,12 +720,12 @@ export async function edgeTTS(params: { timeout: config.timeoutMs ?? timeoutMs, }); - await tts.ttsPromise(safeText, outputPath); + await tts.ttsPromise(text, outputPath); let { size } = statSync(outputPath); if (size === 0) { - await tts.ttsPromise(safeText, outputPath); + await tts.ttsPromise(text, outputPath); ({ size } = statSync(outputPath)); if (size === 0) { From e7fdf9716c773658bb3aaf44ac4f72649e589386 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 14:57:43 -0300 Subject: [PATCH 12/17] style: fix formatter issues --- src/tts/tts-core.ts | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 4472b1e38af..4ce8681c470 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -704,10 +704,6 @@ export async function edgeTTS(params: { }): Promise { const { text, outputPath, config, timeoutMs } = params; - if (!text || text.trim().length === 0) { - throw new Error("TTS text cannot be empty"); - } - const tts = new EdgeTTS({ voice: config.voice, lang: config.lang, @@ -720,16 +716,18 @@ export async function edgeTTS(params: { timeout: config.timeoutMs ?? timeoutMs, }); - await tts.ttsPromise(text, outputPath); - - let { size } = statSync(outputPath); - - if (size === 0) { + if (text && text.trim().length > 0) { await tts.ttsPromise(text, outputPath); - ({ size } = statSync(outputPath)); + + let { size } = statSync(outputPath); if (size === 0) { - throw new Error("Edge TTS produced empty audio file after retry"); + await tts.ttsPromise(text, outputPath); + ({ size } = statSync(outputPath)); + + if (size === 0) { + throw new Error("Edge TTS produced empty audio file after retry"); + } } } } From 9c4b712d69b653d525cf5e9f87263e74318066e8 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 15:10:07 -0300 Subject: [PATCH 13/17] style: fix formatting --- src/tts/tts-core.ts | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 4ce8681c470..ea449e4fcef 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -704,6 +704,10 @@ export async function edgeTTS(params: { }): Promise { const { text, outputPath, config, timeoutMs } = params; + if (!text || text.trim().length === 0) { + throw new Error("Edge TTS requires non-empty text"); + } + const tts = new EdgeTTS({ voice: config.voice, lang: config.lang, @@ -716,18 +720,16 @@ export async function edgeTTS(params: { timeout: config.timeoutMs ?? timeoutMs, }); - if (text && text.trim().length > 0) { - await tts.ttsPromise(text, outputPath); + await tts.ttsPromise(text, outputPath); - let { size } = statSync(outputPath); + let { size } = statSync(outputPath); + + if (size === 0) { + await tts.ttsPromise(text, outputPath); + ({ size } = statSync(outputPath)); if (size === 0) { - await tts.ttsPromise(text, outputPath); - ({ size } = statSync(outputPath)); - - if (size === 0) { - throw new Error("Edge TTS produced empty audio file after retry"); - } + throw new Error("Edge TTS produced empty audio file after retry"); } } } From f43566719e4f35d2a09e6f677b773609e6da2839 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 18:17:32 +0000 Subject: [PATCH 14/17] style: fix formatting --- openclaw@2026.3.14 | 0 oxfmt | 0 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 openclaw@2026.3.14 create mode 100644 oxfmt diff --git a/openclaw@2026.3.14 b/openclaw@2026.3.14 new file mode 100644 index 00000000000..e69de29bb2d diff --git a/oxfmt b/oxfmt new file mode 100644 index 00000000000..e69de29bb2d From 68d93e5f7c53d2bbb8933c69038034a060bfa9b9 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 18:21:34 +0000 Subject: [PATCH 15/17] chore: remove accidental local binaries --- openclaw@2026.3.14 | 0 oxfmt | 0 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 openclaw@2026.3.14 delete mode 100644 oxfmt diff --git a/openclaw@2026.3.14 b/openclaw@2026.3.14 deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/oxfmt b/oxfmt deleted file mode 100644 index e69de29bb2d..00000000000 From f6fcfc4688b05a8a833f1ab18d1b1735c5934c75 Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 15:41:16 -0300 Subject: [PATCH 16/17] style: fix indentation --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index ea449e4fcef..83a325444cf 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -705,7 +705,7 @@ export async function edgeTTS(params: { const { text, outputPath, config, timeoutMs } = params; if (!text || text.trim().length === 0) { - throw new Error("Edge TTS requires non-empty text"); + throw new Error("Edge TTS requires non-empty text."); } const tts = new EdgeTTS({ From 797a721b03f745d044123ae808e7d83992b2eb8b Mon Sep 17 00:00:00 2001 From: Hiago Silva <97215740+Huntterxx@users.noreply.github.com> Date: Sun, 15 Mar 2026 19:13:22 -0300 Subject: [PATCH 17/17] style: fix indentation --- src/tts/tts-core.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tts/tts-core.ts b/src/tts/tts-core.ts index 83a325444cf..ea449e4fcef 100644 --- a/src/tts/tts-core.ts +++ b/src/tts/tts-core.ts @@ -705,7 +705,7 @@ export async function edgeTTS(params: { const { text, outputPath, config, timeoutMs } = params; if (!text || text.trim().length === 0) { - throw new Error("Edge TTS requires non-empty text."); + throw new Error("Edge TTS requires non-empty text"); } const tts = new EdgeTTS({