From 4117dce2d312e4e8efc1911c05b76731391bb406 Mon Sep 17 00:00:00 2001 From: "paseo-bot[bot]" <266920839+paseo-bot[bot]@users.noreply.github.com> Date: Fri, 16 Oct 2026 08:19:21 +0200 Subject: [PATCH] Fix local WAV transcription startup (#7103) * fix(speech): complete local transcription providers * test(speech): document lazy worker assumption Co-authored-by: LauraGPT <18321252+LauraGPT@users.noreply.github.com> --------- Co-authored-by: LauraGPT Co-authored-by: LauraGPT <18321252+LauraGPT@users.noreply.github.com> --- .../scripts/transcribe-local-wav.test.ts | 40 +++++++++++++++++++ .../server/scripts/transcribe-local-wav.ts | 1 + 2 files changed, 41 insertions(+) create mode 100644 packages/server/scripts/transcribe-local-wav.test.ts diff --git a/packages/server/scripts/transcribe-local-wav.test.ts b/packages/server/scripts/transcribe-local-wav.test.ts new file mode 100644 index 0000000000..703025e2c5 --- /dev/null +++ b/packages/server/scripts/transcribe-local-wav.test.ts @@ -0,0 +1,40 @@ +import { spawnSync } from "node:child_process"; +import { mkdtempSync, rmSync } from "node:fs"; +import { tmpdir } from "node:os"; +import path from "node:path"; +import { fileURLToPath } from "node:url"; + +import { afterEach, describe, expect, test } from "vitest"; + +const tempDirs: string[] = []; + +afterEach(() => { + for (const dir of tempDirs.splice(0)) { + rmSync(dir, { recursive: true, force: true }); + } +}); + +describe("transcribe-local-wav CLI", () => { + test("initializes the complete speech provider configuration", () => { + const modelsDir = mkdtempSync(path.join(tmpdir(), "paseo-transcribe-local-")); + tempDirs.push(modelsDir); + const missingWav = path.join(modelsDir, "missing.wav"); + const scriptPath = fileURLToPath(new URL("./transcribe-local-wav.ts", import.meta.url)); + + const result = spawnSync( + process.execPath, + ["--import", "tsx", scriptPath, missingWav, "--models-dir", modelsDir], + { + encoding: "utf8", + timeout: 15_000, + }, + ); + + expect(result.error).toBeUndefined(); + expect(result.status).not.toBe(0); + // The worker client is lazy, so reaching the missing WAV proves provider initialization completed first. + expect(result.stderr).toContain("ENOENT"); + expect(result.stderr).toContain(missingWav); + expect(result.stderr).not.toContain("Cannot read properties of undefined"); + }); +}); diff --git a/packages/server/scripts/transcribe-local-wav.ts b/packages/server/scripts/transcribe-local-wav.ts index 0b323df029..a9cb10b7a2 100644 --- a/packages/server/scripts/transcribe-local-wav.ts +++ b/packages/server/scripts/transcribe-local-wav.ts @@ -120,6 +120,7 @@ async function main(): Promise { const providers: RequestedSpeechProviders = { dictationStt: { provider: "local", explicit: true }, + voiceTurnDetection: { provider: "local", explicit: false, enabled: false }, voiceStt: { provider: "local", explicit: true }, // Not used here, but required by the shared runtime config shape. voiceTts: { provider: "openai", explicit: false },