diff --git a/api/core/virtual_environment/__base/entities.py b/api/core/virtual_environment/__base/entities.py index 253d63d1fa..6ba812e8d2 100644 --- a/api/core/virtual_environment/__base/entities.py +++ b/api/core/virtual_environment/__base/entities.py @@ -14,6 +14,15 @@ class Arch(StrEnum): AMD64 = "amd64" +class OperatingSystem(StrEnum): + """ + Operating system types for virtual environments. + """ + + LINUX = "linux" + DARWIN = "darwin" + + class Metadata(BaseModel): """ Returned metadata about a virtual environment. @@ -21,6 +30,7 @@ class Metadata(BaseModel): id: str = Field(description="The unique identifier of the virtual environment.") arch: Arch = Field(description="Which architecture was used to create the virtual environment.") + os: OperatingSystem = Field(description="The operating system of the virtual environment.") store: Mapping[str, Any] = Field( default_factory=dict, description="The store information of the virtual environment., Additional data." ) diff --git a/api/core/virtual_environment/providers/daytona_sandbox.py b/api/core/virtual_environment/providers/daytona_sandbox.py index 6115cc6402..26993baa15 100644 --- a/api/core/virtual_environment/providers/daytona_sandbox.py +++ b/api/core/virtual_environment/providers/daytona_sandbox.py @@ -29,7 +29,14 @@ class _CommandRecord(TypedDict): exit_code: int | None -from core.virtual_environment.__base.entities import Arch, CommandStatus, ConnectionHandle, FileState, Metadata +from core.virtual_environment.__base.entities import ( + Arch, + CommandStatus, + ConnectionHandle, + FileState, + Metadata, + OperatingSystem, +) from core.virtual_environment.__base.virtual_environment import VirtualEnvironment from core.virtual_environment.channel.queue_transport import QueueTransportReadCloser from core.virtual_environment.channel.transport import ( @@ -117,6 +124,7 @@ class DaytonaEnvironment(VirtualEnvironment): return Metadata( id=sandbox.id, arch=Arch.AMD64, + os=OperatingSystem.LINUX, store={ self.StoreKey.DAYTONA: daytona, self.StoreKey.SANDBOX: sandbox, diff --git a/api/core/virtual_environment/providers/docker_daemon_sandbox.py b/api/core/virtual_environment/providers/docker_daemon_sandbox.py index d34e4aa6c0..bf71ac27cb 100644 --- a/api/core/virtual_environment/providers/docker_daemon_sandbox.py +++ b/api/core/virtual_environment/providers/docker_daemon_sandbox.py @@ -15,7 +15,14 @@ import docker.errors from docker.models.containers import Container import docker -from core.virtual_environment.__base.entities import Arch, CommandStatus, ConnectionHandle, FileState, Metadata +from core.virtual_environment.__base.entities import ( + Arch, + CommandStatus, + ConnectionHandle, + FileState, + Metadata, + OperatingSystem, +) from core.virtual_environment.__base.exec import SandboxConfigValidationError, VirtualEnvironmentLaunchFailedError from core.virtual_environment.__base.virtual_environment import VirtualEnvironment from core.virtual_environment.channel.exec import TransportEOFError @@ -288,6 +295,7 @@ class DockerDaemonEnvironment(VirtualEnvironment): return Metadata( id=container.id, arch=self._get_container_architecture(container), + os=OperatingSystem.LINUX, ) @classmethod diff --git a/api/core/virtual_environment/providers/e2b_sandbox.py b/api/core/virtual_environment/providers/e2b_sandbox.py index e8c841eebd..5f270ca6d0 100644 --- a/api/core/virtual_environment/providers/e2b_sandbox.py +++ b/api/core/virtual_environment/providers/e2b_sandbox.py @@ -10,7 +10,14 @@ from uuid import uuid4 from e2b_code_interpreter import Sandbox # type: ignore[import-untyped] -from core.virtual_environment.__base.entities import Arch, CommandStatus, ConnectionHandle, FileState, Metadata +from core.virtual_environment.__base.entities import ( + Arch, + CommandStatus, + ConnectionHandle, + FileState, + Metadata, + OperatingSystem, +) from core.virtual_environment.__base.exec import ( ArchNotSupportedError, NotSupportedOperationError, @@ -116,11 +123,13 @@ class E2BEnvironment(VirtualEnvironment): envs=dict(environments), ) info = sandbox.get_info(api_key=options.get(self.OptionsKey.API_KEY, "")) - output = sandbox.commands.run("uname -m").stdout.strip() + arch_output = sandbox.commands.run("uname -m").stdout.strip() + os_output = sandbox.commands.run("uname -s").stdout.strip() return Metadata( id=info.sandbox_id, - arch=self._convert_architecture(output), + arch=self._convert_architecture(arch_output), + os=self._convert_operating_system(os_output), store={ self.StoreKey.SANDBOX: sandbox, }, @@ -254,9 +263,6 @@ class E2BEnvironment(VirtualEnvironment): return self.options.get(self.OptionsKey.API_KEY, "") def _convert_architecture(self, arch_str: str) -> Arch: - """ - Convert architecture string to standard format. - """ arch_map = { "x86_64": Arch.AMD64, "aarch64": Arch.ARM64, @@ -270,3 +276,13 @@ class E2BEnvironment(VirtualEnvironment): return arch_map[arch_str] raise ArchNotSupportedError(f"Unsupported architecture: {arch_str}") + + def _convert_operating_system(self, os_str: str) -> OperatingSystem: + os_map = { + "Linux": OperatingSystem.LINUX, + "Darwin": OperatingSystem.DARWIN, + } + if os_str in os_map: + return os_map[os_str] + + raise ArchNotSupportedError(f"Unsupported operating system: {os_str}") diff --git a/api/core/virtual_environment/providers/local_without_isolation.py b/api/core/virtual_environment/providers/local_without_isolation.py index da6fded890..6b4d47203d 100644 --- a/api/core/virtual_environment/providers/local_without_isolation.py +++ b/api/core/virtual_environment/providers/local_without_isolation.py @@ -4,11 +4,18 @@ import subprocess from collections.abc import Mapping, Sequence from functools import cached_property from io import BytesIO -from platform import machine +from platform import machine, system from typing import Any from uuid import uuid4 -from core.virtual_environment.__base.entities import Arch, CommandStatus, ConnectionHandle, FileState, Metadata +from core.virtual_environment.__base.entities import ( + Arch, + CommandStatus, + ConnectionHandle, + FileState, + Metadata, + OperatingSystem, +) from core.virtual_environment.__base.exec import ArchNotSupportedError from core.virtual_environment.__base.virtual_environment import VirtualEnvironment from core.virtual_environment.channel.pipe_transport import PipeReadCloser, PipeWriteCloser @@ -81,6 +88,7 @@ class LocalVirtualEnvironment(VirtualEnvironment): return Metadata( id=id, arch=self._get_os_architecture(), + os=self._get_operating_system(), ) def release_environment(self) -> None: @@ -250,6 +258,16 @@ class LocalVirtualEnvironment(VirtualEnvironment): case _: raise ArchNotSupportedError(f"Unsupported architecture: {arch}") + def _get_operating_system(self) -> OperatingSystem: + os_name = system().lower() + match os_name: + case "linux": + return OperatingSystem.LINUX + case "darwin": + return OperatingSystem.DARWIN + case _: + raise ArchNotSupportedError(f"Unsupported operating system: {os_name}") + @cached_property def _base_working_path(self) -> str: """