Files
lume/libs/python/computer-server/computer_server/utils/helpers.py
2025-12-02 18:23:06 +05:30

82 lines
3.0 KiB
Python

import asyncio
import os
import platform
import subprocess
from typing import overload
def get_current_os() -> str:
"""Determine the current OS.
Returns:
str: The OS type ('android', 'darwin' for macOS, 'linux' for Linux, or 'windows' for Windows)
Raises:
RuntimeError: If unable to determine the current OS
"""
try:
if os.environ.get("IS_CUA_ANDROID") == "true":
# Verify emulator is actually running by checking adb devices
try:
result = subprocess.run(
["adb", "devices"], capture_output=True, text=True, timeout=5
)
if result.returncode == 0 and "emulator-5554" in result.stdout:
return "android"
else:
raise RuntimeError(
"IS_CUA_ANDROID is set but no emulator found. "
"Ensure Android emulator is running and accessible via adb."
)
except subprocess.TimeoutExpired:
raise RuntimeError(
"IS_CUA_ANDROID is set but adb command timed out. "
"Emulator may be starting up or unresponsive."
)
system = platform.system().lower()
if system in ["darwin", "linux", "windows"]:
return system
# Fallback to uname if platform.system() doesn't return expected values (Unix-like systems only)
result = subprocess.run(["uname", "-s"], capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip().lower()
raise RuntimeError(f"Unsupported OS: {system}")
except Exception as e:
raise RuntimeError(f"Failed to determine current OS: {str(e)}")
class CommandExecutor:
def __init__(self, *base_cmd: str) -> None:
"""Initialize with a base command.
Args:
base_cmd: The base command and its initial arguments.
"""
self.__base_cmd = list(base_cmd)
@overload
async def run(self, *args: str, timeout: int = 10) -> tuple[bool, bytes]: ...
@overload
async def run(self, *args: str, decode: bool = True, timeout: int = 10) -> tuple[bool, str]: ...
async def run(
self, *args: str, decode: bool = False, timeout: int = 10
) -> tuple[bool, bytes | str]:
cmd = self.__base_cmd + list(args)
try:
result = await asyncio.create_subprocess_exec(
*cmd, stdout=asyncio.subprocess.PIPE, stderr=asyncio.subprocess.PIPE
)
stdout, stderr = await asyncio.wait_for(result.communicate(), timeout=timeout)
output = stdout or stderr
if decode:
output = output.decode("utf-8")
return result.returncode == 0, output
except asyncio.TimeoutError:
return False, f"Command timed out after {timeout}s".encode("utf-8")
except Exception as e:
return False, str(e).encode("utf-8")