-
Notifications
You must be signed in to change notification settings - Fork 119
feat: add e2b sandbox #541
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
2a1348a
feat: add sandbox imlementation
maksymbuleshnyi c0445b4
fix: revert changes
maksymbuleshnyi 54f96b8
feat: add sandbox abstraction
maksymbuleshnyi 8873d02
Merge branch 'main' into feat/sandbox
maksymbuleshnyi fd37b25
feat: add e2b sandbox
maksymbuleshnyi ba5f620
fix: merge branch
maksymbuleshnyi 43c3d13
Merge branch 'main' into feat/sandbox
maksymbuleshnyi 16c0c59
fix: comments
maksymbuleshnyi 532ddb8
fix: merge branch
maksymbuleshnyi ea72e94
fix: comments
maksymbuleshnyi 34ea5b8
fix: renamed folder and shell method
maksymbuleshnyi 51d6078
feat: add yaml example
maksymbuleshnyi 54040fd
fix: imports
maksymbuleshnyi bcecaf2
fix: update gitignore
maksymbuleshnyi 0c9bbd0
fix: remove key
maksymbuleshnyi f0476b1
feat: add sandbox reconnection and files upload
maksymbuleshnyi 1bfa311
fix: environment variable and type hings
maksymbuleshnyi 23550d3
fix: files upload
maksymbuleshnyi f22599f
feat: add tests
maksymbuleshnyi 4683d97
feat: add tracing example
maksymbuleshnyi b384694
fix: test
maksymbuleshnyi 61f78d7
fix: serialization
maksymbuleshnyi bd20567
fix: tools static list
maksymbuleshnyi 6da66e3
fix: merge branch 'main'
maksymbuleshnyi f6a6d84
fix: serialization
maksymbuleshnyi 427f8ea
fix: remove redundant parameter
maksymbuleshnyi 1fd8c8c
fix: tests
maksymbuleshnyi 3a2ef19
feat: add template support
maksymbuleshnyi 0e69b7c
fix: docstring
maksymbuleshnyi a060448
feat: add e2b integration test
maksymbuleshnyi File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -160,6 +160,7 @@ cython_debug/ | |
| .DS_Store | ||
| .local | ||
| sandbox | ||
| !dynamiq/sandbox/ | ||
|
|
||
| # Chainlit | ||
| .chainlit | ||
|
|
||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| from .base import Sandbox, SandboxConfig, ShellCommandResult | ||
| from .e2b import E2BSandbox | ||
|
|
||
| __all__ = [ | ||
| "Sandbox", | ||
| "SandboxConfig", | ||
| "ShellCommandResult", | ||
| "E2BSandbox", | ||
| ] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| """Base file storage interface and common data structures.""" | ||
|
|
||
| import abc | ||
| from functools import cached_property | ||
| from typing import Any | ||
|
|
||
| from pydantic import BaseModel, ConfigDict, Field, computed_field | ||
|
|
||
| from dynamiq.nodes.node import Node | ||
|
|
||
|
|
||
| class ShellCommandResult(BaseModel): | ||
| """Result of a shell command execution.""" | ||
|
|
||
| stdout: str | ||
| stderr: str | ||
| exit_code: int | None | ||
|
|
||
|
|
||
| class Sandbox(abc.ABC, BaseModel): | ||
| """Abstract base class for sandbox implementations. | ||
|
|
||
| This interface provides a unified way to interact with different | ||
| sandbox backends (in-memory, file system, E2B, Docker, etc.). | ||
| Sandboxes provide file storage and can be extended to support | ||
| code execution and other isolated environment capabilities. | ||
| """ | ||
|
|
||
| @computed_field | ||
| @cached_property | ||
| def type(self) -> str: | ||
| """Returns the backend type as a string.""" | ||
| return f"{self.__module__.rsplit('.', 1)[0]}.{self.__class__.__name__}" | ||
|
|
||
| def to_dict(self, **kwargs) -> dict[str, Any]: | ||
| """Convert the Sandbox instance to a dictionary. | ||
|
|
||
| Returns: | ||
| dict: Dictionary representation of the Sandbox instance. | ||
| """ | ||
| for param in ("include_secure_params", "for_tracing"): | ||
| kwargs.pop(param, None) | ||
| data = self.model_dump(**kwargs) | ||
| data["type"] = self.type | ||
| return data | ||
|
|
||
| def run_command( | ||
maksymbuleshnyi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| self, | ||
| command: str, | ||
| timeout: int = 60, | ||
| background: bool = False, | ||
| ) -> ShellCommandResult: | ||
| """Execute a shell command in the sandbox. | ||
|
|
||
| This is an optional capability. Subclasses that support command execution | ||
| should override this method. The base implementation raises NotImplementedError. | ||
|
|
||
| Args: | ||
| command: Shell command or script to execute. | ||
| timeout: Timeout in seconds (default 60). | ||
| background: If True, run command in background (no output). | ||
|
|
||
| Returns: | ||
| ShellCommandResult with stdout, stderr, and exit_code. | ||
|
|
||
| Raises: | ||
| NotImplementedError: If the sandbox does not support command execution. | ||
| """ | ||
| raise NotImplementedError( | ||
| f"{self.__class__.__name__} does not support command execution. " | ||
| "Use a sandbox backend that supports shell commands (e.g., E2BSandbox)." | ||
| ) | ||
|
|
||
| def get_tools( | ||
| self, | ||
| llm: Any = None, | ||
| file_write_enabled: bool = False, | ||
| ) -> list[Node]: | ||
| """Return tools this sandbox provides for agent use. | ||
|
|
||
| Base implementation returns an empty list. Subclasses can override | ||
| to add tools specific to their sandbox type (e.g., shell execution). | ||
|
|
||
| Args: | ||
| llm: LLM instance for tools that need it. | ||
| file_write_enabled: Whether to include file write tool. | ||
|
|
||
| Returns: | ||
| List of tool instances (Node objects). | ||
| """ | ||
| # Lazy import to avoid circular dependency | ||
| from dynamiq.sandbox.tools.shell import SandboxShellTool | ||
maksymbuleshnyi marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| shell_tool = SandboxShellTool( | ||
| name="shell", | ||
| sandbox=self, | ||
| ) | ||
| return [shell_tool] | ||
|
|
||
|
|
||
| class SandboxConfig(BaseModel): | ||
| """Configuration for sandbox and related features. | ||
|
|
||
| Attributes: | ||
| enabled: Whether sandbox is enabled. | ||
| backend: The sandbox backend to use. | ||
| agent_file_write_enabled: Whether the agent can write files. | ||
| todo_enabled: Whether to enable todo management tools (stored in ._agent/todos.json). | ||
| config: Additional configuration options. | ||
| """ | ||
|
|
||
| enabled: bool = False | ||
| backend: Sandbox = Field(..., description="Sandbox backend to use.") | ||
| todo_enabled: bool = Field( | ||
| default=False, description="Whether to enable todo management tools (todos stored in ._agent/todos.json)." | ||
| ) | ||
| config: dict[str, Any] = Field(default_factory=dict) | ||
|
|
||
| model_config = ConfigDict(arbitrary_types_allowed=True) | ||
|
|
||
| def to_dict(self, **kwargs) -> dict[str, Any]: | ||
| """Convert the SandboxConfig instance to a dictionary.""" | ||
| for_tracing = kwargs.pop("for_tracing", False) | ||
| if for_tracing and not self.enabled: | ||
| return {"enabled": False} | ||
| kwargs.pop("include_secure_params", None) | ||
| config_data = self.model_dump(exclude={"backend"}, **kwargs) | ||
| config_data["backend"] = self.backend.to_dict() | ||
| return config_data | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.