e2b-code-interpreter 0.0.7__tar.gz → 0.0.8__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.
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/PKG-INFO +2 -2
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/e2b_code_interpreter/main.py +32 -14
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/e2b_code_interpreter/messaging.py +7 -5
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/e2b_code_interpreter/models.py +6 -1
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/pyproject.toml +2 -2
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/README.md +0 -0
- {e2b_code_interpreter-0.0.7 → e2b_code_interpreter-0.0.8}/e2b_code_interpreter/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: e2b-code-interpreter
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.8
|
|
4
4
|
Summary: E2B Code Interpreter - Stateful code execution
|
|
5
5
|
Home-page: https://e2b.dev/
|
|
6
6
|
License: Apache-2.0
|
|
@@ -14,7 +14,7 @@ Classifier: Programming Language :: Python :: 3.9
|
|
|
14
14
|
Classifier: Programming Language :: Python :: 3.10
|
|
15
15
|
Classifier: Programming Language :: Python :: 3.11
|
|
16
16
|
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
-
Requires-Dist: e2b (>=0.17.
|
|
17
|
+
Requires-Dist: e2b (>=0.17.1)
|
|
18
18
|
Requires-Dist: pydantic (>1,<3)
|
|
19
19
|
Requires-Dist: websocket-client (>=1.7.0,<2.0.0)
|
|
20
20
|
Project-URL: Bug Tracker, https://github.com/e2b-dev/code-interpreter/issues
|
|
@@ -2,6 +2,8 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import logging
|
|
4
4
|
import threading
|
|
5
|
+
import uuid
|
|
6
|
+
|
|
5
7
|
import requests
|
|
6
8
|
|
|
7
9
|
from concurrent.futures import Future
|
|
@@ -91,16 +93,16 @@ class JupyterExtension:
|
|
|
91
93
|
ws = ws_future.result(timeout=timeout)
|
|
92
94
|
else:
|
|
93
95
|
logger.debug(f"Creating new websocket connection to kernel {kernel_id}")
|
|
94
|
-
ws = self._connect_to_kernel_ws(kernel_id, timeout=timeout)
|
|
96
|
+
ws = self._connect_to_kernel_ws(kernel_id, None, timeout=timeout)
|
|
95
97
|
|
|
96
|
-
|
|
98
|
+
message_id = ws.send_execution_message(code, on_stdout, on_stderr, on_result)
|
|
97
99
|
logger.debug(
|
|
98
|
-
f"Sent execution message to kernel {kernel_id},
|
|
100
|
+
f"Sent execution message to kernel {kernel_id}, message_id: {message_id}"
|
|
99
101
|
)
|
|
100
102
|
|
|
101
|
-
result = ws.get_result(
|
|
103
|
+
result = ws.get_result(message_id, timeout=timeout)
|
|
102
104
|
logger.debug(
|
|
103
|
-
f"Received result from kernel {kernel_id},
|
|
105
|
+
f"Received result from kernel {kernel_id}, message_id: {message_id}, result: {result}"
|
|
104
106
|
)
|
|
105
107
|
|
|
106
108
|
return result
|
|
@@ -139,24 +141,35 @@ class JupyterExtension:
|
|
|
139
141
|
:param timeout: Timeout for the kernel creation request.
|
|
140
142
|
:return: Kernel id of the created kernel
|
|
141
143
|
"""
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
144
|
+
kernel_name = kernel_name or "python3"
|
|
145
|
+
|
|
146
|
+
data = {"path": str(uuid.uuid4()), "kernel": {"name": kernel_name}, "type": "notebook", "name": str(uuid.uuid4())}
|
|
145
147
|
logger.debug(f"Creating kernel with data: {data}")
|
|
146
148
|
|
|
147
149
|
response = requests.post(
|
|
148
|
-
f"{self._sandbox.get_protocol()}://{self._sandbox.get_hostname(8888)}/api/
|
|
150
|
+
f"{self._sandbox.get_protocol()}://{self._sandbox.get_hostname(8888)}/api/sessions",
|
|
149
151
|
json=data,
|
|
150
152
|
timeout=timeout,
|
|
151
153
|
)
|
|
152
154
|
if not response.ok:
|
|
153
155
|
raise KernelException(f"Failed to create kernel: {response.text}")
|
|
154
156
|
|
|
155
|
-
|
|
157
|
+
session_data = response.json()
|
|
158
|
+
session_id = session_data["id"]
|
|
159
|
+
kernel_id = session_data["kernel"]["id"]
|
|
160
|
+
|
|
161
|
+
response = requests.patch(
|
|
162
|
+
f"{self._sandbox.get_protocol()}://{self._sandbox.get_hostname(8888)}/api/sessions/{session_id}",
|
|
163
|
+
json={"path": cwd},
|
|
164
|
+
timeout=timeout,
|
|
165
|
+
)
|
|
166
|
+
if not response.ok:
|
|
167
|
+
raise KernelException(f"Failed to create kernel: {response.text}")
|
|
168
|
+
|
|
156
169
|
logger.debug(f"Created kernel {kernel_id}")
|
|
157
170
|
|
|
158
171
|
threading.Thread(
|
|
159
|
-
target=self._connect_to_kernel_ws, args=(kernel_id, timeout)
|
|
172
|
+
target=self._connect_to_kernel_ws, args=(kernel_id, session_id, timeout)
|
|
160
173
|
).start()
|
|
161
174
|
return kernel_id
|
|
162
175
|
|
|
@@ -186,7 +199,7 @@ class JupyterExtension:
|
|
|
186
199
|
logger.debug(f"Restarted kernel {kernel_id}")
|
|
187
200
|
|
|
188
201
|
threading.Thread(
|
|
189
|
-
target=self._connect_to_kernel_ws, args=(kernel_id, timeout)
|
|
202
|
+
target=self._connect_to_kernel_ws, args=(kernel_id, None, timeout)
|
|
190
203
|
).start()
|
|
191
204
|
|
|
192
205
|
def shutdown_kernel(
|
|
@@ -243,7 +256,7 @@ class JupyterExtension:
|
|
|
243
256
|
ws.result().close()
|
|
244
257
|
|
|
245
258
|
def _connect_to_kernel_ws(
|
|
246
|
-
self, kernel_id: str, timeout: Optional[float] = TIMEOUT
|
|
259
|
+
self, kernel_id: str, session_id: Optional[str], timeout: Optional[float] = TIMEOUT
|
|
247
260
|
) -> JupyterKernelWebSocket:
|
|
248
261
|
"""
|
|
249
262
|
Establishes a WebSocket connection to a specified Jupyter kernel.
|
|
@@ -257,9 +270,12 @@ class JupyterExtension:
|
|
|
257
270
|
future = Future()
|
|
258
271
|
self._connected_kernels[kernel_id] = future
|
|
259
272
|
|
|
273
|
+
session_id = session_id or str(uuid.uuid4())
|
|
260
274
|
ws = JupyterKernelWebSocket(
|
|
261
275
|
url=f"{self._sandbox.get_protocol('ws')}://{self._sandbox.get_hostname(8888)}/api/kernels/{kernel_id}/channels",
|
|
276
|
+
session_id=session_id
|
|
262
277
|
)
|
|
278
|
+
|
|
263
279
|
ws.connect(timeout=timeout)
|
|
264
280
|
logger.debug(f"Connected to kernel's ({kernel_id}) websocket.")
|
|
265
281
|
|
|
@@ -279,12 +295,14 @@ class JupyterExtension:
|
|
|
279
295
|
kernel_id = self._sandbox.filesystem.read(
|
|
280
296
|
"/root/.jupyter/kernel_id", timeout=timeout
|
|
281
297
|
)
|
|
298
|
+
|
|
282
299
|
if kernel_id is None and not self._sandbox.is_open:
|
|
283
300
|
return
|
|
284
301
|
|
|
285
302
|
kernel_id = kernel_id.strip()
|
|
303
|
+
|
|
286
304
|
logger.debug(f"Default kernel id: {kernel_id}")
|
|
287
|
-
self._connect_to_kernel_ws(kernel_id, timeout=timeout)
|
|
305
|
+
self._connect_to_kernel_ws(kernel_id, None, timeout=timeout)
|
|
288
306
|
self._kernel_id_set.set_result(kernel_id)
|
|
289
307
|
|
|
290
308
|
threading.Thread(target=setup_default_kernel).start()
|
|
@@ -25,6 +25,7 @@ class CellExecution:
|
|
|
25
25
|
"""
|
|
26
26
|
|
|
27
27
|
input_accepted: bool = False
|
|
28
|
+
|
|
28
29
|
on_stdout: Optional[Callable[[ProcessMessage], Any]] = None
|
|
29
30
|
on_stderr: Optional[Callable[[ProcessMessage], Any]] = None
|
|
30
31
|
on_result: Optional[Callable[[Result], Any]] = None
|
|
@@ -44,8 +45,9 @@ class CellExecution:
|
|
|
44
45
|
|
|
45
46
|
class JupyterKernelWebSocket:
|
|
46
47
|
|
|
47
|
-
def __init__(self, url: str):
|
|
48
|
+
def __init__(self, url: str, session_id: str):
|
|
48
49
|
self.url = url
|
|
50
|
+
self.session_id = session_id
|
|
49
51
|
self._cells: Dict[str, CellExecution] = {}
|
|
50
52
|
self._waiting_for_replies: Dict[str, DeferredFuture] = {}
|
|
51
53
|
self._queue_in = Queue()
|
|
@@ -101,14 +103,13 @@ class JupyterKernelWebSocket:
|
|
|
101
103
|
|
|
102
104
|
logger.debug("WebSocket started")
|
|
103
105
|
|
|
104
|
-
|
|
105
|
-
def _get_execute_request(msg_id: str, code: str) -> str:
|
|
106
|
+
def _get_execute_request(self, msg_id: str, code: str) -> str:
|
|
106
107
|
return json.dumps(
|
|
107
108
|
{
|
|
108
109
|
"header": {
|
|
109
110
|
"msg_id": msg_id,
|
|
110
111
|
"username": "e2b",
|
|
111
|
-
"session":
|
|
112
|
+
"session": self.session_id,
|
|
112
113
|
"msg_type": "execute_request",
|
|
113
114
|
"version": "5.3",
|
|
114
115
|
},
|
|
@@ -117,7 +118,7 @@ class JupyterKernelWebSocket:
|
|
|
117
118
|
"content": {
|
|
118
119
|
"code": code,
|
|
119
120
|
"silent": False,
|
|
120
|
-
"store_history":
|
|
121
|
+
"store_history": True,
|
|
121
122
|
"user_expressions": {},
|
|
122
123
|
"allow_stdin": False,
|
|
123
124
|
},
|
|
@@ -237,6 +238,7 @@ class JupyterKernelWebSocket:
|
|
|
237
238
|
|
|
238
239
|
elif data["msg_type"] == "execute_input":
|
|
239
240
|
logger.debug(f"Input accepted for {parent_msg_ig}")
|
|
241
|
+
cell.partial_result.execution_count = data["content"]["execution_count"]
|
|
240
242
|
cell.input_accepted = True
|
|
241
243
|
else:
|
|
242
244
|
logger.warning(f"[UNHANDLED MESSAGE TYPE]: {data['msg_type']}")
|
|
@@ -124,6 +124,9 @@ class Result:
|
|
|
124
124
|
"""
|
|
125
125
|
return self.text
|
|
126
126
|
|
|
127
|
+
def __repr__(self) -> str:
|
|
128
|
+
return f"Result({self.text})"
|
|
129
|
+
|
|
127
130
|
def _repr_html_(self) -> Optional[str]:
|
|
128
131
|
"""
|
|
129
132
|
Returns the HTML representation of the data.
|
|
@@ -222,6 +225,8 @@ class Execution(BaseModel):
|
|
|
222
225
|
"Logs printed to stdout and stderr during execution."
|
|
223
226
|
error: Optional[Error] = None
|
|
224
227
|
"Error object if an error occurred, None otherwise."
|
|
228
|
+
execution_count: Optional[int] = None
|
|
229
|
+
"Execution count of the cell."
|
|
225
230
|
|
|
226
231
|
@property
|
|
227
232
|
def text(self) -> Optional[str]:
|
|
@@ -249,7 +254,7 @@ class Execution(BaseModel):
|
|
|
249
254
|
serialized = []
|
|
250
255
|
for result in results:
|
|
251
256
|
serialized_dict = {key: result[key] for key in result.formats()}
|
|
252
|
-
serialized_dict[
|
|
257
|
+
serialized_dict["text"] = result.text
|
|
253
258
|
serialized.append(serialized_dict)
|
|
254
259
|
return serialized
|
|
255
260
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "e2b-code-interpreter"
|
|
3
|
-
version = "0.0.
|
|
3
|
+
version = "0.0.8"
|
|
4
4
|
description = "E2B Code Interpreter - Stateful code execution"
|
|
5
5
|
authors = ["e2b <hello@e2b.dev>"]
|
|
6
6
|
license = "Apache-2.0"
|
|
@@ -14,7 +14,7 @@ python = "^3.8"
|
|
|
14
14
|
|
|
15
15
|
pydantic = ">1, <3"
|
|
16
16
|
websocket-client = "^1.7.0"
|
|
17
|
-
e2b = ">=0.17.
|
|
17
|
+
e2b = ">=0.17.1"
|
|
18
18
|
|
|
19
19
|
[tool.poetry.group.dev.dependencies]
|
|
20
20
|
black = "^24.3.0"
|
|
File without changes
|
|
File without changes
|