blaxel 0.2.34__py3-none-any.whl → 0.2.35__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 (276) hide show
  1. blaxel/__init__.py +2 -2
  2. blaxel/core/client/api/agents/create_agent.py +64 -19
  3. blaxel/core/client/api/agents/delete_agent.py +44 -15
  4. blaxel/core/client/api/agents/get_agent.py +43 -14
  5. blaxel/core/client/api/agents/list_agents.py +40 -11
  6. blaxel/core/client/api/agents/update_agent.py +60 -19
  7. blaxel/core/client/api/compute/create_sandbox.py +60 -23
  8. blaxel/core/client/api/compute/delete_sandbox.py +40 -19
  9. blaxel/core/client/api/compute/get_sandbox.py +39 -18
  10. blaxel/core/client/api/compute/list_sandboxes.py +40 -19
  11. blaxel/core/client/api/compute/update_sandbox.py +56 -23
  12. blaxel/core/client/api/configurations/get_configuration.py +16 -4
  13. blaxel/core/client/api/customdomains/create_custom_domain.py +12 -0
  14. blaxel/core/client/api/customdomains/list_custom_domains.py +16 -4
  15. blaxel/core/client/api/default/get_template.py +8 -4
  16. blaxel/core/client/api/functions/create_function.py +62 -19
  17. blaxel/core/client/api/functions/delete_function.py +46 -15
  18. blaxel/core/client/api/functions/get_function.py +45 -14
  19. blaxel/core/client/api/functions/list_functions.py +44 -15
  20. blaxel/core/client/api/functions/update_function.py +62 -19
  21. blaxel/core/client/api/images/cleanup_images.py +12 -12
  22. blaxel/core/client/api/images/delete_image.py +12 -8
  23. blaxel/core/client/api/images/delete_image_tag.py +12 -8
  24. blaxel/core/client/api/images/get_image.py +12 -8
  25. blaxel/core/client/api/images/list_images.py +12 -8
  26. blaxel/core/client/api/integrations/create_integration_connection.py +56 -23
  27. blaxel/core/client/api/integrations/delete_integration_connection.py +48 -19
  28. blaxel/core/client/api/integrations/get_integration.py +12 -8
  29. blaxel/core/client/api/integrations/get_integration_connection.py +44 -19
  30. blaxel/core/client/api/integrations/get_integration_connection_model.py +2 -2
  31. blaxel/core/client/api/integrations/list_integration_connections.py +36 -19
  32. blaxel/core/client/api/integrations/update_integration_connection.py +52 -19
  33. blaxel/core/client/api/jobs/create_job.py +20 -12
  34. blaxel/core/client/api/jobs/create_job_execution.py +22 -16
  35. blaxel/core/client/api/jobs/delete_job.py +12 -8
  36. blaxel/core/client/api/jobs/delete_job_execution.py +12 -8
  37. blaxel/core/client/api/jobs/get_job.py +24 -20
  38. blaxel/core/client/api/jobs/get_job_execution.py +8 -4
  39. blaxel/core/client/api/jobs/list_job_executions.py +8 -4
  40. blaxel/core/client/api/jobs/list_jobs.py +12 -8
  41. blaxel/core/client/api/jobs/update_job.py +20 -12
  42. blaxel/core/client/api/locations/list_locations.py +12 -8
  43. blaxel/core/client/api/{default → mcphub}/list_mcp_hub_definitions.py +20 -4
  44. blaxel/core/client/api/models/create_model.py +52 -23
  45. blaxel/core/client/api/models/delete_model.py +40 -19
  46. blaxel/core/client/api/models/get_model.py +40 -19
  47. blaxel/core/client/api/models/list_models.py +40 -19
  48. blaxel/core/client/api/models/update_model.py +52 -23
  49. blaxel/core/client/api/policies/create_policy.py +12 -8
  50. blaxel/core/client/api/policies/delete_policy.py +12 -8
  51. blaxel/core/client/api/policies/get_policy.py +12 -8
  52. blaxel/core/client/api/policies/list_policies.py +12 -8
  53. blaxel/core/client/api/policies/update_policy.py +12 -8
  54. blaxel/core/client/api/public_ipslist/list_public_ips.py +37 -5
  55. blaxel/core/client/api/sandboxhub/__init__.py +0 -0
  56. blaxel/core/client/api/{default → sandboxhub}/list_sandbox_hub_definitions.py +20 -4
  57. blaxel/core/client/api/service_accounts/create_api_key_for_service_account.py +12 -8
  58. blaxel/core/client/api/service_accounts/create_workspace_service_account.py +12 -8
  59. blaxel/core/client/api/service_accounts/delete_api_key_for_service_account.py +6 -4
  60. blaxel/core/client/api/service_accounts/delete_workspace_service_account.py +12 -8
  61. blaxel/core/client/api/service_accounts/get_workspace_service_accounts.py +12 -8
  62. blaxel/core/client/api/service_accounts/list_api_keys_for_service_account.py +12 -8
  63. blaxel/core/client/api/service_accounts/update_workspace_service_account.py +8 -8
  64. blaxel/core/client/api/templates/list_templates.py +12 -8
  65. blaxel/core/client/api/volume_templates/create_volume_template.py +8 -4
  66. blaxel/core/client/api/volume_templates/list_volume_templates.py +8 -4
  67. blaxel/core/client/api/volumes/create_volume.py +56 -23
  68. blaxel/core/client/api/volumes/delete_volume.py +44 -19
  69. blaxel/core/client/api/volumes/get_volume.py +40 -19
  70. blaxel/core/client/api/volumes/list_volumes.py +40 -19
  71. blaxel/core/client/api/workspaces/create_workspace.py +54 -23
  72. blaxel/core/client/api/workspaces/delete_workspace.py +42 -19
  73. blaxel/core/client/api/workspaces/get_workspace.py +42 -19
  74. blaxel/core/client/api/workspaces/invite_workspace_user.py +8 -4
  75. blaxel/core/client/api/workspaces/list_workspace_users.py +12 -8
  76. blaxel/core/client/api/workspaces/list_workspaces.py +36 -19
  77. blaxel/core/client/api/workspaces/update_workspace.py +50 -19
  78. blaxel/core/client/models/__init__.py +76 -146
  79. blaxel/core/client/models/agent.py +43 -47
  80. blaxel/core/client/models/agent_runtime.py +139 -0
  81. blaxel/core/client/models/agent_runtime_generation.py +18 -0
  82. blaxel/core/client/models/agent_spec.py +33 -110
  83. blaxel/core/client/models/api_key.py +5 -4
  84. blaxel/core/client/models/core_event.py +5 -5
  85. blaxel/core/client/models/create_api_key_for_service_account_body.py +2 -1
  86. blaxel/core/client/models/create_job_execution_request.py +1 -1
  87. blaxel/core/client/models/create_job_execution_response.py +13 -9
  88. blaxel/core/client/models/custom_domain.py +19 -36
  89. blaxel/core/client/models/custom_domain_metadata.py +4 -3
  90. blaxel/core/client/models/custom_domain_spec.py +14 -5
  91. blaxel/core/client/models/custom_domain_spec_status.py +19 -0
  92. blaxel/core/client/models/entrypoint.py +39 -13
  93. blaxel/core/client/models/{workspace_labels.py → entrypoint_args_item.py} +6 -6
  94. blaxel/core/client/models/entrypoint_env.py +3 -3
  95. blaxel/core/client/models/{job_metrics_executions_total.py → entrypoint_super_gateway_args_item.py} +6 -6
  96. blaxel/core/client/models/{spec_configuration.py → env.py} +17 -8
  97. blaxel/core/{sandbox/client/models/welcome_response.py → client/models/error.py} +26 -23
  98. blaxel/core/client/models/expiration_policy.py +30 -11
  99. blaxel/core/client/models/expiration_policy_action.py +17 -0
  100. blaxel/core/client/models/expiration_policy_type.py +19 -0
  101. blaxel/core/client/models/flavor.py +13 -5
  102. blaxel/core/client/models/flavor_type.py +18 -0
  103. blaxel/core/client/models/form.py +6 -6
  104. blaxel/core/client/models/function.py +43 -47
  105. blaxel/core/client/models/function_runtime.py +138 -0
  106. blaxel/core/client/models/function_runtime_generation.py +18 -0
  107. blaxel/core/client/models/function_spec.py +27 -73
  108. blaxel/core/client/models/function_spec_transport.py +18 -0
  109. blaxel/core/client/models/image.py +19 -36
  110. blaxel/core/client/models/integration_connection.py +25 -39
  111. blaxel/core/client/models/integration_connection_spec.py +8 -5
  112. blaxel/core/client/models/integration_connection_spec_config.py +1 -1
  113. blaxel/core/client/models/integration_connection_spec_secret.py +1 -1
  114. blaxel/core/client/models/integration_endpoint.py +41 -11
  115. blaxel/core/client/models/integration_endpoint_ignore_models_item.py +45 -0
  116. blaxel/core/client/models/{mcp_definition_entrypoint.py → integration_endpoint_models_item.py} +6 -6
  117. blaxel/core/client/models/job.py +43 -47
  118. blaxel/core/client/models/job_execution.py +30 -37
  119. blaxel/core/client/models/job_execution_metadata.py +3 -3
  120. blaxel/core/client/models/job_execution_spec.py +2 -2
  121. blaxel/core/client/models/job_execution_stats.py +5 -5
  122. blaxel/core/client/models/job_execution_status.py +24 -0
  123. blaxel/core/client/models/job_execution_task.py +12 -4
  124. blaxel/core/client/models/job_execution_task_metadata.py +1 -1
  125. blaxel/core/client/models/job_execution_task_spec.py +2 -2
  126. blaxel/core/client/models/job_execution_task_status.py +23 -0
  127. blaxel/core/client/models/job_runtime.py +172 -0
  128. blaxel/core/client/models/job_runtime_generation.py +18 -0
  129. blaxel/core/client/models/job_spec.py +20 -88
  130. blaxel/core/client/models/location_response.py +5 -5
  131. blaxel/core/client/models/mcp_definition.py +30 -17
  132. blaxel/core/client/models/{job_metrics_tasks_total.py → mcp_definition_categories_item.py} +6 -6
  133. blaxel/core/client/models/metadata.py +23 -17
  134. blaxel/core/client/models/metadata_labels.py +4 -1
  135. blaxel/core/client/models/model.py +43 -47
  136. blaxel/core/client/models/model_runtime.py +99 -0
  137. blaxel/core/client/models/model_runtime_type.py +34 -0
  138. blaxel/core/client/models/model_spec.py +12 -58
  139. blaxel/core/client/models/o_auth.py +23 -6
  140. blaxel/core/client/models/{form_oauth.py → o_auth_scope_item.py} +6 -6
  141. blaxel/core/client/models/pending_invitation_accept.py +2 -1
  142. blaxel/core/client/models/pending_invitation_workspace_details.py +27 -6
  143. blaxel/core/client/models/{metrics_request_total_per_code.py → pending_invitation_workspace_details_emails_item.py} +6 -6
  144. blaxel/core/client/models/policy.py +20 -36
  145. blaxel/core/client/models/policy_location.py +13 -5
  146. blaxel/core/client/models/policy_location_type.py +19 -0
  147. blaxel/core/client/models/policy_max_tokens.py +6 -6
  148. blaxel/core/client/models/policy_resource_type.py +20 -0
  149. blaxel/core/client/models/policy_spec.py +31 -10
  150. blaxel/core/client/models/policy_spec_type.py +19 -0
  151. blaxel/core/client/models/port.py +25 -15
  152. blaxel/core/client/models/port_protocol.py +19 -0
  153. blaxel/core/client/models/preview.py +19 -36
  154. blaxel/core/client/models/preview_metadata.py +12 -10
  155. blaxel/core/client/models/preview_token.py +19 -36
  156. blaxel/core/client/models/preview_token_metadata.py +8 -6
  157. blaxel/core/client/models/repository.py +2 -2
  158. blaxel/core/client/models/revision_configuration.py +3 -3
  159. blaxel/core/client/models/sandbox.py +45 -58
  160. blaxel/core/client/models/sandbox_definition.py +37 -22
  161. blaxel/core/client/models/sandbox_definition_categories_item.py +45 -0
  162. blaxel/core/client/models/sandbox_error.py +148 -0
  163. blaxel/core/client/models/sandbox_error_details.py +45 -0
  164. blaxel/core/client/models/sandbox_lifecycle.py +3 -2
  165. blaxel/core/client/models/sandbox_runtime.py +145 -0
  166. blaxel/core/client/models/sandbox_spec.py +33 -134
  167. blaxel/core/client/models/status.py +25 -0
  168. blaxel/core/client/models/template.py +8 -7
  169. blaxel/core/client/models/template_variable.py +5 -5
  170. blaxel/core/client/models/trigger.py +14 -6
  171. blaxel/core/client/models/trigger_configuration.py +7 -6
  172. blaxel/core/client/models/trigger_type.py +19 -0
  173. blaxel/core/client/models/volume.py +35 -47
  174. blaxel/core/client/models/volume_attachment.py +6 -4
  175. blaxel/core/client/models/volume_spec.py +7 -4
  176. blaxel/core/client/models/volume_state.py +3 -3
  177. blaxel/core/client/models/volume_template.py +19 -33
  178. blaxel/core/client/models/volume_template_state.py +12 -4
  179. blaxel/core/client/models/volume_template_state_status.py +19 -0
  180. blaxel/core/client/models/volume_template_version.py +12 -4
  181. blaxel/core/client/models/volume_template_version_status.py +19 -0
  182. blaxel/core/client/models/workspace.py +35 -25
  183. blaxel/core/client/models/workspace_runtime.py +3 -2
  184. blaxel/core/client/models/workspace_status.py +22 -0
  185. blaxel/core/common/__init__.py +1 -1
  186. blaxel/core/jobs/__init__.py +0 -1
  187. blaxel/core/sandbox/__init__.py +2 -0
  188. blaxel/core/sandbox/client/api/process/post_process.py +8 -4
  189. blaxel/core/sandbox/client/models/__init__.py +0 -2
  190. blaxel/core/sandbox/client/models/process_response.py +16 -0
  191. blaxel/core/sandbox/client/models/process_response_status.py +9 -0
  192. blaxel/core/sandbox/default/__init__.py +2 -0
  193. blaxel/core/sandbox/default/interpreter.py +5 -1
  194. blaxel/core/sandbox/default/preview.py +3 -1
  195. blaxel/core/sandbox/default/sandbox.py +51 -16
  196. blaxel/core/sandbox/sync/process.py +2 -1
  197. blaxel/core/sandbox/sync/sandbox.py +34 -13
  198. blaxel/core/tools/common.py +16 -2
  199. blaxel/core/volume/__init__.py +2 -2
  200. blaxel/core/volume/volume.py +32 -10
  201. blaxel/langgraph/tools.py +34 -2
  202. blaxel/openai/tools.py +33 -1
  203. {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/METADATA +3 -3
  204. {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/RECORD +207 -246
  205. blaxel/core/client/models/acl.py +0 -133
  206. blaxel/core/client/models/billable_time_metric.py +0 -89
  207. blaxel/core/client/models/core_spec.py +0 -194
  208. blaxel/core/client/models/core_spec_configurations.py +0 -77
  209. blaxel/core/client/models/histogram_bucket.py +0 -79
  210. blaxel/core/client/models/histogram_stats.py +0 -88
  211. blaxel/core/client/models/integration_model.py +0 -162
  212. blaxel/core/client/models/job_execution_config.py +0 -79
  213. blaxel/core/client/models/job_metrics.py +0 -262
  214. blaxel/core/client/models/jobs_chart_value.py +0 -70
  215. blaxel/core/client/models/jobs_network_chart.py +0 -102
  216. blaxel/core/client/models/jobs_success_failed_chart.py +0 -147
  217. blaxel/core/client/models/jobs_total.py +0 -88
  218. blaxel/core/client/models/last_n_requests_metric.py +0 -97
  219. blaxel/core/client/models/latency_metric.py +0 -148
  220. blaxel/core/client/models/logs_response.py +0 -63
  221. blaxel/core/client/models/logs_response_data.py +0 -99
  222. blaxel/core/client/models/mcp_definition_form.py +0 -45
  223. blaxel/core/client/models/memory_allocation_by_name.py +0 -70
  224. blaxel/core/client/models/memory_allocation_metric.py +0 -61
  225. blaxel/core/client/models/metric.py +0 -79
  226. blaxel/core/client/models/metrics.py +0 -273
  227. blaxel/core/client/models/metrics_models.py +0 -45
  228. blaxel/core/client/models/metrics_rps_per_code.py +0 -45
  229. blaxel/core/client/models/pod_template_spec.py +0 -45
  230. blaxel/core/client/models/request_duration_over_time_metric.py +0 -97
  231. blaxel/core/client/models/request_duration_over_time_metrics.py +0 -84
  232. blaxel/core/client/models/request_total_by_origin_metric.py +0 -129
  233. blaxel/core/client/models/request_total_by_origin_metric_request_total_by_origin.py +0 -45
  234. blaxel/core/client/models/request_total_by_origin_metric_request_total_by_origin_and_code.py +0 -45
  235. blaxel/core/client/models/request_total_metric.py +0 -155
  236. blaxel/core/client/models/request_total_metric_request_total_per_code.py +0 -45
  237. blaxel/core/client/models/request_total_metric_rps_per_code.py +0 -45
  238. blaxel/core/client/models/request_total_response_data.py +0 -97
  239. blaxel/core/client/models/resource.py +0 -99
  240. blaxel/core/client/models/resource_log.py +0 -88
  241. blaxel/core/client/models/resource_log_chart.py +0 -133
  242. blaxel/core/client/models/resource_log_response.py +0 -83
  243. blaxel/core/client/models/resource_metrics.py +0 -618
  244. blaxel/core/client/models/resource_metrics_request_total_per_code.py +0 -45
  245. blaxel/core/client/models/resource_metrics_request_total_per_code_previous.py +0 -45
  246. blaxel/core/client/models/resource_metrics_rps_per_code.py +0 -45
  247. blaxel/core/client/models/resource_metrics_rps_per_code_previous.py +0 -45
  248. blaxel/core/client/models/resource_trace.py +0 -97
  249. blaxel/core/client/models/runtime.py +0 -317
  250. blaxel/core/client/models/runtime_configuration.py +0 -45
  251. blaxel/core/client/models/runtime_startup_probe.py +0 -45
  252. blaxel/core/client/models/sandbox_metrics.py +0 -88
  253. blaxel/core/client/models/serverless_config.py +0 -117
  254. blaxel/core/client/models/serverless_config_configuration.py +0 -45
  255. blaxel/core/client/models/start_sandbox.py +0 -98
  256. blaxel/core/client/models/stop_sandbox.py +0 -98
  257. blaxel/core/client/models/store_agent.py +0 -181
  258. blaxel/core/client/models/store_agent_labels.py +0 -45
  259. blaxel/core/client/models/store_configuration.py +0 -156
  260. blaxel/core/client/models/store_configuration_option.py +0 -79
  261. blaxel/core/client/models/time_to_first_token_over_time_metrics.py +0 -87
  262. blaxel/core/client/models/token_rate_metric.py +0 -106
  263. blaxel/core/client/models/token_rate_metrics.py +0 -124
  264. blaxel/core/client/models/token_total_metric.py +0 -112
  265. blaxel/core/client/models/trace_ids_response.py +0 -45
  266. blaxel/core/client/models/websocket_channel.py +0 -97
  267. blaxel/core/client/models/websocket_message.py +0 -106
  268. blaxel/core/sandbox/client/api/root/delete.py +0 -130
  269. blaxel/core/sandbox/client/api/root/get.py +0 -130
  270. blaxel/core/sandbox/client/api/root/options.py +0 -130
  271. blaxel/core/sandbox/client/api/root/patch.py +0 -130
  272. blaxel/core/sandbox/client/api/root/post.py +0 -130
  273. blaxel/core/sandbox/client/api/root/put.py +0 -130
  274. /blaxel/core/{sandbox/client/api/root → client/api/mcphub}/__init__.py +0 -0
  275. {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/WHEEL +0 -0
  276. {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,22 @@
1
+ from enum import Enum
2
+
3
+
4
+ class WorkspaceStatus(str, Enum):
5
+ ACCOUNT_BINDED = "account_binded"
6
+ ACCOUNT_CONFIGURED = "account_configured"
7
+ CREATED = "created"
8
+ ERROR = "error"
9
+ READY = "ready"
10
+ WORKSPACE_CONFIGURED = "workspace_configured"
11
+
12
+ def __str__(self) -> str:
13
+ return str(self.value)
14
+
15
+ @classmethod
16
+ def _missing_(cls, value: object) -> "WorkspaceStatus | None":
17
+ if isinstance(value, str):
18
+ upper_value = value.upper()
19
+ for member in cls:
20
+ if member.value.upper() == upper_value:
21
+ return member
22
+ return None
@@ -1,7 +1,7 @@
1
1
  from .autoload import autoload
2
2
  from .env import env
3
- from .sentry import capture_exception, flush_sentry, init_sentry, is_sentry_initialized
4
3
  from .internal import get_alphanumeric_limited_hash, get_global_unique_hash
4
+ from .sentry import capture_exception, flush_sentry, init_sentry, is_sentry_initialized
5
5
  from .settings import Settings, settings
6
6
  from .webhook import (
7
7
  AsyncSidecarCallback,
@@ -229,7 +229,6 @@ class BlJob:
229
229
  client=client,
230
230
  body=request,
231
231
  )
232
-
233
232
  if response.status_code != 200:
234
233
  raise Exception(f"Failed to create job execution: {response.status_code}")
235
234
 
@@ -6,6 +6,7 @@ from .client.models import (
6
6
  )
7
7
  from .default import (
8
8
  CodeInterpreter,
9
+ SandboxAPIError,
9
10
  SandboxCodegen,
10
11
  SandboxFileSystem,
11
12
  SandboxInstance,
@@ -34,6 +35,7 @@ from .types import (
34
35
 
35
36
  __all__ = [
36
37
  "SandboxInstance",
38
+ "SandboxAPIError",
37
39
  "SessionCreateOptions",
38
40
  "SessionWithToken",
39
41
  "SandboxConfiguration",
@@ -77,7 +77,8 @@ def sync_detailed(
77
77
  ) -> Response[Union[ErrorResponse, ProcessResponse]]:
78
78
  """Execute a command
79
79
 
80
- Execute a command and return process information
80
+ Execute a command and return process information. If Accept header is text/event-stream, streams
81
+ logs in SSE format and returns the process response as a final event.
81
82
 
82
83
  Args:
83
84
  body (ProcessRequest):
@@ -108,7 +109,8 @@ def sync(
108
109
  ) -> Union[ErrorResponse, ProcessResponse] | None:
109
110
  """Execute a command
110
111
 
111
- Execute a command and return process information
112
+ Execute a command and return process information. If Accept header is text/event-stream, streams
113
+ logs in SSE format and returns the process response as a final event.
112
114
 
113
115
  Args:
114
116
  body (ProcessRequest):
@@ -134,7 +136,8 @@ async def asyncio_detailed(
134
136
  ) -> Response[Union[ErrorResponse, ProcessResponse]]:
135
137
  """Execute a command
136
138
 
137
- Execute a command and return process information
139
+ Execute a command and return process information. If Accept header is text/event-stream, streams
140
+ logs in SSE format and returns the process response as a final event.
138
141
 
139
142
  Args:
140
143
  body (ProcessRequest):
@@ -163,7 +166,8 @@ async def asyncio(
163
166
  ) -> Union[ErrorResponse, ProcessResponse] | None:
164
167
  """Execute a command
165
168
 
166
- Execute a command and return process information
169
+ Execute a command and return process information. If Accept header is text/event-stream, streams
170
+ logs in SSE format and returns the process response as a final event.
167
171
 
168
172
  Args:
169
173
  body (ProcessRequest):
@@ -41,7 +41,6 @@ from .subdirectory import Subdirectory
41
41
  from .success_response import SuccessResponse
42
42
  from .tree_request import TreeRequest
43
43
  from .tree_request_files import TreeRequestFiles
44
- from .welcome_response import WelcomeResponse
45
44
 
46
45
  __all__ = (
47
46
  "ApplyEditRequest",
@@ -83,5 +82,4 @@ __all__ = (
83
82
  "SuccessResponse",
84
83
  "TreeRequest",
85
84
  "TreeRequestFiles",
86
- "WelcomeResponse",
87
85
  )
@@ -21,6 +21,8 @@ class ProcessResponse:
21
21
  pid (str): Example: 1234.
22
22
  started_at (str): Example: Wed, 01 Jan 2023 12:00:00 GMT.
23
23
  status (ProcessResponseStatus): Example: running.
24
+ stderr (str): Example: stderr output.
25
+ stdout (str): Example: stdout output.
24
26
  working_dir (str): Example: /home/user.
25
27
  max_restarts (Union[Unset, int]): Example: 3.
26
28
  restart_count (Union[Unset, int]): Example: 2.
@@ -35,6 +37,8 @@ class ProcessResponse:
35
37
  pid: str
36
38
  started_at: str
37
39
  status: ProcessResponseStatus
40
+ stderr: str
41
+ stdout: str
38
42
  working_dir: str
39
43
  max_restarts: Union[Unset, int] = UNSET
40
44
  restart_count: Union[Unset, int] = UNSET
@@ -58,6 +62,10 @@ class ProcessResponse:
58
62
 
59
63
  status = self.status.value
60
64
 
65
+ stderr = self.stderr
66
+
67
+ stdout = self.stdout
68
+
61
69
  working_dir = self.working_dir
62
70
 
63
71
  max_restarts = self.max_restarts
@@ -78,6 +86,8 @@ class ProcessResponse:
78
86
  "pid": pid,
79
87
  "startedAt": started_at,
80
88
  "status": status,
89
+ "stderr": stderr,
90
+ "stdout": stdout,
81
91
  "workingDir": working_dir,
82
92
  }
83
93
  )
@@ -111,6 +121,10 @@ class ProcessResponse:
111
121
 
112
122
  status = ProcessResponseStatus(d.pop("status"))
113
123
 
124
+ stderr = d.pop("stderr")
125
+
126
+ stdout = d.pop("stdout")
127
+
114
128
  working_dir = d.pop("workingDir") if "workingDir" in d else d.pop("working_dir")
115
129
 
116
130
  max_restarts = d.pop("maxRestarts", d.pop("max_restarts", UNSET))
@@ -128,6 +142,8 @@ class ProcessResponse:
128
142
  pid=pid,
129
143
  started_at=started_at,
130
144
  status=status,
145
+ stderr=stderr,
146
+ stdout=stdout,
131
147
  working_dir=working_dir,
132
148
  max_restarts=max_restarts,
133
149
  restart_count=restart_count,
@@ -10,3 +10,12 @@ class ProcessResponseStatus(str, Enum):
10
10
 
11
11
  def __str__(self) -> str:
12
12
  return str(self.value)
13
+
14
+ @classmethod
15
+ def _missing_(cls, value: object) -> "ProcessResponseStatus | None":
16
+ if isinstance(value, str):
17
+ upper_value = value.upper()
18
+ for member in cls:
19
+ if member.value.upper() == upper_value:
20
+ return member
21
+ return None
@@ -1,5 +1,6 @@
1
1
  from .interpreter import CodeInterpreter
2
2
  from .sandbox import (
3
+ SandboxAPIError,
3
4
  SandboxCodegen,
4
5
  SandboxFileSystem,
5
6
  SandboxInstance,
@@ -9,6 +10,7 @@ from .sandbox import (
9
10
 
10
11
  __all__ = [
11
12
  "SandboxInstance",
13
+ "SandboxAPIError",
12
14
  "SandboxFileSystem",
13
15
  "SandboxPreviews",
14
16
  "SandboxProcess",
@@ -52,7 +52,7 @@ class CodeInterpreter(SandboxInstance):
52
52
  }
53
53
 
54
54
  # Whitelist a minimal set of fields that can be propagated from input
55
- allowed_copy_keys = {"name", "envs", "memory", "region", "headers"}
55
+ allowed_copy_keys = {"name", "envs", "memory", "region", "headers", "labels"}
56
56
 
57
57
  if isinstance(sandbox, dict):
58
58
  for k in allowed_copy_keys:
@@ -67,10 +67,14 @@ class CodeInterpreter(SandboxInstance):
67
67
  payload["memory"] = sandbox.memory
68
68
  if getattr(sandbox, "region", None):
69
69
  payload["region"] = sandbox.region
70
+ if getattr(sandbox, "labels", None):
71
+ payload["labels"] = sandbox.labels
70
72
  elif isinstance(sandbox, Sandbox):
71
73
  # Extract a few basics if available
72
74
  if sandbox.metadata and getattr(sandbox.metadata, "name", None):
73
75
  payload["name"] = sandbox.metadata.name
76
+ if sandbox.metadata and getattr(sandbox.metadata, "labels", None):
77
+ payload["labels"] = sandbox.metadata.labels
74
78
  if sandbox.spec and sandbox.spec.runtime:
75
79
  if getattr(sandbox.spec.runtime, "envs", None):
76
80
  payload["envs"] = sandbox.spec.runtime.envs
@@ -29,6 +29,7 @@ from ...client.models import (
29
29
  Preview,
30
30
  PreviewSpec,
31
31
  PreviewToken,
32
+ PreviewTokenMetadata,
32
33
  PreviewTokenSpec,
33
34
  Sandbox,
34
35
  )
@@ -69,9 +70,10 @@ class SandboxPreviewTokens:
69
70
  self.resource_name,
70
71
  self.preview_name,
71
72
  body=PreviewToken(
73
+ metadata=PreviewTokenMetadata(name=""),
72
74
  spec=PreviewTokenSpec(
73
75
  expires_at=to_utc_z(expires_at),
74
- )
76
+ ),
75
77
  ),
76
78
  client=client,
77
79
  )
@@ -8,7 +8,9 @@ from ...client.api.compute.get_sandbox import asyncio as get_sandbox
8
8
  from ...client.api.compute.list_sandboxes import asyncio as list_sandboxes
9
9
  from ...client.api.compute.update_sandbox import asyncio as update_sandbox
10
10
  from ...client.client import client
11
- from ...client.models import Metadata, Runtime, Sandbox, SandboxSpec
11
+ from ...client.models import Metadata, Sandbox, SandboxRuntime, SandboxSpec
12
+ from ...client.models.error import Error
13
+ from ...client.models.sandbox_error import SandboxError
12
14
  from ...client.types import UNSET
13
15
  from ..types import (
14
16
  SandboxConfiguration,
@@ -23,6 +25,16 @@ from .preview import SandboxPreviews
23
25
  from .process import SandboxProcess
24
26
  from .session import SandboxSessions
25
27
 
28
+
29
+ class SandboxAPIError(Exception):
30
+ """Exception raised when sandbox API returns an error."""
31
+
32
+ def __init__(self, message: str, status_code: int | None = None, code: str | None = None):
33
+ super().__init__(message)
34
+ self.status_code = status_code
35
+ self.code = code
36
+
37
+
26
38
  logger = logging.getLogger(__name__)
27
39
 
28
40
 
@@ -45,6 +57,8 @@ class _AsyncDeleteDescriptor:
45
57
 
46
58
 
47
59
  class SandboxInstance:
60
+ delete: "_AsyncDeleteDescriptor"
61
+
48
62
  def __init__(
49
63
  self,
50
64
  sandbox: Union[Sandbox, SandboxConfiguration],
@@ -156,12 +170,11 @@ class SandboxInstance:
156
170
  sandbox = Sandbox(
157
171
  metadata=Metadata(name=name, labels=config.labels),
158
172
  spec=SandboxSpec(
159
- runtime=Runtime(
173
+ runtime=SandboxRuntime(
160
174
  image=image,
161
175
  memory=memory,
162
176
  ports=ports,
163
177
  envs=envs,
164
- generation="mk3",
165
178
  ),
166
179
  volumes=volumes,
167
180
  ),
@@ -186,19 +199,26 @@ class SandboxInstance:
186
199
  sandbox.metadata = Metadata(name=default_name)
187
200
  if not sandbox.spec:
188
201
  sandbox.spec = SandboxSpec(
189
- runtime=Runtime(image=default_image, memory=default_memory)
202
+ runtime=SandboxRuntime(image=default_image, memory=default_memory)
190
203
  )
191
204
  if not sandbox.spec.runtime:
192
- sandbox.spec.runtime = Runtime(image=default_image, memory=default_memory)
205
+ sandbox.spec.runtime = SandboxRuntime(image=default_image, memory=default_memory)
193
206
 
194
207
  sandbox.spec.runtime.image = sandbox.spec.runtime.image or default_image
195
208
  sandbox.spec.runtime.memory = sandbox.spec.runtime.memory or default_memory
196
- sandbox.spec.runtime.generation = sandbox.spec.runtime.generation or "mk3"
197
209
 
198
210
  response = await create_sandbox(
199
211
  client=client,
200
212
  body=sandbox,
201
213
  )
214
+
215
+ # Check if response is an error
216
+ if isinstance(response, SandboxError):
217
+ status_code = response.status_code if response.status_code is not UNSET else None
218
+ code = response.code if response.code else None
219
+ message = response.message if response.message else str(response)
220
+ raise SandboxAPIError(message, status_code=status_code, code=code)
221
+
202
222
  instance = cls(response)
203
223
  # TODO remove this part once we have a better way to handle this
204
224
  if safe:
@@ -214,11 +234,21 @@ class SandboxInstance:
214
234
  sandbox_name,
215
235
  client=client,
216
236
  )
237
+
238
+ # Check if response is an error
239
+ if isinstance(response, Error):
240
+ status_code = response.code if response.code is not UNSET else None
241
+ message = response.message if response.message is not UNSET else response.error
242
+ raise SandboxAPIError(message, status_code=status_code, code=response.error)
243
+
244
+ if response is None:
245
+ raise SandboxAPIError(f"Sandbox '{sandbox_name}' not found", status_code=404)
246
+
217
247
  return cls(response)
218
248
 
219
249
  @classmethod
220
250
  async def list(cls) -> List["SandboxInstance"]:
221
- response = await list_sandboxes()
251
+ response = await list_sandboxes(client=client)
222
252
  return [cls(sandbox) for sandbox in response]
223
253
 
224
254
  @classmethod
@@ -240,10 +270,12 @@ class SandboxInstance:
240
270
 
241
271
  # Prepare the updated sandbox object
242
272
  updated_sandbox = Sandbox.from_dict(sandbox.to_dict())
273
+ if updated_sandbox is None:
274
+ raise ValueError(f"Sandbox {sandbox_name} not found")
243
275
 
244
276
  # Merge metadata
245
277
  if updated_sandbox.metadata is None:
246
- updated_sandbox.metadata = Metadata()
278
+ updated_sandbox.metadata = Metadata(name=sandbox_name)
247
279
 
248
280
  # Update labels if provided
249
281
  if metadata.labels is not None:
@@ -251,8 +283,11 @@ class SandboxInstance:
251
283
  if updated_sandbox.metadata.labels is None or updated_sandbox.metadata.labels is UNSET:
252
284
  updated_sandbox.metadata.labels = {}
253
285
  else:
254
- # If labels exist, ensure it's a dict
255
- updated_sandbox.metadata.labels = dict(updated_sandbox.metadata.labels)
286
+ # If labels exist, convert to dict (MetadataLabels stores in additional_properties)
287
+ if hasattr(updated_sandbox.metadata.labels, "to_dict"):
288
+ updated_sandbox.metadata.labels = updated_sandbox.metadata.labels.to_dict()
289
+ else:
290
+ updated_sandbox.metadata.labels = dict(updated_sandbox.metadata.labels)
256
291
  updated_sandbox.metadata.labels.update(metadata.labels)
257
292
 
258
293
  # Update display_name if provided
@@ -276,11 +311,9 @@ class SandboxInstance:
276
311
  """Create a sandbox if it doesn't exist, otherwise return existing."""
277
312
  try:
278
313
  return await cls.create(sandbox)
279
- except Exception as e:
314
+ except SandboxAPIError as e:
280
315
  # Check if it's a 409 conflict error (sandbox already exists)
281
- if (hasattr(e, "status_code") and e.status_code == 409) or (
282
- hasattr(e, "code") and e.code in [409, "SANDBOX_ALREADY_EXISTS"]
283
- ):
316
+ if e.status_code == 409 or e.code in [409, "SANDBOX_ALREADY_EXISTS"]:
284
317
  # Extract name from different configuration types
285
318
  if isinstance(sandbox, SandboxCreateConfiguration):
286
319
  name = sandbox.name
@@ -309,7 +342,7 @@ class SandboxInstance:
309
342
 
310
343
  # Otherwise return the existing active sandbox
311
344
  return sandbox_instance
312
- raise e
345
+ raise
313
346
 
314
347
  @classmethod
315
348
  async def from_session(
@@ -321,7 +354,7 @@ class SandboxInstance:
321
354
 
322
355
  # Create a minimal sandbox configuration for session-based access
323
356
  sandbox_name = session.name.split("-")[0] if "-" in session.name else session.name
324
- sandbox = Sandbox(metadata=Metadata(name=sandbox_name))
357
+ sandbox = Sandbox(metadata=Metadata(name=sandbox_name), spec=SandboxSpec())
325
358
 
326
359
  # Use the constructor with force_url, headers, and params
327
360
  return cls(
@@ -338,6 +371,8 @@ async def _delete_sandbox_by_name(sandbox_name: str) -> Sandbox:
338
371
  sandbox_name,
339
372
  client=client,
340
373
  )
374
+ if response is None:
375
+ raise ValueError(f"Sandbox {sandbox_name} not found")
341
376
  return response
342
377
 
343
378
 
@@ -186,7 +186,8 @@ class SyncSandboxProcess(SyncSandboxAction):
186
186
 
187
187
  if on_log or on_stdout or on_stderr:
188
188
  stream_control = self._stream_logs(
189
- result.pid, {"on_log": on_log, "on_stdout": on_stdout, "on_stderr": on_stderr}
189
+ result.pid,
190
+ {"on_log": on_log, "on_stdout": on_stdout, "on_stderr": on_stderr},
190
191
  )
191
192
  return ProcessResponseWithLog(
192
193
  result,
@@ -8,8 +8,11 @@ from ...client.api.compute.get_sandbox import sync as get_sandbox
8
8
  from ...client.api.compute.list_sandboxes import sync as list_sandboxes
9
9
  from ...client.api.compute.update_sandbox import sync as update_sandbox
10
10
  from ...client.client import client
11
- from ...client.models import Metadata, Runtime, Sandbox, SandboxSpec
11
+ from ...client.models import Metadata, Sandbox, SandboxRuntime, SandboxSpec
12
+ from ...client.models.error import Error
13
+ from ...client.models.sandbox_error import SandboxError
12
14
  from ...client.types import UNSET
15
+ from ..default.sandbox import SandboxAPIError
13
16
  from ..types import (
14
17
  SandboxConfiguration,
15
18
  SandboxCreateConfiguration,
@@ -146,12 +149,11 @@ class SyncSandboxInstance:
146
149
  sandbox = Sandbox(
147
150
  metadata=Metadata(name=name, labels=config.labels),
148
151
  spec=SandboxSpec(
149
- runtime=Runtime(
152
+ runtime=SandboxRuntime(
150
153
  image=image,
151
154
  memory=memory,
152
155
  ports=ports,
153
156
  envs=envs,
154
- generation="mk3",
155
157
  ),
156
158
  volumes=volumes,
157
159
  ),
@@ -171,17 +173,24 @@ class SyncSandboxInstance:
171
173
  sandbox.metadata = Metadata(name=default_name)
172
174
  if not sandbox.spec:
173
175
  sandbox.spec = SandboxSpec(
174
- runtime=Runtime(image=default_image, memory=default_memory)
176
+ runtime=SandboxRuntime(image=default_image, memory=default_memory)
175
177
  )
176
178
  if not sandbox.spec.runtime:
177
- sandbox.spec.runtime = Runtime(image=default_image, memory=default_memory)
179
+ sandbox.spec.runtime = SandboxRuntime(image=default_image, memory=default_memory)
178
180
  sandbox.spec.runtime.image = sandbox.spec.runtime.image or default_image
179
181
  sandbox.spec.runtime.memory = sandbox.spec.runtime.memory or default_memory
180
- sandbox.spec.runtime.generation = sandbox.spec.runtime.generation or "mk3"
181
182
  response = create_sandbox(
182
183
  client=client,
183
184
  body=sandbox,
184
185
  )
186
+
187
+ # Check if response is an error
188
+ if isinstance(response, SandboxError):
189
+ status_code = response.status_code if response.status_code is not UNSET else None
190
+ code = response.code if response.code else None
191
+ message = response.message if response.message else str(response)
192
+ raise SandboxAPIError(message, status_code=status_code, code=code)
193
+
185
194
  instance = cls(response)
186
195
  if safe:
187
196
  try:
@@ -196,6 +205,16 @@ class SyncSandboxInstance:
196
205
  sandbox_name,
197
206
  client=client,
198
207
  )
208
+
209
+ # Check if response is an error
210
+ if isinstance(response, Error):
211
+ status_code = response.code if response.code is not UNSET else None
212
+ message = response.message if response.message is not UNSET else response.error
213
+ raise SandboxAPIError(message, status_code=status_code, code=response.error)
214
+
215
+ if response is None:
216
+ raise SandboxAPIError(f"Sandbox '{sandbox_name}' not found", status_code=404)
217
+
199
218
  return cls(response)
200
219
 
201
220
  @classmethod
@@ -216,7 +235,11 @@ class SyncSandboxInstance:
216
235
  if updated_sandbox.metadata.labels is None or updated_sandbox.metadata.labels is UNSET:
217
236
  updated_sandbox.metadata.labels = {}
218
237
  else:
219
- updated_sandbox.metadata.labels = dict(updated_sandbox.metadata.labels)
238
+ # MetadataLabels stores in additional_properties, use to_dict()
239
+ if hasattr(updated_sandbox.metadata.labels, "to_dict"):
240
+ updated_sandbox.metadata.labels = updated_sandbox.metadata.labels.to_dict()
241
+ else:
242
+ updated_sandbox.metadata.labels = dict(updated_sandbox.metadata.labels)
220
243
  updated_sandbox.metadata.labels.update(metadata.labels)
221
244
  if metadata.display_name is not None:
222
245
  updated_sandbox.metadata.display_name = metadata.display_name
@@ -233,10 +256,8 @@ class SyncSandboxInstance:
233
256
  ) -> "SyncSandboxInstance":
234
257
  try:
235
258
  return cls.create(sandbox)
236
- except Exception as e:
237
- if (hasattr(e, "status_code") and e.status_code == 409) or (
238
- hasattr(e, "code") and e.code in [409, "SANDBOX_ALREADY_EXISTS"]
239
- ):
259
+ except SandboxAPIError as e:
260
+ if e.status_code == 409 or e.code in [409, "SANDBOX_ALREADY_EXISTS"]:
240
261
  if isinstance(sandbox, SandboxCreateConfiguration):
241
262
  name = sandbox.name
242
263
  elif isinstance(sandbox, dict):
@@ -256,7 +277,7 @@ class SyncSandboxInstance:
256
277
  if sandbox_instance.status == "TERMINATED":
257
278
  return cls.create(sandbox)
258
279
  return sandbox_instance
259
- raise e
280
+ raise
260
281
 
261
282
  @classmethod
262
283
  def from_session(
@@ -265,7 +286,7 @@ class SyncSandboxInstance:
265
286
  if isinstance(session, dict):
266
287
  session = SessionWithToken.from_dict(session)
267
288
  sandbox_name = session.name.split("-")[0] if "-" in session.name else session.name
268
- sandbox = Sandbox(metadata=Metadata(name=sandbox_name))
289
+ sandbox = Sandbox(metadata=Metadata(name=sandbox_name), spec=SandboxSpec())
269
290
  return cls(
270
291
  sandbox=sandbox,
271
292
  force_url=session.url,
@@ -1,4 +1,4 @@
1
- from typing import Any, Dict, Type
1
+ from typing import Any, Dict, List, Type, Union
2
2
 
3
3
  from pydantic import BaseModel, Field, create_model
4
4
 
@@ -13,6 +13,20 @@ json_type_mapping: Dict[str, Type] = {
13
13
  }
14
14
 
15
15
 
16
+ def _get_python_type_from_json_type(json_type: Union[str, List[str]]) -> Type:
17
+ """Convert JSON Schema type to Python type.
18
+
19
+ Handles both simple types ("string") and nullable types (["string", "null"]).
20
+ """
21
+ if isinstance(json_type, list):
22
+ # Filter out "null" and get the primary type
23
+ non_null_types = [t for t in json_type if t != "null"]
24
+ if non_null_types:
25
+ return json_type_mapping.get(non_null_types[0], str)
26
+ return type(None)
27
+ return json_type_mapping.get(json_type, str)
28
+
29
+
16
30
  def create_model_from_json_schema(
17
31
  schema: Dict[str, Any], model_name: str = "DynamicModel"
18
32
  ) -> Type[BaseModel]:
@@ -32,7 +46,7 @@ def create_model_from_json_schema(
32
46
 
33
47
  for field_name, field_schema in properties.items():
34
48
  json_type = field_schema.get("type", "string")
35
- field_type = json_type_mapping.get(json_type, str)
49
+ field_type = _get_python_type_from_json_type(json_type)
36
50
  if field_name in required_fields:
37
51
  default_value = ...
38
52
  else:
@@ -1,5 +1,5 @@
1
1
  """Volume module for persistent storage management."""
2
2
 
3
- from .volume import SyncVolumeInstance, VolumeCreateConfiguration, VolumeInstance
3
+ from .volume import SyncVolumeInstance, VolumeAPIError, VolumeCreateConfiguration, VolumeInstance
4
4
 
5
- __all__ = ["VolumeInstance", "SyncVolumeInstance", "VolumeCreateConfiguration"]
5
+ __all__ = ["VolumeInstance", "SyncVolumeInstance", "VolumeCreateConfiguration", "VolumeAPIError"]