From 805228e91ec79b7345616a78ef87bde569204688 Mon Sep 17 00:00:00 2001 From: Peixian Gong Date: Tue, 3 Mar 2026 19:56:05 +0800 Subject: [PATCH] fix: add shell=True for npm subprocess calls on Windows On Windows, npm is installed as npm.cmd (a batch script), not a direct executable. When subprocess.run() is called with a list like ['npm', 'install'] without shell=True, Python's CreateProcess cannot locate npm.cmd, resulting in: FileNotFoundError: [WinError 2] The system cannot find the file specified This fix adds a sys.platform == 'win32' check before each npm subprocess call. On Windows, it uses shell=True with a string command so the shell can resolve npm.cmd. On other platforms, the original list-based call is preserved unchanged. Affected locations: - _get_bridge_dir(): npm install, npm run build - channels_login(): npm start No behavioral change on Linux/macOS. --- nanobot/cli/commands.py | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/nanobot/cli/commands.py b/nanobot/cli/commands.py index ddefb94..065eb71 100644 --- a/nanobot/cli/commands.py +++ b/nanobot/cli/commands.py @@ -837,12 +837,19 @@ def _get_bridge_dir() -> Path: shutil.copytree(source, user_bridge, ignore=shutil.ignore_patterns("node_modules", "dist")) # Install and build + is_win = sys.platform == "win32" try: console.print(" Installing dependencies...") - subprocess.run(["npm", "install"], cwd=user_bridge, check=True, capture_output=True) + if is_win: + subprocess.run("npm install", cwd=user_bridge, check=True, capture_output=True, shell=True) + else: + subprocess.run(["npm", "install"], cwd=user_bridge, check=True, capture_output=True) console.print(" Building...") - subprocess.run(["npm", "run", "build"], cwd=user_bridge, check=True, capture_output=True) + if is_win: + subprocess.run("npm run build", cwd=user_bridge, check=True, capture_output=True, shell=True) + else: + subprocess.run(["npm", "run", "build"], cwd=user_bridge, check=True, capture_output=True) console.print("[green]✓[/green] Bridge ready\n") except subprocess.CalledProcessError as e: @@ -876,7 +883,10 @@ def channels_login(): env["AUTH_DIR"] = str(get_runtime_subdir("whatsapp-auth")) try: - subprocess.run(["npm", "start"], cwd=bridge_dir, check=True, env=env) + if sys.platform == "win32": + subprocess.run("npm start", cwd=bridge_dir, check=True, env=env, shell=True) + else: + subprocess.run(["npm", "start"], cwd=bridge_dir, check=True, env=env) except subprocess.CalledProcessError as e: console.print(f"[red]Bridge failed: {e}[/red]") except FileNotFoundError: