hopx-ai 0.1.11__py3-none-any.whl

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.
@@ -0,0 +1,462 @@
1
+ Metadata-Version: 2.4
2
+ Name: hopx-ai
3
+ Version: 0.1.11
4
+ Summary: Official Python SDK for HOPX.AI Sandboxes
5
+ Project-URL: Homepage, https://hopx.ai
6
+ Project-URL: Documentation, https://docs.hopx.ai
7
+ Project-URL: Repository, https://github.com/hopx-ai/hopx
8
+ Project-URL: Issues, https://github.com/hopx-ai/hopx/issues
9
+ Author-email: "HOPX.AI" <support@hopx.ai>
10
+ License: MIT
11
+ Keywords: cloud,containers,hopx,hopx-ai,microvm,sandbox,vm
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3.8
17
+ Classifier: Programming Language :: Python :: 3.9
18
+ Classifier: Programming Language :: Python :: 3.10
19
+ Classifier: Programming Language :: Python :: 3.11
20
+ Classifier: Programming Language :: Python :: 3.12
21
+ Requires-Python: >=3.8
22
+ Requires-Dist: httpx>=0.25.0
23
+ Requires-Dist: pydantic>=2.0.0
24
+ Requires-Dist: typing-extensions>=4.5.0
25
+ Requires-Dist: websockets>=12.0
26
+ Provides-Extra: dev
27
+ Requires-Dist: black>=23.0.0; extra == 'dev'
28
+ Requires-Dist: mypy>=1.0.0; extra == 'dev'
29
+ Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
30
+ Requires-Dist: pytest>=7.0.0; extra == 'dev'
31
+ Requires-Dist: ruff>=0.1.0; extra == 'dev'
32
+ Description-Content-Type: text/markdown
33
+
34
+ # HOPX.AI Python SDK
35
+
36
+ [![PyPI version](https://badge.fury.io/py/hopx-ai.svg)](https://pypi.org/project/hopx-ai/)
37
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)
38
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
39
+
40
+ Official Python SDK for HOPX.AI Sandboxes - Execute code safely in isolated microVM environments.
41
+
42
+ ## Features
43
+
44
+ - 🚀 **47/47 Features** - 100% API coverage
45
+ - 🔒 **Type Safe** - Full Pydantic models with auto-complete
46
+ - ⚡ **Async Support** - Native async/await for all operations
47
+ - 🌊 **WebSocket Streaming** - Real-time code execution, terminal, file watching
48
+ - 🎨 **Rich Outputs** - Automatic capture of plots, images, DataFrames
49
+ - 🔐 **Security First** - Environment variables for secrets, execution timeouts
50
+ - 📦 **Context Managers** - Automatic cleanup with `with` statement
51
+ - 🐍 **Pythonic API** - Follows Python best practices
52
+
53
+ ## Installation
54
+
55
+ ```bash
56
+ pip install hopx-ai
57
+ ```
58
+
59
+ For WebSocket features (optional):
60
+ ```bash
61
+ pip install hopx-ai[websockets]
62
+ ```
63
+
64
+ ## Quick Start
65
+
66
+ ```python
67
+ from hopx_ai import Sandbox
68
+
69
+ # Create sandbox
70
+ with Sandbox.create(template="code-interpreter", api_key="your-api-key") as sandbox:
71
+ # Execute Python code
72
+ result = sandbox.run_code("""
73
+ import pandas as pd
74
+ df = pd.DataFrame({'a': [1, 2, 3], 'b': [4, 5, 6]})
75
+ print(df.sum())
76
+ """)
77
+
78
+ print(result.stdout)
79
+ # Output: a 6
80
+ # b 15
81
+ ```
82
+
83
+ ## Environment Variables
84
+
85
+ ### API Key
86
+
87
+ Set your HOPX API key as an environment variable:
88
+
89
+ ```bash
90
+ export HOPX_API_KEY="hopx_your_key_here"
91
+ ```
92
+
93
+ Or pass it explicitly:
94
+
95
+ ```python
96
+ sandbox = Sandbox.create(
97
+ template="code-interpreter",
98
+ api_key="hopx_your_key_here"
99
+ )
100
+ ```
101
+
102
+ ### Secrets in Code Execution
103
+
104
+ **✅ ALWAYS pass secrets via environment variables:**
105
+
106
+ ```python
107
+ # ✅ GOOD: Secrets via environment variables
108
+ result = sandbox.run_code(
109
+ """
110
+ import os
111
+ api_key = os.getenv('OPENAI_API_KEY')
112
+ # Use api_key safely...
113
+ """,
114
+ env={"OPENAI_API_KEY": "sk-..."}
115
+ )
116
+
117
+ # ❌ BAD: Never hardcode secrets
118
+ # result = sandbox.run_code('api_key = "sk-..."') # DON'T DO THIS!
119
+ ```
120
+
121
+ ## Core Features
122
+
123
+ ### Code Execution
124
+
125
+ ```python
126
+ # Synchronous execution
127
+ result = sandbox.run_code("print('Hello')")
128
+
129
+ # With environment variables
130
+ result = sandbox.run_code(
131
+ "import os; print(os.getenv('MY_VAR'))",
132
+ env={"MY_VAR": "value"}
133
+ )
134
+
135
+ # Async execution (non-blocking)
136
+ execution_id = sandbox.run_code_async("import time; time.sleep(10)")
137
+
138
+ # Background execution (fire-and-forget)
139
+ execution_id = sandbox.run_code_background("# long task...")
140
+
141
+ # IPython/Jupyter-style
142
+ result = sandbox.run_ipython("df.describe()")
143
+ ```
144
+
145
+ ### Real-time Streaming (WebSocket)
146
+
147
+ ```python
148
+ import asyncio
149
+
150
+ async def stream():
151
+ async for message in sandbox.run_code_stream("""
152
+ import time
153
+ for i in range(5):
154
+ print(f"Step {i+1}")
155
+ time.sleep(1)
156
+ """):
157
+ if message['type'] == 'stdout':
158
+ print(message['data'], end='')
159
+
160
+ asyncio.run(stream())
161
+ ```
162
+
163
+ ### File Operations
164
+
165
+ ```python
166
+ # Write file
167
+ sandbox.files.write('/workspace/data.txt', 'Hello, World!')
168
+
169
+ # Read file
170
+ content = sandbox.files.read('/workspace/data.txt')
171
+
172
+ # List directory
173
+ files = sandbox.files.list('/workspace')
174
+ for file in files:
175
+ print(f"{file.name} ({file.size_kb:.2f}KB)")
176
+
177
+ # Upload local file
178
+ sandbox.files.upload('./local.txt', '/workspace/remote.txt')
179
+
180
+ # Download remote file
181
+ sandbox.files.download('/workspace/remote.txt', './local.txt')
182
+
183
+ # Check existence
184
+ if sandbox.files.exists('/workspace/data.txt'):
185
+ print("File exists!")
186
+
187
+ # Remove file/directory
188
+ sandbox.files.remove('/workspace/data.txt')
189
+
190
+ # Create directory
191
+ sandbox.files.mkdir('/workspace/mydir')
192
+
193
+ # Watch filesystem (WebSocket)
194
+ async for event in sandbox.files.watch('/workspace'):
195
+ print(f"{event['event']}: {event['path']}")
196
+ ```
197
+
198
+ ### Commands
199
+
200
+ ```python
201
+ # Run shell command
202
+ result = sandbox.commands.run('ls -la /workspace')
203
+ print(result.stdout)
204
+
205
+ # With environment variables
206
+ result = sandbox.commands.run(
207
+ 'echo "Key: $API_KEY"',
208
+ env={'API_KEY': 'secret'}
209
+ )
210
+
211
+ # Custom working directory
212
+ result = sandbox.commands.run(
213
+ 'pwd',
214
+ working_dir='/workspace/myproject'
215
+ )
216
+ ```
217
+
218
+ ### Environment Variables
219
+
220
+ ```python
221
+ # Get all
222
+ env_vars = sandbox.env.get_all()
223
+
224
+ # Set all (replace)
225
+ sandbox.env.set_all({'API_KEY': 'sk-...', 'DEBUG': 'true'})
226
+
227
+ # Update (merge)
228
+ sandbox.env.update({'NEW_VAR': 'value'})
229
+
230
+ # Delete
231
+ sandbox.env.delete(['VAR_TO_DELETE'])
232
+
233
+ # Get single
234
+ value = sandbox.env.get('API_KEY')
235
+
236
+ # Set single
237
+ sandbox.env.set('API_KEY', 'sk-...')
238
+ ```
239
+
240
+ ### Process Management
241
+
242
+ ```python
243
+ # List processes
244
+ processes = sandbox.list_processes()
245
+ for proc in processes:
246
+ print(f"{proc.pid}: {proc.name} (CPU: {proc.cpu_percent}%)")
247
+
248
+ # Kill process
249
+ sandbox.kill_process(1234)
250
+ ```
251
+
252
+ ### Metrics & Health
253
+
254
+ ```python
255
+ # Get metrics
256
+ metrics = sandbox.get_metrics_snapshot()
257
+ print(f"Total executions: {metrics.total_executions}")
258
+ print(f"Uptime: {metrics.uptime_seconds}s")
259
+
260
+ # Health check
261
+ health = sandbox.get_health()
262
+ print(f"Status: {health.status}")
263
+
264
+ # Cache management
265
+ cache_stats = sandbox.cache.stats()
266
+ print(f"Cache size: {cache_stats.cache.size}")
267
+
268
+ sandbox.cache.clear()
269
+ ```
270
+
271
+ ### Desktop Automation
272
+
273
+ ```python
274
+ # Note: Requires 'desktop' template
275
+ sandbox = Sandbox.create(template='desktop', api_key='...')
276
+
277
+ # Mouse operations
278
+ sandbox.desktop.mouse_click(x=500, y=300, button='left')
279
+ sandbox.desktop.mouse_move(x=600, y=400)
280
+ sandbox.desktop.drag_drop(from_x=100, from_y=100, to_x=300, to_y=300)
281
+
282
+ # Keyboard
283
+ sandbox.desktop.keyboard_type('Hello, World!')
284
+ sandbox.desktop.keyboard_press('Return')
285
+ sandbox.desktop.keyboard_press('Control_L+c') # Ctrl+C
286
+
287
+ # Clipboard
288
+ sandbox.desktop.clipboard_set('text to copy')
289
+ content = sandbox.desktop.clipboard_get()
290
+
291
+ # Screenshots
292
+ screenshot = sandbox.desktop.screenshot()
293
+ with open('screenshot.png', 'wb') as f:
294
+ f.write(screenshot)
295
+
296
+ # OCR (text recognition)
297
+ text = sandbox.desktop.ocr()
298
+ print(f"Found text: {text}")
299
+
300
+ # Find elements
301
+ element = sandbox.desktop.find_element(text='Button')
302
+ if element:
303
+ sandbox.desktop.mouse_click(x=element['x'], y=element['y'])
304
+
305
+ # VNC connection
306
+ vnc_info = sandbox.desktop.get_vnc_url()
307
+ print(f"VNC URL: {vnc_info['url']}")
308
+ ```
309
+
310
+ ### Interactive Terminal (WebSocket)
311
+
312
+ ```python
313
+ import asyncio
314
+
315
+ async def terminal_session():
316
+ async with sandbox.terminal.connect() as term:
317
+ # Send commands
318
+ await sandbox.terminal.send_input(term, 'ls -la\n')
319
+
320
+ # Receive output
321
+ async for message in sandbox.terminal.iter_output(term):
322
+ if message['type'] == 'output':
323
+ print(message['data'], end='')
324
+
325
+ asyncio.run(terminal_session())
326
+ ```
327
+
328
+ ## Advanced Configuration
329
+
330
+ ```python
331
+ sandbox = Sandbox.create(
332
+ template='code-interpreter', # Template defines CPU/RAM/Disk resources
333
+ api_key='your-api-key',
334
+ region='us-west-2', # Preferred region (optional)
335
+ timeout_seconds=600, # Auto-kill after 10 minutes (optional)
336
+ internet_access=True, # Enable internet access (optional, default: True)
337
+ env_vars={ # Pre-set environment variables (optional)
338
+ 'DATABASE_URL': 'postgres://...',
339
+ 'API_KEY': 'sk-...'
340
+ }
341
+ )
342
+
343
+ # Note: Resources (vCPU, RAM, Disk) come from the template.
344
+ # To customize resources, create a custom template with Template.build()
345
+ # See: https://docs.hopx.ai/templates
346
+ ```
347
+
348
+ ## Error Handling
349
+
350
+ ```python
351
+ from hopx_ai.errors import (
352
+ HopxError,
353
+ AuthenticationError,
354
+ NotFoundError,
355
+ FileNotFoundError,
356
+ CodeExecutionError,
357
+ RateLimitError,
358
+ ServerError
359
+ )
360
+
361
+ try:
362
+ with Sandbox.create(template='code-interpreter', api_key='...') as sandbox:
363
+ result = sandbox.run_code("print('Hello')")
364
+
365
+ except AuthenticationError as e:
366
+ print(f"Auth failed: {e.message}")
367
+ print(f"Request ID: {e.request_id}")
368
+
369
+ except FileNotFoundError as e:
370
+ print(f"File not found: {e.path}")
371
+
372
+ except CodeExecutionError as e:
373
+ print(f"Code execution failed: {e.message}")
374
+ print(f"Exit code: {e.exit_code}")
375
+
376
+ except RateLimitError as e:
377
+ print(f"Rate limited: {e.message}")
378
+
379
+ except HopxError as e:
380
+ print(f"API error: {e.message}")
381
+ print(f"Status code: {e.status_code}")
382
+ ```
383
+
384
+ ## Best Practices
385
+
386
+ ### 1. Always Use Context Managers
387
+
388
+ ```python
389
+ # ✅ GOOD: Automatic cleanup
390
+ with Sandbox.create(...) as sandbox:
391
+ # Work here
392
+ pass
393
+ # Sandbox automatically deleted
394
+
395
+ # ❌ BAD: Manual cleanup (easy to forget)
396
+ sandbox = Sandbox.create(...)
397
+ # ... work ...
398
+ sandbox.kill() # Easy to forget if error occurs!
399
+ ```
400
+
401
+ ### 2. Set Timeouts
402
+
403
+ ```python
404
+ # Prevent infinite execution
405
+ result = sandbox.run_code(code, timeout=30)
406
+ ```
407
+
408
+ ### 3. Optimize Performance
409
+
410
+ ```python
411
+ # Set environment variables once
412
+ sandbox.env.set_all({'API_KEY': 'sk-...', 'DB_URL': '...'})
413
+
414
+ # Now available in all executions
415
+ for i in range(100):
416
+ sandbox.run_code('...') # Env vars already set
417
+ ```
418
+
419
+ ## Use Cases
420
+
421
+ ### OpenAI: ChatGPT Code Interpreter
422
+
423
+ ```python
424
+ def execute_user_code(user_code: str):
425
+ with Sandbox.create(template="code-interpreter") as sandbox:
426
+ result = sandbox.run_code(user_code, timeout=30)
427
+ return {
428
+ "output": result.stdout,
429
+ "error": result.stderr,
430
+ "rich_outputs": result.rich_outputs # Images, plots
431
+ }
432
+ ```
433
+
434
+ ### Stripe: Payment Reports
435
+
436
+ ```python
437
+ with Sandbox.create(template="code-interpreter") as sandbox:
438
+ sandbox.env.set('STRIPE_SECRET_KEY', os.getenv('STRIPE_SECRET_KEY'))
439
+
440
+ result = sandbox.run_code("""
441
+ import stripe
442
+ stripe.api_key = os.environ['STRIPE_SECRET_KEY']
443
+ charges = stripe.Charge.list(limit=100)
444
+ # Generate report...
445
+ """)
446
+ ```
447
+
448
+ ## Documentation
449
+
450
+ - **Cookbook**: See [cookbook/python](../../cookbook/python/) for 10 complete examples
451
+ - **API Reference**: [docs.hopx.ai](https://docs.hopx.ai)
452
+ - **GitHub**: [github.com/hopx-ai/hopx](https://github.com/hopx-ai/hopx)
453
+
454
+ ## License
455
+
456
+ MIT License - See [LICENSE](../LICENSE) file for details.
457
+
458
+ ## Support
459
+
460
+ - **Issues**: [github.com/hopx-ai/hopx/issues](https://github.com/hopx-ai/hopx/issues)
461
+ - **Email**: support@hopx.ai
462
+ - **Documentation**: [docs.hopx.ai](https://docs.hopx.ai)
@@ -0,0 +1,29 @@
1
+ hopx_ai/__init__.py,sha256=t7lGXFh84sPBYvMyHhmjltfvzVCRta7elRBNJEn4iSo,2408
2
+ hopx_ai/_agent_client.py,sha256=oqw8Vz2GM0syDkz8UPjQJ8mmCAMxh68l1QV-eTumvfU,14239
3
+ hopx_ai/_async_client.py,sha256=6dBkqAN217RnzZjTzNryzNrOCoZD9wrw4bJW8hSPM6M,8242
4
+ hopx_ai/_client.py,sha256=uVwS4wO_M12jj2xVYd2ZpmgTn58jCD7P5Na_fRSuvD0,8121
5
+ hopx_ai/_utils.py,sha256=Ho0lTdl8zKI4U4eSXUmzMgHL3ShLD0RJ08j8NCXW2P0,228
6
+ hopx_ai/_ws_client.py,sha256=px-MFrKXD01wDp0Uj_Mf4vlUUyp9qYGd9eIIaYyWcvY,4155
7
+ hopx_ai/async_sandbox.py,sha256=W8Cdtiuppo3IoJyV0CsuaeFZxPsZTvkQMUxr0gKiA9I,13978
8
+ hopx_ai/cache.py,sha256=ps5VlDiMn4Lv0aNCQGwEllfyd67C5MHkvM_KY0ZEnTs,2758
9
+ hopx_ai/commands.py,sha256=0hIXaaLbQI__7ff38LKt8-L9xYNi89KO8IA8ix4_gzQ,5305
10
+ hopx_ai/desktop.py,sha256=aeXM19_otLFoI-zOEjx9uGLS6eXkmVmA-hEr2WAhF3U,36462
11
+ hopx_ai/env_vars.py,sha256=AuuTkmbn4hHMwOhigMsIPUOfCoumGjjgjFnPrAGwElk,7648
12
+ hopx_ai/errors.py,sha256=20dic5dU02bcwYSvPF4T_haeXqKOnOpjbvIeInkptu0,7022
13
+ hopx_ai/files.py,sha256=hu8oPCk7aCilowtx4oopxUSyA-_yLO9uNUkV-jkVivQ,15882
14
+ hopx_ai/models.py,sha256=NSsEC1tmYRggxkn-0PLOVL7mwPqUJu3VV0PIO1LXnkM,8725
15
+ hopx_ai/models_updated.py,sha256=aJx637PiSf8U3G96rdOC2pA0TIe-qohg6LpAnnrEaeI,8395
16
+ hopx_ai/sandbox.py,sha256=tST17ysD_jVmeOuV5PFw2qHBF9UfE8uFbQKQ-PpOun0,48972
17
+ hopx_ai/terminal.py,sha256=9U7FaHGnz2WJPrhCDONWiAuZ_iY5rORJN7jg7HCFqR4,4914
18
+ hopx_ai/_generated/__init__.py,sha256=adL9hY0cJi3SsBPLXlVi0k0jZVEPGK6ElW9DAMgpPvA,645
19
+ hopx_ai/_generated/models.py,sha256=fIjm0hPhQSJAVA25h65y3lWRsomIewV7WAi9EfnLHeQ,18099
20
+ hopx_ai/template/__init__.py,sha256=hVpTtDq-LoU6P-oUsj7VZUM9TMVFmgZP0USDpwDwT84,802
21
+ hopx_ai/template/build_flow.py,sha256=RdwO5tqcIneX7mmS25CZmm-fKnzFe3hmUHq_ycP9HLs,17483
22
+ hopx_ai/template/builder.py,sha256=k3TiMnNzaiXZG59ojalfZkyR2aqP8cVBGxx_ljJ_3Qo,9579
23
+ hopx_ai/template/file_hasher.py,sha256=Gn5p31Eq_dLspqh5xXM281dX9obJXjRLqUpDcYwUDh0,2453
24
+ hopx_ai/template/ready_checks.py,sha256=i7mM3b1IHafzruc0x3xDCFn-RlhjTOh2AgMfOIt6uM0,2627
25
+ hopx_ai/template/tar_creator.py,sha256=Nm53_Wbl-aJs47LgrUmk3GixClU9FiRtB0aqISuob3k,3711
26
+ hopx_ai/template/types.py,sha256=y_2QgyDVXx7WHxWxjlhAovXlHzOKImt4DIy3Avg-mO0,4376
27
+ hopx_ai-0.1.11.dist-info/METADATA,sha256=68qPJgoVaMuKZyy8_Kdb5RzDkbmCNf8BSzZy_MKwKtI,11499
28
+ hopx_ai-0.1.11.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
29
+ hopx_ai-0.1.11.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any