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.
- blaxel/__init__.py +2 -2
- blaxel/core/client/api/agents/create_agent.py +64 -19
- blaxel/core/client/api/agents/delete_agent.py +44 -15
- blaxel/core/client/api/agents/get_agent.py +43 -14
- blaxel/core/client/api/agents/list_agents.py +40 -11
- blaxel/core/client/api/agents/update_agent.py +60 -19
- blaxel/core/client/api/compute/create_sandbox.py +60 -23
- blaxel/core/client/api/compute/delete_sandbox.py +40 -19
- blaxel/core/client/api/compute/get_sandbox.py +39 -18
- blaxel/core/client/api/compute/list_sandboxes.py +40 -19
- blaxel/core/client/api/compute/update_sandbox.py +56 -23
- blaxel/core/client/api/configurations/get_configuration.py +16 -4
- blaxel/core/client/api/customdomains/create_custom_domain.py +12 -0
- blaxel/core/client/api/customdomains/list_custom_domains.py +16 -4
- blaxel/core/client/api/default/get_template.py +8 -4
- blaxel/core/client/api/functions/create_function.py +62 -19
- blaxel/core/client/api/functions/delete_function.py +46 -15
- blaxel/core/client/api/functions/get_function.py +45 -14
- blaxel/core/client/api/functions/list_functions.py +44 -15
- blaxel/core/client/api/functions/update_function.py +62 -19
- blaxel/core/client/api/images/cleanup_images.py +12 -12
- blaxel/core/client/api/images/delete_image.py +12 -8
- blaxel/core/client/api/images/delete_image_tag.py +12 -8
- blaxel/core/client/api/images/get_image.py +12 -8
- blaxel/core/client/api/images/list_images.py +12 -8
- blaxel/core/client/api/integrations/create_integration_connection.py +56 -23
- blaxel/core/client/api/integrations/delete_integration_connection.py +48 -19
- blaxel/core/client/api/integrations/get_integration.py +12 -8
- blaxel/core/client/api/integrations/get_integration_connection.py +44 -19
- blaxel/core/client/api/integrations/get_integration_connection_model.py +2 -2
- blaxel/core/client/api/integrations/list_integration_connections.py +36 -19
- blaxel/core/client/api/integrations/update_integration_connection.py +52 -19
- blaxel/core/client/api/jobs/create_job.py +20 -12
- blaxel/core/client/api/jobs/create_job_execution.py +22 -16
- blaxel/core/client/api/jobs/delete_job.py +12 -8
- blaxel/core/client/api/jobs/delete_job_execution.py +12 -8
- blaxel/core/client/api/jobs/get_job.py +24 -20
- blaxel/core/client/api/jobs/get_job_execution.py +8 -4
- blaxel/core/client/api/jobs/list_job_executions.py +8 -4
- blaxel/core/client/api/jobs/list_jobs.py +12 -8
- blaxel/core/client/api/jobs/update_job.py +20 -12
- blaxel/core/client/api/locations/list_locations.py +12 -8
- blaxel/core/client/api/{default → mcphub}/list_mcp_hub_definitions.py +20 -4
- blaxel/core/client/api/models/create_model.py +52 -23
- blaxel/core/client/api/models/delete_model.py +40 -19
- blaxel/core/client/api/models/get_model.py +40 -19
- blaxel/core/client/api/models/list_models.py +40 -19
- blaxel/core/client/api/models/update_model.py +52 -23
- blaxel/core/client/api/policies/create_policy.py +12 -8
- blaxel/core/client/api/policies/delete_policy.py +12 -8
- blaxel/core/client/api/policies/get_policy.py +12 -8
- blaxel/core/client/api/policies/list_policies.py +12 -8
- blaxel/core/client/api/policies/update_policy.py +12 -8
- blaxel/core/client/api/public_ipslist/list_public_ips.py +37 -5
- blaxel/core/client/api/sandboxhub/__init__.py +0 -0
- blaxel/core/client/api/{default → sandboxhub}/list_sandbox_hub_definitions.py +20 -4
- blaxel/core/client/api/service_accounts/create_api_key_for_service_account.py +12 -8
- blaxel/core/client/api/service_accounts/create_workspace_service_account.py +12 -8
- blaxel/core/client/api/service_accounts/delete_api_key_for_service_account.py +6 -4
- blaxel/core/client/api/service_accounts/delete_workspace_service_account.py +12 -8
- blaxel/core/client/api/service_accounts/get_workspace_service_accounts.py +12 -8
- blaxel/core/client/api/service_accounts/list_api_keys_for_service_account.py +12 -8
- blaxel/core/client/api/service_accounts/update_workspace_service_account.py +8 -8
- blaxel/core/client/api/templates/list_templates.py +12 -8
- blaxel/core/client/api/volume_templates/create_volume_template.py +8 -4
- blaxel/core/client/api/volume_templates/list_volume_templates.py +8 -4
- blaxel/core/client/api/volumes/create_volume.py +56 -23
- blaxel/core/client/api/volumes/delete_volume.py +44 -19
- blaxel/core/client/api/volumes/get_volume.py +40 -19
- blaxel/core/client/api/volumes/list_volumes.py +40 -19
- blaxel/core/client/api/workspaces/create_workspace.py +54 -23
- blaxel/core/client/api/workspaces/delete_workspace.py +42 -19
- blaxel/core/client/api/workspaces/get_workspace.py +42 -19
- blaxel/core/client/api/workspaces/invite_workspace_user.py +8 -4
- blaxel/core/client/api/workspaces/list_workspace_users.py +12 -8
- blaxel/core/client/api/workspaces/list_workspaces.py +36 -19
- blaxel/core/client/api/workspaces/update_workspace.py +50 -19
- blaxel/core/client/models/__init__.py +76 -146
- blaxel/core/client/models/agent.py +43 -47
- blaxel/core/client/models/agent_runtime.py +139 -0
- blaxel/core/client/models/agent_runtime_generation.py +18 -0
- blaxel/core/client/models/agent_spec.py +33 -110
- blaxel/core/client/models/api_key.py +5 -4
- blaxel/core/client/models/core_event.py +5 -5
- blaxel/core/client/models/create_api_key_for_service_account_body.py +2 -1
- blaxel/core/client/models/create_job_execution_request.py +1 -1
- blaxel/core/client/models/create_job_execution_response.py +13 -9
- blaxel/core/client/models/custom_domain.py +19 -36
- blaxel/core/client/models/custom_domain_metadata.py +4 -3
- blaxel/core/client/models/custom_domain_spec.py +14 -5
- blaxel/core/client/models/custom_domain_spec_status.py +19 -0
- blaxel/core/client/models/entrypoint.py +39 -13
- blaxel/core/client/models/{workspace_labels.py → entrypoint_args_item.py} +6 -6
- blaxel/core/client/models/entrypoint_env.py +3 -3
- blaxel/core/client/models/{job_metrics_executions_total.py → entrypoint_super_gateway_args_item.py} +6 -6
- blaxel/core/client/models/{spec_configuration.py → env.py} +17 -8
- blaxel/core/{sandbox/client/models/welcome_response.py → client/models/error.py} +26 -23
- blaxel/core/client/models/expiration_policy.py +30 -11
- blaxel/core/client/models/expiration_policy_action.py +17 -0
- blaxel/core/client/models/expiration_policy_type.py +19 -0
- blaxel/core/client/models/flavor.py +13 -5
- blaxel/core/client/models/flavor_type.py +18 -0
- blaxel/core/client/models/form.py +6 -6
- blaxel/core/client/models/function.py +43 -47
- blaxel/core/client/models/function_runtime.py +138 -0
- blaxel/core/client/models/function_runtime_generation.py +18 -0
- blaxel/core/client/models/function_spec.py +27 -73
- blaxel/core/client/models/function_spec_transport.py +18 -0
- blaxel/core/client/models/image.py +19 -36
- blaxel/core/client/models/integration_connection.py +25 -39
- blaxel/core/client/models/integration_connection_spec.py +8 -5
- blaxel/core/client/models/integration_connection_spec_config.py +1 -1
- blaxel/core/client/models/integration_connection_spec_secret.py +1 -1
- blaxel/core/client/models/integration_endpoint.py +41 -11
- blaxel/core/client/models/integration_endpoint_ignore_models_item.py +45 -0
- blaxel/core/client/models/{mcp_definition_entrypoint.py → integration_endpoint_models_item.py} +6 -6
- blaxel/core/client/models/job.py +43 -47
- blaxel/core/client/models/job_execution.py +30 -37
- blaxel/core/client/models/job_execution_metadata.py +3 -3
- blaxel/core/client/models/job_execution_spec.py +2 -2
- blaxel/core/client/models/job_execution_stats.py +5 -5
- blaxel/core/client/models/job_execution_status.py +24 -0
- blaxel/core/client/models/job_execution_task.py +12 -4
- blaxel/core/client/models/job_execution_task_metadata.py +1 -1
- blaxel/core/client/models/job_execution_task_spec.py +2 -2
- blaxel/core/client/models/job_execution_task_status.py +23 -0
- blaxel/core/client/models/job_runtime.py +172 -0
- blaxel/core/client/models/job_runtime_generation.py +18 -0
- blaxel/core/client/models/job_spec.py +20 -88
- blaxel/core/client/models/location_response.py +5 -5
- blaxel/core/client/models/mcp_definition.py +30 -17
- blaxel/core/client/models/{job_metrics_tasks_total.py → mcp_definition_categories_item.py} +6 -6
- blaxel/core/client/models/metadata.py +23 -17
- blaxel/core/client/models/metadata_labels.py +4 -1
- blaxel/core/client/models/model.py +43 -47
- blaxel/core/client/models/model_runtime.py +99 -0
- blaxel/core/client/models/model_runtime_type.py +34 -0
- blaxel/core/client/models/model_spec.py +12 -58
- blaxel/core/client/models/o_auth.py +23 -6
- blaxel/core/client/models/{form_oauth.py → o_auth_scope_item.py} +6 -6
- blaxel/core/client/models/pending_invitation_accept.py +2 -1
- blaxel/core/client/models/pending_invitation_workspace_details.py +27 -6
- blaxel/core/client/models/{metrics_request_total_per_code.py → pending_invitation_workspace_details_emails_item.py} +6 -6
- blaxel/core/client/models/policy.py +20 -36
- blaxel/core/client/models/policy_location.py +13 -5
- blaxel/core/client/models/policy_location_type.py +19 -0
- blaxel/core/client/models/policy_max_tokens.py +6 -6
- blaxel/core/client/models/policy_resource_type.py +20 -0
- blaxel/core/client/models/policy_spec.py +31 -10
- blaxel/core/client/models/policy_spec_type.py +19 -0
- blaxel/core/client/models/port.py +25 -15
- blaxel/core/client/models/port_protocol.py +19 -0
- blaxel/core/client/models/preview.py +19 -36
- blaxel/core/client/models/preview_metadata.py +12 -10
- blaxel/core/client/models/preview_token.py +19 -36
- blaxel/core/client/models/preview_token_metadata.py +8 -6
- blaxel/core/client/models/repository.py +2 -2
- blaxel/core/client/models/revision_configuration.py +3 -3
- blaxel/core/client/models/sandbox.py +45 -58
- blaxel/core/client/models/sandbox_definition.py +37 -22
- blaxel/core/client/models/sandbox_definition_categories_item.py +45 -0
- blaxel/core/client/models/sandbox_error.py +148 -0
- blaxel/core/client/models/sandbox_error_details.py +45 -0
- blaxel/core/client/models/sandbox_lifecycle.py +3 -2
- blaxel/core/client/models/sandbox_runtime.py +145 -0
- blaxel/core/client/models/sandbox_spec.py +33 -134
- blaxel/core/client/models/status.py +25 -0
- blaxel/core/client/models/template.py +8 -7
- blaxel/core/client/models/template_variable.py +5 -5
- blaxel/core/client/models/trigger.py +14 -6
- blaxel/core/client/models/trigger_configuration.py +7 -6
- blaxel/core/client/models/trigger_type.py +19 -0
- blaxel/core/client/models/volume.py +35 -47
- blaxel/core/client/models/volume_attachment.py +6 -4
- blaxel/core/client/models/volume_spec.py +7 -4
- blaxel/core/client/models/volume_state.py +3 -3
- blaxel/core/client/models/volume_template.py +19 -33
- blaxel/core/client/models/volume_template_state.py +12 -4
- blaxel/core/client/models/volume_template_state_status.py +19 -0
- blaxel/core/client/models/volume_template_version.py +12 -4
- blaxel/core/client/models/volume_template_version_status.py +19 -0
- blaxel/core/client/models/workspace.py +35 -25
- blaxel/core/client/models/workspace_runtime.py +3 -2
- blaxel/core/client/models/workspace_status.py +22 -0
- blaxel/core/common/__init__.py +1 -1
- blaxel/core/jobs/__init__.py +0 -1
- blaxel/core/sandbox/__init__.py +2 -0
- blaxel/core/sandbox/client/api/process/post_process.py +8 -4
- blaxel/core/sandbox/client/models/__init__.py +0 -2
- blaxel/core/sandbox/client/models/process_response.py +16 -0
- blaxel/core/sandbox/client/models/process_response_status.py +9 -0
- blaxel/core/sandbox/default/__init__.py +2 -0
- blaxel/core/sandbox/default/interpreter.py +5 -1
- blaxel/core/sandbox/default/preview.py +3 -1
- blaxel/core/sandbox/default/sandbox.py +51 -16
- blaxel/core/sandbox/sync/process.py +2 -1
- blaxel/core/sandbox/sync/sandbox.py +34 -13
- blaxel/core/tools/common.py +16 -2
- blaxel/core/volume/__init__.py +2 -2
- blaxel/core/volume/volume.py +32 -10
- blaxel/langgraph/tools.py +34 -2
- blaxel/openai/tools.py +33 -1
- {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/METADATA +3 -3
- {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/RECORD +207 -246
- blaxel/core/client/models/acl.py +0 -133
- blaxel/core/client/models/billable_time_metric.py +0 -89
- blaxel/core/client/models/core_spec.py +0 -194
- blaxel/core/client/models/core_spec_configurations.py +0 -77
- blaxel/core/client/models/histogram_bucket.py +0 -79
- blaxel/core/client/models/histogram_stats.py +0 -88
- blaxel/core/client/models/integration_model.py +0 -162
- blaxel/core/client/models/job_execution_config.py +0 -79
- blaxel/core/client/models/job_metrics.py +0 -262
- blaxel/core/client/models/jobs_chart_value.py +0 -70
- blaxel/core/client/models/jobs_network_chart.py +0 -102
- blaxel/core/client/models/jobs_success_failed_chart.py +0 -147
- blaxel/core/client/models/jobs_total.py +0 -88
- blaxel/core/client/models/last_n_requests_metric.py +0 -97
- blaxel/core/client/models/latency_metric.py +0 -148
- blaxel/core/client/models/logs_response.py +0 -63
- blaxel/core/client/models/logs_response_data.py +0 -99
- blaxel/core/client/models/mcp_definition_form.py +0 -45
- blaxel/core/client/models/memory_allocation_by_name.py +0 -70
- blaxel/core/client/models/memory_allocation_metric.py +0 -61
- blaxel/core/client/models/metric.py +0 -79
- blaxel/core/client/models/metrics.py +0 -273
- blaxel/core/client/models/metrics_models.py +0 -45
- blaxel/core/client/models/metrics_rps_per_code.py +0 -45
- blaxel/core/client/models/pod_template_spec.py +0 -45
- blaxel/core/client/models/request_duration_over_time_metric.py +0 -97
- blaxel/core/client/models/request_duration_over_time_metrics.py +0 -84
- blaxel/core/client/models/request_total_by_origin_metric.py +0 -129
- blaxel/core/client/models/request_total_by_origin_metric_request_total_by_origin.py +0 -45
- blaxel/core/client/models/request_total_by_origin_metric_request_total_by_origin_and_code.py +0 -45
- blaxel/core/client/models/request_total_metric.py +0 -155
- blaxel/core/client/models/request_total_metric_request_total_per_code.py +0 -45
- blaxel/core/client/models/request_total_metric_rps_per_code.py +0 -45
- blaxel/core/client/models/request_total_response_data.py +0 -97
- blaxel/core/client/models/resource.py +0 -99
- blaxel/core/client/models/resource_log.py +0 -88
- blaxel/core/client/models/resource_log_chart.py +0 -133
- blaxel/core/client/models/resource_log_response.py +0 -83
- blaxel/core/client/models/resource_metrics.py +0 -618
- blaxel/core/client/models/resource_metrics_request_total_per_code.py +0 -45
- blaxel/core/client/models/resource_metrics_request_total_per_code_previous.py +0 -45
- blaxel/core/client/models/resource_metrics_rps_per_code.py +0 -45
- blaxel/core/client/models/resource_metrics_rps_per_code_previous.py +0 -45
- blaxel/core/client/models/resource_trace.py +0 -97
- blaxel/core/client/models/runtime.py +0 -317
- blaxel/core/client/models/runtime_configuration.py +0 -45
- blaxel/core/client/models/runtime_startup_probe.py +0 -45
- blaxel/core/client/models/sandbox_metrics.py +0 -88
- blaxel/core/client/models/serverless_config.py +0 -117
- blaxel/core/client/models/serverless_config_configuration.py +0 -45
- blaxel/core/client/models/start_sandbox.py +0 -98
- blaxel/core/client/models/stop_sandbox.py +0 -98
- blaxel/core/client/models/store_agent.py +0 -181
- blaxel/core/client/models/store_agent_labels.py +0 -45
- blaxel/core/client/models/store_configuration.py +0 -156
- blaxel/core/client/models/store_configuration_option.py +0 -79
- blaxel/core/client/models/time_to_first_token_over_time_metrics.py +0 -87
- blaxel/core/client/models/token_rate_metric.py +0 -106
- blaxel/core/client/models/token_rate_metrics.py +0 -124
- blaxel/core/client/models/token_total_metric.py +0 -112
- blaxel/core/client/models/trace_ids_response.py +0 -45
- blaxel/core/client/models/websocket_channel.py +0 -97
- blaxel/core/client/models/websocket_message.py +0 -106
- blaxel/core/sandbox/client/api/root/delete.py +0 -130
- blaxel/core/sandbox/client/api/root/get.py +0 -130
- blaxel/core/sandbox/client/api/root/options.py +0 -130
- blaxel/core/sandbox/client/api/root/patch.py +0 -130
- blaxel/core/sandbox/client/api/root/post.py +0 -130
- blaxel/core/sandbox/client/api/root/put.py +0 -130
- /blaxel/core/{sandbox/client/api/root → client/api/mcphub}/__init__.py +0 -0
- {blaxel-0.2.34.dist-info → blaxel-0.2.35.dist-info}/WHEEL +0 -0
- {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
|
blaxel/core/common/__init__.py
CHANGED
|
@@ -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,
|
blaxel/core/jobs/__init__.py
CHANGED
blaxel/core/sandbox/__init__.py
CHANGED
|
@@ -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,
|
|
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=
|
|
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=
|
|
202
|
+
runtime=SandboxRuntime(image=default_image, memory=default_memory)
|
|
190
203
|
)
|
|
191
204
|
if not sandbox.spec.runtime:
|
|
192
|
-
sandbox.spec.runtime =
|
|
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,
|
|
255
|
-
|
|
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
|
|
314
|
+
except SandboxAPIError as e:
|
|
280
315
|
# Check if it's a 409 conflict error (sandbox already exists)
|
|
281
|
-
if
|
|
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
|
|
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,
|
|
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,
|
|
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=
|
|
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=
|
|
176
|
+
runtime=SandboxRuntime(image=default_image, memory=default_memory)
|
|
175
177
|
)
|
|
176
178
|
if not sandbox.spec.runtime:
|
|
177
|
-
sandbox.spec.runtime =
|
|
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
|
-
|
|
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
|
|
237
|
-
if
|
|
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
|
|
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,
|
blaxel/core/tools/common.py
CHANGED
|
@@ -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 =
|
|
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:
|
blaxel/core/volume/__init__.py
CHANGED
|
@@ -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"]
|