fix: hide WhatsApp adapter helper subprocesses on Windows - #75224
fix: hide WhatsApp adapter helper subprocesses on Windows#75224Clawdy-ast wants to merge 1 commit into
Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for tracing the remaining WhatsApp console-flash paths. The production change addresses real omissions on current main: plugins/platforms/whatsapp/adapter.py:223, :349, and :554 call synchronous helpers without creationflags, while hermes_cli/_subprocess_compat.py:212 provides the intended Windows-only CREATE_NO_WINDOW helper.
Problems
tests/gateway/test_whatsapp_windows_subprocess_flags.py:20parsesinspect.getsource()withast. This is a source-shape test, which is explicitly banned byAGENTS.md:1382; it will not validate the runtime subprocess contract.- The branch conflicts with current main. Preserve current UTF-8 subprocess decoding at
plugins/platforms/whatsapp/adapter.py:226,:352, and:558when applying the three flags.
Suggested changes
- Replace the AST test with behavioral mock-based tests that execute each path and assert
subprocess.run(..., creationflags=windows_hide_flags()). The existing disconnect assertion attests/gateway/test_whatsapp_connect.py:395is the right pattern for the taskkill path.
Automated hermes-sweeper review.
| def _subprocess_run_calls(function): | ||
| """Return direct ``subprocess.run`` call nodes from *function*.""" | ||
| tree = ast.parse(textwrap.dedent(inspect.getsource(function))) | ||
| return [ |
There was a problem hiding this comment.
Please replace this source-inspection test with behavioral tests that mock subprocess.run, execute each relevant path, and assert its runtime kwargs. AGENTS.md:1382 explicitly bans tests that read production source because they couple to implementation shape rather than behavior.
996e639 to
bf8c654
Compare
The gateway commonly runs under pythonw.exe (console-less); a console application spawned from it without CREATE_NO_WINDOW creates a visible window. Worst offender: the Node requirements probe invoked by the channel monitor every ~5 minutes while the bridge is down. Route all seven synchronous subprocess.run sites in the WhatsApp adapter through a module-level _run_hidden() wrapper that injects creationflags=windows_hide_flags() by default (0 on POSIX), so future spawn sites inherit the fix. Fifth fix in this console-flash class (NousResearch#53282, NousResearch#56747, NousResearch#63698, NousResearch#68457). Behavioral regression tests execute each Windows-reachable path with a mocked subprocess.run and assert the captured kwargs; a contract test on the wrapper guards recurrence. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
bf8c654 to
783c97a
Compare
|
Thanks for the review — both findings were valid, and the encoding one would have been a silent regression. Point-by-point resolution on the rebased branch: 1. AST/source-shape test (AGENTS.md violation) — RESOLVED, removed. 2. Branch conflict / UTF-8 decoding regression — RESOLVED, rebased. One scoping decision made without you, flagged for explicit review: the One structural change beyond the review's scope: this is the fifth fix in this console-flash class (#53282, #56747, #63698, #68457). The per-call-site kwargs are now factored into a module-level Verification on the rebased branch (Windows 11, Python 3.13):
To make the next round unambiguous, three yes/no questions:
If all three are "yes / yes / file it", this PR needs no further changes from my side. |
What does this PR do?
Stops visible console windows flashing on Windows when the gateway runs under
pythonw.exe(console-less) and the WhatsApp adapter spawns synchronous helper processes. The worst offender is the Node requirements probe incheck_whatsapp_requirements(), which the gateway's channel monitor invokes every ~5 minutes — on an affected machine this produces a visible "Terminal" window flash on a permanent ~5-minute cycle whenever the WhatsApp platform is enabled but its bridge isn't connected.Empirically traced on Windows 11: a visible-window watcher (EnumWindows polling) captured the flash bursts on a perfect 306-second cadence, each coinciding with a
node.exe --versionchild of the gatewaypythonwprocess. After this fix: zero visible windows across multiple monitor cycles.Rather than hand-passing
creationflagsat each call site, this adds a module-level_run_hidden()wrapper that injectscreationflags=windows_hide_flags()by default (a no-op returning 0 on POSIX —hermes_cli/_subprocess_compat.pyprovides the helper), and routes all seven synchronoussubprocess.runsites in the adapter through it. This bug class has recurred repeatedly (#53282, #56747, #63698, #68457, and now this PR); with the wrapper, a future spawn site added to this module inherits the fix by default instead of depending on reviewer vigilance.The long-lived bridge
Popenis untouched — it already correctly useswindows_detach_popen_kwargs().Related Issue
No open issue. Same Windows console-flash class as closed #53282, #56747, #63698, #68457 — this PR covers the WhatsApp adapter call sites those fixes did not reach.
Type of Change
Changes Made
plugins/platforms/whatsapp/adapter.py— add_run_hidden()(asubprocess.runwrapper defaultingcreationflags=windows_hide_flags()) and route all seven synchronous spawn sites through it: the Node--versionprobe, thetaskkillin_terminate_bridge_process(), thenetstat/taskkillpair in_kill_port_process(), thelsof/ssprobes in_listener_pids_on_port(), and thenpm installinconnect(). The existing UTF-8 decoding (encoding='utf-8', errors='replace') at every site is preserved.tests/gateway/test_whatsapp_adapter_hides_console_window.py(new) — behavioral tests: each Windows-reachable path is executed with a mockedsubprocess.runand the captured kwargs asserted (per review feedback, no source/AST inspection). Includes a contract test on_run_hiddenitself as the recurrence guard. POSIX-only paths (lsof/ss) are not asserted as Windows behavior.tests/gateway/test_whatsapp_connect.py— existing bridge-termination assertion updated for the new kwarg.How to Test
pytest tests/gateway/test_whatsapp_adapter_hides_console_window.py tests/gateway/test_whatsapp_connect.py -qpythonwwith WhatsApp enabled and its bridge not connected; pre-fix, a console window flashes every ~5 minutes on the monitor cycle — post-fix, none.Checklist
Code
fix(scope):,feat(scope):, etc.)pytest tests/gateway/ -q) on the rebased branchDocumentation & Housekeeping
cli-config.yaml.example— N/A (no config keys changed)CONTRIBUTING.mdorAGENTS.md— N/A (no architecture change)windows_hide_flags()returns 0 on non-Windows by design, and POSIXPopenacceptscreationflags=0🤖 Generated with Claude Code