chore: import upstream snapshot with attribution
This commit is contained in:
@@ -0,0 +1,227 @@
|
||||
import urllib.parse
|
||||
from typing import Optional, TypedDict
|
||||
|
||||
from packaging.version import Version
|
||||
|
||||
from e2b.connection_config import ConnectionConfig, default_username
|
||||
from e2b.envd.api import ENVD_API_FILES_ROUTE
|
||||
from e2b.envd.versions import ENVD_DEFAULT_USER
|
||||
from e2b.exceptions import InvalidArgumentException
|
||||
from e2b.sandbox.signature import get_signature
|
||||
|
||||
|
||||
class SandboxOpts(TypedDict):
|
||||
sandbox_id: str
|
||||
sandbox_domain: Optional[str]
|
||||
envd_version: Version
|
||||
envd_access_token: Optional[str]
|
||||
traffic_access_token: Optional[str]
|
||||
connection_config: ConnectionConfig
|
||||
|
||||
|
||||
class SandboxBase:
|
||||
mcp_port = 50005
|
||||
|
||||
default_sandbox_timeout = 300
|
||||
|
||||
default_template = "base"
|
||||
default_mcp_template = "mcp-gateway"
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
sandbox_id: str,
|
||||
envd_version: Version,
|
||||
envd_access_token: Optional[str],
|
||||
sandbox_domain: Optional[str],
|
||||
connection_config: ConnectionConfig,
|
||||
traffic_access_token: Optional[str] = None,
|
||||
):
|
||||
self.__connection_config = connection_config
|
||||
self.__sandbox_id = sandbox_id
|
||||
self.__sandbox_domain = sandbox_domain or self.connection_config.domain
|
||||
self.__envd_version = envd_version
|
||||
self.__envd_access_token = envd_access_token
|
||||
self.__traffic_access_token = traffic_access_token
|
||||
self.__envd_api_url = self.connection_config.get_sandbox_url(
|
||||
self.sandbox_id, self.sandbox_domain
|
||||
)
|
||||
self.__envd_direct_url = self.connection_config.get_sandbox_direct_url(
|
||||
self.sandbox_id, self.sandbox_domain
|
||||
)
|
||||
self.__mcp_token: Optional[str] = None
|
||||
|
||||
@property
|
||||
def _envd_access_token(self) -> Optional[str]:
|
||||
"""Private property to access the envd token"""
|
||||
return self.__envd_access_token
|
||||
|
||||
@property
|
||||
def _mcp_token(self) -> Optional[str]:
|
||||
return self.__mcp_token
|
||||
|
||||
@_mcp_token.setter
|
||||
def _mcp_token(self, token: str) -> None:
|
||||
self.__mcp_token = token
|
||||
|
||||
@property
|
||||
def connection_config(self) -> ConnectionConfig:
|
||||
return self.__connection_config
|
||||
|
||||
@property
|
||||
def _envd_version(self) -> Version:
|
||||
return self.__envd_version
|
||||
|
||||
@property
|
||||
def traffic_access_token(self) -> Optional[str]:
|
||||
return self.__traffic_access_token
|
||||
|
||||
@property
|
||||
def sandbox_domain(self) -> str:
|
||||
return self.__sandbox_domain
|
||||
|
||||
@property
|
||||
def envd_api_url(self) -> str:
|
||||
return self.__envd_api_url
|
||||
|
||||
@property
|
||||
def envd_direct_url(self) -> str:
|
||||
return self.__envd_direct_url
|
||||
|
||||
@property
|
||||
def sandbox_id(self) -> str:
|
||||
"""
|
||||
Unique identifier of the sandbox.
|
||||
"""
|
||||
return self.__sandbox_id
|
||||
|
||||
def _file_url(
|
||||
self,
|
||||
path: str,
|
||||
user: Optional[str] = None,
|
||||
signature: Optional[str] = None,
|
||||
signature_expiration: Optional[int] = None,
|
||||
) -> str:
|
||||
url = urllib.parse.urljoin(self.envd_direct_url, ENVD_API_FILES_ROUTE)
|
||||
query = {"path": path} if path else {}
|
||||
|
||||
if user:
|
||||
query["username"] = user
|
||||
|
||||
if signature:
|
||||
query["signature"] = signature
|
||||
|
||||
if signature_expiration:
|
||||
if signature is None:
|
||||
raise ValueError("signature_expiration requires signature to be set")
|
||||
query["signature_expiration"] = str(signature_expiration)
|
||||
|
||||
params = urllib.parse.urlencode(
|
||||
query,
|
||||
quote_via=urllib.parse.quote,
|
||||
)
|
||||
url = urllib.parse.urljoin(url, f"?{params}")
|
||||
|
||||
return url
|
||||
|
||||
def download_url(
|
||||
self,
|
||||
path: str,
|
||||
user: Optional[str] = None,
|
||||
use_signature_expiration: Optional[int] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Get the URL to download a file from the sandbox.
|
||||
|
||||
:param path: Path to the file to download
|
||||
:param user: User to download the file as
|
||||
:param use_signature_expiration: Expiration time for the signed URL in seconds
|
||||
|
||||
:return: URL for downloading file
|
||||
"""
|
||||
|
||||
use_signature = self._envd_access_token is not None
|
||||
if not use_signature and use_signature_expiration is not None:
|
||||
raise InvalidArgumentException(
|
||||
"Signature expiration can be used only when sandbox is created as secured."
|
||||
)
|
||||
|
||||
username = user
|
||||
if username is None and self._envd_version < ENVD_DEFAULT_USER:
|
||||
username = default_username
|
||||
|
||||
if use_signature:
|
||||
signature = get_signature(
|
||||
path,
|
||||
"read",
|
||||
username,
|
||||
self._envd_access_token,
|
||||
use_signature_expiration,
|
||||
)
|
||||
return self._file_url(
|
||||
path, username, signature["signature"], signature["expiration"]
|
||||
)
|
||||
else:
|
||||
return self._file_url(path, username)
|
||||
|
||||
def upload_url(
|
||||
self,
|
||||
path: str,
|
||||
user: Optional[str] = None,
|
||||
use_signature_expiration: Optional[int] = None,
|
||||
) -> str:
|
||||
"""
|
||||
Get the URL to upload a file to the sandbox.
|
||||
|
||||
You have to send a POST request to this URL with the file as multipart/form-data.
|
||||
|
||||
:param path: Path to the file to upload
|
||||
:param user: User to upload the file as
|
||||
:param use_signature_expiration: Expiration time for the signed URL in seconds
|
||||
|
||||
:return: URL for uploading file
|
||||
"""
|
||||
|
||||
use_signature = self._envd_access_token is not None
|
||||
if not use_signature and use_signature_expiration is not None:
|
||||
raise InvalidArgumentException(
|
||||
"Signature expiration can be used only when sandbox is created as secured."
|
||||
)
|
||||
|
||||
username = user
|
||||
if username is None and self._envd_version < ENVD_DEFAULT_USER:
|
||||
username = default_username
|
||||
|
||||
if use_signature:
|
||||
signature = get_signature(
|
||||
path,
|
||||
"write",
|
||||
username,
|
||||
self._envd_access_token,
|
||||
use_signature_expiration,
|
||||
)
|
||||
return self._file_url(
|
||||
path, username, signature["signature"], signature["expiration"]
|
||||
)
|
||||
else:
|
||||
return self._file_url(path, username)
|
||||
|
||||
def get_host(self, port: int) -> str:
|
||||
"""
|
||||
Get the host address to connect to the sandbox.
|
||||
You can then use this address to connect to the sandbox port from outside the sandbox via HTTP or WebSocket.
|
||||
|
||||
:param port: Port to connect to
|
||||
|
||||
:return: Host address to connect to
|
||||
"""
|
||||
return self.connection_config.get_host(
|
||||
self.sandbox_id, self.sandbox_domain, port
|
||||
)
|
||||
|
||||
def get_mcp_url(self) -> str:
|
||||
"""
|
||||
Get the MCP URL for the sandbox.
|
||||
|
||||
:returns MCP URL for the sandbox.
|
||||
"""
|
||||
return f"https://{self.get_host(self.mcp_port)}/mcp"
|
||||
Reference in New Issue
Block a user