opensandbox-code-interpreter 0.1.1__tar.gz → 0.1.2__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.
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/.gitignore +11 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/PKG-INFO +15 -7
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/README.md +10 -2
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/pyproject.toml +4 -4
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/adapters/code_adapter.py +21 -1
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/adapters/code_adapter.py +50 -9
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/LICENSE +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/adapters/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/adapters/converter/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/adapters/converter/code_execution_converter.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/adapters/factory.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/code_interpreter.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/models/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/models/code.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/models/code_sync.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/py.typed +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/services/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/services/code.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/adapters/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/adapters/factory.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/code_interpreter.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/services/__init__.py +0 -0
- {opensandbox_code_interpreter-0.1.1 → opensandbox_code_interpreter-0.1.2}/src/code_interpreter/sync/services/code.py +0 -0
|
@@ -133,6 +133,8 @@ dist
|
|
|
133
133
|
# Gatsby files
|
|
134
134
|
.cache/
|
|
135
135
|
public
|
|
136
|
+
!docs/public/
|
|
137
|
+
!docs/public/CNAME
|
|
136
138
|
|
|
137
139
|
# Serverless directories
|
|
138
140
|
.serverless/
|
|
@@ -222,6 +224,9 @@ secrets/
|
|
|
222
224
|
|
|
223
225
|
# Generated API documentation
|
|
224
226
|
docs/generated/
|
|
227
|
+
docs/.vitepress/generated/
|
|
228
|
+
docs/.vitepress/dist/
|
|
229
|
+
docs/.vitepress/cache/
|
|
225
230
|
apidocs/
|
|
226
231
|
|
|
227
232
|
# Test results
|
|
@@ -263,3 +268,9 @@ nbdist/
|
|
|
263
268
|
# Generated files
|
|
264
269
|
generated/
|
|
265
270
|
**/generated/**
|
|
271
|
+
|
|
272
|
+
# gVisor runtime binaries (downloaded dynamically)
|
|
273
|
+
kubernetes/test/kind/gvisor/runsc
|
|
274
|
+
kubernetes/test/kind/gvisor/containerd-shim-runsc-v1
|
|
275
|
+
bin/
|
|
276
|
+
obj/
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensandbox-code-interpreter
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: OpenSandbox Code Interpreter Python SDK - Advanced code execution with persistent contexts
|
|
5
|
-
Project-URL: Homepage, https://
|
|
5
|
+
Project-URL: Homepage, https://open-sandbox.ai
|
|
6
6
|
Project-URL: Repository, https://github.com/alibaba/OpenSandbox
|
|
7
|
-
Project-URL: Documentation, https://
|
|
7
|
+
Project-URL: Documentation, https://open-sandbox.ai
|
|
8
8
|
Project-URL: Issues, https://github.com/alibaba/OpenSandbox/issues
|
|
9
9
|
Author-email: OpenSandbox Team <ninan.nn@alibaba-inc.com>
|
|
10
10
|
License: Apache License
|
|
@@ -223,8 +223,8 @@ Classifier: Programming Language :: Python :: 3.13
|
|
|
223
223
|
Classifier: Topic :: Software Development :: Libraries
|
|
224
224
|
Classifier: Typing :: Typed
|
|
225
225
|
Requires-Python: >=3.10
|
|
226
|
-
Requires-Dist: opensandbox<0.2.0,>=0.1.
|
|
227
|
-
Requires-Dist: pydantic<3.0,>=2.
|
|
226
|
+
Requires-Dist: opensandbox<0.2.0,>=0.1.6
|
|
227
|
+
Requires-Dist: pydantic<3.0,>=2.4.2
|
|
228
228
|
Description-Content-Type: text/markdown
|
|
229
229
|
|
|
230
230
|
# OpenSandbox Code Interpreter SDK for Python
|
|
@@ -281,7 +281,7 @@ async def main() -> None:
|
|
|
281
281
|
|
|
282
282
|
# 2. Create a Sandbox with the code-interpreter image + runtime versions
|
|
283
283
|
sandbox = await Sandbox.create(
|
|
284
|
-
"opensandbox/code-interpreter:
|
|
284
|
+
"opensandbox/code-interpreter:v1.0.2",
|
|
285
285
|
connection_config=config,
|
|
286
286
|
entrypoint=["/opt/opensandbox/code-interpreter.sh"],
|
|
287
287
|
env={
|
|
@@ -342,7 +342,7 @@ config = ConnectionConfigSync(
|
|
|
342
342
|
)
|
|
343
343
|
|
|
344
344
|
sandbox = SandboxSync.create(
|
|
345
|
-
"opensandbox/code-interpreter:
|
|
345
|
+
"opensandbox/code-interpreter:v1.0.2",
|
|
346
346
|
connection_config=config,
|
|
347
347
|
entrypoint=["/opt/opensandbox/code-interpreter.sh"],
|
|
348
348
|
env={"PYTHON_VERSION": "3.11"},
|
|
@@ -355,6 +355,14 @@ with sandbox:
|
|
|
355
355
|
sandbox.kill()
|
|
356
356
|
```
|
|
357
357
|
|
|
358
|
+
### Installing Python packages at runtime
|
|
359
|
+
|
|
360
|
+
You can install packages directly via `sandbox.commands.run(...)`:
|
|
361
|
+
|
|
362
|
+
```python
|
|
363
|
+
execution = await sandbox.commands.run("pip install pandas numpy")
|
|
364
|
+
```
|
|
365
|
+
|
|
358
366
|
## Runtime Configuration
|
|
359
367
|
|
|
360
368
|
### Docker Image
|
|
@@ -52,7 +52,7 @@ async def main() -> None:
|
|
|
52
52
|
|
|
53
53
|
# 2. Create a Sandbox with the code-interpreter image + runtime versions
|
|
54
54
|
sandbox = await Sandbox.create(
|
|
55
|
-
"opensandbox/code-interpreter:
|
|
55
|
+
"opensandbox/code-interpreter:v1.0.2",
|
|
56
56
|
connection_config=config,
|
|
57
57
|
entrypoint=["/opt/opensandbox/code-interpreter.sh"],
|
|
58
58
|
env={
|
|
@@ -113,7 +113,7 @@ config = ConnectionConfigSync(
|
|
|
113
113
|
)
|
|
114
114
|
|
|
115
115
|
sandbox = SandboxSync.create(
|
|
116
|
-
"opensandbox/code-interpreter:
|
|
116
|
+
"opensandbox/code-interpreter:v1.0.2",
|
|
117
117
|
connection_config=config,
|
|
118
118
|
entrypoint=["/opt/opensandbox/code-interpreter.sh"],
|
|
119
119
|
env={"PYTHON_VERSION": "3.11"},
|
|
@@ -126,6 +126,14 @@ with sandbox:
|
|
|
126
126
|
sandbox.kill()
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
+
### Installing Python packages at runtime
|
|
130
|
+
|
|
131
|
+
You can install packages directly via `sandbox.commands.run(...)`:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
execution = await sandbox.commands.run("pip install pandas numpy")
|
|
135
|
+
```
|
|
136
|
+
|
|
129
137
|
## Runtime Configuration
|
|
130
138
|
|
|
131
139
|
### Docker Image
|
|
@@ -42,14 +42,14 @@ classifiers = [
|
|
|
42
42
|
"Typing :: Typed",
|
|
43
43
|
]
|
|
44
44
|
dependencies = [
|
|
45
|
-
"pydantic>=2.
|
|
46
|
-
"opensandbox>=0.1.
|
|
45
|
+
"pydantic>=2.4.2,<3.0",
|
|
46
|
+
"opensandbox>=0.1.6,<0.2.0",
|
|
47
47
|
]
|
|
48
48
|
|
|
49
49
|
[project.urls]
|
|
50
|
-
Homepage = "https://
|
|
50
|
+
Homepage = "https://open-sandbox.ai"
|
|
51
51
|
Repository = "https://github.com/alibaba/OpenSandbox"
|
|
52
|
-
Documentation = "https://
|
|
52
|
+
Documentation = "https://open-sandbox.ai"
|
|
53
53
|
Issues = "https://github.com/alibaba/OpenSandbox/issues"
|
|
54
54
|
|
|
55
55
|
[tool.hatch.version]
|
|
@@ -22,6 +22,7 @@ API clients and handling SSE streaming for real-time code execution.
|
|
|
22
22
|
|
|
23
23
|
import json
|
|
24
24
|
import logging
|
|
25
|
+
import time
|
|
25
26
|
|
|
26
27
|
import httpx
|
|
27
28
|
from opensandbox.adapters.converter.event_node import EventNode
|
|
@@ -32,6 +33,7 @@ from opensandbox.adapters.converter.execution_event_dispatcher import (
|
|
|
32
33
|
ExecutionEventDispatcher,
|
|
33
34
|
)
|
|
34
35
|
from opensandbox.adapters.converter.response_handler import (
|
|
36
|
+
extract_request_id,
|
|
35
37
|
handle_api_error,
|
|
36
38
|
require_parsed,
|
|
37
39
|
)
|
|
@@ -49,6 +51,22 @@ from code_interpreter.services.code import Codes
|
|
|
49
51
|
logger = logging.getLogger(__name__)
|
|
50
52
|
|
|
51
53
|
|
|
54
|
+
def _normalize_sse_event(event_dict: dict) -> dict:
|
|
55
|
+
if "type" in event_dict and "timestamp" in event_dict:
|
|
56
|
+
return event_dict
|
|
57
|
+
if "code" in event_dict and "message" in event_dict:
|
|
58
|
+
return {
|
|
59
|
+
"type": "error",
|
|
60
|
+
"timestamp": int(time.time() * 1000),
|
|
61
|
+
"error": {
|
|
62
|
+
"ename": str(event_dict["code"]),
|
|
63
|
+
"evalue": str(event_dict["message"]),
|
|
64
|
+
"traceback": [],
|
|
65
|
+
},
|
|
66
|
+
}
|
|
67
|
+
return event_dict
|
|
68
|
+
|
|
69
|
+
|
|
52
70
|
class CodesAdapter(Codes):
|
|
53
71
|
"""
|
|
54
72
|
Adapter implementation for code execution service.
|
|
@@ -88,6 +106,7 @@ class CodesAdapter(Codes):
|
|
|
88
106
|
headers = {
|
|
89
107
|
"User-Agent": self.connection_config.user_agent,
|
|
90
108
|
**self.connection_config.headers,
|
|
109
|
+
**self.execd_endpoint.headers,
|
|
91
110
|
}
|
|
92
111
|
|
|
93
112
|
# Execd API does not require authentication
|
|
@@ -287,6 +306,7 @@ class CodesAdapter(Codes):
|
|
|
287
306
|
raise SandboxApiException(
|
|
288
307
|
message=f"Failed to run code. Status code: {response.status_code}",
|
|
289
308
|
status_code=response.status_code,
|
|
309
|
+
request_id=extract_request_id(response.headers),
|
|
290
310
|
)
|
|
291
311
|
|
|
292
312
|
dispatcher = ExecutionEventDispatcher(execution, handlers)
|
|
@@ -301,7 +321,7 @@ class CodesAdapter(Codes):
|
|
|
301
321
|
data = data[5:].strip()
|
|
302
322
|
|
|
303
323
|
try:
|
|
304
|
-
event_dict = json.loads(data)
|
|
324
|
+
event_dict = _normalize_sse_event(json.loads(data))
|
|
305
325
|
event_node = EventNode(**event_dict)
|
|
306
326
|
await dispatcher.dispatch(event_node)
|
|
307
327
|
except json.JSONDecodeError:
|
|
@@ -19,6 +19,7 @@ Synchronous adapter for code execution service (including SSE streaming).
|
|
|
19
19
|
|
|
20
20
|
import json
|
|
21
21
|
import logging
|
|
22
|
+
import time
|
|
22
23
|
|
|
23
24
|
import httpx
|
|
24
25
|
from opensandbox.adapters.converter.event_node import EventNode
|
|
@@ -26,6 +27,7 @@ from opensandbox.adapters.converter.exception_converter import (
|
|
|
26
27
|
ExceptionConverter,
|
|
27
28
|
)
|
|
28
29
|
from opensandbox.adapters.converter.response_handler import (
|
|
30
|
+
extract_request_id,
|
|
29
31
|
handle_api_error,
|
|
30
32
|
require_parsed,
|
|
31
33
|
)
|
|
@@ -44,6 +46,22 @@ from code_interpreter.sync.services.code import CodesSync
|
|
|
44
46
|
logger = logging.getLogger(__name__)
|
|
45
47
|
|
|
46
48
|
|
|
49
|
+
def _normalize_sse_event(event_dict: dict) -> dict:
|
|
50
|
+
if "type" in event_dict and "timestamp" in event_dict:
|
|
51
|
+
return event_dict
|
|
52
|
+
if "code" in event_dict and "message" in event_dict:
|
|
53
|
+
return {
|
|
54
|
+
"type": "error",
|
|
55
|
+
"timestamp": int(time.time() * 1000),
|
|
56
|
+
"error": {
|
|
57
|
+
"ename": str(event_dict["code"]),
|
|
58
|
+
"evalue": str(event_dict["message"]),
|
|
59
|
+
"traceback": [],
|
|
60
|
+
},
|
|
61
|
+
}
|
|
62
|
+
return event_dict
|
|
63
|
+
|
|
64
|
+
|
|
47
65
|
class CodesAdapterSync(CodesSync):
|
|
48
66
|
"""
|
|
49
67
|
Synchronous adapter for code execution service.
|
|
@@ -63,7 +81,9 @@ class CodesAdapterSync(CodesSync):
|
|
|
63
81
|
RUN_CODE_PATH = "/code"
|
|
64
82
|
CREATE_CONTEXT_PATH = "/code/context"
|
|
65
83
|
|
|
66
|
-
def __init__(
|
|
84
|
+
def __init__(
|
|
85
|
+
self, execd_endpoint: SandboxEndpoint, connection_config: ConnectionConfigSync
|
|
86
|
+
) -> None:
|
|
67
87
|
"""
|
|
68
88
|
Initialize the code service adapter (sync).
|
|
69
89
|
|
|
@@ -78,7 +98,11 @@ class CodesAdapterSync(CodesSync):
|
|
|
78
98
|
base_url = f"{self.connection_config.protocol}://{self.execd_endpoint.endpoint}"
|
|
79
99
|
timeout_seconds = self.connection_config.request_timeout.total_seconds()
|
|
80
100
|
timeout = httpx.Timeout(timeout_seconds)
|
|
81
|
-
headers = {
|
|
101
|
+
headers = {
|
|
102
|
+
"User-Agent": self.connection_config.user_agent,
|
|
103
|
+
**self.connection_config.headers,
|
|
104
|
+
**(self.execd_endpoint.headers or {}),
|
|
105
|
+
}
|
|
82
106
|
|
|
83
107
|
self._client = Client(base_url=base_url, timeout=timeout)
|
|
84
108
|
self._httpx_client = httpx.Client(
|
|
@@ -89,16 +113,24 @@ class CodesAdapterSync(CodesSync):
|
|
|
89
113
|
)
|
|
90
114
|
self._client.set_httpx_client(self._httpx_client)
|
|
91
115
|
|
|
92
|
-
sse_headers = {
|
|
116
|
+
sse_headers = {
|
|
117
|
+
**headers,
|
|
118
|
+
"Accept": "text/event-stream",
|
|
119
|
+
"Cache-Control": "no-cache",
|
|
120
|
+
}
|
|
93
121
|
self._sse_client = httpx.Client(
|
|
94
122
|
headers=sse_headers,
|
|
95
|
-
timeout=httpx.Timeout(
|
|
123
|
+
timeout=httpx.Timeout(
|
|
124
|
+
connect=timeout_seconds, read=None, write=timeout_seconds, pool=None
|
|
125
|
+
),
|
|
96
126
|
transport=self.connection_config.transport,
|
|
97
127
|
)
|
|
98
128
|
|
|
99
129
|
def _get_execd_url(self, path: str) -> str:
|
|
100
130
|
"""Build URL for execd endpoint."""
|
|
101
|
-
return
|
|
131
|
+
return (
|
|
132
|
+
f"{self.connection_config.protocol}://{self.execd_endpoint.endpoint}{path}"
|
|
133
|
+
)
|
|
102
134
|
|
|
103
135
|
def create_context(self, language: str) -> CodeContextSync:
|
|
104
136
|
"""
|
|
@@ -225,7 +257,11 @@ class CodesAdapterSync(CodesSync):
|
|
|
225
257
|
raise InvalidArgumentException("Code cannot be empty")
|
|
226
258
|
|
|
227
259
|
try:
|
|
228
|
-
if
|
|
260
|
+
if (
|
|
261
|
+
context is not None
|
|
262
|
+
and language is not None
|
|
263
|
+
and context.language != language
|
|
264
|
+
):
|
|
229
265
|
raise InvalidArgumentException(
|
|
230
266
|
f"language '{language}' must match context.language '{context.language}'"
|
|
231
267
|
)
|
|
@@ -233,7 +269,9 @@ class CodesAdapterSync(CodesSync):
|
|
|
233
269
|
if context is None:
|
|
234
270
|
# Default context: language default context (server-side behavior).
|
|
235
271
|
# When context.id is omitted, execd will create/reuse a default session per language.
|
|
236
|
-
context = CodeContextSync(
|
|
272
|
+
context = CodeContextSync(
|
|
273
|
+
language=language or SupportedLanguageSync.PYTHON
|
|
274
|
+
)
|
|
237
275
|
api_request = {
|
|
238
276
|
"code": code,
|
|
239
277
|
"context": {
|
|
@@ -252,6 +290,7 @@ class CodesAdapterSync(CodesSync):
|
|
|
252
290
|
raise SandboxApiException(
|
|
253
291
|
message=f"Failed to run code. Status code: {response.status_code}",
|
|
254
292
|
status_code=response.status_code,
|
|
293
|
+
request_id=extract_request_id(response.headers),
|
|
255
294
|
)
|
|
256
295
|
|
|
257
296
|
for line in response.iter_lines():
|
|
@@ -261,7 +300,7 @@ class CodesAdapterSync(CodesSync):
|
|
|
261
300
|
if data.startswith("data:"):
|
|
262
301
|
data = data[5:].strip()
|
|
263
302
|
try:
|
|
264
|
-
event_dict = json.loads(data)
|
|
303
|
+
event_dict = _normalize_sse_event(json.loads(data))
|
|
265
304
|
event_node = EventNode(**event_dict)
|
|
266
305
|
dispatcher.dispatch(event_node)
|
|
267
306
|
except json.JSONDecodeError:
|
|
@@ -286,7 +325,9 @@ class CodesAdapterSync(CodesSync):
|
|
|
286
325
|
try:
|
|
287
326
|
from opensandbox.api.execd.api.code_interpreting import interrupt_code
|
|
288
327
|
|
|
289
|
-
response_obj = interrupt_code.sync_detailed(
|
|
328
|
+
response_obj = interrupt_code.sync_detailed(
|
|
329
|
+
client=self._client, id=execution_id
|
|
330
|
+
)
|
|
290
331
|
handle_api_error(response_obj, "Interrupt code execution")
|
|
291
332
|
except Exception as e:
|
|
292
333
|
logger.error("Failed to interrupt code execution", exc_info=e)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|