deepagents-opensandbox 1.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- deepagents_opensandbox-1.0.1/.github/workflows/publish-to-pypi.yml +73 -0
- deepagents_opensandbox-1.0.1/.gitignore +112 -0
- deepagents_opensandbox-1.0.1/AGENTS.md +70 -0
- deepagents_opensandbox-1.0.1/LICENSE +21 -0
- deepagents_opensandbox-1.0.1/PKG-INFO +132 -0
- deepagents_opensandbox-1.0.1/README.md +120 -0
- deepagents_opensandbox-1.0.1/deepagents_opensandbox/__init__.py +27 -0
- deepagents_opensandbox-1.0.1/deepagents_opensandbox/backend.py +151 -0
- deepagents_opensandbox-1.0.1/deepagents_opensandbox/provider.py +286 -0
- deepagents_opensandbox-1.0.1/pyproject.toml +70 -0
- deepagents_opensandbox-1.0.1/uv.lock +3375 -0
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
- '*'
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
package-test:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- uses: actions/setup-python@v5
|
|
19
|
+
with:
|
|
20
|
+
python-version: "3.11"
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
run: python -m pip install uv
|
|
24
|
+
|
|
25
|
+
- name: Run tests
|
|
26
|
+
run: |
|
|
27
|
+
uv sync
|
|
28
|
+
uv run --group dev pytest
|
|
29
|
+
|
|
30
|
+
release-build:
|
|
31
|
+
runs-on: ubuntu-latest
|
|
32
|
+
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- uses: actions/setup-python@v5
|
|
37
|
+
with:
|
|
38
|
+
python-version: "3.11"
|
|
39
|
+
|
|
40
|
+
- name: Build release distributions
|
|
41
|
+
run: |
|
|
42
|
+
# NOTE: put your own distribution build steps here.
|
|
43
|
+
python -m pip install build
|
|
44
|
+
python -m build
|
|
45
|
+
|
|
46
|
+
- name: Upload distributions
|
|
47
|
+
uses: actions/upload-artifact@v4
|
|
48
|
+
with:
|
|
49
|
+
name: release-dists
|
|
50
|
+
path: dist/
|
|
51
|
+
|
|
52
|
+
pypi-publish:
|
|
53
|
+
runs-on: ubuntu-latest
|
|
54
|
+
needs:
|
|
55
|
+
- release-build
|
|
56
|
+
permissions:
|
|
57
|
+
id-token: write
|
|
58
|
+
|
|
59
|
+
environment:
|
|
60
|
+
name: pypi
|
|
61
|
+
url: https://pypi.org/p/opensandbox
|
|
62
|
+
|
|
63
|
+
steps:
|
|
64
|
+
- name: Retrieve release distributions
|
|
65
|
+
uses: actions/download-artifact@v4
|
|
66
|
+
with:
|
|
67
|
+
name: release-dists
|
|
68
|
+
path: dist/
|
|
69
|
+
|
|
70
|
+
- name: Publish release distributions to PyPI
|
|
71
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
72
|
+
with:
|
|
73
|
+
packages-dir: dist/
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
env/
|
|
12
|
+
build/
|
|
13
|
+
develop-eggs/
|
|
14
|
+
dist/
|
|
15
|
+
downloads/
|
|
16
|
+
eggs/
|
|
17
|
+
.eggs/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
*.egg-info/
|
|
24
|
+
.installed.cfg
|
|
25
|
+
*.egg
|
|
26
|
+
|
|
27
|
+
# PyInstaller
|
|
28
|
+
# Usually these files are written by a python script from a template
|
|
29
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
30
|
+
*.manifest
|
|
31
|
+
*.spec
|
|
32
|
+
|
|
33
|
+
# Installer logs
|
|
34
|
+
pip-log.txt
|
|
35
|
+
pip-delete-this-directory.txt
|
|
36
|
+
|
|
37
|
+
# Unit test / coverage reports
|
|
38
|
+
htmlcov/
|
|
39
|
+
.tox/
|
|
40
|
+
.coverage
|
|
41
|
+
.coverage.*
|
|
42
|
+
.cache
|
|
43
|
+
nosetests.xml
|
|
44
|
+
coverage.xml
|
|
45
|
+
*.cover
|
|
46
|
+
.hypothesis/
|
|
47
|
+
|
|
48
|
+
# Translations
|
|
49
|
+
*.mo
|
|
50
|
+
*.pot
|
|
51
|
+
|
|
52
|
+
# Django stuff:
|
|
53
|
+
*.log
|
|
54
|
+
local_settings.py
|
|
55
|
+
|
|
56
|
+
# Flask stuff:
|
|
57
|
+
instance/
|
|
58
|
+
.webassets-cache
|
|
59
|
+
|
|
60
|
+
# Scrapy stuff:
|
|
61
|
+
.scrapy
|
|
62
|
+
|
|
63
|
+
# Sphinx documentation
|
|
64
|
+
docs/_build/
|
|
65
|
+
|
|
66
|
+
# PyBuilder
|
|
67
|
+
target/
|
|
68
|
+
|
|
69
|
+
# Jupyter Notebook
|
|
70
|
+
.ipynb_checkpoints
|
|
71
|
+
|
|
72
|
+
# pyenv
|
|
73
|
+
.python-version
|
|
74
|
+
|
|
75
|
+
# celery beat schedule file
|
|
76
|
+
celerybeat-schedule
|
|
77
|
+
|
|
78
|
+
# SageMath parsed files
|
|
79
|
+
*.sage.py
|
|
80
|
+
|
|
81
|
+
# dotenv
|
|
82
|
+
.env
|
|
83
|
+
|
|
84
|
+
# virtualenv
|
|
85
|
+
.venv
|
|
86
|
+
venv/
|
|
87
|
+
ENV/
|
|
88
|
+
|
|
89
|
+
# Spyder project settings
|
|
90
|
+
.spyderproject
|
|
91
|
+
.spyproject
|
|
92
|
+
|
|
93
|
+
# Rope project settings
|
|
94
|
+
.ropeproject
|
|
95
|
+
|
|
96
|
+
# mkdocs documentation
|
|
97
|
+
/site
|
|
98
|
+
|
|
99
|
+
# mypy
|
|
100
|
+
.mypy_cache/
|
|
101
|
+
|
|
102
|
+
# this package
|
|
103
|
+
.idea/
|
|
104
|
+
.vscode/
|
|
105
|
+
.cursor/
|
|
106
|
+
.claude/
|
|
107
|
+
.codex/
|
|
108
|
+
.pytest_cache/
|
|
109
|
+
.DS_Store
|
|
110
|
+
*.pyc
|
|
111
|
+
*.swp
|
|
112
|
+
*.whl
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# AGENTS.md
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
`deepagents-opensandbox` is a Python package that implements a sandbox backend for the [DeepAgents](https://github.com/shkarupa-alex/deepagents) framework using [OpenSandbox](https://github.com/alibaba/OpenSandbox). It allows DeepAgents to execute code and commands in isolated OpenSandbox environments.
|
|
5
|
+
|
|
6
|
+
- **Language**: Python 3.11+
|
|
7
|
+
- **Dependency Manager**: `uv`
|
|
8
|
+
|
|
9
|
+
## Project Structure
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
deepagents-opensandbox/
|
|
13
|
+
├── deepagents_opensandbox/
|
|
14
|
+
│ ├── __init__.py # Package exports
|
|
15
|
+
│ ├── backend.py # OpensandboxBackend implementation
|
|
16
|
+
│ ├── provider.py # OpensandboxProvider implementation
|
|
17
|
+
│ ├── conftest.py # Shared test fixtures
|
|
18
|
+
│ ├── backend_test.py # Backend unit and integration tests
|
|
19
|
+
│ └── provider_test.py # Provider unit and integration tests
|
|
20
|
+
├── pyproject.toml # Project configuration and dependencies
|
|
21
|
+
├── uv.lock # Dependency lock file
|
|
22
|
+
├── docker-compose.yaml # Local dev server (OpenSandbox in Docker)
|
|
23
|
+
└── AGENTS.md # Documentation for AI coding agents
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Architecture
|
|
27
|
+
|
|
28
|
+
### 1. `OpensandboxBackend` (`backend.py`)
|
|
29
|
+
- Inherits from `BaseSandbox` from `deepagents.backends.sandbox`.
|
|
30
|
+
- Wraps `SandboxSync` for execute/upload/download.
|
|
31
|
+
- Command execution via `sandbox.commands.run()` + `sandbox.commands.get_command_status()`.
|
|
32
|
+
- File upload via `sandbox.files.write_file()`, download via `sandbox.files.read_bytes()`.
|
|
33
|
+
|
|
34
|
+
### 2. `OpensandboxProvider` (`provider.py`)
|
|
35
|
+
- Inherits from `SandboxProvider` from `deepagents_cli.integrations.sandbox_provider`.
|
|
36
|
+
- Lifecycle management: create, connect, delete (sync + async).
|
|
37
|
+
- Async path (`aget_or_create`) uses native async SDK (`Sandbox`) for non-blocking creation, then wraps in sync `SandboxSync` backend.
|
|
38
|
+
- Configuration via env vars: `OPEN_SANDBOX_API_KEY`, `OPEN_SANDBOX_DOMAIN`.
|
|
39
|
+
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
- **Unit tests**: `uv run python -m pytest deepagents_opensandbox/ -v -k "not integration"`
|
|
43
|
+
- **Integration tests**: `OPEN_SANDBOX_DOMAIN=localhost:8090 uv run python -m pytest deepagents_opensandbox/ -v -k integration`
|
|
44
|
+
- **All tests**: `OPEN_SANDBOX_DOMAIN=localhost:8090 uv run python -m pytest deepagents_opensandbox/ -v`
|
|
45
|
+
- **Lint**: `uv run ruff check deepagents_opensandbox/`
|
|
46
|
+
- **Format check**: `uv run ruff format --check deepagents_opensandbox/`
|
|
47
|
+
|
|
48
|
+
## Server proxy mode
|
|
49
|
+
|
|
50
|
+
The SDK can talk to sandbox containers in two ways:
|
|
51
|
+
|
|
52
|
+
1. **Direct** (`use_server_proxy=False`, default): SDK connects to container IP/port directly. Works when client and containers are on the same network.
|
|
53
|
+
2. **Server proxy** (`use_server_proxy=True`): All execd requests go through the OpenSandbox server at `OPEN_SANDBOX_DOMAIN`. Required when the client cannot reach container IPs (e.g. server in Docker, client on host — `host.docker.internal` is not resolvable from macOS host).
|
|
54
|
+
|
|
55
|
+
`use_server_proxy` defaults to `False` in `OpensandboxProvider`. Integration tests pass `True` explicitly because they run from the host against a Docker-based server. Our docker-compose setup runs the server in Docker with `host_ip = "host.docker.internal"`.
|
|
56
|
+
|
|
57
|
+
## Known issues
|
|
58
|
+
|
|
59
|
+
- **Server ≤ v0.1.4**: proxy handler in `lifecycle.py` drops query parameters on GET requests (builds `target_url` without `request.url.query`). File downloads via proxy return `400 MISSING_QUERY`. Fixed in `main` (not yet released). Workaround: build server image from source. Our docker-compose uses a locally-built image with this fix.
|
|
60
|
+
|
|
61
|
+
## Development Standards
|
|
62
|
+
|
|
63
|
+
### Code Style
|
|
64
|
+
- **Formatter/Linter**: `ruff` (configuration in `pyproject.toml`).
|
|
65
|
+
- **Type Hints**: Strict typing enforced.
|
|
66
|
+
- **Docstrings**: Google-style for public APIs.
|
|
67
|
+
|
|
68
|
+
### Testing
|
|
69
|
+
- Tests are in `*_test.py` files alongside source code.
|
|
70
|
+
- Integration tests are gated by `OPEN_SANDBOX_DOMAIN` env var and a TCP connectivity check (`integration_server_available()` in `conftest.py`).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Shkarupa Alex
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: deepagents-opensandbox
|
|
3
|
+
Version: 1.0.1
|
|
4
|
+
Summary: Opensandbox backend for DeepAgents
|
|
5
|
+
License-File: LICENSE
|
|
6
|
+
Requires-Python: >=3.11
|
|
7
|
+
Requires-Dist: deepagents>=0.4.5
|
|
8
|
+
Requires-Dist: opensandbox>=0.1.5
|
|
9
|
+
Provides-Extra: cli
|
|
10
|
+
Requires-Dist: deepagents-cli>=0.0.27; extra == 'cli'
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# deepagents-opensandbox
|
|
14
|
+
|
|
15
|
+
OpenSandbox backend for the [DeepAgents](https://github.com/shkarupa-alex/deepagents) framework. This package enables DeepAgents to launch and control isolated sandbox environments using [OpenSandbox](https://github.com/nicholasgriffintn/OpenSandbox).
|
|
16
|
+
|
|
17
|
+
## Key Features
|
|
18
|
+
|
|
19
|
+
- **Sandbox Provider**: Manages the lifecycle of OpenSandbox instances (create, connect, delete) via the `SandboxProvider` interface from `deepagents-cli`.
|
|
20
|
+
- **Sandbox Backend**: Provides a standard interface for command execution and file operations within a sandbox using the synchronous OpenSandbox SDK (`SandboxSync`).
|
|
21
|
+
- **DeepAgents Integration**: Fully compatible with `BaseSandbox` and `SandboxProvider` interfaces.
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
pip install deepagents-opensandbox
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
## Usage
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
from deepagents_opensandbox import OpensandboxProvider
|
|
33
|
+
|
|
34
|
+
# Initialize the provider (uses OPEN_SANDBOX_API_KEY and OPEN_SANDBOX_DOMAIN env vars)
|
|
35
|
+
provider = OpensandboxProvider()
|
|
36
|
+
|
|
37
|
+
# Create a new sandbox
|
|
38
|
+
sandbox = provider.get_or_create(image="python:3.11")
|
|
39
|
+
|
|
40
|
+
# Execute a command
|
|
41
|
+
result = sandbox.execute("echo 'Hello World'")
|
|
42
|
+
print(result.output)
|
|
43
|
+
|
|
44
|
+
# Clean up
|
|
45
|
+
provider.delete(sandbox_id=sandbox.id)
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Using the backend directly
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
from opensandbox.sync.sandbox import SandboxSync
|
|
52
|
+
from deepagents_opensandbox import OpensandboxBackend
|
|
53
|
+
|
|
54
|
+
sandbox = SandboxSync.create("python:3.11")
|
|
55
|
+
backend = OpensandboxBackend(sandbox=sandbox)
|
|
56
|
+
|
|
57
|
+
result = backend.execute("python --version")
|
|
58
|
+
print(result.output)
|
|
59
|
+
|
|
60
|
+
sandbox.kill()
|
|
61
|
+
sandbox.close()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Configuration
|
|
65
|
+
|
|
66
|
+
| Environment Variable | Description | Default |
|
|
67
|
+
|---------------------------|--------------------------------------|------------------|
|
|
68
|
+
| `OPEN_SANDBOX_API_KEY` | API key for authentication | *(none)* |
|
|
69
|
+
| `OPEN_SANDBOX_DOMAIN` | OpenSandbox server domain | `localhost:8080` |
|
|
70
|
+
|
|
71
|
+
### Server proxy mode
|
|
72
|
+
|
|
73
|
+
By default, the SDK connects directly to sandbox container IPs. This works when the client and sandbox containers share the same network (e.g. both on the host, or in the same Docker/Kubernetes network).
|
|
74
|
+
|
|
75
|
+
When the OpenSandbox **server runs inside Docker** and the client runs on the **host machine**, container IPs (like `host.docker.internal`) are not reachable from the host. In this case, enable server proxy mode so that all execd requests are routed through the server:
|
|
76
|
+
|
|
77
|
+
```python
|
|
78
|
+
provider = OpensandboxProvider(use_server_proxy=True)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
| Deployment | `use_server_proxy` |
|
|
82
|
+
|-----------------------------------------|--------------------|
|
|
83
|
+
| Server native on host, client on host | `False` (default) |
|
|
84
|
+
| Server in Docker, client on host | `True` |
|
|
85
|
+
| Server in Docker, client in same network| `False` |
|
|
86
|
+
| Kubernetes with proper networking | `False` |
|
|
87
|
+
|
|
88
|
+
> **Note:** OpenSandbox server `v0.1.4` and earlier have a [bug](https://github.com/alibaba/OpenSandbox) where the proxy handler drops query parameters on GET requests, causing file downloads to fail with `400 MISSING_QUERY`. The fix is merged into `main` but not yet released. If you hit this issue, build the server image from source (`server/` directory).
|
|
89
|
+
|
|
90
|
+
## Development
|
|
91
|
+
|
|
92
|
+
This project uses `uv` for dependency management.
|
|
93
|
+
|
|
94
|
+
### Prerequisites
|
|
95
|
+
|
|
96
|
+
- [uv](https://github.com/astral-sh/uv) installed.
|
|
97
|
+
- Python 3.11 or higher.
|
|
98
|
+
|
|
99
|
+
### Setup
|
|
100
|
+
|
|
101
|
+
Install dependencies:
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv sync
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### Testing
|
|
108
|
+
|
|
109
|
+
Tests are split into unit tests (mocked) and integration tests (requiring a real server).
|
|
110
|
+
|
|
111
|
+
**Run Unit Tests (Mocked)**
|
|
112
|
+
|
|
113
|
+
These tests mock the OpenSandbox SDK calls and do not require a running server.
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
uv run python -m pytest deepagents_opensandbox/ -v
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Run Integration Tests**
|
|
120
|
+
|
|
121
|
+
These tests verify behavior against a real OpenSandbox server. They use `use_server_proxy=True` since the test runner is on the host while the server is in Docker.
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
OPEN_SANDBOX_DOMAIN=localhost:8090 uv run python -m pytest deepagents_opensandbox/ -v -k integration
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Linting
|
|
128
|
+
|
|
129
|
+
```bash
|
|
130
|
+
uv run ruff check deepagents_opensandbox/
|
|
131
|
+
uv run ruff format --check deepagents_opensandbox/
|
|
132
|
+
```
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# deepagents-opensandbox
|
|
2
|
+
|
|
3
|
+
OpenSandbox backend for the [DeepAgents](https://github.com/shkarupa-alex/deepagents) framework. This package enables DeepAgents to launch and control isolated sandbox environments using [OpenSandbox](https://github.com/nicholasgriffintn/OpenSandbox).
|
|
4
|
+
|
|
5
|
+
## Key Features
|
|
6
|
+
|
|
7
|
+
- **Sandbox Provider**: Manages the lifecycle of OpenSandbox instances (create, connect, delete) via the `SandboxProvider` interface from `deepagents-cli`.
|
|
8
|
+
- **Sandbox Backend**: Provides a standard interface for command execution and file operations within a sandbox using the synchronous OpenSandbox SDK (`SandboxSync`).
|
|
9
|
+
- **DeepAgents Integration**: Fully compatible with `BaseSandbox` and `SandboxProvider` interfaces.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
pip install deepagents-opensandbox
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```python
|
|
20
|
+
from deepagents_opensandbox import OpensandboxProvider
|
|
21
|
+
|
|
22
|
+
# Initialize the provider (uses OPEN_SANDBOX_API_KEY and OPEN_SANDBOX_DOMAIN env vars)
|
|
23
|
+
provider = OpensandboxProvider()
|
|
24
|
+
|
|
25
|
+
# Create a new sandbox
|
|
26
|
+
sandbox = provider.get_or_create(image="python:3.11")
|
|
27
|
+
|
|
28
|
+
# Execute a command
|
|
29
|
+
result = sandbox.execute("echo 'Hello World'")
|
|
30
|
+
print(result.output)
|
|
31
|
+
|
|
32
|
+
# Clean up
|
|
33
|
+
provider.delete(sandbox_id=sandbox.id)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Using the backend directly
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
from opensandbox.sync.sandbox import SandboxSync
|
|
40
|
+
from deepagents_opensandbox import OpensandboxBackend
|
|
41
|
+
|
|
42
|
+
sandbox = SandboxSync.create("python:3.11")
|
|
43
|
+
backend = OpensandboxBackend(sandbox=sandbox)
|
|
44
|
+
|
|
45
|
+
result = backend.execute("python --version")
|
|
46
|
+
print(result.output)
|
|
47
|
+
|
|
48
|
+
sandbox.kill()
|
|
49
|
+
sandbox.close()
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Configuration
|
|
53
|
+
|
|
54
|
+
| Environment Variable | Description | Default |
|
|
55
|
+
|---------------------------|--------------------------------------|------------------|
|
|
56
|
+
| `OPEN_SANDBOX_API_KEY` | API key for authentication | *(none)* |
|
|
57
|
+
| `OPEN_SANDBOX_DOMAIN` | OpenSandbox server domain | `localhost:8080` |
|
|
58
|
+
|
|
59
|
+
### Server proxy mode
|
|
60
|
+
|
|
61
|
+
By default, the SDK connects directly to sandbox container IPs. This works when the client and sandbox containers share the same network (e.g. both on the host, or in the same Docker/Kubernetes network).
|
|
62
|
+
|
|
63
|
+
When the OpenSandbox **server runs inside Docker** and the client runs on the **host machine**, container IPs (like `host.docker.internal`) are not reachable from the host. In this case, enable server proxy mode so that all execd requests are routed through the server:
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
provider = OpensandboxProvider(use_server_proxy=True)
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
| Deployment | `use_server_proxy` |
|
|
70
|
+
|-----------------------------------------|--------------------|
|
|
71
|
+
| Server native on host, client on host | `False` (default) |
|
|
72
|
+
| Server in Docker, client on host | `True` |
|
|
73
|
+
| Server in Docker, client in same network| `False` |
|
|
74
|
+
| Kubernetes with proper networking | `False` |
|
|
75
|
+
|
|
76
|
+
> **Note:** OpenSandbox server `v0.1.4` and earlier have a [bug](https://github.com/alibaba/OpenSandbox) where the proxy handler drops query parameters on GET requests, causing file downloads to fail with `400 MISSING_QUERY`. The fix is merged into `main` but not yet released. If you hit this issue, build the server image from source (`server/` directory).
|
|
77
|
+
|
|
78
|
+
## Development
|
|
79
|
+
|
|
80
|
+
This project uses `uv` for dependency management.
|
|
81
|
+
|
|
82
|
+
### Prerequisites
|
|
83
|
+
|
|
84
|
+
- [uv](https://github.com/astral-sh/uv) installed.
|
|
85
|
+
- Python 3.11 or higher.
|
|
86
|
+
|
|
87
|
+
### Setup
|
|
88
|
+
|
|
89
|
+
Install dependencies:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
uv sync
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Testing
|
|
96
|
+
|
|
97
|
+
Tests are split into unit tests (mocked) and integration tests (requiring a real server).
|
|
98
|
+
|
|
99
|
+
**Run Unit Tests (Mocked)**
|
|
100
|
+
|
|
101
|
+
These tests mock the OpenSandbox SDK calls and do not require a running server.
|
|
102
|
+
|
|
103
|
+
```bash
|
|
104
|
+
uv run python -m pytest deepagents_opensandbox/ -v
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
**Run Integration Tests**
|
|
108
|
+
|
|
109
|
+
These tests verify behavior against a real OpenSandbox server. They use `use_server_proxy=True` since the test runner is on the host while the server is in Docker.
|
|
110
|
+
|
|
111
|
+
```bash
|
|
112
|
+
OPEN_SANDBOX_DOMAIN=localhost:8090 uv run python -m pytest deepagents_opensandbox/ -v -k integration
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Linting
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
uv run ruff check deepagents_opensandbox/
|
|
119
|
+
uv run ruff format --check deepagents_opensandbox/
|
|
120
|
+
```
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"""Opensandbox integration for DeepAgents.
|
|
2
|
+
|
|
3
|
+
This package provides:
|
|
4
|
+
- OpensandboxBackend: Sandbox backend for executing commands in OpenSandbox containers
|
|
5
|
+
- OpensandboxProvider: Provider for managing OpenSandbox lifecycle (requires ``deepagents-cli``)
|
|
6
|
+
|
|
7
|
+
Example usage:
|
|
8
|
+
```python
|
|
9
|
+
from deepagents_opensandbox import OpensandboxProvider
|
|
10
|
+
|
|
11
|
+
provider = OpensandboxProvider()
|
|
12
|
+
sandbox = provider.get_or_create(image="python:3.11")
|
|
13
|
+
result = sandbox.execute("echo 'Hello'")
|
|
14
|
+
provider.delete(sandbox_id=sandbox.id)
|
|
15
|
+
```
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from deepagents_opensandbox.backend import OpensandboxBackend
|
|
19
|
+
|
|
20
|
+
__all__ = ["OpensandboxBackend"]
|
|
21
|
+
|
|
22
|
+
try:
|
|
23
|
+
from deepagents_opensandbox.provider import OpensandboxProvider
|
|
24
|
+
|
|
25
|
+
__all__ += ["OpensandboxProvider"] # type: ignore[assignment]
|
|
26
|
+
except ImportError:
|
|
27
|
+
pass
|