Duibonduil's picture
Upload 5 files
44e7e06 verified
import abc
import asyncio
import logging
import uuid
from typing import Dict, List, Any, Optional
from aworld.sandbox.api.setup import SandboxSetup
from aworld.sandbox.models import SandboxStatus, SandboxEnvType, SandboxInfo
from aworld.sandbox.run.mcp_servers import McpServers
class Sandbox(SandboxSetup):
"""
Sandbox abstract base class that defines the interface for all sandbox implementations.
A sandbox provides an isolated environment for executing code and operations.
"""
default_sandbox_timeout = 3000
@property
def sandbox_id(self) -> str:
"""
Returns the unique identifier of the sandbox.
"""
return self._sandbox_id
@property
def status(self) -> SandboxStatus:
"""
Returns the current status of the sandbox.
"""
return self._status
@property
def timeout(self) -> int:
"""
Returns the timeout value for sandbox operations.
"""
return self._timeout
@property
def metadata(self) -> Dict[str, Any]:
"""
Returns the sandbox metadata.
"""
return self._metadata
@property
def env_type(self) -> SandboxEnvType:
"""
Returns the environment type of the sandbox.
"""
return self._env_type
@property
def mcp_config(self) -> Any:
"""
Returns the MCP configuration.
"""
return self._mcp_config
@property
def mcp_servers(self) -> List[str]:
"""
Returns the list of MCP servers.
"""
return self._mcp_servers
@property
@abc.abstractmethod
def mcpservers(self) -> McpServers:
"""
Module for running MCP in the sandbox.
Returns:
McpServers: The MCP servers instance.
"""
pass
def __init__(
self,
sandbox_id: Optional[str] = None,
env_type: Optional[int] = None,
metadata: Optional[Dict[str, str]] = None,
timeout: Optional[int] = None,
mcp_servers: Optional[List[str]] = None,
mcp_config: Optional[Any] = None,
):
"""
Initialize a new Sandbox instance.
Args:
sandbox_id: Unique identifier for the sandbox. If None, one will be generated.
env_type: The environment type (LOCAL, K8S, SUPERCOMPUTER).
metadata: Additional metadata for the sandbox.
timeout: Timeout for sandbox operations.
mcp_servers: List of MCP servers to use.
mcp_config: Configuration for MCP servers.
"""
# Initialize basic attributes
self._sandbox_id = sandbox_id or str(uuid.uuid4())
self._status = SandboxStatus.INIT
self._timeout = timeout or self.default_sandbox_timeout
self._metadata = metadata or {}
self._env_type = env_type or SandboxEnvType.LOCAL
self._mcp_servers = mcp_servers or []
self._mcp_config = mcp_config or {}
@abc.abstractmethod
def get_info(self) -> SandboxInfo:
"""
Returns information about the sandbox.
Returns:
SandboxInfo: Information about the sandbox.
"""
pass
@abc.abstractmethod
async def remove(self) -> bool:
"""
Remove the sandbox and clean up all resources.
Returns:
bool: True if removal was successful, False otherwise.
"""
pass
@abc.abstractmethod
async def cleanup(self) -> bool:
"""
Clean up the sandbox resources.
Returns:
bool: True if cleanup was successful, False otherwise.
"""
pass
def __del__(self):
"""
Ensure resources are cleaned up when the object is garbage collected.
"""
try:
# Handle the case where an event loop already exists
try:
loop = asyncio.get_running_loop()
logging.warning("Cannot clean up sandbox in __del__ when event loop is already running")
return
except RuntimeError:
# No running event loop, create a new one
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
loop.run_until_complete(self.cleanup())
loop.close()
except Exception as e:
logging.warning(f"Failed to cleanup sandbox resources during garbage collection: {e}")