blaxel 0.2.8__py3-none-any.whl → 0.2.9__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.
- blaxel/core/sandbox/__init__.py +2 -0
- blaxel/core/sandbox/process.py +9 -6
- blaxel/core/sandbox/sandbox.py +15 -2
- blaxel/core/sandbox/types.py +24 -0
- {blaxel-0.2.8.dist-info → blaxel-0.2.9.dist-info}/METADATA +1 -1
- {blaxel-0.2.8.dist-info → blaxel-0.2.9.dist-info}/RECORD +8 -8
- {blaxel-0.2.8.dist-info → blaxel-0.2.9.dist-info}/WHEEL +0 -0
- {blaxel-0.2.8.dist-info → blaxel-0.2.9.dist-info}/licenses/LICENSE +0 -0
blaxel/core/sandbox/__init__.py
CHANGED
@@ -8,6 +8,7 @@ from .sandbox import (
|
|
8
8
|
from .types import (
|
9
9
|
CopyResponse,
|
10
10
|
ProcessRequestWithLog,
|
11
|
+
ProcessResponseWithLog,
|
11
12
|
SandboxConfiguration,
|
12
13
|
SandboxCreateConfiguration,
|
13
14
|
SandboxFilesystemFile,
|
@@ -30,4 +31,5 @@ __all__ = [
|
|
30
31
|
"SandboxPreviews",
|
31
32
|
"SandboxProcess",
|
32
33
|
"ProcessRequestWithLog",
|
34
|
+
"ProcessResponseWithLog",
|
33
35
|
]
|
blaxel/core/sandbox/process.py
CHANGED
@@ -7,7 +7,7 @@ from ..common.settings import settings
|
|
7
7
|
from .action import SandboxAction
|
8
8
|
from .client.models import ProcessResponse, SuccessResponse
|
9
9
|
from .client.models.process_request import ProcessRequest
|
10
|
-
from .types import ProcessRequestWithLog, SandboxConfiguration
|
10
|
+
from .types import ProcessRequestWithLog, ProcessResponseWithLog, SandboxConfiguration
|
11
11
|
|
12
12
|
|
13
13
|
class SandboxProcess(SandboxAction):
|
@@ -77,7 +77,8 @@ class SandboxProcess(SandboxAction):
|
|
77
77
|
|
78
78
|
async def exec(
|
79
79
|
self, process: Union[ProcessRequest, ProcessRequestWithLog, Dict[str, Any]]
|
80
|
-
) -> ProcessResponse:
|
80
|
+
) -> Union[ProcessResponse, ProcessResponseWithLog]:
|
81
|
+
"""Execute a process in the sandbox."""
|
81
82
|
on_log = None
|
82
83
|
if isinstance(process, ProcessRequestWithLog):
|
83
84
|
on_log = process.on_log
|
@@ -95,7 +96,6 @@ class SandboxProcess(SandboxAction):
|
|
95
96
|
# Always start process without wait_for_completion to avoid server-side blocking
|
96
97
|
if should_wait_for_completion and on_log is not None:
|
97
98
|
process.wait_for_completion = False
|
98
|
-
|
99
99
|
async with self.get_client() as client_instance:
|
100
100
|
response = await client_instance.post("/process", json=process.to_dict())
|
101
101
|
# Parse JSON response only once, with better error handling
|
@@ -118,7 +118,7 @@ class SandboxProcess(SandboxAction):
|
|
118
118
|
stream_control = self.stream_logs(result.pid, {"on_log": on_log})
|
119
119
|
try:
|
120
120
|
# Wait for process completion
|
121
|
-
result = await self.wait(result.pid, interval=
|
121
|
+
result = await self.wait(result.pid, interval=500, max_wait=1000 * 60 * 60)
|
122
122
|
finally:
|
123
123
|
# Clean up log streaming
|
124
124
|
if stream_control:
|
@@ -126,8 +126,11 @@ class SandboxProcess(SandboxAction):
|
|
126
126
|
else:
|
127
127
|
# For non-blocking execution, set up log streaming immediately if requested
|
128
128
|
if on_log is not None:
|
129
|
-
|
130
|
-
|
129
|
+
stream_control = self.stream_logs(result.pid, {"on_log": on_log})
|
130
|
+
return ProcessResponseWithLog(
|
131
|
+
result, lambda: stream_control["close"]() if stream_control else None
|
132
|
+
)
|
133
|
+
|
131
134
|
return result
|
132
135
|
|
133
136
|
async def wait(
|
blaxel/core/sandbox/sandbox.py
CHANGED
@@ -47,7 +47,7 @@ class SandboxInstance:
|
|
47
47
|
def spec(self):
|
48
48
|
return self.sandbox.spec
|
49
49
|
|
50
|
-
async def wait(self, max_wait: int = 60000, interval: int = 1000) ->
|
50
|
+
async def wait(self, max_wait: int = 60000, interval: int = 1000) -> "SandboxInstance":
|
51
51
|
start_time = time.time() * 1000 # Convert to milliseconds
|
52
52
|
while self.sandbox.status != "DEPLOYED":
|
53
53
|
await asyncio.sleep(interval / 1000) # Convert to seconds
|
@@ -68,6 +68,17 @@ class SandboxInstance:
|
|
68
68
|
if (time.time() * 1000) - start_time > max_wait:
|
69
69
|
raise Exception("Sandbox did not deploy in time")
|
70
70
|
|
71
|
+
if self.sandbox.status == "DEPLOYED":
|
72
|
+
try:
|
73
|
+
# This is a hack for sometime receiving a 502,
|
74
|
+
# need to remove this once we have a better way to handle this
|
75
|
+
await self.fs.ls("/")
|
76
|
+
except:
|
77
|
+
# pass
|
78
|
+
pass
|
79
|
+
|
80
|
+
return self
|
81
|
+
|
71
82
|
@classmethod
|
72
83
|
async def create(
|
73
84
|
cls, sandbox: Union[Sandbox, SandboxCreateConfiguration, Dict[str, Any], None] = None
|
@@ -109,7 +120,9 @@ class SandboxInstance:
|
|
109
120
|
sandbox = Sandbox(
|
110
121
|
metadata=Metadata(name=name),
|
111
122
|
spec=SandboxSpec(
|
112
|
-
runtime=Runtime(
|
123
|
+
runtime=Runtime(
|
124
|
+
image=image, memory=memory, ports=ports, envs=envs, generation="mk3"
|
125
|
+
)
|
113
126
|
),
|
114
127
|
)
|
115
128
|
else:
|
blaxel/core/sandbox/types.py
CHANGED
@@ -6,6 +6,7 @@ from attrs import define as _attrs_define
|
|
6
6
|
from ..client.models import Port, Sandbox
|
7
7
|
from ..client.types import UNSET
|
8
8
|
from .client.models.process_request import ProcessRequest
|
9
|
+
from .client.models.process_response import ProcessResponse
|
9
10
|
|
10
11
|
|
11
12
|
class SessionCreateOptions:
|
@@ -182,3 +183,26 @@ class SandboxCreateConfiguration:
|
|
182
183
|
@_attrs_define
|
183
184
|
class ProcessRequestWithLog(ProcessRequest):
|
184
185
|
on_log: Callable[[str], None] = None
|
186
|
+
|
187
|
+
|
188
|
+
class ProcessResponseWithLog:
|
189
|
+
"""A process response with additional close functionality for stream management."""
|
190
|
+
|
191
|
+
def __init__(self, process_response: ProcessResponse, close_func: Callable[[], None]):
|
192
|
+
self._process_response = process_response
|
193
|
+
self._close_func = close_func
|
194
|
+
|
195
|
+
def close(self) -> None:
|
196
|
+
"""Close the log stream without terminating the process."""
|
197
|
+
self._close_func()
|
198
|
+
|
199
|
+
def __getattr__(self, name: str) -> Any:
|
200
|
+
"""Delegate attribute access to the underlying ProcessResponse."""
|
201
|
+
return getattr(self._process_response, name)
|
202
|
+
|
203
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
204
|
+
"""Handle setting attributes, preserving special attributes."""
|
205
|
+
if name.startswith("_") or name == "close":
|
206
|
+
super().__setattr__(name, value)
|
207
|
+
else:
|
208
|
+
setattr(self._process_response, name, value)
|
@@ -304,15 +304,15 @@ blaxel/core/mcp/__init__.py,sha256=5VjkiQFb1QWW5QKRgwPHARlxZJ9Xqaz0diJTpM8LLF0,1
|
|
304
304
|
blaxel/core/mcp/client.py,sha256=aK3wSnsO8DmT1BZqw4eiCMF71Jwvni6Qga0DhPP806Y,5437
|
305
305
|
blaxel/core/mcp/server.py,sha256=tXySGZKgK3IllYOzYOecp58BixKBkmAIvQp_4nSM_Ww,5919
|
306
306
|
blaxel/core/models/__init__.py,sha256=HbRDsMnUFHkPC-MMkzPXh4mUqkVjqO6p3j7m00N_XSo,1722
|
307
|
-
blaxel/core/sandbox/__init__.py,sha256=
|
307
|
+
blaxel/core/sandbox/__init__.py,sha256=sDsT9d6_bQvB-7dR6ZxODYrkzqQdQznhtXTfdqcSRLI,731
|
308
308
|
blaxel/core/sandbox/action.py,sha256=9Zjkco7YkLzBThD3N2Hr5SpeEiqU_-Ktk8HlKpkpiAg,2802
|
309
309
|
blaxel/core/sandbox/filesystem.py,sha256=dyIvDdlPZO0ijD6mXXX8Yl0t75VijQ6_uMz_9rJd-_4,11317
|
310
310
|
blaxel/core/sandbox/network.py,sha256=P5jLd4AAg1zgyIK4qGWvZaDZ5BzIcxRx2ffz_JLsLMI,357
|
311
311
|
blaxel/core/sandbox/preview.py,sha256=g0uVbMsIi8gRXmmyOfSyqm1qO4Cv6rsq92fs_k884dY,6120
|
312
|
-
blaxel/core/sandbox/process.py,sha256=
|
313
|
-
blaxel/core/sandbox/sandbox.py,sha256=
|
312
|
+
blaxel/core/sandbox/process.py,sha256=95fu9WU-CCdJcnHV8tYErkKTv5YoRcOqO68BH9NopvQ,8837
|
313
|
+
blaxel/core/sandbox/sandbox.py,sha256=J7wGqtelXZFk5XV99qTWSWS0TMHjo2C5qqZ7EYrD8j8,9036
|
314
314
|
blaxel/core/sandbox/session.py,sha256=3PfoekfdVzLYttsmKeK3MePhuprjqv_FDyVQTQME0OE,5277
|
315
|
-
blaxel/core/sandbox/types.py,sha256=
|
315
|
+
blaxel/core/sandbox/types.py,sha256=hf3WCk8P2e87jT4cJGuz3aZCihffun8bVb2k91YfVBU,6894
|
316
316
|
blaxel/core/sandbox/client/__init__.py,sha256=N26bD5o1jsTb48oExow6Rgivd8ylaU9jaWZfZsVilP8,128
|
317
317
|
blaxel/core/sandbox/client/client.py,sha256=tcP8cJ4Q3dV9aB3yQ01dDXO-ekfsa3WGGFz4DQAEf8I,7079
|
318
318
|
blaxel/core/sandbox/client/errors.py,sha256=gO8GBmKqmSNgAg-E5oT-oOyxztvp7V_6XG7OUTT15q0,546
|
@@ -402,7 +402,7 @@ blaxel/telemetry/instrumentation/map.py,sha256=PCzZJj39yiYVYJrxLBNP-NW-tjjYyTijw
|
|
402
402
|
blaxel/telemetry/instrumentation/utils.py,sha256=KInMYZH-mu9_wvetmf0EmgrfN3Sw8IWk2Y95v2u90_U,1901
|
403
403
|
blaxel/telemetry/log/log.py,sha256=RvQByRjZMoP_dRaAZu8oK6DTegsHs-xV4W-UIqis6CA,2461
|
404
404
|
blaxel/telemetry/log/logger.py,sha256=NPAS3g82ryROjvc_DEZaTIfrcehoLEZoP-JkLxADxc0,4113
|
405
|
-
blaxel-0.2.
|
406
|
-
blaxel-0.2.
|
407
|
-
blaxel-0.2.
|
408
|
-
blaxel-0.2.
|
405
|
+
blaxel-0.2.9.dist-info/METADATA,sha256=9bQ896L9Q_2VbaSu0vqkvYf_vJ8KAtnn4RKyOFFGlm4,9875
|
406
|
+
blaxel-0.2.9.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
407
|
+
blaxel-0.2.9.dist-info/licenses/LICENSE,sha256=p5PNQvpvyDT_0aYBDgmV1fFI_vAD2aSV0wWG7VTgRis,1069
|
408
|
+
blaxel-0.2.9.dist-info/RECORD,,
|
File without changes
|
File without changes
|