mirror of
https://github.com/trycua/computer.git
synced 2026-01-03 20:10:04 -06:00
Merge branch 'main' into feature/computer/typescript
This commit is contained in:
@@ -3,8 +3,7 @@
|
||||
from abc import ABC, abstractmethod
|
||||
from typing import Optional, Dict, Any, Tuple, List
|
||||
from ..logger import Logger, LogLevel
|
||||
from .models import MouseButton
|
||||
|
||||
from .models import MouseButton, CommandResult
|
||||
|
||||
class BaseComputerInterface(ABC):
|
||||
"""Base class for computer control interfaces."""
|
||||
@@ -234,8 +233,31 @@ class BaseComputerInterface(ABC):
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def run_command(self, command: str) -> Tuple[str, str]:
|
||||
"""Run shell command."""
|
||||
async def run_command(self, command: str) -> CommandResult:
|
||||
"""Run shell command and return structured result.
|
||||
|
||||
Executes a shell command using subprocess.run with shell=True and check=False.
|
||||
The command is run in the target environment and captures both stdout and stderr.
|
||||
|
||||
Args:
|
||||
command (str): The shell command to execute
|
||||
|
||||
Returns:
|
||||
CommandResult: A structured result containing:
|
||||
- stdout (str): Standard output from the command
|
||||
- stderr (str): Standard error from the command
|
||||
- returncode (int): Exit code from the command (0 indicates success)
|
||||
|
||||
Raises:
|
||||
RuntimeError: If the command execution fails at the system level
|
||||
|
||||
Example:
|
||||
result = await interface.run_command("ls -la")
|
||||
if result.returncode == 0:
|
||||
print(f"Output: {result.stdout}")
|
||||
else:
|
||||
print(f"Error: {result.stderr}, Exit code: {result.returncode}")
|
||||
"""
|
||||
pass
|
||||
|
||||
# Accessibility Actions
|
||||
|
||||
@@ -9,8 +9,7 @@ import websockets
|
||||
from ..logger import Logger, LogLevel
|
||||
from .base import BaseComputerInterface
|
||||
from ..utils import decode_base64_image, encode_base64_image, bytes_to_image, draw_box, resize_image
|
||||
from .models import Key, KeyType, MouseButton
|
||||
|
||||
from .models import Key, KeyType, MouseButton, CommandResult
|
||||
|
||||
class LinuxComputerInterface(BaseComputerInterface):
|
||||
"""Interface for Linux."""
|
||||
@@ -616,11 +615,15 @@ class LinuxComputerInterface(BaseComputerInterface):
|
||||
if not result.get("success", False):
|
||||
raise RuntimeError(result.get("error", "Failed to delete directory"))
|
||||
|
||||
async def run_command(self, command: str) -> Tuple[str, str]:
|
||||
async def run_command(self, command: str) -> CommandResult:
|
||||
result = await self._send_command("run_command", {"command": command})
|
||||
if not result.get("success", False):
|
||||
raise RuntimeError(result.get("error", "Failed to run command"))
|
||||
return result.get("stdout", ""), result.get("stderr", "")
|
||||
return CommandResult(
|
||||
stdout=result.get("stdout", ""),
|
||||
stderr=result.get("stderr", ""),
|
||||
returncode=result.get("return_code", 0)
|
||||
)
|
||||
|
||||
# Accessibility Actions
|
||||
async def get_accessibility_tree(self) -> Dict[str, Any]:
|
||||
|
||||
@@ -9,8 +9,7 @@ import websockets
|
||||
from ..logger import Logger, LogLevel
|
||||
from .base import BaseComputerInterface
|
||||
from ..utils import decode_base64_image, encode_base64_image, bytes_to_image, draw_box, resize_image
|
||||
from .models import Key, KeyType, MouseButton
|
||||
|
||||
from .models import Key, KeyType, MouseButton, CommandResult
|
||||
|
||||
class MacOSComputerInterface(BaseComputerInterface):
|
||||
"""Interface for macOS."""
|
||||
@@ -623,11 +622,15 @@ class MacOSComputerInterface(BaseComputerInterface):
|
||||
if not result.get("success", False):
|
||||
raise RuntimeError(result.get("error", "Failed to delete directory"))
|
||||
|
||||
async def run_command(self, command: str) -> Tuple[str, str]:
|
||||
async def run_command(self, command: str) -> CommandResult:
|
||||
result = await self._send_command("run_command", {"command": command})
|
||||
if not result.get("success", False):
|
||||
raise RuntimeError(result.get("error", "Failed to run command"))
|
||||
return result.get("stdout", ""), result.get("stderr", "")
|
||||
return CommandResult(
|
||||
stdout=result.get("stdout", ""),
|
||||
stderr=result.get("stderr", ""),
|
||||
returncode=result.get("return_code", 0)
|
||||
)
|
||||
|
||||
# Accessibility Actions
|
||||
async def get_accessibility_tree(self) -> Dict[str, Any]:
|
||||
|
||||
@@ -1,5 +1,17 @@
|
||||
from enum import Enum
|
||||
from typing import Dict, List, Any, TypedDict, Union, Literal
|
||||
from dataclasses import dataclass
|
||||
|
||||
@dataclass
|
||||
class CommandResult:
|
||||
stdout: str
|
||||
stderr: str
|
||||
returncode: int
|
||||
|
||||
def __init__(self, stdout: str, stderr: str, returncode: int):
|
||||
self.stdout = stdout
|
||||
self.stderr = stderr
|
||||
self.returncode = returncode
|
||||
|
||||
# Navigation key literals
|
||||
NavigationKey = Literal['pagedown', 'pageup', 'home', 'end', 'left', 'right', 'up', 'down']
|
||||
|
||||
@@ -9,8 +9,7 @@ import websockets
|
||||
from ..logger import Logger, LogLevel
|
||||
from .base import BaseComputerInterface
|
||||
from ..utils import decode_base64_image, encode_base64_image, bytes_to_image, draw_box, resize_image
|
||||
from .models import Key, KeyType, MouseButton
|
||||
|
||||
from .models import Key, KeyType, MouseButton, CommandResult
|
||||
|
||||
class WindowsComputerInterface(BaseComputerInterface):
|
||||
"""Interface for Windows."""
|
||||
@@ -615,11 +614,15 @@ class WindowsComputerInterface(BaseComputerInterface):
|
||||
if not result.get("success", False):
|
||||
raise RuntimeError(result.get("error", "Failed to delete directory"))
|
||||
|
||||
async def run_command(self, command: str) -> Tuple[str, str]:
|
||||
async def run_command(self, command: str) -> CommandResult:
|
||||
result = await self._send_command("run_command", {"command": command})
|
||||
if not result.get("success", False):
|
||||
raise RuntimeError(result.get("error", "Failed to run command"))
|
||||
return result.get("stdout", ""), result.get("stderr", "")
|
||||
return CommandResult(
|
||||
stdout=result.get("stdout", ""),
|
||||
stderr=result.get("stderr", ""),
|
||||
returncode=result.get("return_code", 0)
|
||||
)
|
||||
|
||||
# Accessibility Actions
|
||||
async def get_accessibility_tree(self) -> Dict[str, Any]:
|
||||
|
||||
@@ -4,7 +4,7 @@ build-backend = "pdm.backend"
|
||||
|
||||
[project]
|
||||
name = "cua-computer"
|
||||
version = "0.2.0"
|
||||
version = "0.3.0"
|
||||
description = "Computer-Use Interface (CUI) framework powering Cua"
|
||||
readme = "README.md"
|
||||
authors = [
|
||||
|
||||
Reference in New Issue
Block a user