voidrun 0.0.5__tar.gz → 0.0.7__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.
- voidrun-0.0.7/PKG-INFO +522 -0
- voidrun-0.0.7/README.md +498 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/pyproject.toml +2 -1
- voidrun-0.0.7/scripts/run_all_examples.sh +46 -0
- voidrun-0.0.7/voidrun/__init__.py +29 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_sandbox_request.py +4 -4
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/image.py +8 -4
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/sandbox.py +13 -7
- voidrun-0.0.7/voidrun/client.py +399 -0
- voidrun-0.0.7/voidrun/constants.py +29 -0
- voidrun-0.0.7/voidrun/interpreter.py +176 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/sandbox.py +112 -38
- voidrun-0.0.5/PKG-INFO +0 -899
- voidrun-0.0.5/README.md +0 -875
- voidrun-0.0.5/voidrun/__init__.py +0 -4
- voidrun-0.0.5/voidrun/client.py +0 -140
- voidrun-0.0.5/voidrun/interpreter.py +0 -99
- {voidrun-0.0.5 → voidrun-0.0.7}/.gitignore +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/__init__.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/__init__.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/execution_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/file_system_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/images_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/organizations_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/sandboxes_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/system_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api/users_api.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api_client.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/api_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/configuration.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/exceptions.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/__init__.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/activate_api_key_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/api_key_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/api_response_sandbox.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/api_response_sandboxes_list.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/api_response_sandboxes_list_meta.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/command_kill_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/command_list_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/command_run_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/command_wait_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/compress_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_file_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_image_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_pty_session200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_pty_session200_response_all_of_data.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_pty_session_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/create_sandbox201_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/disk_usage.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/error_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/exec_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/exec_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/exec_response_data.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/execute_in_session_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/extract_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/file_event.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/file_info.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/file_stats.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/generate_api_key_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/generated_api_key_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_current_user200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_current_user200_response_orgs_inner.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_org_users200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_org_users200_response_all_of_data_inner.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_pty_buffer200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_pty_buffer200_response_all_of_data.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/get_version200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/kill_background_process_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/list_files200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/list_files200_response_data.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/list_pty_sessions200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/list_pty_sessions200_response_all_of_data.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/organization.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/process_info.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/pty_session_info.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/resize_terminal_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/run_background_command_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/session_exec_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/session_exec_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/session_exec_stream_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/start_watch200_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/start_watch200_response_data.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/start_watch_request.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/models/success_response.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/py.typed +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/api_client/rest.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/commands.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/fs.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/pty.py +0 -0
- {voidrun-0.0.5 → voidrun-0.0.7}/voidrun/response.py +0 -0
voidrun-0.0.7/PKG-INFO
ADDED
|
@@ -0,0 +1,522 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: voidrun
|
|
3
|
+
Version: 0.0.7
|
|
4
|
+
Summary: Python SDK for VoidRun AI Sandbox
|
|
5
|
+
Project-URL: Homepage, https://voidrun.io
|
|
6
|
+
Project-URL: Documentation, https://docs.voidrun.io
|
|
7
|
+
Project-URL: Repository, https://github.com/voidrun/py-sdk
|
|
8
|
+
Author-email: VoidRun Team <support@voidrun.io>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
Classifier: Framework :: AsyncIO
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Requires-Python: >=3.9
|
|
15
|
+
Requires-Dist: certifi
|
|
16
|
+
Requires-Dist: httpx>=0.24.0
|
|
17
|
+
Requires-Dist: pydantic>=2.0.0
|
|
18
|
+
Requires-Dist: python-dateutil>=2.8.2
|
|
19
|
+
Requires-Dist: python-dotenv>=1.0.0
|
|
20
|
+
Requires-Dist: typing-extensions>=4.0.0
|
|
21
|
+
Requires-Dist: urllib3>=2.0.0
|
|
22
|
+
Requires-Dist: websockets>=11.0
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
25
|
+
# VoidRun Python SDK
|
|
26
|
+
|
|
27
|
+
Python client for [VoidRun](https://voidrun.io) AI sandboxes: run commands, manage files, use pseudo-terminals, stream output, and execute multi-language code in isolated environments.
|
|
28
|
+
|
|
29
|
+
The high-level API is aligned with the official **TypeScript SDK** (`create_sandbox`, `list_sandboxes`, `remove_sandbox`, `Sandbox.run_code`, `CodeExecutionResult`, and shared defaults).
|
|
30
|
+
|
|
31
|
+
[](https://pypi.org/project/voidrun/)
|
|
32
|
+
[](https://opensource.org/licenses/MIT)
|
|
33
|
+
|
|
34
|
+
## Table of contents
|
|
35
|
+
|
|
36
|
+
- [Features](#features)
|
|
37
|
+
- [Requirements](#requirements)
|
|
38
|
+
- [Installation](#installation)
|
|
39
|
+
- [Configuration](#configuration)
|
|
40
|
+
- [Quick start](#quick-start)
|
|
41
|
+
- [Parity with the TypeScript SDK](#parity-with-the-typescript-sdk)
|
|
42
|
+
- [Core concepts](#core-concepts)
|
|
43
|
+
- [Code execution and interpreter](#code-execution-and-interpreter)
|
|
44
|
+
- [Background commands](#background-commands)
|
|
45
|
+
- [File system](#file-system)
|
|
46
|
+
- [File watching (async)](#file-watching-async)
|
|
47
|
+
- [Pseudo-terminal (PTY)](#pseudo-terminal-pty)
|
|
48
|
+
- [API reference (summary)](#api-reference-summary)
|
|
49
|
+
- [Runnable examples](#runnable-examples)
|
|
50
|
+
- [Development and tests](#development-and-tests)
|
|
51
|
+
- [Building and publishing](#building-and-publishing)
|
|
52
|
+
- [Error handling](#error-handling)
|
|
53
|
+
- [Troubleshooting](#troubleshooting)
|
|
54
|
+
- [Contributing, license, support](#contributing-license-support)
|
|
55
|
+
|
|
56
|
+
## Features
|
|
57
|
+
|
|
58
|
+
- **Sandbox lifecycle**: Create, list, fetch, start/stop/pause/resume, and remove sandboxes (sync and async).
|
|
59
|
+
- **Shell execution**: `exec` with optional `ExecRequest`; SSE streaming via `exec_stream`.
|
|
60
|
+
- **Code interpreter**: `run_code` / `interpreter.run` return a structured **`CodeExecutionResult`** (stdout, stderr, success, exit_code, results, logs).
|
|
61
|
+
- **Files**: Create, upload, download, list, move, copy, compress, extract, permissions, search, disk usage.
|
|
62
|
+
- **File watching**: WebSocket-backed directory watches (async).
|
|
63
|
+
- **PTY**: Ephemeral and persistent terminal sessions, resize, `run_command` with prompt detection.
|
|
64
|
+
- **Background commands**: Run, list, attach, wait, kill long-running processes.
|
|
65
|
+
|
|
66
|
+
## Requirements
|
|
67
|
+
|
|
68
|
+
- Python **3.9+**
|
|
69
|
+
- Dependencies: see [`pyproject.toml`](pyproject.toml) (Pydantic v2, httpx, urllib3, websockets, python-dotenv, etc.).
|
|
70
|
+
|
|
71
|
+
## Installation
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install voidrun
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
With Poetry:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
poetry add voidrun
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**From this repository** (editable install for development):
|
|
84
|
+
|
|
85
|
+
```bash
|
|
86
|
+
cd py-sdk
|
|
87
|
+
pip install -e .
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Configuration
|
|
91
|
+
|
|
92
|
+
`VoidRun` and `AsyncVoidRun` require an **API key**. The **API base URL** defaults to the hosted endpoint (**`DEFAULT_API_BASE_URL`**, aligned with the TypeScript SDK and OpenAPI **`servers`**). Set **`VR_API_URL`** or **`API_URL`**, or pass **`base_url=`**, only for **self-hosted** deployments.
|
|
93
|
+
|
|
94
|
+
### Constructor
|
|
95
|
+
|
|
96
|
+
```python
|
|
97
|
+
from voidrun import VoidRun
|
|
98
|
+
|
|
99
|
+
vr = VoidRun(
|
|
100
|
+
api_key="your-api-key", # optional if VR_API_KEY / API_KEY is set
|
|
101
|
+
)
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Environment variables
|
|
105
|
+
|
|
106
|
+
| Variable | Purpose |
|
|
107
|
+
|----------|---------|
|
|
108
|
+
| `VR_API_KEY` or `API_KEY` | API key (required unless passed to the constructor). |
|
|
109
|
+
| `VR_API_URL` or `API_URL` | *(Self-hosted only.)* Overrides the default API base URL. |
|
|
110
|
+
|
|
111
|
+
### Defaults (aligned with TypeScript SDK)
|
|
112
|
+
|
|
113
|
+
Exported from `voidrun`:
|
|
114
|
+
|
|
115
|
+
| Constant | Value | Meaning |
|
|
116
|
+
|----------|-------|---------|
|
|
117
|
+
| `DEFAULT_API_BASE_URL` | `https://platform.void-run.com/api` | Default API host when `VR_API_URL` / `API_URL` are unset. |
|
|
118
|
+
| `DEFAULT_SANDBOX_IMAGE` | `"code"` | Default image id when creating a sandbox without `image=`. |
|
|
119
|
+
| `DEFAULT_SANDBOX_CPU` | `1` | Default CPU count. |
|
|
120
|
+
| `DEFAULT_SANDBOX_MEM` | `1024` | Default memory in MB. |
|
|
121
|
+
|
|
122
|
+
For **self-hosted** VoidRun, set **`VR_API_URL`** (or **`API_URL`**) to your instance’s API root (including `/api` if that is how your server is mounted).
|
|
123
|
+
|
|
124
|
+
## Quick start
|
|
125
|
+
|
|
126
|
+
### Synchronous (recommended shape)
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from voidrun import VoidRun
|
|
130
|
+
|
|
131
|
+
vr = VoidRun() # uses VR_API_KEY; default base URL unless VR_API_URL / API_URL is set
|
|
132
|
+
|
|
133
|
+
sandbox = vr.create_sandbox(mem=1024, cpu=1)
|
|
134
|
+
|
|
135
|
+
result = sandbox.exec('echo "Hello from VoidRun"')
|
|
136
|
+
# Exec returns VoidRunResponse whose .data is ExecResponseData
|
|
137
|
+
print(result.data.stdout)
|
|
138
|
+
|
|
139
|
+
sandbox.remove()
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Async
|
|
143
|
+
|
|
144
|
+
```python
|
|
145
|
+
import asyncio
|
|
146
|
+
from voidrun import AsyncVoidRun
|
|
147
|
+
|
|
148
|
+
async def main():
|
|
149
|
+
async with AsyncVoidRun() as vr:
|
|
150
|
+
sandbox = await vr.create_sandbox(mem=1024, cpu=1)
|
|
151
|
+
result = sandbox.exec('echo "Hello"')
|
|
152
|
+
print(result.data.stdout)
|
|
153
|
+
await sandbox.remove_async()
|
|
154
|
+
|
|
155
|
+
asyncio.run(main())
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
### Context managers (auto cleanup)
|
|
159
|
+
|
|
160
|
+
Sync: exiting the block calls `remove()`. Async: `__aexit__` calls `remove_async()`.
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
with vr.create_sandbox() as sandbox:
|
|
164
|
+
print(sandbox.id)
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
```python
|
|
168
|
+
async with await vr.create_sandbox() as sandbox:
|
|
169
|
+
print(sandbox.id)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Parity with the TypeScript SDK
|
|
173
|
+
|
|
174
|
+
Use the same mental model as `@voidrun/sdk` (or the internal TS client):
|
|
175
|
+
|
|
176
|
+
| TypeScript (concept) | Python |
|
|
177
|
+
|----------------------|--------|
|
|
178
|
+
| `createSandbox` | `VoidRun.create_sandbox` / `await AsyncVoidRun.create_sandbox` |
|
|
179
|
+
| `getSandbox` | `get_sandbox` |
|
|
180
|
+
| `listSandboxes` | `list_sandboxes` → `ListSandboxesResult` |
|
|
181
|
+
| `removeSandbox` | `remove_sandbox` or `sandbox.remove()` |
|
|
182
|
+
| `sandbox.runCode` | `sandbox.run_code` |
|
|
183
|
+
| `CodeExecutionResult` | `CodeExecutionResult` (Pydantic model) |
|
|
184
|
+
| `CodeInterpreter` | `CodeInterpreter` (alias: `Interpreter` on `sandbox.interpreter`) |
|
|
185
|
+
|
|
186
|
+
**Listing sandboxes** returns a **`ListSandboxesResult`** with:
|
|
187
|
+
|
|
188
|
+
- `.sandboxes`: list of `Sandbox` instances
|
|
189
|
+
- `.meta`: `ListSandboxesMeta` (`total`, `page`, `limit`, `total_pages`)
|
|
190
|
+
|
|
191
|
+
## Core concepts
|
|
192
|
+
|
|
193
|
+
### `VoidRun` / `AsyncVoidRun`
|
|
194
|
+
|
|
195
|
+
**Recommended methods**
|
|
196
|
+
|
|
197
|
+
- `create_sandbox(...)` → `Sandbox`
|
|
198
|
+
- `get_sandbox(sandbox_id)` → `Sandbox`
|
|
199
|
+
- `list_sandboxes(page=..., limit=...)` → `ListSandboxesResult`
|
|
200
|
+
- `remove_sandbox(sandbox_id)` → `None`
|
|
201
|
+
|
|
202
|
+
`AsyncVoidRun` exposes the same names with `await` and provides `aclose()` (and `async with` support) to shut down the thread pool used for API calls.
|
|
203
|
+
|
|
204
|
+
**Keyword aliases**
|
|
205
|
+
|
|
206
|
+
Create options accept both snake_case and camelCase where noted in code (e.g. `env_vars` / `envVars`, `org_id` / `orgId`).
|
|
207
|
+
|
|
208
|
+
### `Sandbox`
|
|
209
|
+
|
|
210
|
+
Notable attributes: `id`, `name`, `cpu`, `mem`, `org_id`, `status`, `env_vars`, `image`, `region`, `ref_id`, `auto_sleep`, `disk_mb`, `created_at`, `created_by`.
|
|
211
|
+
|
|
212
|
+
Sub-clients:
|
|
213
|
+
|
|
214
|
+
- `.fs`: file operations
|
|
215
|
+
- `.pty`: pseudo-terminal
|
|
216
|
+
- `.interpreter`: `CodeInterpreter`
|
|
217
|
+
- `.commands`: background processes
|
|
218
|
+
|
|
219
|
+
Lifecycle:
|
|
220
|
+
|
|
221
|
+
- `start`, `stop`, `pause`, `resume` (and `*_async` variants where applicable)
|
|
222
|
+
- `remove()` / `remove_async()`: delete sandbox on the API
|
|
223
|
+
- `delete()` / `delete_async()`: deprecated aliases for `remove`
|
|
224
|
+
|
|
225
|
+
`info()` returns `self` (same idea as TS `sandbox.info()`).
|
|
226
|
+
|
|
227
|
+
## Code execution and interpreter
|
|
228
|
+
|
|
229
|
+
### `sandbox.exec`
|
|
230
|
+
|
|
231
|
+
Accepts a command string, or keyword `command=`, or a full **`ExecRequest`**:
|
|
232
|
+
|
|
233
|
+
```python
|
|
234
|
+
from voidrun.api_client.models.exec_request import ExecRequest
|
|
235
|
+
|
|
236
|
+
r = sandbox.exec("uname -a")
|
|
237
|
+
r = sandbox.exec(command="pwd", cwd="/tmp", timeout=60)
|
|
238
|
+
r = sandbox.exec(ExecRequest(command="ls", cwd="/"))
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
Return type: **`VoidRunResponse[ExecResponseData]`**: the API’s outer **`ExecResponse`** envelope is unwrapped so **`r.data`** is **`ExecResponseData`** (stdout / stderr / exit_code):
|
|
242
|
+
|
|
243
|
+
```python
|
|
244
|
+
print(r.data.stdout, r.data.stderr, r.data.exit_code)
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Streaming (`exec_stream`)
|
|
248
|
+
|
|
249
|
+
Provide callbacks for SSE events (`on_stdout`, `on_stderr`, `on_exit`, `on_error`).
|
|
250
|
+
|
|
251
|
+
### Interpreter and `run_code`
|
|
252
|
+
|
|
253
|
+
`sandbox.interpreter` is a **`CodeInterpreter`**. Both `interpreter.run(...)` and **`sandbox.run_code(...)`** return **`CodeExecutionResult`** directly (no `.data` nesting):
|
|
254
|
+
|
|
255
|
+
```python
|
|
256
|
+
result = sandbox.run_code("print(2 + 2)", language="python")
|
|
257
|
+
print(result.stdout.strip()) # "4"
|
|
258
|
+
print(result.success)
|
|
259
|
+
|
|
260
|
+
result = sandbox.interpreter.run("console.log(1+1)", language="javascript")
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
**Supported languages** (typical): `python`, `javascript`, `typescript`, `node`, `bash`, `sh` (as supported by your VoidRun deployment).
|
|
264
|
+
|
|
265
|
+
## Background commands
|
|
266
|
+
|
|
267
|
+
```python
|
|
268
|
+
run_result = sandbox.commands.run(
|
|
269
|
+
"sleep 5 && echo done",
|
|
270
|
+
{"DEBUG": "true"},
|
|
271
|
+
"/tmp",
|
|
272
|
+
0,
|
|
273
|
+
)
|
|
274
|
+
print(run_result.data.pid)
|
|
275
|
+
|
|
276
|
+
sandbox.commands.list()
|
|
277
|
+
sandbox.commands.connect(pid, on_stdout=..., on_stderr=..., on_exit=...)
|
|
278
|
+
sandbox.commands.wait(pid)
|
|
279
|
+
sandbox.commands.kill(pid)
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Response shapes follow the generated OpenAPI models; access fields via `.data` on `VoidRunResponse` where applicable.
|
|
283
|
+
|
|
284
|
+
## File system
|
|
285
|
+
|
|
286
|
+
```python
|
|
287
|
+
sandbox.fs.create_file("/tmp/hello.txt")
|
|
288
|
+
sandbox.fs.upload_file("/tmp/hello.txt", "Hello, World!")
|
|
289
|
+
sandbox.fs.upload_file_from_path("/tmp/remote.txt", "/local/file.txt")
|
|
290
|
+
|
|
291
|
+
data = sandbox.fs.download_file("/tmp/hello.txt")
|
|
292
|
+
sandbox.fs.delete_file("/tmp/hello.txt")
|
|
293
|
+
|
|
294
|
+
result = sandbox.fs.list_files("/tmp")
|
|
295
|
+
files = result.data
|
|
296
|
+
|
|
297
|
+
sandbox.fs.stat_file("/tmp/hello.txt")
|
|
298
|
+
sandbox.fs.create_directory("/tmp/mydir")
|
|
299
|
+
sandbox.fs.move_file("/tmp/a.txt", "/tmp/b.txt")
|
|
300
|
+
sandbox.fs.copy_file("/tmp/a.txt", "/tmp/copy.txt")
|
|
301
|
+
sandbox.fs.change_permissions("/tmp/a.txt", "755")
|
|
302
|
+
|
|
303
|
+
sandbox.fs.head_tail("/tmp/log.txt", head=True, lines=10)
|
|
304
|
+
sandbox.fs.search_files("/tmp", "*.txt")
|
|
305
|
+
sandbox.fs.disk_usage("/tmp")
|
|
306
|
+
|
|
307
|
+
archive = sandbox.fs.compress_file("/tmp", "tar.gz")
|
|
308
|
+
sandbox.fs.extract_archive("/tmp/archive.tar.gz", "/tmp/extracted")
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
## File watching (async)
|
|
312
|
+
|
|
313
|
+
```python
|
|
314
|
+
import asyncio
|
|
315
|
+
from voidrun import AsyncVoidRun
|
|
316
|
+
|
|
317
|
+
async def watch_tmp():
|
|
318
|
+
async with AsyncVoidRun() as vr:
|
|
319
|
+
sandbox = await vr.create_sandbox()
|
|
320
|
+
|
|
321
|
+
watcher = await sandbox.fs.watch(
|
|
322
|
+
"/app",
|
|
323
|
+
recursive=True,
|
|
324
|
+
on_event=lambda evt: print(evt.get("path"), evt.get("type")),
|
|
325
|
+
on_error=lambda err: print("watch error:", err),
|
|
326
|
+
)
|
|
327
|
+
|
|
328
|
+
await asyncio.sleep(60)
|
|
329
|
+
watcher.close()
|
|
330
|
+
await sandbox.remove_async()
|
|
331
|
+
|
|
332
|
+
asyncio.run(watch_tmp())
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
## Pseudo-terminal (PTY)
|
|
336
|
+
|
|
337
|
+
### Ephemeral session
|
|
338
|
+
|
|
339
|
+
```python
|
|
340
|
+
import asyncio
|
|
341
|
+
from voidrun import AsyncVoidRun
|
|
342
|
+
|
|
343
|
+
async def ephemeral():
|
|
344
|
+
async with AsyncVoidRun() as vr:
|
|
345
|
+
sandbox = await vr.create_sandbox()
|
|
346
|
+
pty = await sandbox.pty.connect(
|
|
347
|
+
on_data=lambda data: print(data, end=""),
|
|
348
|
+
on_error=lambda err: print("PTY error:", err),
|
|
349
|
+
)
|
|
350
|
+
pty.send_input('echo "Hello"\n')
|
|
351
|
+
await asyncio.sleep(2)
|
|
352
|
+
await pty.close()
|
|
353
|
+
await sandbox.remove_async()
|
|
354
|
+
|
|
355
|
+
asyncio.run(ephemeral())
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Persistent session
|
|
359
|
+
|
|
360
|
+
```python
|
|
361
|
+
async def persistent():
|
|
362
|
+
async with AsyncVoidRun() as vr:
|
|
363
|
+
sandbox = await vr.create_sandbox()
|
|
364
|
+
response = sandbox.pty.create_session()
|
|
365
|
+
session_id = response.data.data.session_id
|
|
366
|
+
|
|
367
|
+
pty = await sandbox.pty.connect(
|
|
368
|
+
session_id=session_id,
|
|
369
|
+
on_data=lambda data: print(data, end=""),
|
|
370
|
+
)
|
|
371
|
+
pty.send_input('echo "Hello"\n')
|
|
372
|
+
await pty.close()
|
|
373
|
+
|
|
374
|
+
reconnected = await sandbox.pty.connect(
|
|
375
|
+
session_id=session_id,
|
|
376
|
+
on_data=lambda data: print(data, end=""),
|
|
377
|
+
)
|
|
378
|
+
await reconnected.close()
|
|
379
|
+
|
|
380
|
+
sandbox.pty.delete_session(session_id)
|
|
381
|
+
await sandbox.remove_async()
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
### Helpers
|
|
385
|
+
|
|
386
|
+
```python
|
|
387
|
+
# After connect(...)
|
|
388
|
+
output = await pty.run_command("ls -la", timeout=5000, prompt="# ")
|
|
389
|
+
await pty.resize(80, 24)
|
|
390
|
+
|
|
391
|
+
sandbox.pty.list()
|
|
392
|
+
sandbox.pty.delete_session(session_id)
|
|
393
|
+
```
|
|
394
|
+
|
|
395
|
+
## API reference (summary)
|
|
396
|
+
|
|
397
|
+
### Exports (`from voidrun import ...`)
|
|
398
|
+
|
|
399
|
+
`VoidRun`, `AsyncVoidRun`, `Sandbox`, `CodeInterpreter`, `Interpreter` (alias), `CodeExecutionResult`, `ListSandboxesResult`, `ListSandboxesMeta`, `DEFAULT_SANDBOX_*`.
|
|
400
|
+
|
|
401
|
+
### `CodeExecutionResult`
|
|
402
|
+
|
|
403
|
+
| Field | Type | Description |
|
|
404
|
+
|-------|------|-------------|
|
|
405
|
+
| `success` | `bool` | Derived from exit code. |
|
|
406
|
+
| `stdout` / `stderr` | `str` | Combined streams. |
|
|
407
|
+
| `exit_code` | `int \| None` | Process exit code. |
|
|
408
|
+
| `results` | `Any` | Parsed output when applicable. |
|
|
409
|
+
| `error` | `str \| None` | Error hint (often stderr). |
|
|
410
|
+
| `logs` | `dict` | e.g. `stdout` / `stderr` line lists. |
|
|
411
|
+
|
|
412
|
+
### OpenAPI client
|
|
413
|
+
|
|
414
|
+
The package includes a generated **`voidrun.api_client`** module. Regenerate it when the VoidRun OpenAPI specification changes (same spec as other official clients). After regen, confirm **sandbox `status`** values still match the server (e.g. `running`, `stopped`, `paused`, `error`, `killed`, `deleted`, …).
|
|
415
|
+
|
|
416
|
+
## Runnable examples
|
|
417
|
+
|
|
418
|
+
The [`examples/`](examples/) directory contains scripts for sync/async usage, exec, FS, lifecycle, PTY, background commands, and the code interpreter.
|
|
419
|
+
|
|
420
|
+
**Run all examples** (loads `py-sdk/.env` if present, sets `PYTHONPATH`):
|
|
421
|
+
|
|
422
|
+
```bash
|
|
423
|
+
chmod +x scripts/run_all_examples.sh # once
|
|
424
|
+
./scripts/run_all_examples.sh
|
|
425
|
+
```
|
|
426
|
+
|
|
427
|
+
The script exits with status **1** if any example fails (useful for CI).
|
|
428
|
+
|
|
429
|
+
**Single example**
|
|
430
|
+
|
|
431
|
+
From the `py-sdk` directory (with `PYTHONPATH` including the repo root, same as the batch script):
|
|
432
|
+
|
|
433
|
+
```bash
|
|
434
|
+
export VR_API_KEY="your-api-key"
|
|
435
|
+
export PYTHONPATH="$(pwd)"
|
|
436
|
+
|
|
437
|
+
python3 examples/sync_usage.py
|
|
438
|
+
python3 examples/async_usage.py
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
Use an API key from the same VoidRun deployment as the API host (hosted default, or set **`VR_API_URL`** for self-hosted).
|
|
442
|
+
|
|
443
|
+
## Development and tests
|
|
444
|
+
|
|
445
|
+
```bash
|
|
446
|
+
cd py-sdk
|
|
447
|
+
pip install -e .
|
|
448
|
+
pip install pytest pytest-asyncio pytest-mock
|
|
449
|
+
|
|
450
|
+
pytest tests/
|
|
451
|
+
```
|
|
452
|
+
|
|
453
|
+
Hatch shortcut:
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
hatch run test
|
|
457
|
+
hatch run all-examples # runs scripts/run_all_examples.sh
|
|
458
|
+
```
|
|
459
|
+
|
|
460
|
+
## Building and publishing
|
|
461
|
+
|
|
462
|
+
```bash
|
|
463
|
+
pip install build
|
|
464
|
+
python -m build
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
Or with Poetry: `poetry build` / `poetry publish`. See [`pyproject.toml`](pyproject.toml) for package metadata.
|
|
468
|
+
|
|
469
|
+
## Error handling
|
|
470
|
+
|
|
471
|
+
Failures raise exceptions from the OpenAPI client (for example **`ApiException`**) with HTTP status and body. Parse the error body for `error` and `details` fields returned by the VoidRun API.
|
|
472
|
+
|
|
473
|
+
```python
|
|
474
|
+
from voidrun import VoidRun
|
|
475
|
+
from voidrun.api_client.rest import ApiException
|
|
476
|
+
|
|
477
|
+
vr = VoidRun()
|
|
478
|
+
|
|
479
|
+
try:
|
|
480
|
+
vr.get_sandbox("nonexistent-id")
|
|
481
|
+
except ApiException as e:
|
|
482
|
+
print(e.status, e.body)
|
|
483
|
+
```
|
|
484
|
+
|
|
485
|
+
## Troubleshooting
|
|
486
|
+
|
|
487
|
+
### "API key is required …"
|
|
488
|
+
|
|
489
|
+
Set `VR_API_KEY` or pass `api_key=` to the constructor.
|
|
490
|
+
|
|
491
|
+
### "Base URL is required …"
|
|
492
|
+
|
|
493
|
+
You cleared the base URL (for example empty **`VR_API_URL`**). Omit the variable to use the packaged default, or set **`VR_API_URL`** / **`API_URL`** (self-hosted) with the correct prefix (often `/api`).
|
|
494
|
+
|
|
495
|
+
### Unauthorized / invalid API key
|
|
496
|
+
|
|
497
|
+
The key must match the VoidRun API you are calling (hosted default host or your self-hosted **`VR_API_URL`**). A local `.env` pointing at `localhost` with a cloud key (or vice versa) will return 401.
|
|
498
|
+
|
|
499
|
+
### Sandbox creation failures
|
|
500
|
+
|
|
501
|
+
Respect minimum **CPU** and **memory** enforced by your org/plan. Defaults are 1 CPU and 1024 MB; increase if the API rejects smaller values.
|
|
502
|
+
|
|
503
|
+
### PTY timeouts
|
|
504
|
+
|
|
505
|
+
Increase `timeout` in `run_command`, or allow more time before closing the session.
|
|
506
|
+
|
|
507
|
+
### File not found
|
|
508
|
+
|
|
509
|
+
List parent directories with `sandbox.fs.list_files` and confirm paths inside the sandbox.
|
|
510
|
+
|
|
511
|
+
## Contributing, license, support
|
|
512
|
+
|
|
513
|
+
Contributions are welcome; see the repository’s contributing guidelines if present.
|
|
514
|
+
|
|
515
|
+
- **License:** MIT: see the `LICENSE` file.
|
|
516
|
+
- **PyPI:** [voidrun](https://pypi.org/project/voidrun/)
|
|
517
|
+
- **Issues / discussions:** [GitHub](https://github.com/voidrun/py-sdk)
|
|
518
|
+
- **Contact:** support@voidrun.io (see [`pyproject.toml`](pyproject.toml) authors)
|
|
519
|
+
|
|
520
|
+
---
|
|
521
|
+
|
|
522
|
+
Made with care by VoidRun.
|