voidrun 0.0.2__tar.gz → 0.0.4__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.4/PKG-INFO +899 -0
- voidrun-0.0.4/README.md +875 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/pyproject.toml +1 -1
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_sandbox_request.py +3 -3
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/client.py +1 -1
- voidrun-0.0.2/PKG-INFO +0 -214
- voidrun-0.0.2/README.md +0 -190
- {voidrun-0.0.2 → voidrun-0.0.4}/.gitignore +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/__init__.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/__init__.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/__init__.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/authentication_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/execution_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/file_system_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/images_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/organizations_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/sandboxes_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api/system_api.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api_client.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/api_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/configuration.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/exceptions.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/__init__.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/activate_api_key_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/api_key_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/api_response_sandbox.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/api_response_sandboxes_list.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/api_response_sandboxes_list_meta.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/command_kill_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/command_list_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/command_run_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/command_wait_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/compress_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_file_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_image_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_pty_session200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_pty_session200_response_all_of_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_pty_session_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/create_sandbox201_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/disk_usage.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/error_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/exec_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/exec_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/exec_response_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/execute_in_session_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/extract_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/file_event.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/file_info.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/file_stats.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/generate_api_key_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/generated_api_key_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/get_org_users200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/get_org_users200_response_all_of_data_inner.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/get_pty_buffer200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/get_pty_buffer200_response_all_of_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/get_version200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/image.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/kill_background_process_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/list_files200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/list_files200_response_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/list_pty_sessions200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/list_pty_sessions200_response_all_of_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/organization.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/process_info.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/pty_session_info.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/register_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/register_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/register_response_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/resize_terminal_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/restore_sandbox_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/run_background_command_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/sandbox.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/session_exec_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/session_exec_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/session_exec_stream_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/snapshot.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/start_watch200_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/start_watch200_response_data.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/start_watch_request.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/models/success_response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/py.typed +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/api_client/rest.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/commands.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/fs.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/interpreter.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/pty.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/response.py +0 -0
- {voidrun-0.0.2 → voidrun-0.0.4}/voidrun/sandbox.py +0 -0
voidrun-0.0.4/PKG-INFO
ADDED
|
@@ -0,0 +1,899 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: voidrun
|
|
3
|
+
Version: 0.0.4
|
|
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
|
+
A powerful Python SDK for interacting with VoidRun AI Sandboxes. Execute code, manage files, watch file changes, and interact with pseudo-terminals in isolated environments.
|
|
28
|
+
|
|
29
|
+
[](https://pypi.org/project/voidrun/)
|
|
30
|
+
[](https://opensource.org/licenses/MIT)
|
|
31
|
+
|
|
32
|
+
## Features
|
|
33
|
+
|
|
34
|
+
- 🏗️ **Sandbox Management** - Create, list, start, stop, pause, resume, and remove sandboxes
|
|
35
|
+
- 🚀 **Code Execution** - Execute commands with real-time streaming output capture
|
|
36
|
+
- 📁 **File Operations** - Create, read, delete, compress, and extract files
|
|
37
|
+
- 👀 **File Watching** - Monitor file changes in real-time via WebSocket
|
|
38
|
+
- 💻 **Pseudo-Terminal (PTY)** - Interactive terminal sessions (ephemeral & persistent)
|
|
39
|
+
- 🧠 **Code Interpreter** - Easy multi-language code execution (Python, JavaScript, Bash)
|
|
40
|
+
- ⚡ **Background Commands** - Run, list, kill, and attach to background processes
|
|
41
|
+
- 🎯 **Sync & Async** - Both synchronous and asynchronous APIs
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
With pip:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
pip install voidrun
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
With Poetry:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
poetry add voidrun
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Quick Start
|
|
58
|
+
|
|
59
|
+
### Basic Usage (Sync)
|
|
60
|
+
|
|
61
|
+
```python
|
|
62
|
+
from voidrun import VoidRun
|
|
63
|
+
|
|
64
|
+
# Initialize the SDK with your credentials
|
|
65
|
+
vr = VoidRun(api_key="your-api-key-here")
|
|
66
|
+
|
|
67
|
+
# Create a sandbox
|
|
68
|
+
sandbox = vr.sandboxes.create(mem=1024, cpu=1).data
|
|
69
|
+
|
|
70
|
+
# Execute a command
|
|
71
|
+
result = sandbox.exec('echo "Hello from VoidRun"')
|
|
72
|
+
print(result.data.data.stdout)
|
|
73
|
+
|
|
74
|
+
# Clean up
|
|
75
|
+
sandbox.delete()
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Basic Usage (Async)
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
import asyncio
|
|
82
|
+
from voidrun import AsyncVoidRun
|
|
83
|
+
|
|
84
|
+
async def main():
|
|
85
|
+
vr = AsyncVoidRun(api_key="your-api-key-here")
|
|
86
|
+
|
|
87
|
+
sandbox = await vr.sandboxes.create(mem=1024, cpu=1)
|
|
88
|
+
|
|
89
|
+
result = sandbox.exec('echo "Hello from VoidRun"')
|
|
90
|
+
print(result.data.data.stdout)
|
|
91
|
+
|
|
92
|
+
await sandbox.delete_async()
|
|
93
|
+
await vr.aclose()
|
|
94
|
+
|
|
95
|
+
asyncio.run(main())
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Core Concepts
|
|
99
|
+
|
|
100
|
+
### Sandboxes
|
|
101
|
+
|
|
102
|
+
An isolated environment where you can execute code, manage files, and run terminals.
|
|
103
|
+
|
|
104
|
+
```python
|
|
105
|
+
# Create a sandbox with options (sync)
|
|
106
|
+
sandbox = vr.sandboxes.create(
|
|
107
|
+
name="my-sandbox", # Optional: Sandbox name
|
|
108
|
+
mem=1024, # Memory in MB (optional, has defaults)
|
|
109
|
+
cpu=1, # CPU cores (optional, has defaults)
|
|
110
|
+
image="template-id", # Optional: Image ID
|
|
111
|
+
env_vars={ # Optional: Environment variables
|
|
112
|
+
"DEBUG": "true",
|
|
113
|
+
"LOG_LEVEL": "info"
|
|
114
|
+
}
|
|
115
|
+
).data
|
|
116
|
+
|
|
117
|
+
# Using context manager (auto-cleanup)
|
|
118
|
+
with vr.sandboxes.create(name="my-sandbox").data as sandbox:
|
|
119
|
+
# Work with sandbox
|
|
120
|
+
pass
|
|
121
|
+
# Sandbox automatically deleted
|
|
122
|
+
|
|
123
|
+
# List all sandboxes
|
|
124
|
+
resp = vr.sandboxes.list()
|
|
125
|
+
sandboxes = resp.data
|
|
126
|
+
print(f"Total sandboxes: {len(sandboxes)}")
|
|
127
|
+
|
|
128
|
+
# Get a specific sandbox
|
|
129
|
+
existing = vr.sandboxes.get(sandbox_id).data
|
|
130
|
+
|
|
131
|
+
# Sandbox lifecycle management
|
|
132
|
+
sandbox.start() # Start a stopped sandbox
|
|
133
|
+
sandbox.stop() # Stop a running sandbox
|
|
134
|
+
sandbox.pause() # Pause a running sandbox
|
|
135
|
+
sandbox.resume() # Resume a paused sandbox
|
|
136
|
+
|
|
137
|
+
# Remove a sandbox
|
|
138
|
+
sandbox.delete()
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Code Execution
|
|
142
|
+
|
|
143
|
+
Execute commands and capture output, errors, and exit codes.
|
|
144
|
+
|
|
145
|
+
#### Synchronous Execution
|
|
146
|
+
|
|
147
|
+
```python
|
|
148
|
+
result = sandbox.exec("ls -la /home")
|
|
149
|
+
|
|
150
|
+
print(result.data.data.stdout) # standard output
|
|
151
|
+
print(result.data.data.stderr) # standard error
|
|
152
|
+
print(result.data.data.exit_code) # exit code
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
#### Streaming Execution (SSE)
|
|
156
|
+
|
|
157
|
+
For real-time output, provide streaming handlers:
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
def on_stdout(data):
|
|
161
|
+
print("stdout:", data)
|
|
162
|
+
|
|
163
|
+
def on_stderr(data):
|
|
164
|
+
print("stderr:", data)
|
|
165
|
+
|
|
166
|
+
def on_exit(result):
|
|
167
|
+
print("exit:", result)
|
|
168
|
+
|
|
169
|
+
def on_error(error):
|
|
170
|
+
print("error:", error)
|
|
171
|
+
|
|
172
|
+
sandbox.exec_stream(
|
|
173
|
+
"seq 1 10 | while read i; do echo \"Line $i\"; sleep 1; done",
|
|
174
|
+
on_stdout=on_stdout,
|
|
175
|
+
on_stderr=on_stderr,
|
|
176
|
+
on_exit=on_exit,
|
|
177
|
+
on_error=on_error
|
|
178
|
+
)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
#### Execution with Options
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
result = sandbox.exec(
|
|
185
|
+
"echo $MY_VAR && pwd",
|
|
186
|
+
cwd="/tmp", # Working directory
|
|
187
|
+
env={"MY_VAR": "test_value"}, # Environment variables
|
|
188
|
+
timeout=30 # Timeout in seconds
|
|
189
|
+
)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Code Interpreter
|
|
193
|
+
|
|
194
|
+
Execute code in multiple programming languages with a simple, intuitive API.
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
# Execute Python code
|
|
198
|
+
result = sandbox.interpreter.run('print(2 + 2)', language="python")
|
|
199
|
+
print(result.data.stdout.strip()) # "4"
|
|
200
|
+
print(result.data.success) # True
|
|
201
|
+
|
|
202
|
+
# Execute JavaScript code
|
|
203
|
+
js_result = sandbox.interpreter.run('console.log("Hello")', language="javascript")
|
|
204
|
+
|
|
205
|
+
# Check execution result
|
|
206
|
+
print(result.data.exit_code) # 0 for success
|
|
207
|
+
print(result.data.results) # Parsed results
|
|
208
|
+
print(result.data.logs) # {"stdout": [...], "stderr": [...]}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**Supported Languages:** `python`, `javascript`, `typescript`, `node`, `bash`, `sh`
|
|
212
|
+
|
|
213
|
+
### Background Commands
|
|
214
|
+
|
|
215
|
+
Run long-running processes in the background and manage them.
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
# Start a background process
|
|
219
|
+
run_result = sandbox.commands.run(
|
|
220
|
+
"sleep 100 && echo 'Done'", # command
|
|
221
|
+
{"DEBUG": "true"}, # env (optional)
|
|
222
|
+
"/tmp", # cwd (optional)
|
|
223
|
+
0 # timeout (0 = no timeout)
|
|
224
|
+
)
|
|
225
|
+
print(run_result.data.pid) # Process ID
|
|
226
|
+
|
|
227
|
+
# List all running processes
|
|
228
|
+
list_result = sandbox.commands.list()
|
|
229
|
+
print(list_result.data) # Array of ProcessInfo
|
|
230
|
+
|
|
231
|
+
# Attach to a process and stream output
|
|
232
|
+
def on_stdout(data):
|
|
233
|
+
print(data)
|
|
234
|
+
|
|
235
|
+
def on_stderr(data):
|
|
236
|
+
print(data)
|
|
237
|
+
|
|
238
|
+
def on_exit(result):
|
|
239
|
+
print("Process exited:", result)
|
|
240
|
+
|
|
241
|
+
sandbox.commands.connect(
|
|
242
|
+
run_result.data.pid,
|
|
243
|
+
on_stdout=on_stdout,
|
|
244
|
+
on_stderr=on_stderr,
|
|
245
|
+
on_exit=on_exit
|
|
246
|
+
)
|
|
247
|
+
|
|
248
|
+
# Wait for a process to complete
|
|
249
|
+
wait_result = sandbox.commands.wait(run_result.data.pid)
|
|
250
|
+
print(wait_result.data.exit_code)
|
|
251
|
+
|
|
252
|
+
# Kill a running process
|
|
253
|
+
kill_result = sandbox.commands.kill(run_result.data.pid)
|
|
254
|
+
print(kill_result.data.success)
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### File Operations
|
|
258
|
+
|
|
259
|
+
Create, read, update, and manage files in the sandbox.
|
|
260
|
+
|
|
261
|
+
```python
|
|
262
|
+
# Create a file
|
|
263
|
+
sandbox.fs.create_file("/tmp/hello.txt")
|
|
264
|
+
|
|
265
|
+
# Upload content to file
|
|
266
|
+
sandbox.fs.upload_file("/tmp/hello.txt", "Hello, World!")
|
|
267
|
+
|
|
268
|
+
# Upload from local file path
|
|
269
|
+
sandbox.fs.upload_file_from_path("/tmp/remote.txt", "/local/file.txt")
|
|
270
|
+
|
|
271
|
+
# Read a file
|
|
272
|
+
data = sandbox.fs.download_file("/tmp/hello.txt")
|
|
273
|
+
content = data.decode("utf-8")
|
|
274
|
+
|
|
275
|
+
# Delete a file
|
|
276
|
+
sandbox.fs.delete_file("/tmp/hello.txt")
|
|
277
|
+
|
|
278
|
+
# List directory
|
|
279
|
+
result = sandbox.fs.list_files("/tmp")
|
|
280
|
+
files = result.data
|
|
281
|
+
print([f.name for f in files])
|
|
282
|
+
|
|
283
|
+
# Get file stats
|
|
284
|
+
stats = sandbox.fs.stat_file("/tmp/hello.txt")
|
|
285
|
+
|
|
286
|
+
# Create directory
|
|
287
|
+
sandbox.fs.create_directory("/tmp/mydir")
|
|
288
|
+
|
|
289
|
+
# Move file
|
|
290
|
+
sandbox.fs.move_file("/tmp/file.txt", "/tmp/newfile.txt")
|
|
291
|
+
|
|
292
|
+
# Copy file
|
|
293
|
+
sandbox.fs.copy_file("/tmp/file.txt", "/tmp/copy.txt")
|
|
294
|
+
|
|
295
|
+
# Change permissions
|
|
296
|
+
sandbox.fs.change_permissions("/tmp/file.txt", "755")
|
|
297
|
+
|
|
298
|
+
# Head/Tail - read first or last lines
|
|
299
|
+
head = sandbox.fs.head_tail("/tmp/file.txt", head=True, lines=10)
|
|
300
|
+
tail = sandbox.fs.head_tail("/tmp/file.txt", head=False, lines=10)
|
|
301
|
+
|
|
302
|
+
# Search files by pattern
|
|
303
|
+
search = sandbox.fs.search_files("/tmp", "*.txt")
|
|
304
|
+
|
|
305
|
+
# Get folder size
|
|
306
|
+
size = sandbox.fs.disk_usage("/tmp")
|
|
307
|
+
|
|
308
|
+
# Compress files
|
|
309
|
+
archive = sandbox.fs.compress_file("/tmp", "tar.gz")
|
|
310
|
+
print(archive.data)
|
|
311
|
+
|
|
312
|
+
# Extract archive
|
|
313
|
+
sandbox.fs.extract_archive("/tmp/archive.tar.gz", "/tmp/extracted")
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
### File Watching (Async)
|
|
317
|
+
|
|
318
|
+
Monitor file changes in real-time.
|
|
319
|
+
|
|
320
|
+
```python
|
|
321
|
+
import asyncio
|
|
322
|
+
from voidrun import AsyncVoidRun
|
|
323
|
+
|
|
324
|
+
async def watch_tmp():
|
|
325
|
+
vr = AsyncVoidRun()
|
|
326
|
+
sandbox = await vr.sandboxes.create()
|
|
327
|
+
|
|
328
|
+
watcher = await sandbox.fs.watch(
|
|
329
|
+
"/app",
|
|
330
|
+
recursive=True,
|
|
331
|
+
on_event=lambda evt: print(f"File changed: {evt.get('path')} - {evt.get('type')}"),
|
|
332
|
+
on_error=lambda err: print("Watch error:", err),
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
# Keep watching for a while
|
|
336
|
+
await asyncio.sleep(60)
|
|
337
|
+
|
|
338
|
+
# Stop watching
|
|
339
|
+
watcher.close()
|
|
340
|
+
|
|
341
|
+
await sandbox.delete_async()
|
|
342
|
+
await vr.aclose()
|
|
343
|
+
|
|
344
|
+
asyncio.run(watch_tmp())
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
### Pseudo-Terminal (PTY)
|
|
348
|
+
|
|
349
|
+
Interactive terminal sessions with two modes:
|
|
350
|
+
|
|
351
|
+
#### Ephemeral Sessions (Temporary)
|
|
352
|
+
|
|
353
|
+
```python
|
|
354
|
+
import asyncio
|
|
355
|
+
from voidrun import AsyncVoidRun
|
|
356
|
+
|
|
357
|
+
async def ephemeral_pty():
|
|
358
|
+
vr = AsyncVoidRun()
|
|
359
|
+
sandbox = await vr.sandboxes.create()
|
|
360
|
+
|
|
361
|
+
# Connect to ephemeral PTY (no session management - temporary shell)
|
|
362
|
+
pty = await sandbox.pty.connect(
|
|
363
|
+
on_data=lambda data: print(data, end=""),
|
|
364
|
+
on_error=lambda err: print("PTY error:", err),
|
|
365
|
+
)
|
|
366
|
+
|
|
367
|
+
# Send commands
|
|
368
|
+
pty.send_input('echo "Hello"\n')
|
|
369
|
+
pty.send_input("pwd\n")
|
|
370
|
+
|
|
371
|
+
await asyncio.sleep(2)
|
|
372
|
+
|
|
373
|
+
# Close connection
|
|
374
|
+
await pty.close()
|
|
375
|
+
|
|
376
|
+
await sandbox.delete_async()
|
|
377
|
+
await vr.aclose()
|
|
378
|
+
|
|
379
|
+
asyncio.run(ephemeral_pty())
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
#### Persistent Sessions
|
|
383
|
+
|
|
384
|
+
```python
|
|
385
|
+
import asyncio
|
|
386
|
+
from voidrun import AsyncVoidRun
|
|
387
|
+
|
|
388
|
+
async def persistent_pty():
|
|
389
|
+
vr = AsyncVoidRun()
|
|
390
|
+
sandbox = await vr.sandboxes.create()
|
|
391
|
+
|
|
392
|
+
# Create a persistent session
|
|
393
|
+
response = sandbox.pty.create_session()
|
|
394
|
+
session_id = response.data.data.session_id
|
|
395
|
+
|
|
396
|
+
# Connect to the session
|
|
397
|
+
pty = await sandbox.pty.connect(
|
|
398
|
+
session_id=session_id,
|
|
399
|
+
on_data=lambda data: print(data, end=""),
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
# Send commands
|
|
403
|
+
pty.send_input('echo "Hello"\n')
|
|
404
|
+
|
|
405
|
+
# Close connection (session persists)
|
|
406
|
+
await pty.close()
|
|
407
|
+
|
|
408
|
+
# Reconnect later - session and output persist
|
|
409
|
+
reconnected = await sandbox.pty.connect(
|
|
410
|
+
session_id=session_id,
|
|
411
|
+
on_data=lambda data: print(data, end=""), # Includes buffered output
|
|
412
|
+
)
|
|
413
|
+
|
|
414
|
+
await reconnected.close()
|
|
415
|
+
|
|
416
|
+
# Delete the session when done
|
|
417
|
+
sandbox.pty.delete_session(session_id)
|
|
418
|
+
|
|
419
|
+
await sandbox.delete_async()
|
|
420
|
+
await vr.aclose()
|
|
421
|
+
|
|
422
|
+
asyncio.run(persistent_pty())
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
#### Interactive Commands
|
|
426
|
+
|
|
427
|
+
Run commands with automatic prompt detection:
|
|
428
|
+
|
|
429
|
+
```python
|
|
430
|
+
pty = await sandbox.pty.connect(session_id=session_id)
|
|
431
|
+
|
|
432
|
+
output = await pty.run_command(
|
|
433
|
+
"ls -la",
|
|
434
|
+
timeout=5000,
|
|
435
|
+
prompt="# " # Prompt to detect (default: "# ")
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
print("Output:", output)
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
#### Resize Terminal
|
|
442
|
+
|
|
443
|
+
```python
|
|
444
|
+
await pty.resize(80, 24) # columns, rows
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
#### Session Management
|
|
448
|
+
|
|
449
|
+
```python
|
|
450
|
+
# List all sessions
|
|
451
|
+
sessions = sandbox.pty.list()
|
|
452
|
+
|
|
453
|
+
# Delete a session
|
|
454
|
+
sandbox.pty.delete_session(session_id)
|
|
455
|
+
```
|
|
456
|
+
|
|
457
|
+
## API Reference
|
|
458
|
+
|
|
459
|
+
### VoidRun Class
|
|
460
|
+
|
|
461
|
+
Main synchronous client for interacting with the API.
|
|
462
|
+
|
|
463
|
+
```python
|
|
464
|
+
vr = VoidRun(api_key="...")
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
**Options:**
|
|
468
|
+
|
|
469
|
+
- `api_key: str` - API key (defaults to `os.environ.get("VR_API_KEY")`)
|
|
470
|
+
|
|
471
|
+
**Properties:**
|
|
472
|
+
|
|
473
|
+
- `sandboxes: SandboxesFacade` - Sandbox management interface
|
|
474
|
+
|
|
475
|
+
**Methods:**
|
|
476
|
+
|
|
477
|
+
- `sandboxes.create(...)` - Create a new sandbox
|
|
478
|
+
- `name?: str` - Sandbox name
|
|
479
|
+
- `cpu?: int` - CPU cores
|
|
480
|
+
- `mem?: int` - Memory in MB
|
|
481
|
+
- `image?: str` - Image ID
|
|
482
|
+
- `env_vars?: dict` - Environment variables
|
|
483
|
+
- `sandboxes.list(page=1, limit=50)` - List all sandboxes
|
|
484
|
+
- `sandboxes.get(id: str)` - Get a specific sandbox
|
|
485
|
+
- `sandboxes.delete(id: str)` - Delete a sandbox
|
|
486
|
+
|
|
487
|
+
### AsyncVoidRun Class
|
|
488
|
+
|
|
489
|
+
Main asynchronous client for interacting with the API.
|
|
490
|
+
|
|
491
|
+
```python
|
|
492
|
+
vr = AsyncVoidRun(api_key="...")
|
|
493
|
+
```
|
|
494
|
+
|
|
495
|
+
**Options:** Same as `VoidRun`
|
|
496
|
+
|
|
497
|
+
**Methods:**
|
|
498
|
+
|
|
499
|
+
- `sandboxes.create(...)` - Create a new sandbox (async)
|
|
500
|
+
- `sandboxes.list(...)` - List all sandboxes (async)
|
|
501
|
+
- `sandboxes.get(id)` - Get a specific sandbox (async)
|
|
502
|
+
- `sandboxes.delete(id)` - Delete a sandbox (async)
|
|
503
|
+
- `aclose()` - Close the async client
|
|
504
|
+
|
|
505
|
+
### Sandbox Class
|
|
506
|
+
|
|
507
|
+
Represents an isolated sandbox environment.
|
|
508
|
+
|
|
509
|
+
**Properties:**
|
|
510
|
+
|
|
511
|
+
- `id: str` - Sandbox ID
|
|
512
|
+
- `name: str` - Sandbox name
|
|
513
|
+
- `cpu: int` - CPU cores
|
|
514
|
+
- `mem: int` - Memory in MB
|
|
515
|
+
- `org_id: str` - Organization ID
|
|
516
|
+
- `status: str` - Sandbox status
|
|
517
|
+
- `env_vars: dict` - Environment variables
|
|
518
|
+
- `fs: FS` - File system interface
|
|
519
|
+
- `pty: PTY` - PTY interface
|
|
520
|
+
- `interpreter: Interpreter` - Code interpreter
|
|
521
|
+
- `commands: Commands` - Background commands interface
|
|
522
|
+
|
|
523
|
+
**Methods:**
|
|
524
|
+
|
|
525
|
+
- `exec(command: str, timeout=30, env=None, cwd=None)` - Execute a command
|
|
526
|
+
- `exec_stream(command: str, timeout=30, env=None, cwd=None, on_stdout=None, on_stderr=None, on_exit=None, on_error=None)` - Streaming execution
|
|
527
|
+
- `interpreter.run(code: str, language="python", timeout=60)` - Execute code
|
|
528
|
+
- `start()` - Start the sandbox
|
|
529
|
+
- `stop()` - Stop the sandbox
|
|
530
|
+
- `pause()` - Pause the sandbox
|
|
531
|
+
- `resume()` - Resume the sandbox
|
|
532
|
+
- `delete()` - Delete the sandbox
|
|
533
|
+
- `delete_async()` - Delete the sandbox (async)
|
|
534
|
+
|
|
535
|
+
**Exec Response:**
|
|
536
|
+
|
|
537
|
+
```python
|
|
538
|
+
{
|
|
539
|
+
data: {
|
|
540
|
+
stdout: str, # standard output
|
|
541
|
+
stderr: str, # standard error
|
|
542
|
+
exit_code: int # exit code
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
```
|
|
546
|
+
|
|
547
|
+
**Code Execution Result:**
|
|
548
|
+
|
|
549
|
+
```python
|
|
550
|
+
{
|
|
551
|
+
success: bool,
|
|
552
|
+
results: Any, # Parsed results
|
|
553
|
+
stdout: str, # Combined stdout
|
|
554
|
+
stderr: str, # Combined stderr
|
|
555
|
+
error: Optional[str], # Error message if any
|
|
556
|
+
exit_code: Optional[int], # Process exit code
|
|
557
|
+
logs: {
|
|
558
|
+
stdout: List[str], # Individual stdout lines
|
|
559
|
+
stderr: List[str] # Individual stderr lines
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### Commands Class
|
|
565
|
+
|
|
566
|
+
Background process management.
|
|
567
|
+
|
|
568
|
+
**Methods:**
|
|
569
|
+
|
|
570
|
+
- `run(command: str, env=None, cwd=None, timeout=0)` - Start a background process
|
|
571
|
+
- `list()` - List all running processes
|
|
572
|
+
- `kill(pid: int)` - Kill a process
|
|
573
|
+
- `connect(pid: int, on_stdout=None, on_stderr=None, on_exit=None, on_error=None)` - Attach to process output stream
|
|
574
|
+
- `wait(pid: int)` - Wait for process to complete
|
|
575
|
+
|
|
576
|
+
### FS Class
|
|
577
|
+
|
|
578
|
+
Manage files and directories.
|
|
579
|
+
|
|
580
|
+
**Methods:**
|
|
581
|
+
|
|
582
|
+
- `create_file(path: str)` - Create a file
|
|
583
|
+
- `upload_file(path: str, content: str)` - Upload file content
|
|
584
|
+
- `upload_file_from_path(path: str, file_path: str)` - Upload from local path
|
|
585
|
+
- `download_file(path: str)` - Download file as bytes
|
|
586
|
+
- `delete_file(path: str)` - Delete a file/directory
|
|
587
|
+
- `list_files(path: str)` - List directory contents
|
|
588
|
+
- `stat_file(path: str)` - Get file metadata
|
|
589
|
+
- `create_directory(path: str)` - Create a directory
|
|
590
|
+
- `compress_file(path: str, format="tar.gz")` - Create archive
|
|
591
|
+
- `extract_archive(archive: str, dest=None)` - Extract archive
|
|
592
|
+
- `move_file(source: str, destination: str)` - Move/rename file
|
|
593
|
+
- `copy_file(source: str, destination: str)` - Copy file
|
|
594
|
+
- `change_permissions(path: str, mode: str)` - Change file permissions
|
|
595
|
+
- `head_tail(path: str, lines=10, head=True)` - Read file head/tail
|
|
596
|
+
- `search_files(path: str, pattern: str)` - Search files by pattern
|
|
597
|
+
- `disk_usage(path: str)` - Get folder size
|
|
598
|
+
- `watch(path: str, recursive=True, ignore_hidden=True, on_event=None, on_error=None)` - Watch for file changes (async)
|
|
599
|
+
|
|
600
|
+
### PTY Class
|
|
601
|
+
|
|
602
|
+
Pseudo-terminal operations.
|
|
603
|
+
|
|
604
|
+
**Methods:**
|
|
605
|
+
|
|
606
|
+
- `list()` - List active sessions
|
|
607
|
+
- `create_session(cols=80, rows=24)` - Create a persistent session
|
|
608
|
+
- `connect(session_id=None, on_data=None, on_close=None, on_error=None)` - Connect to PTY
|
|
609
|
+
- `delete_session(session_id: str)` - Delete a session
|
|
610
|
+
|
|
611
|
+
### PtySession Methods
|
|
612
|
+
|
|
613
|
+
- `send_input(data: str)` - Send data to terminal
|
|
614
|
+
- `run_command(cmd: str, timeout=30000, prompt="# ")` - Execute with prompt detection
|
|
615
|
+
- `resize(cols: int, rows: int)` - Resize terminal
|
|
616
|
+
- `close()` - Close connection
|
|
617
|
+
|
|
618
|
+
## Examples
|
|
619
|
+
|
|
620
|
+
### Execute Python Script
|
|
621
|
+
|
|
622
|
+
```python
|
|
623
|
+
from voidrun import VoidRun
|
|
624
|
+
|
|
625
|
+
vr = VoidRun()
|
|
626
|
+
sandbox = vr.sandboxes.create(mem=1024, cpu=1).data
|
|
627
|
+
|
|
628
|
+
# Create Python script
|
|
629
|
+
sandbox.fs.create_file("/tmp/script.py")
|
|
630
|
+
sandbox.fs.upload_file(
|
|
631
|
+
"/tmp/script.py",
|
|
632
|
+
"""
|
|
633
|
+
import sys
|
|
634
|
+
print("Python version:", sys.version)
|
|
635
|
+
print("Hello from Python!")
|
|
636
|
+
"""
|
|
637
|
+
)
|
|
638
|
+
|
|
639
|
+
result = sandbox.exec("python3 /tmp/script.py")
|
|
640
|
+
print(result.data.data.stdout)
|
|
641
|
+
|
|
642
|
+
sandbox.delete()
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### Code Interpreter Workflow
|
|
646
|
+
|
|
647
|
+
```python
|
|
648
|
+
sandbox = vr.sandboxes.create(name="interpreter-demo").data
|
|
649
|
+
|
|
650
|
+
# Python data analysis
|
|
651
|
+
result = sandbox.interpreter.run("""
|
|
652
|
+
import json
|
|
653
|
+
data = [1, 2, 3, 4, 5]
|
|
654
|
+
result = {
|
|
655
|
+
"sum": sum(data),
|
|
656
|
+
"avg": sum(data) / len(data),
|
|
657
|
+
"max": max(data)
|
|
658
|
+
}
|
|
659
|
+
print(json.dumps(result))
|
|
660
|
+
""", language="python")
|
|
661
|
+
|
|
662
|
+
print(result.data.results) # Parsed JSON output
|
|
663
|
+
|
|
664
|
+
# JavaScript
|
|
665
|
+
js_result = sandbox.interpreter.run("""
|
|
666
|
+
const fib = (n) => n <= 1 ? n : fib(n-1) + fib(n-2);
|
|
667
|
+
console.log(fib(10));
|
|
668
|
+
""", language="javascript")
|
|
669
|
+
|
|
670
|
+
sandbox.delete()
|
|
671
|
+
```
|
|
672
|
+
|
|
673
|
+
### Background Process Management
|
|
674
|
+
|
|
675
|
+
```python
|
|
676
|
+
sandbox = vr.sandboxes.create().data
|
|
677
|
+
|
|
678
|
+
# Start a long-running process
|
|
679
|
+
run_result = sandbox.commands.run("tail -f /var/log/syslog")
|
|
680
|
+
pid = run_result.data.pid
|
|
681
|
+
|
|
682
|
+
# Attach to stream output
|
|
683
|
+
sandbox.commands.connect(
|
|
684
|
+
pid,
|
|
685
|
+
on_stdout=lambda data: print(data),
|
|
686
|
+
on_exit=lambda result: print("Exited:", result)
|
|
687
|
+
)
|
|
688
|
+
|
|
689
|
+
# Later, kill the process
|
|
690
|
+
sandbox.commands.kill(pid)
|
|
691
|
+
|
|
692
|
+
sandbox.delete()
|
|
693
|
+
```
|
|
694
|
+
|
|
695
|
+
### Monitor Code Changes
|
|
696
|
+
|
|
697
|
+
```python
|
|
698
|
+
import asyncio
|
|
699
|
+
from voidrun import AsyncVoidRun
|
|
700
|
+
|
|
701
|
+
async def watch_changes():
|
|
702
|
+
vr = AsyncVoidRun()
|
|
703
|
+
sandbox = await vr.sandboxes.create(mem=1024, cpu=1)
|
|
704
|
+
|
|
705
|
+
# Watch for file changes
|
|
706
|
+
watcher = await sandbox.fs.watch(
|
|
707
|
+
"/app/src",
|
|
708
|
+
recursive=True,
|
|
709
|
+
on_event=lambda event: print(f"File {event.get('type')}: {event.get('path')}"),
|
|
710
|
+
)
|
|
711
|
+
|
|
712
|
+
# Keep watching for a while
|
|
713
|
+
await asyncio.sleep(60)
|
|
714
|
+
|
|
715
|
+
watcher.close()
|
|
716
|
+
await sandbox.delete_async()
|
|
717
|
+
await vr.aclose()
|
|
718
|
+
|
|
719
|
+
asyncio.run(watch_changes())
|
|
720
|
+
```
|
|
721
|
+
|
|
722
|
+
### Build & Test Workflow
|
|
723
|
+
|
|
724
|
+
```python
|
|
725
|
+
sandbox = vr.sandboxes.create(mem=2048, cpu=2).data
|
|
726
|
+
|
|
727
|
+
# Upload source code
|
|
728
|
+
sandbox.fs.create_file("/app/main.js")
|
|
729
|
+
sandbox.fs.upload_file("/app/main.js", "console.log('Hello World');")
|
|
730
|
+
|
|
731
|
+
# Install dependencies
|
|
732
|
+
result = sandbox.exec("npm install")
|
|
733
|
+
if result.data.data.exit_code != 0:
|
|
734
|
+
raise Error("Install failed")
|
|
735
|
+
|
|
736
|
+
# Run tests
|
|
737
|
+
result = sandbox.exec("npm test")
|
|
738
|
+
print("Test output:", result.data.data.stdout)
|
|
739
|
+
|
|
740
|
+
# Build
|
|
741
|
+
result = sandbox.exec("npm run build")
|
|
742
|
+
print("Build output:", result.data.data.stdout)
|
|
743
|
+
|
|
744
|
+
sandbox.delete()
|
|
745
|
+
```
|
|
746
|
+
|
|
747
|
+
## Configuration
|
|
748
|
+
|
|
749
|
+
The SDK can be configured by passing options to the constructor or using environment variables:
|
|
750
|
+
|
|
751
|
+
```python
|
|
752
|
+
vr = VoidRun(
|
|
753
|
+
api_key="your-api-key", # Required: Your API key
|
|
754
|
+
)
|
|
755
|
+
```
|
|
756
|
+
|
|
757
|
+
Environment variables:
|
|
758
|
+
|
|
759
|
+
```bash
|
|
760
|
+
export VR_API_KEY="your-api-key"
|
|
761
|
+
```
|
|
762
|
+
|
|
763
|
+
## Error Handling
|
|
764
|
+
|
|
765
|
+
```python
|
|
766
|
+
from voidrun import VoidRun
|
|
767
|
+
|
|
768
|
+
try:
|
|
769
|
+
sandbox = vr.sandboxes.create(mem=256, cpu=0.5)
|
|
770
|
+
except Exception as e:
|
|
771
|
+
print("Error:", str(e))
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
Common errors:
|
|
775
|
+
|
|
776
|
+
- **Validation Error** - Invalid sandbox parameters
|
|
777
|
+
- **Authentication Error** - Invalid or missing API key
|
|
778
|
+
- **Not Found** - Sandbox or session doesn't exist
|
|
779
|
+
- **Timeout** - Operation took too long
|
|
780
|
+
|
|
781
|
+
## Testing
|
|
782
|
+
|
|
783
|
+
Run the examples:
|
|
784
|
+
|
|
785
|
+
```bash
|
|
786
|
+
# Set your API key
|
|
787
|
+
export VR_API_KEY="your-api-key"
|
|
788
|
+
|
|
789
|
+
# Run sync example
|
|
790
|
+
python -m examples.sync_usage
|
|
791
|
+
|
|
792
|
+
# Run async example
|
|
793
|
+
python -m examples.async_usage
|
|
794
|
+
|
|
795
|
+
# Run other examples
|
|
796
|
+
python -m examples.test_sandbox_exec
|
|
797
|
+
python -m examples.test_sandbox_fs
|
|
798
|
+
python -m examples.test_sandbox_lifecycle
|
|
799
|
+
python -m examples.test_pty
|
|
800
|
+
python -m examples.test_background_exec
|
|
801
|
+
python -m examples.code_interpreter_example
|
|
802
|
+
```
|
|
803
|
+
|
|
804
|
+
## Building from Source
|
|
805
|
+
|
|
806
|
+
```bash
|
|
807
|
+
# Install dependencies
|
|
808
|
+
pip install -e .
|
|
809
|
+
|
|
810
|
+
# Or with poetry
|
|
811
|
+
poetry install
|
|
812
|
+
```
|
|
813
|
+
|
|
814
|
+
## Publishing
|
|
815
|
+
|
|
816
|
+
```bash
|
|
817
|
+
# Build and publish to PyPI
|
|
818
|
+
poetry build
|
|
819
|
+
poetry publish
|
|
820
|
+
```
|
|
821
|
+
|
|
822
|
+
## Troubleshooting
|
|
823
|
+
|
|
824
|
+
### "API key is required (pass it or set VR_API_KEY/API_KEY)"
|
|
825
|
+
|
|
826
|
+
Pass your API key in the constructor:
|
|
827
|
+
|
|
828
|
+
```python
|
|
829
|
+
vr = VoidRun(api_key="your-api-key")
|
|
830
|
+
```
|
|
831
|
+
|
|
832
|
+
Or set environment variable:
|
|
833
|
+
|
|
834
|
+
```bash
|
|
835
|
+
export VR_API_KEY="your-api-key"
|
|
836
|
+
```
|
|
837
|
+
|
|
838
|
+
### "Sandbox creation failed"
|
|
839
|
+
|
|
840
|
+
Ensure your sandbox parameters are valid:
|
|
841
|
+
|
|
842
|
+
- `mem`: minimum 1024 MB
|
|
843
|
+
- `cpu`: minimum 1 core
|
|
844
|
+
|
|
845
|
+
```python
|
|
846
|
+
sandbox = vr.sandboxes.create(
|
|
847
|
+
mem=1024, # At least 1GB
|
|
848
|
+
cpu=1, # At least 1 core
|
|
849
|
+
)
|
|
850
|
+
```
|
|
851
|
+
|
|
852
|
+
### "PTY Connection Timeout"
|
|
853
|
+
|
|
854
|
+
Increase timeout for slow systems:
|
|
855
|
+
|
|
856
|
+
```python
|
|
857
|
+
pty = await sandbox.pty.connect(
|
|
858
|
+
session_id=session_id,
|
|
859
|
+
on_data=lambda data: print(data),
|
|
860
|
+
)
|
|
861
|
+
|
|
862
|
+
# For run_command
|
|
863
|
+
output = await pty.run_command("slow-command", timeout=30000) # 30 seconds
|
|
864
|
+
```
|
|
865
|
+
|
|
866
|
+
### "File Not Found"
|
|
867
|
+
|
|
868
|
+
Check the file path:
|
|
869
|
+
|
|
870
|
+
```python
|
|
871
|
+
# List files to verify path
|
|
872
|
+
files = sandbox.fs.list_files("/app")
|
|
873
|
+
print([f.name for f in files.data])
|
|
874
|
+
|
|
875
|
+
# Then access specific file
|
|
876
|
+
content = sandbox.fs.download_file("/app/file.txt")
|
|
877
|
+
```
|
|
878
|
+
|
|
879
|
+
## API Documentation
|
|
880
|
+
|
|
881
|
+
Full API documentation is available at the VoidRun docs site.
|
|
882
|
+
|
|
883
|
+
## Contributing
|
|
884
|
+
|
|
885
|
+
Contributions are welcome! Please check the main repository for guidelines.
|
|
886
|
+
|
|
887
|
+
## License
|
|
888
|
+
|
|
889
|
+
MIT License - See LICENSE file for details
|
|
890
|
+
|
|
891
|
+
## Support
|
|
892
|
+
|
|
893
|
+
- 📧 Email: support@void-run.com
|
|
894
|
+
- 🐛 Issues: [GitHub Issues](https://github.com/voidrun/py-sdk/issues)
|
|
895
|
+
- 💬 Discussions: [GitHub Discussions](https://github.com/voidrun/py-sdk/discussions)
|
|
896
|
+
|
|
897
|
+
---
|
|
898
|
+
|
|
899
|
+
**Made with ❤️ by VoidRun**
|