blaxel 0.2.31__py3-none-any.whl → 0.2.31rc121__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.
Files changed (174) hide show
  1. blaxel/__init__.py +3 -3
  2. blaxel/core/agents/__init__.py +6 -13
  3. blaxel/core/authentication/__init__.py +1 -2
  4. blaxel/core/authentication/devicemode.py +1 -9
  5. blaxel/core/authentication/oauth.py +6 -13
  6. blaxel/core/authentication/types.py +0 -1
  7. blaxel/core/cache/cache.py +3 -10
  8. blaxel/core/client/api/agents/list_agent_revisions.py +1 -3
  9. blaxel/core/client/api/compute/delete_sandbox_preview_token.py +2 -6
  10. blaxel/core/client/api/compute/start_sandbox.py +1 -3
  11. blaxel/core/client/api/compute/stop_sandbox.py +1 -3
  12. blaxel/core/client/api/default/list_sandbox_hub_definitions.py +2 -6
  13. blaxel/core/client/api/functions/list_function_revisions.py +1 -3
  14. blaxel/core/client/api/images/cleanup_images.py +1 -3
  15. blaxel/core/client/api/integrations/list_integration_connections.py +2 -6
  16. blaxel/core/client/api/invitations/list_all_pending_invitations.py +1 -3
  17. blaxel/core/client/api/jobs/create_job_execution.py +1 -3
  18. blaxel/core/client/api/jobs/delete_job_execution.py +1 -3
  19. blaxel/core/client/api/jobs/get_job_execution.py +1 -3
  20. blaxel/core/client/api/jobs/list_job_executions.py +2 -6
  21. blaxel/core/client/api/jobs/list_job_revisions.py +1 -3
  22. blaxel/core/client/api/locations/list_locations.py +1 -3
  23. blaxel/core/client/api/models/list_model_revisions.py +1 -3
  24. blaxel/core/client/api/service_accounts/create_workspace_service_account.py +2 -6
  25. blaxel/core/client/api/service_accounts/delete_workspace_service_account.py +2 -6
  26. blaxel/core/client/api/service_accounts/get_workspace_service_accounts.py +1 -3
  27. blaxel/core/client/api/service_accounts/update_workspace_service_account.py +2 -6
  28. blaxel/core/client/api/volume_templates/list_volume_templates.py +1 -3
  29. blaxel/core/client/api/workspaces/accept_workspace_invitation.py +2 -6
  30. blaxel/core/client/api/workspaces/invite_workspace_user.py +2 -6
  31. blaxel/core/client/api/workspaces/update_workspace_user_role.py +2 -6
  32. blaxel/core/client/client.py +1 -3
  33. blaxel/core/client/models/agent.py +4 -11
  34. blaxel/core/client/models/agent_spec.py +5 -18
  35. blaxel/core/client/models/billable_time_metric.py +1 -0
  36. blaxel/core/client/models/configuration.py +1 -0
  37. blaxel/core/client/models/core_spec.py +3 -10
  38. blaxel/core/client/models/core_spec_configurations.py +1 -0
  39. blaxel/core/client/models/create_job_execution_request.py +1 -0
  40. blaxel/core/client/models/create_job_execution_response.py +1 -0
  41. blaxel/core/client/models/custom_domain.py +2 -5
  42. blaxel/core/client/models/custom_domain_metadata.py +1 -0
  43. blaxel/core/client/models/custom_domain_spec.py +2 -5
  44. blaxel/core/client/models/delete_volume_template_version_response_200.py +2 -5
  45. blaxel/core/client/models/entrypoint.py +1 -0
  46. blaxel/core/client/models/form.py +2 -5
  47. blaxel/core/client/models/function.py +4 -11
  48. blaxel/core/client/models/function_spec.py +4 -13
  49. blaxel/core/client/models/image.py +2 -5
  50. blaxel/core/client/models/image_spec.py +1 -0
  51. blaxel/core/client/models/integration.py +3 -10
  52. blaxel/core/client/models/integration_connection.py +2 -5
  53. blaxel/core/client/models/integration_connection_spec.py +1 -0
  54. blaxel/core/client/models/integration_endpoint.py +2 -5
  55. blaxel/core/client/models/integration_endpoints.py +2 -0
  56. blaxel/core/client/models/job.py +4 -11
  57. blaxel/core/client/models/job_execution.py +2 -5
  58. blaxel/core/client/models/job_execution_spec.py +1 -0
  59. blaxel/core/client/models/job_execution_task.py +2 -5
  60. blaxel/core/client/models/job_metrics.py +2 -5
  61. blaxel/core/client/models/job_spec.py +4 -13
  62. blaxel/core/client/models/jobs_network_chart.py +1 -0
  63. blaxel/core/client/models/jobs_success_failed_chart.py +3 -10
  64. blaxel/core/client/models/latency_metric.py +2 -5
  65. blaxel/core/client/models/location_response.py +1 -0
  66. blaxel/core/client/models/mcp_definition.py +2 -5
  67. blaxel/core/client/models/metadata.py +1 -0
  68. blaxel/core/client/models/metrics.py +4 -11
  69. blaxel/core/client/models/model.py +4 -11
  70. blaxel/core/client/models/model_spec.py +3 -10
  71. blaxel/core/client/models/pending_invitation_accept.py +2 -5
  72. blaxel/core/client/models/pending_invitation_render.py +3 -10
  73. blaxel/core/client/models/policy.py +2 -5
  74. blaxel/core/client/models/policy_spec.py +4 -11
  75. blaxel/core/client/models/preview.py +2 -5
  76. blaxel/core/client/models/preview_spec.py +1 -0
  77. blaxel/core/client/models/preview_token.py +2 -5
  78. blaxel/core/client/models/public_ips.py +1 -0
  79. blaxel/core/client/models/request_duration_over_time_metrics.py +1 -0
  80. blaxel/core/client/models/request_total_by_origin_metric.py +7 -16
  81. blaxel/core/client/models/request_total_metric.py +3 -8
  82. blaxel/core/client/models/resource_metrics.py +17 -58
  83. blaxel/core/client/models/runtime.py +1 -0
  84. blaxel/core/client/models/sandbox.py +4 -11
  85. blaxel/core/client/models/sandbox_definition.py +1 -0
  86. blaxel/core/client/models/sandbox_lifecycle.py +1 -0
  87. blaxel/core/client/models/sandbox_spec.py +6 -21
  88. blaxel/core/client/models/serverless_config.py +1 -0
  89. blaxel/core/client/models/start_sandbox.py +2 -5
  90. blaxel/core/client/models/stop_sandbox.py +2 -5
  91. blaxel/core/client/models/store_agent.py +1 -0
  92. blaxel/core/client/models/store_configuration.py +1 -0
  93. blaxel/core/client/models/template.py +1 -0
  94. blaxel/core/client/models/time_to_first_token_over_time_metrics.py +2 -3
  95. blaxel/core/client/models/token_rate_metrics.py +1 -0
  96. blaxel/core/client/models/trigger.py +1 -0
  97. blaxel/core/client/models/trigger_configuration.py +1 -0
  98. blaxel/core/client/models/volume.py +4 -11
  99. blaxel/core/client/models/volume_template.py +2 -5
  100. blaxel/core/client/models/workspace.py +2 -5
  101. blaxel/core/client/response_interceptor.py +1 -3
  102. blaxel/core/common/autoload.py +11 -9
  103. blaxel/core/common/env.py +8 -10
  104. blaxel/core/common/settings.py +2 -4
  105. blaxel/core/common/webhook.py +1 -0
  106. blaxel/core/jobs/__init__.py +3 -13
  107. blaxel/core/mcp/client.py +2 -8
  108. blaxel/core/mcp/server.py +2 -8
  109. blaxel/core/models/__init__.py +5 -6
  110. blaxel/core/sandbox/__init__.py +1 -1
  111. blaxel/core/sandbox/client/api/codegen/get_codegen_reranking_path.py +2 -6
  112. blaxel/core/sandbox/client/api/fastapply/put_codegen_fastapply_path.py +2 -6
  113. blaxel/core/sandbox/client/api/filesystem/delete_filesystem_multipart_upload_id_abort.py +2 -6
  114. blaxel/core/sandbox/client/api/filesystem/delete_filesystem_path.py +2 -6
  115. blaxel/core/sandbox/client/api/filesystem/delete_filesystem_tree_path.py +2 -6
  116. blaxel/core/sandbox/client/api/filesystem/get_filesystem_content_search_path.py +1 -3
  117. blaxel/core/sandbox/client/api/filesystem/get_filesystem_find_path.py +2 -6
  118. blaxel/core/sandbox/client/api/filesystem/get_filesystem_search_path.py +2 -6
  119. blaxel/core/sandbox/client/api/filesystem/get_watch_filesystem_path.py +2 -6
  120. blaxel/core/sandbox/client/api/filesystem/post_filesystem_multipart_upload_id_complete.py +2 -6
  121. blaxel/core/sandbox/client/api/filesystem/put_filesystem_path.py +2 -6
  122. blaxel/core/sandbox/client/api/process/delete_process_identifier.py +2 -6
  123. blaxel/core/sandbox/client/api/process/delete_process_identifier_kill.py +2 -6
  124. blaxel/core/sandbox/client/api/process/get_process.py +1 -3
  125. blaxel/core/sandbox/client/api/process/get_process_identifier.py +2 -6
  126. blaxel/core/sandbox/client/api/process/get_process_identifier_logs.py +2 -6
  127. blaxel/core/sandbox/client/api/process/get_process_identifier_logs_stream.py +2 -6
  128. blaxel/core/sandbox/client/api/process/post_process.py +2 -6
  129. blaxel/core/sandbox/client/client.py +1 -3
  130. blaxel/core/sandbox/client/models/filesystem_multipart_upload_parts.py +1 -3
  131. blaxel/core/sandbox/default/__init__.py +1 -0
  132. blaxel/core/sandbox/default/action.py +3 -3
  133. blaxel/core/sandbox/default/codegen.py +4 -2
  134. blaxel/core/sandbox/default/filesystem.py +82 -38
  135. blaxel/core/sandbox/default/interpreter.py +10 -17
  136. blaxel/core/sandbox/default/preview.py +2 -6
  137. blaxel/core/sandbox/default/process.py +7 -25
  138. blaxel/core/sandbox/default/sandbox.py +2 -7
  139. blaxel/core/sandbox/sync/__init__.py +2 -0
  140. blaxel/core/sandbox/sync/action.py +3 -2
  141. blaxel/core/sandbox/sync/codegen.py +5 -1
  142. blaxel/core/sandbox/sync/filesystem.py +6 -17
  143. blaxel/core/sandbox/sync/interpreter.py +6 -10
  144. blaxel/core/sandbox/sync/network.py +2 -0
  145. blaxel/core/sandbox/sync/preview.py +9 -21
  146. blaxel/core/sandbox/sync/process.py +8 -32
  147. blaxel/core/sandbox/sync/sandbox.py +6 -13
  148. blaxel/core/sandbox/sync/session.py +4 -6
  149. blaxel/core/sandbox/types.py +1 -2
  150. blaxel/core/tools/__init__.py +6 -30
  151. blaxel/core/tools/common.py +1 -1
  152. blaxel/core/tools/types.py +1 -2
  153. blaxel/crewai/model.py +5 -20
  154. blaxel/googleadk/__init__.py +1 -1
  155. blaxel/googleadk/tools.py +5 -3
  156. blaxel/langgraph/custom/gemini.py +133 -126
  157. blaxel/langgraph/model.py +50 -54
  158. blaxel/langgraph/tools.py +3 -9
  159. blaxel/llamaindex/custom/cohere.py +16 -25
  160. blaxel/llamaindex/model.py +57 -44
  161. blaxel/llamaindex/tools.py +3 -2
  162. blaxel/pydantic/custom/gemini.py +3 -3
  163. blaxel/pydantic/tools.py +4 -2
  164. blaxel/telemetry/exporters.py +3 -10
  165. blaxel/telemetry/instrumentation/blaxel_langgraph.py +2 -4
  166. blaxel/telemetry/instrumentation/blaxel_langgraph_gemini.py +5 -22
  167. blaxel/telemetry/instrumentation/utils.py +3 -3
  168. blaxel/telemetry/log/log.py +3 -2
  169. blaxel/telemetry/log/logger.py +15 -21
  170. blaxel/telemetry/span.py +6 -10
  171. {blaxel-0.2.31.dist-info → blaxel-0.2.31rc121.dist-info}/METADATA +2 -2
  172. {blaxel-0.2.31.dist-info → blaxel-0.2.31rc121.dist-info}/RECORD +174 -174
  173. {blaxel-0.2.31.dist-info → blaxel-0.2.31rc121.dist-info}/WHEEL +0 -0
  174. {blaxel-0.2.31.dist-info → blaxel-0.2.31rc121.dist-info}/licenses/LICENSE +0 -0
@@ -15,15 +15,11 @@ from ...client.api.compute.delete_sandbox_preview import (
15
15
  from ...client.api.compute.delete_sandbox_preview_token import (
16
16
  asyncio as delete_sandbox_preview_token,
17
17
  )
18
- from ...client.api.compute.get_sandbox_preview import (
19
- asyncio as get_sandbox_preview,
20
- )
18
+ from ...client.api.compute.get_sandbox_preview import asyncio as get_sandbox_preview
21
19
  from ...client.api.compute.list_sandbox_preview_tokens import (
22
20
  asyncio as list_sandbox_preview_tokens,
23
21
  )
24
- from ...client.api.compute.list_sandbox_previews import (
25
- asyncio as list_sandbox_previews,
26
- )
22
+ from ...client.api.compute.list_sandbox_previews import asyncio as list_sandbox_previews
27
23
  from ...client.client import client
28
24
  from ...client.models import (
29
25
  Preview,
@@ -6,11 +6,7 @@ import httpx
6
6
  from ...common.settings import settings
7
7
  from ..client.models import ProcessResponse, SuccessResponse
8
8
  from ..client.models.process_request import ProcessRequest
9
- from ..types import (
10
- ProcessRequestWithLog,
11
- ProcessResponseWithLog,
12
- SandboxConfiguration,
13
- )
9
+ from ..types import ProcessRequestWithLog, ProcessResponseWithLog, SandboxConfiguration
14
10
  from .action import SandboxAction
15
11
 
16
12
 
@@ -19,9 +15,7 @@ class SandboxProcess(SandboxAction):
19
15
  super().__init__(sandbox_config)
20
16
 
21
17
  def stream_logs(
22
- self,
23
- process_name: str,
24
- options: Dict[str, Callable[[str], None]] | None = None,
18
+ self, process_name: str, options: Dict[str, Callable[[str], None]] | None = None
25
19
  ) -> Dict[str, Callable[[], None]]:
26
20
  """Stream logs from a process with automatic reconnection and deduplication."""
27
21
  if options is None:
@@ -117,9 +111,7 @@ class SandboxProcess(SandboxAction):
117
111
  return {"close": close}
118
112
 
119
113
  def _stream_logs(
120
- self,
121
- identifier: str,
122
- options: Dict[str, Callable[[str], None]] | None = None,
114
+ self, identifier: str, options: Dict[str, Callable[[str], None]] | None = None
123
115
  ) -> Dict[str, Callable[[], None]]:
124
116
  """Private method to stream logs from a process with callbacks for different output types."""
125
117
  if options is None:
@@ -183,8 +175,7 @@ class SandboxProcess(SandboxAction):
183
175
  return {"close": close}
184
176
 
185
177
  async def exec(
186
- self,
187
- process: Union[ProcessRequest, ProcessRequestWithLog, Dict[str, Any]],
178
+ self, process: Union[ProcessRequest, ProcessRequestWithLog, Dict[str, Any]]
188
179
  ) -> Union[ProcessResponse, ProcessResponseWithLog]:
189
180
  """Execute a process in the sandbox."""
190
181
  on_log = None
@@ -209,14 +200,13 @@ class SandboxProcess(SandboxAction):
209
200
  # Always start process without wait_for_completion to avoid server-side blocking
210
201
  if should_wait_for_completion and on_log is not None:
211
202
  process.wait_for_completion = False
212
-
203
+
213
204
  client = self.get_client()
214
205
  response = await client.post("/process", json=process.to_dict())
215
206
  try:
216
207
  content_bytes = await response.aread()
217
208
  self.handle_response_error(response)
218
209
  import json
219
-
220
210
  response_data = json.loads(content_bytes) if content_bytes else None
221
211
  result = ProcessResponse.from_dict(response_data)
222
212
  finally:
@@ -237,8 +227,7 @@ class SandboxProcess(SandboxAction):
237
227
  if on_log is not None:
238
228
  stream_control = self._stream_logs(result.pid, {"on_log": on_log})
239
229
  return ProcessResponseWithLog(
240
- result,
241
- lambda: stream_control["close"]() if stream_control else None,
230
+ result, lambda: stream_control["close"]() if stream_control else None
242
231
  )
243
232
 
244
233
  return result
@@ -266,7 +255,6 @@ class SandboxProcess(SandboxAction):
266
255
 
267
256
  async def get(self, identifier: str) -> ProcessResponse:
268
257
  import json
269
-
270
258
  client = self.get_client()
271
259
  response = await client.get(f"/process/{identifier}")
272
260
  try:
@@ -278,7 +266,6 @@ class SandboxProcess(SandboxAction):
278
266
 
279
267
  async def list(self) -> list[ProcessResponse]:
280
268
  import json
281
-
282
269
  client = self.get_client()
283
270
  response = await client.get("/process")
284
271
  try:
@@ -290,7 +277,6 @@ class SandboxProcess(SandboxAction):
290
277
 
291
278
  async def stop(self, identifier: str) -> SuccessResponse:
292
279
  import json
293
-
294
280
  client = self.get_client()
295
281
  response = await client.delete(f"/process/{identifier}")
296
282
  try:
@@ -302,7 +288,6 @@ class SandboxProcess(SandboxAction):
302
288
 
303
289
  async def kill(self, identifier: str) -> SuccessResponse:
304
290
  import json
305
-
306
291
  client = self.get_client()
307
292
  response = await client.delete(f"/process/{identifier}/kill")
308
293
  try:
@@ -313,12 +298,9 @@ class SandboxProcess(SandboxAction):
313
298
  await response.aclose()
314
299
 
315
300
  async def logs(
316
- self,
317
- identifier: str,
318
- log_type: Literal["stdout", "stderr", "all"] = "all",
301
+ self, identifier: str, log_type: Literal["stdout", "stderr", "all"] = "all"
319
302
  ) -> str:
320
303
  import json
321
-
322
304
  client = self.get_client()
323
305
  response = await client.get(f"/process/{identifier}/logs")
324
306
  try:
@@ -105,8 +105,7 @@ class SandboxInstance:
105
105
  or "expires" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
106
106
  or "region" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
107
107
  or "lifecycle" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
108
- or "snapshot_enabled"
109
- in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
108
+ or "snapshot_enabled" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
110
109
  )
111
110
  )
112
111
  ):
@@ -133,11 +132,7 @@ class SandboxInstance:
133
132
  metadata=Metadata(name=name),
134
133
  spec=SandboxSpec(
135
134
  runtime=Runtime(
136
- image=image,
137
- memory=memory,
138
- ports=ports,
139
- envs=envs,
140
- generation="mk3",
135
+ image=image, memory=memory, ports=ports, envs=envs, generation="mk3"
141
136
  ),
142
137
  volumes=volumes,
143
138
  ),
@@ -15,3 +15,5 @@ __all__ = [
15
15
  "SyncSandboxCodegen",
16
16
  "SyncCodeInterpreter",
17
17
  ]
18
+
19
+
@@ -51,8 +51,7 @@ class SyncSandboxAction:
51
51
  def get_client(self) -> httpx.Client:
52
52
  if self.sandbox_config.force_url:
53
53
  return httpx.Client(
54
- base_url=self.sandbox_config.force_url,
55
- headers=self.sandbox_config.headers,
54
+ base_url=self.sandbox_config.force_url, headers=self.sandbox_config.headers
56
55
  )
57
56
  return httpx.Client(
58
57
  base_url=self.url,
@@ -62,3 +61,5 @@ class SyncSandboxAction:
62
61
  def handle_response_error(self, response: httpx.Response):
63
62
  if not response.is_success:
64
63
  raise ResponseError(response)
64
+
65
+
@@ -20,7 +20,9 @@ class SyncSandboxCodegen(SyncSandboxAction):
20
20
  def __init__(self, sandbox_config: SandboxConfiguration):
21
21
  super().__init__(sandbox_config)
22
22
 
23
- def fastapply(self, path: str, code_edit: str, model: str | None = None) -> ApplyEditResponse:
23
+ def fastapply(
24
+ self, path: str, code_edit: str, model: str | None = None
25
+ ) -> ApplyEditResponse:
24
26
  body = ApplyEditRequest(code_edit=code_edit, model=model)
25
27
  client = Client(
26
28
  base_url=self.url,
@@ -64,3 +66,5 @@ class SyncSandboxCodegen(SyncSandboxAction):
64
66
  if isinstance(response, ErrorResponse):
65
67
  raise Exception(f"Reranking failed: {response}")
66
68
  return response
69
+
70
+
@@ -61,11 +61,7 @@ class SyncSandboxFileSystem(SyncSandboxAction):
61
61
  return self._upload_with_multipart(path, content, "0644")
62
62
  binary_file = io.BytesIO(content)
63
63
  files = {
64
- "file": (
65
- "binary-file.bin",
66
- binary_file,
67
- "application/octet-stream",
68
- ),
64
+ "file": ("binary-file.bin", binary_file, "application/octet-stream"),
69
65
  }
70
66
  data = {"permissions": "0644", "path": path}
71
67
  url = f"{self.url}/filesystem/{path}"
@@ -199,10 +195,7 @@ class SyncSandboxFileSystem(SyncSandboxAction):
199
195
  name=file_event_data.get("name", ""),
200
196
  content=file_event_data.get("content"),
201
197
  )
202
- if options.get("with_content") and file_event.op in [
203
- "CREATE",
204
- "WRITE",
205
- ]:
198
+ if options.get("with_content") and file_event.op in ["CREATE", "WRITE"]:
206
199
  try:
207
200
  file_path = file_event.path
208
201
  if file_path.endswith("/"):
@@ -251,9 +244,7 @@ class SyncSandboxFileSystem(SyncSandboxAction):
251
244
  self.handle_response_error(response)
252
245
  return response.json()
253
246
 
254
- def _complete_multipart_upload(
255
- self, upload_id: str, parts: List[Dict[str, Any]]
256
- ) -> SuccessResponse:
247
+ def _complete_multipart_upload(self, upload_id: str, parts: List[Dict[str, Any]]) -> SuccessResponse:
257
248
  url = f"{self.url}/filesystem-multipart/{upload_id}/complete"
258
249
  headers = {**settings.headers, **self.sandbox_config.headers}
259
250
  body = {"parts": parts}
@@ -270,9 +261,7 @@ class SyncSandboxFileSystem(SyncSandboxAction):
270
261
  if not response.is_success:
271
262
  logger.warning(f"Failed to abort multipart upload: {response.status_code}")
272
263
 
273
- def _upload_with_multipart(
274
- self, path: str, data: bytes, permissions: str = "0644"
275
- ) -> SuccessResponse:
264
+ def _upload_with_multipart(self, path: str, data: bytes, permissions: str = "0644") -> SuccessResponse:
276
265
  init_response = self._initiate_multipart_upload(path, permissions)
277
266
  upload_id = init_response.get("uploadId")
278
267
  if not upload_id:
@@ -285,10 +274,8 @@ class SyncSandboxFileSystem(SyncSandboxAction):
285
274
  for i in range(0, num_parts, MAX_PARALLEL_UPLOADS):
286
275
  threads = []
287
276
  results: Dict[int, Dict[str, Any]] = {}
288
-
289
277
  def make_upload(part_number: int, chunk: bytes):
290
278
  results[part_number] = self._upload_part(upload_id, part_number, chunk)
291
-
292
279
  for j in range(MAX_PARALLEL_UPLOADS):
293
280
  if i + j >= num_parts:
294
281
  break
@@ -311,3 +298,5 @@ class SyncSandboxFileSystem(SyncSandboxAction):
311
298
  except Exception as abort_error:
312
299
  logger.warning(f"Failed to abort multipart upload: {abort_error}")
313
300
  raise error
301
+
302
+
@@ -15,9 +15,7 @@ class SyncCodeInterpreter(SyncSandboxInstance):
15
15
  DEFAULT_PORTS = [
16
16
  {"name": "jupyter", "target": 8888, "protocol": "HTTP"},
17
17
  ]
18
- DEFAULT_LIFECYCLE = {
19
- "expirationPolicies": [{"type": "ttl-idle", "value": "30m", "action": "delete"}]
20
- }
18
+ DEFAULT_LIFECYCLE = {"expirationPolicies": [{ "type": "ttl-idle", "value": "30m", "action": "delete" }]}
21
19
 
22
20
  @classmethod
23
21
  def get(cls, sandbox_name: str) -> "SyncCodeInterpreter":
@@ -223,10 +221,7 @@ class SyncCodeInterpreter(SyncSandboxInstance):
223
221
  # Use the process client to inherit base_url and headers
224
222
  with self.process.get_client() as client:
225
223
  timeout_cfg = httpx.Timeout(
226
- connect=connect_timeout,
227
- read=read_timeout,
228
- write=write_timeout,
229
- pool=pool_timeout,
224
+ connect=connect_timeout, read=read_timeout, write=write_timeout, pool=pool_timeout
230
225
  )
231
226
  with client.stream(
232
227
  "POST",
@@ -243,9 +238,7 @@ class SyncCodeInterpreter(SyncSandboxInstance):
243
238
  if not line:
244
239
  continue
245
240
  try:
246
- decoded = (
247
- line.decode() if isinstance(line, bytes | bytearray) else str(line)
248
- )
241
+ decoded = line.decode() if isinstance(line, bytes | bytearray) else str(line)
249
242
  except Exception:
250
243
  decoded = str(line)
251
244
  try:
@@ -277,6 +270,7 @@ class SyncCodeInterpreter(SyncSandboxInstance):
277
270
  if cwd:
278
271
  data["cwd"] = cwd
279
272
 
273
+
280
274
  with self.process.get_client() as client:
281
275
  response = client.post(
282
276
  "/port/8888/contexts",
@@ -289,3 +283,5 @@ class SyncCodeInterpreter(SyncSandboxInstance):
289
283
  raise RuntimeError(details)
290
284
  data = response.json()
291
285
  return SyncCodeInterpreter.Context.from_json(data)
286
+
287
+
@@ -7,3 +7,5 @@ class SyncSandboxNetwork(SyncSandboxAction):
7
7
  super().__init__(sandbox_config)
8
8
 
9
9
  # Placeholder for future sync network operations
10
+
11
+
@@ -3,27 +3,13 @@ from datetime import datetime
3
3
  from typing import Any, Dict, List, Union
4
4
 
5
5
  from ...client import errors
6
- from ...client.api.compute.create_sandbox_preview import (
7
- sync as create_sandbox_preview,
8
- )
9
- from ...client.api.compute.create_sandbox_preview_token import (
10
- sync as create_sandbox_preview_token,
11
- )
12
- from ...client.api.compute.delete_sandbox_preview import (
13
- sync as delete_sandbox_preview,
14
- )
15
- from ...client.api.compute.delete_sandbox_preview_token import (
16
- sync as delete_sandbox_preview_token,
17
- )
18
- from ...client.api.compute.get_sandbox_preview import (
19
- sync as get_sandbox_preview,
20
- )
21
- from ...client.api.compute.list_sandbox_preview_tokens import (
22
- sync as list_sandbox_preview_tokens,
23
- )
24
- from ...client.api.compute.list_sandbox_previews import (
25
- sync as list_sandbox_previews,
26
- )
6
+ from ...client.api.compute.create_sandbox_preview import sync as create_sandbox_preview
7
+ from ...client.api.compute.create_sandbox_preview_token import sync as create_sandbox_preview_token
8
+ from ...client.api.compute.delete_sandbox_preview import sync as delete_sandbox_preview
9
+ from ...client.api.compute.delete_sandbox_preview_token import sync as delete_sandbox_preview_token
10
+ from ...client.api.compute.get_sandbox_preview import sync as get_sandbox_preview
11
+ from ...client.api.compute.list_sandbox_preview_tokens import sync as list_sandbox_preview_tokens
12
+ from ...client.api.compute.list_sandbox_previews import sync as list_sandbox_previews
27
13
  from ...client.client import client
28
14
  from ...client.models import (
29
15
  Preview,
@@ -169,3 +155,5 @@ def to_utc_z(dt: datetime) -> str:
169
155
  elif "T" in iso_string and not iso_string.endswith("Z"):
170
156
  return iso_string + "Z"
171
157
  return iso_string
158
+
159
+
@@ -7,11 +7,7 @@ import httpx
7
7
  from ...common.settings import settings
8
8
  from ..client.models import ProcessResponse, SuccessResponse
9
9
  from ..client.models.process_request import ProcessRequest
10
- from ..types import (
11
- ProcessRequestWithLog,
12
- ProcessResponseWithLog,
13
- SandboxConfiguration,
14
- )
10
+ from ..types import ProcessRequestWithLog, ProcessResponseWithLog, SandboxConfiguration
15
11
  from .action import SyncSandboxAction
16
12
 
17
13
 
@@ -20,9 +16,7 @@ class SyncSandboxProcess(SyncSandboxAction):
20
16
  super().__init__(sandbox_config)
21
17
 
22
18
  def stream_logs(
23
- self,
24
- process_name: str,
25
- options: Dict[str, Callable[[str], None]] | None = None,
19
+ self, process_name: str, options: Dict[str, Callable[[str], None]] | None = None
26
20
  ) -> Dict[str, Callable[[], None]]:
27
21
  if options is None:
28
22
  options = {}
@@ -37,7 +31,6 @@ class SyncSandboxProcess(SyncSandboxAction):
37
31
  def start_stream():
38
32
  nonlocal current_close
39
33
  log_counter = [0]
40
-
41
34
  def make_dedup(cb_key: str):
42
35
  def inner(content: str):
43
36
  key = f"{log_counter[0]}:{content}"
@@ -46,9 +39,7 @@ class SyncSandboxProcess(SyncSandboxAction):
46
39
  seen_logs.add(key)
47
40
  if options.get(cb_key):
48
41
  options[cb_key](content)
49
-
50
42
  return inner
51
-
52
43
  wrapped_options: Dict[str, Callable[[str], None]] = {}
53
44
  if "on_log" in options:
54
45
  wrapped_options["on_log"] = make_dedup("on_log")
@@ -59,11 +50,9 @@ class SyncSandboxProcess(SyncSandboxAction):
59
50
  if current_close["fn"]:
60
51
  current_close["fn"]()
61
52
  current_close["fn"] = self._stream_logs(process_name, wrapped_options)["close"]
62
-
63
53
  def schedule():
64
54
  if is_running.is_set():
65
55
  start_stream()
66
-
67
56
  with timer_lock:
68
57
  if reconnect_timer["t"]:
69
58
  reconnect_timer["t"].cancel()
@@ -71,9 +60,7 @@ class SyncSandboxProcess(SyncSandboxAction):
71
60
  reconnect_timer["t"] = t
72
61
  t.daemon = True
73
62
  t.start()
74
-
75
63
  start_stream()
76
-
77
64
  def close():
78
65
  is_running.clear()
79
66
  with timer_lock:
@@ -84,18 +71,14 @@ class SyncSandboxProcess(SyncSandboxAction):
84
71
  current_close["fn"]()
85
72
  current_close["fn"] = None
86
73
  seen_logs.clear()
87
-
88
74
  return {"close": close}
89
75
 
90
76
  def _stream_logs(
91
- self,
92
- identifier: str,
93
- options: Dict[str, Callable[[str], None]] | None = None,
77
+ self, identifier: str, options: Dict[str, Callable[[str], None]] | None = None
94
78
  ) -> Dict[str, Callable[[], None]]:
95
79
  if options is None:
96
80
  options = {}
97
81
  closed = threading.Event()
98
-
99
82
  def run():
100
83
  url = f"{self.url}/process/{identifier}/logs/stream"
101
84
  headers = {**settings.headers, **self.sandbox_config.headers}
@@ -133,18 +116,14 @@ class SyncSandboxProcess(SyncSandboxAction):
133
116
  # Ignore on close
134
117
  if not closed.is_set():
135
118
  raise e
136
-
137
119
  thread = threading.Thread(target=run, daemon=True)
138
120
  thread.start()
139
-
140
121
  def close():
141
122
  closed.set()
142
-
143
123
  return {"close": close}
144
124
 
145
125
  def exec(
146
- self,
147
- process: Union[ProcessRequest, ProcessRequestWithLog, Dict[str, Any]],
126
+ self, process: Union[ProcessRequest, ProcessRequestWithLog, Dict[str, Any]]
148
127
  ) -> Union[ProcessResponse, ProcessResponseWithLog]:
149
128
  on_log = None
150
129
  if isinstance(process, ProcessRequestWithLog):
@@ -185,8 +164,7 @@ class SyncSandboxProcess(SyncSandboxAction):
185
164
  if on_log is not None:
186
165
  stream_control = self._stream_logs(result.pid, {"on_log": on_log})
187
166
  return ProcessResponseWithLog(
188
- result,
189
- lambda: stream_control["close"]() if stream_control else None,
167
+ result, lambda: stream_control["close"]() if stream_control else None
190
168
  )
191
169
  return result
192
170
 
@@ -229,11 +207,7 @@ class SyncSandboxProcess(SyncSandboxAction):
229
207
  self.handle_response_error(response)
230
208
  return SuccessResponse.from_dict(response.json())
231
209
 
232
- def logs(
233
- self,
234
- identifier: str,
235
- log_type: Literal["stdout", "stderr", "all"] = "all",
236
- ) -> str:
210
+ def logs(self, identifier: str, log_type: Literal["stdout", "stderr", "all"] = "all") -> str:
237
211
  with self.get_client() as client_instance:
238
212
  response = client_instance.get(f"/process/{identifier}/logs")
239
213
  self.handle_response_error(response)
@@ -245,3 +219,5 @@ class SyncSandboxProcess(SyncSandboxAction):
245
219
  elif log_type == "stderr":
246
220
  return data.get("stderr", "")
247
221
  raise Exception("Unsupported log type")
222
+
223
+
@@ -100,8 +100,7 @@ class SyncSandboxInstance:
100
100
  or "expires" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
101
101
  or "region" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
102
102
  or "lifecycle" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
103
- or "snapshot_enabled"
104
- in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
103
+ or "snapshot_enabled" in (sandbox if isinstance(sandbox, dict) else sandbox.__dict__)
105
104
  )
106
105
  )
107
106
  ):
@@ -123,11 +122,7 @@ class SyncSandboxInstance:
123
122
  metadata=Metadata(name=name),
124
123
  spec=SandboxSpec(
125
124
  runtime=Runtime(
126
- image=image,
127
- memory=memory,
128
- ports=ports,
129
- envs=envs,
130
- generation="mk3",
125
+ image=image, memory=memory, ports=ports, envs=envs, generation="mk3"
131
126
  ),
132
127
  volumes=volumes,
133
128
  ),
@@ -188,9 +183,7 @@ class SyncSandboxInstance:
188
183
  return response
189
184
 
190
185
  @classmethod
191
- def update_metadata(
192
- cls, sandbox_name: str, metadata: SandboxUpdateMetadata
193
- ) -> "SyncSandboxInstance":
186
+ def update_metadata(cls, sandbox_name: str, metadata: SandboxUpdateMetadata) -> "SyncSandboxInstance":
194
187
  sandbox_instance = cls.get(sandbox_name)
195
188
  sandbox = sandbox_instance.sandbox
196
189
  updated_sandbox = Sandbox.from_dict(sandbox.to_dict())
@@ -243,9 +236,7 @@ class SyncSandboxInstance:
243
236
  raise e
244
237
 
245
238
  @classmethod
246
- def from_session(
247
- cls, session: Union[SessionWithToken, Dict[str, Any]]
248
- ) -> "SyncSandboxInstance":
239
+ def from_session(cls, session: Union[SessionWithToken, Dict[str, Any]]) -> "SyncSandboxInstance":
249
240
  if isinstance(session, dict):
250
241
  session = SessionWithToken.from_dict(session)
251
242
  sandbox_name = session.name.split("-")[0] if "-" in session.name else session.name
@@ -256,3 +247,5 @@ class SyncSandboxInstance:
256
247
  headers={"X-Blaxel-Preview-Token": session.token},
257
248
  params={"bl_preview_token": session.token},
258
249
  )
250
+
251
+
@@ -22,9 +22,7 @@ class SyncSandboxSessions:
22
22
  def sandbox_name(self) -> str:
23
23
  return self.sandbox_config.metadata.name if self.sandbox_config.metadata else ""
24
24
 
25
- def create(
26
- self, options: Union[SessionCreateOptions, Dict[str, Any]] | None = None
27
- ) -> SessionWithToken:
25
+ def create(self, options: Union[SessionCreateOptions, Dict[str, Any]] | None = None) -> SessionWithToken:
28
26
  if options is None:
29
27
  options = SessionCreateOptions()
30
28
  elif isinstance(options, dict):
@@ -114,9 +112,9 @@ class SyncSandboxSessions:
114
112
  return delete_sandbox_preview.sync(self.sandbox_name, name, client=client)
115
113
 
116
114
  def get_token(self, preview_name: str):
117
- tokens_response = list_sandbox_preview_tokens.sync(
118
- self.sandbox_name, preview_name, client=client
119
- )
115
+ tokens_response = list_sandbox_preview_tokens.sync(self.sandbox_name, preview_name, client=client)
120
116
  if not tokens_response:
121
117
  return None
122
118
  return tokens_response[0]
119
+
120
+
@@ -148,8 +148,7 @@ class SandboxCreateConfiguration:
148
148
  memory: int | None = None,
149
149
  ports: Union[List[Port], List[Dict[str, Any]]] | None = None,
150
150
  envs: List[Dict[str, str]] | None = None,
151
- volumes: Union[List[VolumeBinding], List[VolumeAttachment], List[Dict[str, Any]]]
152
- | None = None,
151
+ volumes: Union[List[VolumeBinding], List[VolumeAttachment], List[Dict[str, Any]]] | None = None,
153
152
  ttl: str | None = None,
154
153
  expires: datetime | None = None,
155
154
  region: str | None = None,
@@ -8,12 +8,7 @@ from typing import Any, cast
8
8
  import httpx
9
9
  from mcp import ClientSession
10
10
  from mcp.client.streamable_http import streamablehttp_client
11
- from mcp.types import (
12
- CallToolRequest,
13
- CallToolRequestParams,
14
- CallToolResult,
15
- ClientRequest,
16
- )
11
+ from mcp.types import CallToolRequest, CallToolRequestParams, CallToolResult, ClientRequest
17
12
  from mcp.types import Tool as MCPTool
18
13
 
19
14
  from ..common.internal import get_forced_url, get_global_unique_hash
@@ -29,13 +24,7 @@ if os.getenv("BL_SERVER_PORT"):
29
24
 
30
25
 
31
26
  class PersistentMcpClient:
32
- def __init__(
33
- self,
34
- name: str,
35
- timeout: int = DEFAULT_TIMEOUT,
36
- timeout_enabled: bool = True,
37
- transport: str = None,
38
- ):
27
+ def __init__(self, name: str, timeout: int = DEFAULT_TIMEOUT, timeout_enabled: bool = True, transport: str = None):
39
28
  self.name = name
40
29
  self.timeout = timeout
41
30
  self.type = "function"
@@ -108,9 +97,7 @@ class PersistentMcpClient:
108
97
  await self.initialize()
109
98
  if self.timeout_enabled:
110
99
  self._remove_timer()
111
- logger.debug(
112
- f"Calling tool {tool_name} with arguments {arguments} and meta {self.metas}"
113
- )
100
+ logger.debug(f"Calling tool {tool_name} with arguments {arguments} and meta {self.metas}")
114
101
 
115
102
  # Pass meta as a separate field instead of merging into arguments
116
103
  # This matches the TypeScript SDK pattern and MCP protocol specification
@@ -183,9 +170,7 @@ class PersistentMcpClient:
183
170
 
184
171
  except Exception as e:
185
172
  # Default to websocket if we can't determine the transport type
186
- logger.warning(
187
- f"Failed to detect transport type for {self.name}: {e}. Defaulting to websocket."
188
- )
173
+ logger.warning(f"Failed to detect transport type for {self.name}: {e}. Defaulting to websocket.")
189
174
  self.transport_name = "websocket"
190
175
 
191
176
  return self.transport_name
@@ -341,10 +326,7 @@ class BlTools:
341
326
  if not toolPersistances.get(name):
342
327
  logger.debug(f"Creating new persistent connection for {name}")
343
328
  toolPersistances[name] = PersistentMcpClient(
344
- name,
345
- timeout=self.timeout,
346
- timeout_enabled=self.timeout_enabled,
347
- transport=self.transport,
329
+ name, timeout=self.timeout, timeout_enabled=self.timeout_enabled, transport=self.transport
348
330
  )
349
331
  await toolPersistances[name].list_tools()
350
332
  logger.debug(f"Loaded {len(toolPersistances[name].get_tools())} tools")
@@ -364,10 +346,4 @@ def bl_tools(
364
346
  timeout_enabled: bool = True,
365
347
  transport: str = None,
366
348
  ) -> BlTools:
367
- return BlTools(
368
- functions,
369
- metas=metas,
370
- timeout=timeout,
371
- timeout_enabled=timeout_enabled,
372
- transport=transport,
373
- )
349
+ return BlTools(functions, metas=metas, timeout=timeout, timeout_enabled=timeout_enabled, transport=transport)
@@ -42,4 +42,4 @@ def create_model_from_json_schema(
42
42
  field_type,
43
43
  Field(default_value, description=field_schema.get("description", "")),
44
44
  )
45
- return create_model(model_name, **fields)
45
+ return create_model(model_name, **fields)
@@ -12,10 +12,9 @@ class ToolException(Exception): # noqa: N818
12
12
  to the agent as observation, and printed in red on the console.
13
13
  """
14
14
 
15
-
16
15
  class Tool(BaseModel):
17
16
  name: str
18
17
  description: str
19
18
  input_schema: Dict[str, Any]
20
19
  coroutine: Callable[..., Awaitable[Any]] | None = None
21
- sync_coroutine: Callable[..., Any] | None = None
20
+ sync_coroutine: Callable[..., Any] | None = None