From 5d4fbb2e1ca14470ff2bfcd2b332e18900a674ef Mon Sep 17 00:00:00 2001 From: stantheman0128 Date: Sat, 18 Jul 2026 08:28:43 +0800 Subject: [PATCH 1/2] fix(windows): hide console windows for AEC, text-monitor, and mic-listener Native Windows helper binaries were spawned without windowsHide, flashing consoles during meeting AEC, text-edit monitoring, and mic activity detection. Co-authored-by: Cursor --- src/helpers/audioActivityDetector.js | 1 + src/helpers/meetingAecManager.js | 1 + src/helpers/textEditMonitor.js | 2 ++ .../helpers/windows-helper-spawn-hide.test.js | 32 +++++++++++++++++++ 4 files changed, 36 insertions(+) create mode 100644 test/helpers/windows-helper-spawn-hide.test.js diff --git a/src/helpers/audioActivityDetector.js b/src/helpers/audioActivityDetector.js index 883adc000..84b957f17 100644 --- a/src/helpers/audioActivityDetector.js +++ b/src/helpers/audioActivityDetector.js @@ -262,6 +262,7 @@ class AudioActivityDetector extends EventEmitter { // stdin must be "pipe" — the Windows binary monitors stdin for parent death const child = spawn(binaryPath, ["--exclude-pid", String(process.pid)], { stdio: ["pipe", "pipe", "pipe"], + windowsHide: true, }); this._listenerProcess = child; diff --git a/src/helpers/meetingAecManager.js b/src/helpers/meetingAecManager.js index 081a13b05..d2e6e5890 100644 --- a/src/helpers/meetingAecManager.js +++ b/src/helpers/meetingAecManager.js @@ -78,6 +78,7 @@ class MeetingAecManager { const child = spawn(binaryPath, ["--sample-rate", String(SAMPLE_RATE)], { stdio: ["pipe", "pipe", "pipe"], + windowsHide: true, }); this.process = child; diff --git a/src/helpers/textEditMonitor.js b/src/helpers/textEditMonitor.js index b22458565..349710ca3 100644 --- a/src/helpers/textEditMonitor.js +++ b/src/helpers/textEditMonitor.js @@ -247,6 +247,7 @@ class TextEditMonitor extends EventEmitter { this.process = spawn(command, args, { stdio: ["pipe", "pipe", "pipe"], + windowsHide: true, }); // Send original text via stdin @@ -391,6 +392,7 @@ class TextEditMonitor extends EventEmitter { this.process = spawn(command, [...args, String(targetPid)], { stdio: ["pipe", "pipe", "pipe"], + windowsHide: true, }); this.process.stdin.write(originalText + "\n"); diff --git a/test/helpers/windows-helper-spawn-hide.test.js b/test/helpers/windows-helper-spawn-hide.test.js new file mode 100644 index 000000000..5c6763f80 --- /dev/null +++ b/test/helpers/windows-helper-spawn-hide.test.js @@ -0,0 +1,32 @@ +const test = require("node:test"); +const assert = require("node:assert/strict"); +const fs = require("fs"); +const path = require("path"); + +const ROOT = path.join(__dirname, "../.."); + +function read(rel) { + return fs.readFileSync(path.join(ROOT, rel), "utf8"); +} + +test("meeting AEC helper spawn sets windowsHide", () => { + const src = read("src/helpers/meetingAecManager.js"); + assert.match( + src, + /spawn\(binaryPath,\s*\["--sample-rate"[\s\S]*?windowsHide:\s*true/ + ); +}); + +test("text edit monitor spawns set windowsHide", () => { + const src = read("src/helpers/textEditMonitor.js"); + const hides = (src.match(/windowsHide:\s*true/g) || []).length; + assert.ok(hides >= 2, `expected both monitor spawns to set windowsHide, got ${hides}`); +}); + +test("Windows mic-listener spawn sets windowsHide", () => { + const src = read("src/helpers/audioActivityDetector.js"); + assert.match( + src, + /_tryEventDrivenWin32[\s\S]*?spawn\(binaryPath,\s*\["--exclude-pid"[\s\S]*?windowsHide:\s*true/ + ); +}); From 84d9e85afa4edb3859d3a89e95eb1cf6d1ee3c3e Mon Sep 17 00:00:00 2001 From: Gabriel Stein Date: Sun, 19 Jul 2026 12:37:49 -0700 Subject: [PATCH 2/2] test(windows): tighten windowsHide spawn assertions and match test naming convention --- .../helpers/windows-helper-spawn-hide.test.js | 32 ------------------- test/helpers/windowsHelperSpawnHide.test.js | 27 ++++++++++++++++ 2 files changed, 27 insertions(+), 32 deletions(-) delete mode 100644 test/helpers/windows-helper-spawn-hide.test.js create mode 100644 test/helpers/windowsHelperSpawnHide.test.js diff --git a/test/helpers/windows-helper-spawn-hide.test.js b/test/helpers/windows-helper-spawn-hide.test.js deleted file mode 100644 index 5c6763f80..000000000 --- a/test/helpers/windows-helper-spawn-hide.test.js +++ /dev/null @@ -1,32 +0,0 @@ -const test = require("node:test"); -const assert = require("node:assert/strict"); -const fs = require("fs"); -const path = require("path"); - -const ROOT = path.join(__dirname, "../.."); - -function read(rel) { - return fs.readFileSync(path.join(ROOT, rel), "utf8"); -} - -test("meeting AEC helper spawn sets windowsHide", () => { - const src = read("src/helpers/meetingAecManager.js"); - assert.match( - src, - /spawn\(binaryPath,\s*\["--sample-rate"[\s\S]*?windowsHide:\s*true/ - ); -}); - -test("text edit monitor spawns set windowsHide", () => { - const src = read("src/helpers/textEditMonitor.js"); - const hides = (src.match(/windowsHide:\s*true/g) || []).length; - assert.ok(hides >= 2, `expected both monitor spawns to set windowsHide, got ${hides}`); -}); - -test("Windows mic-listener spawn sets windowsHide", () => { - const src = read("src/helpers/audioActivityDetector.js"); - assert.match( - src, - /_tryEventDrivenWin32[\s\S]*?spawn\(binaryPath,\s*\["--exclude-pid"[\s\S]*?windowsHide:\s*true/ - ); -}); diff --git a/test/helpers/windowsHelperSpawnHide.test.js b/test/helpers/windowsHelperSpawnHide.test.js new file mode 100644 index 000000000..c68a11144 --- /dev/null +++ b/test/helpers/windowsHelperSpawnHide.test.js @@ -0,0 +1,27 @@ +const test = require("node:test"); +const assert = require("node:assert/strict"); +const fs = require("fs"); +const path = require("path"); + +function read(rel) { + return fs.readFileSync(path.join(__dirname, "../..", rel), "utf8"); +} + +function hiddenSpawnCount(src) { + return (src.match(/spawn\([^{}]*\{[^{}]*windowsHide: true/g) || []).length; +} + +test("meeting AEC helper spawn sets windowsHide", () => { + assert.equal(hiddenSpawnCount(read("src/helpers/meetingAecManager.js")), 1); +}); + +test("text edit monitor spawns set windowsHide", () => { + assert.equal(hiddenSpawnCount(read("src/helpers/textEditMonitor.js")), 2); +}); + +test("Windows mic-listener spawn sets windowsHide", () => { + assert.match( + read("src/helpers/audioActivityDetector.js"), + /spawn\(binaryPath, \["--exclude-pid"[^{}]*\{[^{}]*windowsHide: true/ + ); +});