diff --git a/libs/python/computer-server/computer_server/handlers/linux.py b/libs/python/computer-server/computer_server/handlers/linux.py index ac0bb91d..6fe80a1c 100644 --- a/libs/python/computer-server/computer_server/handlers/linux.py +++ b/libs/python/computer-server/computer_server/handlers/linux.py @@ -10,6 +10,7 @@ To use GUI automation in a headless environment: from typing import Dict, Any, List, Tuple, Optional import logging import subprocess +import asyncio import base64 import os import json @@ -278,7 +279,20 @@ class LinuxAutomationHandler(BaseAutomationHandler): # Command Execution async def run_command(self, command: str) -> Dict[str, Any]: try: - process = subprocess.run(command, shell=True, capture_output=True, text=True) - return {"success": True, "stdout": process.stdout, "stderr": process.stderr, "return_code": process.returncode} + # Create subprocess + process = await asyncio.create_subprocess_shell( + command, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + # Wait for the subprocess to finish + stdout, stderr = await process.communicate() + # Return decoded output + return { + "success": True, + "stdout": stdout.decode() if stdout else "", + "stderr": stderr.decode() if stderr else "", + "return_code": process.returncode + } except Exception as e: return {"success": False, "error": str(e)} diff --git a/libs/python/computer-server/computer_server/handlers/macos.py b/libs/python/computer-server/computer_server/handlers/macos.py index 9d8e344a..0cba0ca3 100644 --- a/libs/python/computer-server/computer_server/handlers/macos.py +++ b/libs/python/computer-server/computer_server/handlers/macos.py @@ -45,6 +45,7 @@ import objc import re import json import copy +import asyncio from .base import BaseAccessibilityHandler, BaseAutomationHandler import logging @@ -935,9 +936,20 @@ class MacOSAutomationHandler(BaseAutomationHandler): async def run_command(self, command: str) -> Dict[str, Any]: """Run a shell command and return its output.""" try: - import subprocess - - process = subprocess.run(command, shell=True, capture_output=True, text=True) - return {"success": True, "stdout": process.stdout, "stderr": process.stderr} + # Create subprocess + process = await asyncio.create_subprocess_shell( + command, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE + ) + # Wait for the subprocess to finish + stdout, stderr = await process.communicate() + # Return decoded output + return { + "success": True, + "stdout": stdout.decode() if stdout else "", + "stderr": stderr.decode() if stderr else "", + "return_code": process.returncode + } except Exception as e: return {"success": False, "error": str(e)} diff --git a/libs/python/computer-server/computer_server/handlers/windows.py b/libs/python/computer-server/computer_server/handlers/windows.py index d88dfe0b..485aff4a 100644 --- a/libs/python/computer-server/computer_server/handlers/windows.py +++ b/libs/python/computer-server/computer_server/handlers/windows.py @@ -7,6 +7,7 @@ for accessibility and system operations. from typing import Dict, Any, List, Tuple, Optional import logging import subprocess +import asyncio import base64 import os from io import BytesIO @@ -387,18 +388,19 @@ class WindowsAutomationHandler(BaseAutomationHandler): # Command Execution async def run_command(self, command: str) -> Dict[str, Any]: try: - # Use cmd.exe for Windows commands - process = subprocess.run( - command, - shell=True, - capture_output=True, - text=True, - creationflags=subprocess.CREATE_NO_WINDOW if os.name == 'nt' else 0 + # Create subprocess + process = await asyncio.create_subprocess_shell( + command, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE ) + # Wait for the subprocess to finish + stdout, stderr = await process.communicate() + # Return decoded output return { "success": True, - "stdout": process.stdout, - "stderr": process.stderr, + "stdout": stdout.decode() if stdout else "", + "stderr": stderr.decode() if stderr else "", "return_code": process.returncode } except Exception as e: