blaxel 0.64.0__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 +8 -0
- blaxel/agents/__init__.py +5 -0
- blaxel/agents/chain.py +153 -0
- blaxel/agents/chat.py +286 -0
- blaxel/agents/decorator.py +208 -0
- blaxel/agents/thread.py +24 -0
- blaxel/agents/voice/openai.py +255 -0
- blaxel/agents/voice/utils.py +25 -0
- blaxel/api/__init__.py +1 -0
- blaxel/api/agents/__init__.py +0 -0
- blaxel/api/agents/create_agent.py +155 -0
- blaxel/api/agents/delete_agent.py +146 -0
- blaxel/api/agents/get_agent.py +146 -0
- blaxel/api/agents/get_agent_logs.py +151 -0
- blaxel/api/agents/get_agent_metrics.py +150 -0
- blaxel/api/agents/get_agent_trace_ids.py +201 -0
- blaxel/api/agents/list_agent_revisions.py +155 -0
- blaxel/api/agents/list_agents.py +127 -0
- blaxel/api/agents/update_agent.py +168 -0
- blaxel/api/configurations/__init__.py +0 -0
- blaxel/api/configurations/get_configuration.py +122 -0
- blaxel/api/default/__init__.py +0 -0
- blaxel/api/default/get_trace.py +150 -0
- blaxel/api/default/get_trace_ids.py +218 -0
- blaxel/api/default/get_trace_logs.py +186 -0
- blaxel/api/default/list_mcp_hub_definitions.py +127 -0
- blaxel/api/functions/__init__.py +0 -0
- blaxel/api/functions/create_function.py +155 -0
- blaxel/api/functions/delete_function.py +146 -0
- blaxel/api/functions/get_function.py +146 -0
- blaxel/api/functions/get_function_logs.py +151 -0
- blaxel/api/functions/get_function_metrics.py +150 -0
- blaxel/api/functions/get_function_trace_ids.py +201 -0
- blaxel/api/functions/list_function_revisions.py +158 -0
- blaxel/api/functions/list_functions.py +131 -0
- blaxel/api/functions/update_function.py +168 -0
- blaxel/api/integrations/__init__.py +0 -0
- blaxel/api/integrations/create_integration_connection.py +167 -0
- blaxel/api/integrations/delete_integration_connection.py +158 -0
- blaxel/api/integrations/get_integration.py +97 -0
- blaxel/api/integrations/get_integration_connection.py +158 -0
- blaxel/api/integrations/get_integration_connection_model.py +104 -0
- blaxel/api/integrations/get_integration_connection_model_endpoint_configurations.py +97 -0
- blaxel/api/integrations/list_integration_connection_models.py +97 -0
- blaxel/api/integrations/list_integration_connections.py +139 -0
- blaxel/api/integrations/update_integration_connection.py +180 -0
- blaxel/api/invitations/__init__.py +0 -0
- blaxel/api/invitations/list_all_pending_invitations.py +142 -0
- blaxel/api/knowledgebases/__init__.py +0 -0
- blaxel/api/knowledgebases/create_knowledgebase.py +163 -0
- blaxel/api/knowledgebases/delete_knowledgebase.py +154 -0
- blaxel/api/knowledgebases/get_knowledgebase.py +154 -0
- blaxel/api/knowledgebases/list_knowledgebase_revisions.py +158 -0
- blaxel/api/knowledgebases/list_knowledgebases.py +139 -0
- blaxel/api/knowledgebases/update_knowledgebase.py +176 -0
- blaxel/api/locations/__init__.py +0 -0
- blaxel/api/locations/list_locations.py +139 -0
- blaxel/api/metrics/__init__.py +0 -0
- blaxel/api/metrics/get_metrics.py +130 -0
- blaxel/api/models/__init__.py +0 -0
- blaxel/api/models/create_model.py +163 -0
- blaxel/api/models/delete_model.py +154 -0
- blaxel/api/models/get_model.py +154 -0
- blaxel/api/models/get_model_logs.py +155 -0
- blaxel/api/models/get_model_metrics.py +158 -0
- blaxel/api/models/get_model_trace_ids.py +201 -0
- blaxel/api/models/list_model_revisions.py +158 -0
- blaxel/api/models/list_models.py +135 -0
- blaxel/api/models/update_model.py +176 -0
- blaxel/api/policies/__init__.py +0 -0
- blaxel/api/policies/create_policy.py +167 -0
- blaxel/api/policies/delete_policy.py +154 -0
- blaxel/api/policies/get_policy.py +154 -0
- blaxel/api/policies/list_policies.py +139 -0
- blaxel/api/policies/update_policy.py +180 -0
- blaxel/api/privateclusters/__init__.py +0 -0
- blaxel/api/privateclusters/create_private_cluster.py +132 -0
- blaxel/api/privateclusters/delete_private_cluster.py +156 -0
- blaxel/api/privateclusters/get_private_cluster.py +159 -0
- blaxel/api/privateclusters/get_private_cluster_health.py +97 -0
- blaxel/api/privateclusters/list_private_clusters.py +140 -0
- blaxel/api/privateclusters/update_private_cluster.py +156 -0
- blaxel/api/privateclusters/update_private_cluster_health.py +97 -0
- blaxel/api/service_accounts/__init__.py +0 -0
- blaxel/api/service_accounts/create_api_key_for_service_account.py +177 -0
- blaxel/api/service_accounts/create_workspace_service_account.py +170 -0
- blaxel/api/service_accounts/delete_api_key_for_service_account.py +104 -0
- blaxel/api/service_accounts/delete_workspace_service_account.py +160 -0
- blaxel/api/service_accounts/get_workspace_service_accounts.py +141 -0
- blaxel/api/service_accounts/list_api_keys_for_service_account.py +163 -0
- blaxel/api/service_accounts/update_workspace_service_account.py +183 -0
- blaxel/api/store/__init__.py +0 -0
- blaxel/api/store/get_store_agent.py +146 -0
- blaxel/api/store/get_store_function.py +146 -0
- blaxel/api/store/list_store_agents.py +131 -0
- blaxel/api/store/list_store_functions.py +131 -0
- blaxel/api/workspaces/__init__.py +0 -0
- blaxel/api/workspaces/accept_workspace_invitation.py +161 -0
- blaxel/api/workspaces/create_worspace.py +163 -0
- blaxel/api/workspaces/decline_workspace_invitation.py +158 -0
- blaxel/api/workspaces/delete_workspace.py +154 -0
- blaxel/api/workspaces/get_workspace.py +154 -0
- blaxel/api/workspaces/invite_workspace_user.py +174 -0
- blaxel/api/workspaces/leave_workspace.py +161 -0
- blaxel/api/workspaces/list_workspace_users.py +139 -0
- blaxel/api/workspaces/list_workspaces.py +139 -0
- blaxel/api/workspaces/remove_workspace_user.py +101 -0
- blaxel/api/workspaces/update_workspace.py +176 -0
- blaxel/api/workspaces/update_workspace_user_role.py +187 -0
- blaxel/authentication/__init__.py +45 -0
- blaxel/authentication/apikey.py +50 -0
- blaxel/authentication/authentication.py +176 -0
- blaxel/authentication/clientcredentials.py +103 -0
- blaxel/authentication/credentials.py +295 -0
- blaxel/authentication/device_mode.py +197 -0
- blaxel/client.py +281 -0
- blaxel/common/__init__.py +17 -0
- blaxel/common/error.py +27 -0
- blaxel/common/instrumentation.py +317 -0
- blaxel/common/logger.py +60 -0
- blaxel/common/secrets.py +39 -0
- blaxel/common/settings.py +150 -0
- blaxel/common/slugify.py +18 -0
- blaxel/common/utils.py +34 -0
- blaxel/deploy/__init__.py +8 -0
- blaxel/deploy/deploy.py +316 -0
- blaxel/deploy/format.py +46 -0
- blaxel/deploy/parser.py +192 -0
- blaxel/errors.py +16 -0
- blaxel/functions/__init__.py +7 -0
- blaxel/functions/common.py +228 -0
- blaxel/functions/decorator.py +64 -0
- blaxel/functions/local/local.py +48 -0
- blaxel/functions/mcp/client.py +96 -0
- blaxel/functions/mcp/mcp.py +168 -0
- blaxel/functions/mcp/utils.py +56 -0
- blaxel/functions/remote/remote.py +183 -0
- blaxel/models/__init__.py +233 -0
- blaxel/models/acl.py +133 -0
- blaxel/models/agent.py +126 -0
- blaxel/models/agent_chain.py +88 -0
- blaxel/models/agent_spec.py +346 -0
- blaxel/models/api_key.py +142 -0
- blaxel/models/configuration.py +85 -0
- blaxel/models/continent.py +70 -0
- blaxel/models/core_event.py +97 -0
- blaxel/models/core_spec.py +249 -0
- blaxel/models/core_spec_configurations.py +77 -0
- blaxel/models/country.py +70 -0
- blaxel/models/create_api_key_for_service_account_body.py +69 -0
- blaxel/models/create_workspace_service_account_body.py +71 -0
- blaxel/models/create_workspace_service_account_response_200.py +105 -0
- blaxel/models/delete_workspace_service_account_response_200.py +96 -0
- blaxel/models/entrypoint.py +96 -0
- blaxel/models/entrypoint_env.py +45 -0
- blaxel/models/flavor.py +70 -0
- blaxel/models/form.py +120 -0
- blaxel/models/form_config.py +45 -0
- blaxel/models/form_oauthomitempty.py +45 -0
- blaxel/models/form_secrets.py +45 -0
- blaxel/models/function.py +126 -0
- blaxel/models/function_kit.py +97 -0
- blaxel/models/function_spec.py +310 -0
- blaxel/models/get_trace_ids_response_200.py +45 -0
- blaxel/models/get_trace_logs_response_200.py +45 -0
- blaxel/models/get_trace_response_200.py +45 -0
- blaxel/models/get_workspace_service_accounts_response_200_item.py +96 -0
- blaxel/models/histogram_bucket.py +79 -0
- blaxel/models/histogram_stats.py +88 -0
- blaxel/models/integration_connection.py +96 -0
- blaxel/models/integration_connection_spec.py +114 -0
- blaxel/models/integration_connection_spec_config.py +45 -0
- blaxel/models/integration_connection_spec_secret.py +45 -0
- blaxel/models/integration_model.py +162 -0
- blaxel/models/integration_repository.py +88 -0
- blaxel/models/invite_workspace_user_body.py +60 -0
- blaxel/models/knowledgebase.py +126 -0
- blaxel/models/knowledgebase_spec.py +163 -0
- blaxel/models/knowledgebase_spec_options.py +45 -0
- blaxel/models/last_n_requests_metric.py +79 -0
- blaxel/models/latency_metric.py +144 -0
- blaxel/models/location_response.py +113 -0
- blaxel/models/mcp_definition.py +188 -0
- blaxel/models/mcp_definition_entrypoint.py +45 -0
- blaxel/models/mcp_definition_form.py +45 -0
- blaxel/models/metadata.py +139 -0
- blaxel/models/metadata_labels.py +45 -0
- blaxel/models/metric.py +79 -0
- blaxel/models/metrics.py +169 -0
- blaxel/models/metrics_models.py +45 -0
- blaxel/models/metrics_request_total_per_code.py +45 -0
- blaxel/models/metrics_rps_per_code.py +45 -0
- blaxel/models/model.py +126 -0
- blaxel/models/model_private_cluster.py +79 -0
- blaxel/models/model_spec.py +249 -0
- blaxel/models/o_auth.py +72 -0
- blaxel/models/owner_fields.py +70 -0
- blaxel/models/pending_invitation.py +124 -0
- blaxel/models/pending_invitation_accept.py +85 -0
- blaxel/models/pending_invitation_render.py +147 -0
- blaxel/models/pending_invitation_render_invited_by.py +88 -0
- blaxel/models/pending_invitation_render_workspace.py +70 -0
- blaxel/models/pending_invitation_workspace_details.py +72 -0
- blaxel/models/pod_template_spec.py +45 -0
- blaxel/models/policy.py +96 -0
- blaxel/models/policy_location.py +70 -0
- blaxel/models/policy_max_tokens.py +106 -0
- blaxel/models/policy_spec.py +151 -0
- blaxel/models/private_cluster.py +183 -0
- blaxel/models/private_location.py +61 -0
- blaxel/models/repository.py +70 -0
- blaxel/models/request_duration_over_time_metric.py +97 -0
- blaxel/models/request_duration_over_time_metrics.py +80 -0
- blaxel/models/request_total_by_origin_metric.py +115 -0
- blaxel/models/request_total_by_origin_metric_request_total_by_origin.py +45 -0
- blaxel/models/request_total_by_origin_metric_request_total_by_origin_and_code.py +45 -0
- blaxel/models/request_total_metric.py +123 -0
- blaxel/models/request_total_metric_request_total_per_code.py +45 -0
- blaxel/models/request_total_metric_rps_per_code.py +45 -0
- blaxel/models/resource_log.py +79 -0
- blaxel/models/resource_metrics.py +270 -0
- blaxel/models/resource_metrics_request_total_per_code.py +45 -0
- blaxel/models/resource_metrics_rps_per_code.py +45 -0
- blaxel/models/revision_configuration.py +97 -0
- blaxel/models/revision_metadata.py +124 -0
- blaxel/models/runtime.py +196 -0
- blaxel/models/runtime_startup_probe.py +45 -0
- blaxel/models/serverless_config.py +80 -0
- blaxel/models/spec_configuration.py +70 -0
- blaxel/models/store_agent.py +178 -0
- blaxel/models/store_agent_labels.py +45 -0
- blaxel/models/store_configuration.py +151 -0
- blaxel/models/store_configuration_option.py +79 -0
- blaxel/models/store_function.py +211 -0
- blaxel/models/store_function_kit.py +97 -0
- blaxel/models/store_function_labels.py +45 -0
- blaxel/models/store_function_parameter.py +88 -0
- blaxel/models/time_fields.py +70 -0
- blaxel/models/token_rate_metric.py +88 -0
- blaxel/models/token_rate_metrics.py +120 -0
- blaxel/models/token_total_metric.py +106 -0
- blaxel/models/trace_ids_response.py +45 -0
- blaxel/models/update_workspace_service_account_body.py +69 -0
- blaxel/models/update_workspace_service_account_response_200.py +96 -0
- blaxel/models/update_workspace_user_role_body.py +60 -0
- blaxel/models/websocket_channel.py +88 -0
- blaxel/models/workspace.py +148 -0
- blaxel/models/workspace_labels.py +45 -0
- blaxel/models/workspace_user.py +115 -0
- blaxel/py.typed +1 -0
- blaxel/run.py +108 -0
- blaxel/serve/app.py +131 -0
- blaxel/serve/middlewares/__init__.py +10 -0
- blaxel/serve/middlewares/accesslog.py +32 -0
- blaxel/serve/middlewares/processtime.py +28 -0
- blaxel/types.py +46 -0
- blaxel-0.64.0.dist-info/METADATA +96 -0
- blaxel-0.64.0.dist-info/RECORD +261 -0
- blaxel-0.64.0.dist-info/WHEEL +4 -0
- blaxel-0.64.0.dist-info/entry_points.txt +2 -0
- blaxel-0.64.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,88 @@
|
|
1
|
+
from typing import Any, TypeVar, Union
|
2
|
+
|
3
|
+
from attrs import define as _attrs_define
|
4
|
+
from attrs import field as _attrs_field
|
5
|
+
|
6
|
+
from ..types import UNSET, Unset
|
7
|
+
|
8
|
+
T = TypeVar("T", bound="WebsocketChannel")
|
9
|
+
|
10
|
+
|
11
|
+
@_attrs_define
|
12
|
+
class WebsocketChannel:
|
13
|
+
"""WebSocket connection details
|
14
|
+
|
15
|
+
Attributes:
|
16
|
+
created_at (Union[Unset, str]): The date and time when the resource was created
|
17
|
+
updated_at (Union[Unset, str]): The date and time when the resource was updated
|
18
|
+
connection_id (Union[Unset, str]): Unique connection ID
|
19
|
+
workspace (Union[Unset, str]): Workspace the connection belongs to
|
20
|
+
"""
|
21
|
+
|
22
|
+
created_at: Union[Unset, str] = UNSET
|
23
|
+
updated_at: Union[Unset, str] = UNSET
|
24
|
+
connection_id: Union[Unset, str] = UNSET
|
25
|
+
workspace: Union[Unset, str] = UNSET
|
26
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
27
|
+
|
28
|
+
def to_dict(self) -> dict[str, Any]:
|
29
|
+
created_at = self.created_at
|
30
|
+
|
31
|
+
updated_at = self.updated_at
|
32
|
+
|
33
|
+
connection_id = self.connection_id
|
34
|
+
|
35
|
+
workspace = self.workspace
|
36
|
+
|
37
|
+
field_dict: dict[str, Any] = {}
|
38
|
+
field_dict.update(self.additional_properties)
|
39
|
+
field_dict.update({})
|
40
|
+
if created_at is not UNSET:
|
41
|
+
field_dict["createdAt"] = created_at
|
42
|
+
if updated_at is not UNSET:
|
43
|
+
field_dict["updatedAt"] = updated_at
|
44
|
+
if connection_id is not UNSET:
|
45
|
+
field_dict["connection_id"] = connection_id
|
46
|
+
if workspace is not UNSET:
|
47
|
+
field_dict["workspace"] = workspace
|
48
|
+
|
49
|
+
return field_dict
|
50
|
+
|
51
|
+
@classmethod
|
52
|
+
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
|
53
|
+
if not src_dict:
|
54
|
+
return None
|
55
|
+
d = src_dict.copy()
|
56
|
+
created_at = d.pop("createdAt", UNSET)
|
57
|
+
|
58
|
+
updated_at = d.pop("updatedAt", UNSET)
|
59
|
+
|
60
|
+
connection_id = d.pop("connection_id", UNSET)
|
61
|
+
|
62
|
+
workspace = d.pop("workspace", UNSET)
|
63
|
+
|
64
|
+
websocket_channel = cls(
|
65
|
+
created_at=created_at,
|
66
|
+
updated_at=updated_at,
|
67
|
+
connection_id=connection_id,
|
68
|
+
workspace=workspace,
|
69
|
+
)
|
70
|
+
|
71
|
+
websocket_channel.additional_properties = d
|
72
|
+
return websocket_channel
|
73
|
+
|
74
|
+
@property
|
75
|
+
def additional_keys(self) -> list[str]:
|
76
|
+
return list(self.additional_properties.keys())
|
77
|
+
|
78
|
+
def __getitem__(self, key: str) -> Any:
|
79
|
+
return self.additional_properties[key]
|
80
|
+
|
81
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
82
|
+
self.additional_properties[key] = value
|
83
|
+
|
84
|
+
def __delitem__(self, key: str) -> None:
|
85
|
+
del self.additional_properties[key]
|
86
|
+
|
87
|
+
def __contains__(self, key: str) -> bool:
|
88
|
+
return key in self.additional_properties
|
@@ -0,0 +1,148 @@
|
|
1
|
+
from typing import TYPE_CHECKING, Any, TypeVar, Union
|
2
|
+
|
3
|
+
from attrs import define as _attrs_define
|
4
|
+
from attrs import field as _attrs_field
|
5
|
+
|
6
|
+
from ..types import UNSET, Unset
|
7
|
+
|
8
|
+
if TYPE_CHECKING:
|
9
|
+
from ..models.workspace_labels import WorkspaceLabels
|
10
|
+
|
11
|
+
|
12
|
+
T = TypeVar("T", bound="Workspace")
|
13
|
+
|
14
|
+
|
15
|
+
@_attrs_define
|
16
|
+
class Workspace:
|
17
|
+
"""Workspace
|
18
|
+
|
19
|
+
Attributes:
|
20
|
+
created_at (Union[Unset, str]): The date and time when the resource was created
|
21
|
+
updated_at (Union[Unset, str]): The date and time when the resource was updated
|
22
|
+
created_by (Union[Unset, str]): The user or service account who created the resource
|
23
|
+
updated_by (Union[Unset, str]): The user or service account who updated the resource
|
24
|
+
account_id (Union[Unset, str]): Workspace account id
|
25
|
+
display_name (Union[Unset, str]): Workspace display name
|
26
|
+
labels (Union[Unset, WorkspaceLabels]): Workspace labels
|
27
|
+
name (Union[Unset, str]): Workspace name
|
28
|
+
region (Union[Unset, str]): Workspace write region
|
29
|
+
"""
|
30
|
+
|
31
|
+
created_at: Union[Unset, str] = UNSET
|
32
|
+
updated_at: Union[Unset, str] = UNSET
|
33
|
+
created_by: Union[Unset, str] = UNSET
|
34
|
+
updated_by: Union[Unset, str] = UNSET
|
35
|
+
account_id: Union[Unset, str] = UNSET
|
36
|
+
display_name: Union[Unset, str] = UNSET
|
37
|
+
labels: Union[Unset, "WorkspaceLabels"] = UNSET
|
38
|
+
name: Union[Unset, str] = UNSET
|
39
|
+
region: Union[Unset, str] = UNSET
|
40
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
41
|
+
|
42
|
+
def to_dict(self) -> dict[str, Any]:
|
43
|
+
created_at = self.created_at
|
44
|
+
|
45
|
+
updated_at = self.updated_at
|
46
|
+
|
47
|
+
created_by = self.created_by
|
48
|
+
|
49
|
+
updated_by = self.updated_by
|
50
|
+
|
51
|
+
account_id = self.account_id
|
52
|
+
|
53
|
+
display_name = self.display_name
|
54
|
+
|
55
|
+
labels: Union[Unset, dict[str, Any]] = UNSET
|
56
|
+
if self.labels and not isinstance(self.labels, Unset) and not isinstance(self.labels, dict):
|
57
|
+
labels = self.labels.to_dict()
|
58
|
+
elif self.labels and isinstance(self.labels, dict):
|
59
|
+
labels = self.labels
|
60
|
+
|
61
|
+
name = self.name
|
62
|
+
|
63
|
+
region = self.region
|
64
|
+
|
65
|
+
field_dict: dict[str, Any] = {}
|
66
|
+
field_dict.update(self.additional_properties)
|
67
|
+
field_dict.update({})
|
68
|
+
if created_at is not UNSET:
|
69
|
+
field_dict["createdAt"] = created_at
|
70
|
+
if updated_at is not UNSET:
|
71
|
+
field_dict["updatedAt"] = updated_at
|
72
|
+
if created_by is not UNSET:
|
73
|
+
field_dict["createdBy"] = created_by
|
74
|
+
if updated_by is not UNSET:
|
75
|
+
field_dict["updatedBy"] = updated_by
|
76
|
+
if account_id is not UNSET:
|
77
|
+
field_dict["accountId"] = account_id
|
78
|
+
if display_name is not UNSET:
|
79
|
+
field_dict["displayName"] = display_name
|
80
|
+
if labels is not UNSET:
|
81
|
+
field_dict["labels"] = labels
|
82
|
+
if name is not UNSET:
|
83
|
+
field_dict["name"] = name
|
84
|
+
if region is not UNSET:
|
85
|
+
field_dict["region"] = region
|
86
|
+
|
87
|
+
return field_dict
|
88
|
+
|
89
|
+
@classmethod
|
90
|
+
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
|
91
|
+
from ..models.workspace_labels import WorkspaceLabels
|
92
|
+
|
93
|
+
if not src_dict:
|
94
|
+
return None
|
95
|
+
d = src_dict.copy()
|
96
|
+
created_at = d.pop("createdAt", UNSET)
|
97
|
+
|
98
|
+
updated_at = d.pop("updatedAt", UNSET)
|
99
|
+
|
100
|
+
created_by = d.pop("createdBy", UNSET)
|
101
|
+
|
102
|
+
updated_by = d.pop("updatedBy", UNSET)
|
103
|
+
|
104
|
+
account_id = d.pop("accountId", UNSET)
|
105
|
+
|
106
|
+
display_name = d.pop("displayName", UNSET)
|
107
|
+
|
108
|
+
_labels = d.pop("labels", UNSET)
|
109
|
+
labels: Union[Unset, WorkspaceLabels]
|
110
|
+
if isinstance(_labels, Unset):
|
111
|
+
labels = UNSET
|
112
|
+
else:
|
113
|
+
labels = WorkspaceLabels.from_dict(_labels)
|
114
|
+
|
115
|
+
name = d.pop("name", UNSET)
|
116
|
+
|
117
|
+
region = d.pop("region", UNSET)
|
118
|
+
|
119
|
+
workspace = cls(
|
120
|
+
created_at=created_at,
|
121
|
+
updated_at=updated_at,
|
122
|
+
created_by=created_by,
|
123
|
+
updated_by=updated_by,
|
124
|
+
account_id=account_id,
|
125
|
+
display_name=display_name,
|
126
|
+
labels=labels,
|
127
|
+
name=name,
|
128
|
+
region=region,
|
129
|
+
)
|
130
|
+
|
131
|
+
workspace.additional_properties = d
|
132
|
+
return workspace
|
133
|
+
|
134
|
+
@property
|
135
|
+
def additional_keys(self) -> list[str]:
|
136
|
+
return list(self.additional_properties.keys())
|
137
|
+
|
138
|
+
def __getitem__(self, key: str) -> Any:
|
139
|
+
return self.additional_properties[key]
|
140
|
+
|
141
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
142
|
+
self.additional_properties[key] = value
|
143
|
+
|
144
|
+
def __delitem__(self, key: str) -> None:
|
145
|
+
del self.additional_properties[key]
|
146
|
+
|
147
|
+
def __contains__(self, key: str) -> bool:
|
148
|
+
return key in self.additional_properties
|
@@ -0,0 +1,45 @@
|
|
1
|
+
from typing import Any, TypeVar
|
2
|
+
|
3
|
+
from attrs import define as _attrs_define
|
4
|
+
from attrs import field as _attrs_field
|
5
|
+
|
6
|
+
T = TypeVar("T", bound="WorkspaceLabels")
|
7
|
+
|
8
|
+
|
9
|
+
@_attrs_define
|
10
|
+
class WorkspaceLabels:
|
11
|
+
"""Workspace labels"""
|
12
|
+
|
13
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
14
|
+
|
15
|
+
def to_dict(self) -> dict[str, Any]:
|
16
|
+
field_dict: dict[str, Any] = {}
|
17
|
+
field_dict.update(self.additional_properties)
|
18
|
+
|
19
|
+
return field_dict
|
20
|
+
|
21
|
+
@classmethod
|
22
|
+
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
|
23
|
+
if not src_dict:
|
24
|
+
return None
|
25
|
+
d = src_dict.copy()
|
26
|
+
workspace_labels = cls()
|
27
|
+
|
28
|
+
workspace_labels.additional_properties = d
|
29
|
+
return workspace_labels
|
30
|
+
|
31
|
+
@property
|
32
|
+
def additional_keys(self) -> list[str]:
|
33
|
+
return list(self.additional_properties.keys())
|
34
|
+
|
35
|
+
def __getitem__(self, key: str) -> Any:
|
36
|
+
return self.additional_properties[key]
|
37
|
+
|
38
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
39
|
+
self.additional_properties[key] = value
|
40
|
+
|
41
|
+
def __delitem__(self, key: str) -> None:
|
42
|
+
del self.additional_properties[key]
|
43
|
+
|
44
|
+
def __contains__(self, key: str) -> bool:
|
45
|
+
return key in self.additional_properties
|
@@ -0,0 +1,115 @@
|
|
1
|
+
from typing import Any, TypeVar, Union
|
2
|
+
|
3
|
+
from attrs import define as _attrs_define
|
4
|
+
from attrs import field as _attrs_field
|
5
|
+
|
6
|
+
from ..types import UNSET, Unset
|
7
|
+
|
8
|
+
T = TypeVar("T", bound="WorkspaceUser")
|
9
|
+
|
10
|
+
|
11
|
+
@_attrs_define
|
12
|
+
class WorkspaceUser:
|
13
|
+
"""Workspace user
|
14
|
+
|
15
|
+
Attributes:
|
16
|
+
accepted (Union[Unset, bool]): Whether the user has accepted the workspace invitation
|
17
|
+
email (Union[Unset, str]): Workspace user email
|
18
|
+
email_verified (Union[Unset, bool]): Whether the user's email has been verified
|
19
|
+
family_name (Union[Unset, str]): Workspace user family name
|
20
|
+
given_name (Union[Unset, str]): Workspace user given name
|
21
|
+
role (Union[Unset, str]): Workspace user role
|
22
|
+
sub (Union[Unset, str]): Workspace user identifier
|
23
|
+
"""
|
24
|
+
|
25
|
+
accepted: Union[Unset, bool] = UNSET
|
26
|
+
email: Union[Unset, str] = UNSET
|
27
|
+
email_verified: Union[Unset, bool] = UNSET
|
28
|
+
family_name: Union[Unset, str] = UNSET
|
29
|
+
given_name: Union[Unset, str] = UNSET
|
30
|
+
role: Union[Unset, str] = UNSET
|
31
|
+
sub: Union[Unset, str] = UNSET
|
32
|
+
additional_properties: dict[str, Any] = _attrs_field(init=False, factory=dict)
|
33
|
+
|
34
|
+
def to_dict(self) -> dict[str, Any]:
|
35
|
+
accepted = self.accepted
|
36
|
+
|
37
|
+
email = self.email
|
38
|
+
|
39
|
+
email_verified = self.email_verified
|
40
|
+
|
41
|
+
family_name = self.family_name
|
42
|
+
|
43
|
+
given_name = self.given_name
|
44
|
+
|
45
|
+
role = self.role
|
46
|
+
|
47
|
+
sub = self.sub
|
48
|
+
|
49
|
+
field_dict: dict[str, Any] = {}
|
50
|
+
field_dict.update(self.additional_properties)
|
51
|
+
field_dict.update({})
|
52
|
+
if accepted is not UNSET:
|
53
|
+
field_dict["accepted"] = accepted
|
54
|
+
if email is not UNSET:
|
55
|
+
field_dict["email"] = email
|
56
|
+
if email_verified is not UNSET:
|
57
|
+
field_dict["email_verified"] = email_verified
|
58
|
+
if family_name is not UNSET:
|
59
|
+
field_dict["family_name"] = family_name
|
60
|
+
if given_name is not UNSET:
|
61
|
+
field_dict["given_name"] = given_name
|
62
|
+
if role is not UNSET:
|
63
|
+
field_dict["role"] = role
|
64
|
+
if sub is not UNSET:
|
65
|
+
field_dict["sub"] = sub
|
66
|
+
|
67
|
+
return field_dict
|
68
|
+
|
69
|
+
@classmethod
|
70
|
+
def from_dict(cls: type[T], src_dict: dict[str, Any]) -> T:
|
71
|
+
if not src_dict:
|
72
|
+
return None
|
73
|
+
d = src_dict.copy()
|
74
|
+
accepted = d.pop("accepted", UNSET)
|
75
|
+
|
76
|
+
email = d.pop("email", UNSET)
|
77
|
+
|
78
|
+
email_verified = d.pop("email_verified", UNSET)
|
79
|
+
|
80
|
+
family_name = d.pop("family_name", UNSET)
|
81
|
+
|
82
|
+
given_name = d.pop("given_name", UNSET)
|
83
|
+
|
84
|
+
role = d.pop("role", UNSET)
|
85
|
+
|
86
|
+
sub = d.pop("sub", UNSET)
|
87
|
+
|
88
|
+
workspace_user = cls(
|
89
|
+
accepted=accepted,
|
90
|
+
email=email,
|
91
|
+
email_verified=email_verified,
|
92
|
+
family_name=family_name,
|
93
|
+
given_name=given_name,
|
94
|
+
role=role,
|
95
|
+
sub=sub,
|
96
|
+
)
|
97
|
+
|
98
|
+
workspace_user.additional_properties = d
|
99
|
+
return workspace_user
|
100
|
+
|
101
|
+
@property
|
102
|
+
def additional_keys(self) -> list[str]:
|
103
|
+
return list(self.additional_properties.keys())
|
104
|
+
|
105
|
+
def __getitem__(self, key: str) -> Any:
|
106
|
+
return self.additional_properties[key]
|
107
|
+
|
108
|
+
def __setitem__(self, key: str, value: Any) -> None:
|
109
|
+
self.additional_properties[key] = value
|
110
|
+
|
111
|
+
def __delitem__(self, key: str) -> None:
|
112
|
+
del self.additional_properties[key]
|
113
|
+
|
114
|
+
def __contains__(self, key: str) -> bool:
|
115
|
+
return key in self.additional_properties
|
blaxel/py.typed
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# Marker file for PEP 561
|
blaxel/run.py
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
"""
|
2
|
+
This module provides functionality for executing HTTP requests against Blaxel resources.
|
3
|
+
"""
|
4
|
+
import urllib.parse
|
5
|
+
from typing import Any
|
6
|
+
|
7
|
+
import requests
|
8
|
+
|
9
|
+
from blaxel.client import AuthenticatedClient
|
10
|
+
from blaxel.common import HTTPError, get_settings
|
11
|
+
|
12
|
+
|
13
|
+
class RunClient:
|
14
|
+
"""Provides functionality for executing HTTP requests against Blaxel resources.
|
15
|
+
|
16
|
+
This module contains the RunClient class which handles authenticated HTTP requests to Blaxel
|
17
|
+
resources. It allows users to interact with different resource types (like functions or services), supporting various HTTP methods and request parameters.
|
18
|
+
|
19
|
+
Example:
|
20
|
+
```python
|
21
|
+
client = new_client()
|
22
|
+
run_client = RunClient(client)
|
23
|
+
response = run_client.run(
|
24
|
+
resource_type="function",
|
25
|
+
resource_name="my-function",
|
26
|
+
method="POST",
|
27
|
+
json={"key": "value"}
|
28
|
+
)
|
29
|
+
```
|
30
|
+
|
31
|
+
Args:
|
32
|
+
client (AuthenticatedClient): An authenticated client instance for making HTTP requests.
|
33
|
+
"""
|
34
|
+
|
35
|
+
def __init__(self, client: AuthenticatedClient):
|
36
|
+
self.client = client
|
37
|
+
|
38
|
+
def run(
|
39
|
+
self,
|
40
|
+
resource_type: str,
|
41
|
+
resource_name: str,
|
42
|
+
method: str,
|
43
|
+
path: str = "",
|
44
|
+
headers: dict[str, str] | None = None,
|
45
|
+
json: dict[str, Any] | None = None,
|
46
|
+
data: str | None = None,
|
47
|
+
params: dict[str, str] | None = None,
|
48
|
+
cloud: bool = False,
|
49
|
+
service_name: str | None = None,
|
50
|
+
) -> requests.Response:
|
51
|
+
"""Execute an HTTP request against a Blaxel resource.
|
52
|
+
|
53
|
+
Args:
|
54
|
+
resource_type (str): The type of resource to interact with (e.g., 'function', 'service').
|
55
|
+
resource_name (str): The name of the specific resource.
|
56
|
+
method (str): The HTTP method to use (e.g., 'GET', 'POST', 'PUT', 'DELETE').
|
57
|
+
path (str, optional): Additional path segments to append to the resource URL. Defaults to "".
|
58
|
+
headers (dict[str, str] | None, optional): HTTP headers to include in the request. Defaults to None.
|
59
|
+
json (dict[str, Any] | None, optional): JSON payload to send with the request. Defaults to None.
|
60
|
+
data (str | None, optional): Raw data to send with the request. Defaults to None.
|
61
|
+
params (dict[str, str] | None, optional): Query parameters to include in the URL. Defaults to None.
|
62
|
+
cloud (bool, optional): Whether to use the cloud endpoint. Defaults to False.
|
63
|
+
service_name (str | None, optional): The name of the service to use. Defaults to None.
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
requests.Response: The HTTP response from the server.
|
67
|
+
|
68
|
+
Raises:
|
69
|
+
HTTPError: If the server responds with a status code >= 400.
|
70
|
+
"""
|
71
|
+
settings = get_settings()
|
72
|
+
headers = headers or {}
|
73
|
+
params = params or {}
|
74
|
+
|
75
|
+
if cloud and path and service_name:
|
76
|
+
url = f"https://{service_name}.{settings.run_internal_hostname}/{path}"
|
77
|
+
|
78
|
+
if cloud and not path and service_name:
|
79
|
+
url = f"https://{service_name}.{settings.run_internal_hostname}"
|
80
|
+
|
81
|
+
if not cloud and path:
|
82
|
+
url = urllib.parse.urljoin(settings.run_url, f"{settings.workspace}/{resource_type}s/{resource_name}/{path}")
|
83
|
+
|
84
|
+
if not cloud and not path:
|
85
|
+
url = urllib.parse.urljoin(settings.run_url, f"{settings.workspace}/{resource_type}s/{resource_name}")
|
86
|
+
|
87
|
+
kwargs = {
|
88
|
+
"headers": headers,
|
89
|
+
"params": {**params},
|
90
|
+
}
|
91
|
+
if data:
|
92
|
+
kwargs["data"] = data
|
93
|
+
if json:
|
94
|
+
kwargs["json"] = json
|
95
|
+
|
96
|
+
response = self.client.get_httpx_client().request(method, url, **kwargs)
|
97
|
+
if response.status_code >= 400 and not cloud:
|
98
|
+
raise HTTPError(response.status_code, response.text)
|
99
|
+
if response.status_code >= 400 and cloud: # Redirect to the public endpoint if the resource is in the cloud and the request fails
|
100
|
+
if path:
|
101
|
+
url = urllib.parse.urljoin(settings.run_url, f"{settings.workspace}/{resource_type}s/{resource_name}/{path}")
|
102
|
+
else:
|
103
|
+
url = urllib.parse.urljoin(settings.run_url, f"{settings.workspace}/{resource_type}s/{resource_name}")
|
104
|
+
response = self.client.get_httpx_client().request(method, url, **kwargs)
|
105
|
+
if response.status_code >= 400:
|
106
|
+
raise HTTPError(response.status_code, response.text)
|
107
|
+
return response
|
108
|
+
return response
|
blaxel/serve/app.py
ADDED
@@ -0,0 +1,131 @@
|
|
1
|
+
"""Module: app
|
2
|
+
|
3
|
+
This module sets up and runs the Blaxel server using FastAPI.
|
4
|
+
It configures middleware, handles server lifespan events, and defines endpoints.
|
5
|
+
"""
|
6
|
+
|
7
|
+
import asyncio
|
8
|
+
import importlib
|
9
|
+
import inspect
|
10
|
+
import os
|
11
|
+
import sys
|
12
|
+
import traceback
|
13
|
+
from contextlib import asynccontextmanager
|
14
|
+
from logging import getLogger
|
15
|
+
from uuid import uuid4
|
16
|
+
|
17
|
+
from asgi_correlation_id import CorrelationIdMiddleware
|
18
|
+
from fastapi import FastAPI, Request, Response, WebSocket
|
19
|
+
from fastapi.responses import JSONResponse
|
20
|
+
|
21
|
+
from blaxel.aimon import HTTPError, get_settings, init
|
22
|
+
from blaxel.aimon.instrumentation import instrument_app, shutdown_instrumentation
|
23
|
+
|
24
|
+
from .middlewares import AccessLogMiddleware, AddProcessTimeHeader
|
25
|
+
|
26
|
+
sys.path.insert(0, os.getcwd())
|
27
|
+
sys.path.insert(0, os.path.join(os.getcwd(), "src"))
|
28
|
+
|
29
|
+
|
30
|
+
def import_module():
|
31
|
+
"""Dynamically imports the main server module based on settings.
|
32
|
+
|
33
|
+
Returns:
|
34
|
+
Callable: The main function to run the server.
|
35
|
+
"""
|
36
|
+
settings = get_settings()
|
37
|
+
main_module = importlib.import_module(".".join(settings.server.module.split(".")[0:-1]))
|
38
|
+
func = getattr(main_module, settings.server.module.split(".")[-1])
|
39
|
+
return func
|
40
|
+
|
41
|
+
|
42
|
+
settings = init()
|
43
|
+
logger = getLogger(__name__)
|
44
|
+
logger.info(f"Importing server module: {settings.server.module}")
|
45
|
+
func = import_module()
|
46
|
+
logger.info(
|
47
|
+
f"Running server"
|
48
|
+
f" on {settings.server.host}:{settings.server.port}"
|
49
|
+
)
|
50
|
+
func_params = inspect.signature(func).parameters
|
51
|
+
websocket_detected = False
|
52
|
+
if "websocket" in func_params:
|
53
|
+
websocket_detected = True
|
54
|
+
|
55
|
+
@asynccontextmanager
|
56
|
+
async def lifespan(app: FastAPI):
|
57
|
+
"""Manages the lifespan events of the FastAPI application.
|
58
|
+
|
59
|
+
Args:
|
60
|
+
app (FastAPI): The FastAPI application instance.
|
61
|
+
"""
|
62
|
+
yield
|
63
|
+
shutdown_instrumentation()
|
64
|
+
|
65
|
+
|
66
|
+
app = FastAPI(docs_url=None, redoc_url=None, lifespan=lifespan)
|
67
|
+
app.add_middleware(
|
68
|
+
CorrelationIdMiddleware,
|
69
|
+
header_name="x-blaxel-request-id",
|
70
|
+
generator=lambda: str(uuid4()),
|
71
|
+
)
|
72
|
+
app.add_middleware(AddProcessTimeHeader)
|
73
|
+
app.add_middleware(AccessLogMiddleware)
|
74
|
+
instrument_app(app)
|
75
|
+
|
76
|
+
@app.get("/health")
|
77
|
+
async def health():
|
78
|
+
"""Health check endpoint.
|
79
|
+
|
80
|
+
Returns:
|
81
|
+
dict: A simple status message indicating the server is running.
|
82
|
+
"""
|
83
|
+
return {"status": "ok"}
|
84
|
+
|
85
|
+
if websocket_detected:
|
86
|
+
@app.websocket("/ws")
|
87
|
+
async def websocket_endpoint(websocket: WebSocket):
|
88
|
+
await websocket.accept()
|
89
|
+
|
90
|
+
original_func = getattr(func, "__wrapped__", func)
|
91
|
+
if asyncio.iscoroutinefunction(func) or asyncio.iscoroutinefunction(original_func):
|
92
|
+
await func(websocket)
|
93
|
+
else:
|
94
|
+
func(websocket)
|
95
|
+
|
96
|
+
else:
|
97
|
+
@app.post("/")
|
98
|
+
async def root(request: Request):
|
99
|
+
logger = getLogger(__name__)
|
100
|
+
try:
|
101
|
+
original_func = getattr(func, "__wrapped__", func)
|
102
|
+
if asyncio.iscoroutinefunction(func) or asyncio.iscoroutinefunction(original_func):
|
103
|
+
response = await func(request)
|
104
|
+
else:
|
105
|
+
response = func(request)
|
106
|
+
|
107
|
+
if isinstance(response, Response):
|
108
|
+
return response
|
109
|
+
if type(response) is str:
|
110
|
+
return Response(
|
111
|
+
content=response,
|
112
|
+
headers={"Content-Type": "text/plain"},
|
113
|
+
media_type="text/plain",
|
114
|
+
status_code=200,
|
115
|
+
)
|
116
|
+
return JSONResponse(status_code=200, content=response)
|
117
|
+
except ValueError as e:
|
118
|
+
content = {"error": str(e)}
|
119
|
+
content["traceback"] = str(traceback.format_exc())
|
120
|
+
logger.error(str(traceback.format_exc()))
|
121
|
+
return JSONResponse(status_code=400, content=content)
|
122
|
+
except HTTPError as e:
|
123
|
+
content = {"error": e.message, "status_code": e.status_code}
|
124
|
+
content["traceback"] = str(traceback.format_exc())
|
125
|
+
logger.error(f"{e.status_code} {str(traceback.format_exc())}")
|
126
|
+
return JSONResponse(status_code=e.status_code, content=content)
|
127
|
+
except Exception as e:
|
128
|
+
content = {"error": f"Internal server error, {e}"}
|
129
|
+
content["traceback"] = str(traceback.format_exc())
|
130
|
+
logger.error(str(traceback.format_exc()))
|
131
|
+
return JSONResponse(status_code=500, content=content)
|
@@ -0,0 +1,10 @@
|
|
1
|
+
"""Package: middlewares
|
2
|
+
|
3
|
+
This package contains custom middleware classes for the Blaxel server,
|
4
|
+
including access logging and process time header addition.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from .accesslog import AccessLogMiddleware
|
8
|
+
from .processtime import AddProcessTimeHeader
|
9
|
+
|
10
|
+
__all__ = ["AccessLogMiddleware", "AddProcessTimeHeader"]
|
@@ -0,0 +1,32 @@
|
|
1
|
+
"""Module: accesslog
|
2
|
+
|
3
|
+
Defines the AccessLogMiddleware for logging HTTP requests and responses.
|
4
|
+
"""
|
5
|
+
|
6
|
+
from logging import getLogger
|
7
|
+
|
8
|
+
from starlette.middleware.base import BaseHTTPMiddleware
|
9
|
+
|
10
|
+
|
11
|
+
class AccessLogMiddleware(BaseHTTPMiddleware):
|
12
|
+
"""Middleware for logging access information of each HTTP request."""
|
13
|
+
|
14
|
+
async def dispatch(self, request, call_next):
|
15
|
+
"""Processes each request to log access details.
|
16
|
+
|
17
|
+
Args:
|
18
|
+
request (Request): The incoming HTTP request.
|
19
|
+
call_next (Callable): The next middleware or endpoint handler.
|
20
|
+
|
21
|
+
Returns:
|
22
|
+
Response: The HTTP response generated by the next handler.
|
23
|
+
"""
|
24
|
+
logger = getLogger(__name__)
|
25
|
+
response = await call_next(request)
|
26
|
+
process_time = response.headers.get("X-Process-Time")
|
27
|
+
rid_header = response.headers.get("X-Request-Id")
|
28
|
+
request_id = rid_header or response.headers.get("X-Blaxel-Request-Id")
|
29
|
+
logger.info(
|
30
|
+
f"{request.method} {request.url.path} {response.status_code} {process_time}ms rid={request_id}"
|
31
|
+
)
|
32
|
+
return response
|