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.
Files changed (261) hide show
  1. blaxel/__init__.py +8 -0
  2. blaxel/agents/__init__.py +5 -0
  3. blaxel/agents/chain.py +153 -0
  4. blaxel/agents/chat.py +286 -0
  5. blaxel/agents/decorator.py +208 -0
  6. blaxel/agents/thread.py +24 -0
  7. blaxel/agents/voice/openai.py +255 -0
  8. blaxel/agents/voice/utils.py +25 -0
  9. blaxel/api/__init__.py +1 -0
  10. blaxel/api/agents/__init__.py +0 -0
  11. blaxel/api/agents/create_agent.py +155 -0
  12. blaxel/api/agents/delete_agent.py +146 -0
  13. blaxel/api/agents/get_agent.py +146 -0
  14. blaxel/api/agents/get_agent_logs.py +151 -0
  15. blaxel/api/agents/get_agent_metrics.py +150 -0
  16. blaxel/api/agents/get_agent_trace_ids.py +201 -0
  17. blaxel/api/agents/list_agent_revisions.py +155 -0
  18. blaxel/api/agents/list_agents.py +127 -0
  19. blaxel/api/agents/update_agent.py +168 -0
  20. blaxel/api/configurations/__init__.py +0 -0
  21. blaxel/api/configurations/get_configuration.py +122 -0
  22. blaxel/api/default/__init__.py +0 -0
  23. blaxel/api/default/get_trace.py +150 -0
  24. blaxel/api/default/get_trace_ids.py +218 -0
  25. blaxel/api/default/get_trace_logs.py +186 -0
  26. blaxel/api/default/list_mcp_hub_definitions.py +127 -0
  27. blaxel/api/functions/__init__.py +0 -0
  28. blaxel/api/functions/create_function.py +155 -0
  29. blaxel/api/functions/delete_function.py +146 -0
  30. blaxel/api/functions/get_function.py +146 -0
  31. blaxel/api/functions/get_function_logs.py +151 -0
  32. blaxel/api/functions/get_function_metrics.py +150 -0
  33. blaxel/api/functions/get_function_trace_ids.py +201 -0
  34. blaxel/api/functions/list_function_revisions.py +158 -0
  35. blaxel/api/functions/list_functions.py +131 -0
  36. blaxel/api/functions/update_function.py +168 -0
  37. blaxel/api/integrations/__init__.py +0 -0
  38. blaxel/api/integrations/create_integration_connection.py +167 -0
  39. blaxel/api/integrations/delete_integration_connection.py +158 -0
  40. blaxel/api/integrations/get_integration.py +97 -0
  41. blaxel/api/integrations/get_integration_connection.py +158 -0
  42. blaxel/api/integrations/get_integration_connection_model.py +104 -0
  43. blaxel/api/integrations/get_integration_connection_model_endpoint_configurations.py +97 -0
  44. blaxel/api/integrations/list_integration_connection_models.py +97 -0
  45. blaxel/api/integrations/list_integration_connections.py +139 -0
  46. blaxel/api/integrations/update_integration_connection.py +180 -0
  47. blaxel/api/invitations/__init__.py +0 -0
  48. blaxel/api/invitations/list_all_pending_invitations.py +142 -0
  49. blaxel/api/knowledgebases/__init__.py +0 -0
  50. blaxel/api/knowledgebases/create_knowledgebase.py +163 -0
  51. blaxel/api/knowledgebases/delete_knowledgebase.py +154 -0
  52. blaxel/api/knowledgebases/get_knowledgebase.py +154 -0
  53. blaxel/api/knowledgebases/list_knowledgebase_revisions.py +158 -0
  54. blaxel/api/knowledgebases/list_knowledgebases.py +139 -0
  55. blaxel/api/knowledgebases/update_knowledgebase.py +176 -0
  56. blaxel/api/locations/__init__.py +0 -0
  57. blaxel/api/locations/list_locations.py +139 -0
  58. blaxel/api/metrics/__init__.py +0 -0
  59. blaxel/api/metrics/get_metrics.py +130 -0
  60. blaxel/api/models/__init__.py +0 -0
  61. blaxel/api/models/create_model.py +163 -0
  62. blaxel/api/models/delete_model.py +154 -0
  63. blaxel/api/models/get_model.py +154 -0
  64. blaxel/api/models/get_model_logs.py +155 -0
  65. blaxel/api/models/get_model_metrics.py +158 -0
  66. blaxel/api/models/get_model_trace_ids.py +201 -0
  67. blaxel/api/models/list_model_revisions.py +158 -0
  68. blaxel/api/models/list_models.py +135 -0
  69. blaxel/api/models/update_model.py +176 -0
  70. blaxel/api/policies/__init__.py +0 -0
  71. blaxel/api/policies/create_policy.py +167 -0
  72. blaxel/api/policies/delete_policy.py +154 -0
  73. blaxel/api/policies/get_policy.py +154 -0
  74. blaxel/api/policies/list_policies.py +139 -0
  75. blaxel/api/policies/update_policy.py +180 -0
  76. blaxel/api/privateclusters/__init__.py +0 -0
  77. blaxel/api/privateclusters/create_private_cluster.py +132 -0
  78. blaxel/api/privateclusters/delete_private_cluster.py +156 -0
  79. blaxel/api/privateclusters/get_private_cluster.py +159 -0
  80. blaxel/api/privateclusters/get_private_cluster_health.py +97 -0
  81. blaxel/api/privateclusters/list_private_clusters.py +140 -0
  82. blaxel/api/privateclusters/update_private_cluster.py +156 -0
  83. blaxel/api/privateclusters/update_private_cluster_health.py +97 -0
  84. blaxel/api/service_accounts/__init__.py +0 -0
  85. blaxel/api/service_accounts/create_api_key_for_service_account.py +177 -0
  86. blaxel/api/service_accounts/create_workspace_service_account.py +170 -0
  87. blaxel/api/service_accounts/delete_api_key_for_service_account.py +104 -0
  88. blaxel/api/service_accounts/delete_workspace_service_account.py +160 -0
  89. blaxel/api/service_accounts/get_workspace_service_accounts.py +141 -0
  90. blaxel/api/service_accounts/list_api_keys_for_service_account.py +163 -0
  91. blaxel/api/service_accounts/update_workspace_service_account.py +183 -0
  92. blaxel/api/store/__init__.py +0 -0
  93. blaxel/api/store/get_store_agent.py +146 -0
  94. blaxel/api/store/get_store_function.py +146 -0
  95. blaxel/api/store/list_store_agents.py +131 -0
  96. blaxel/api/store/list_store_functions.py +131 -0
  97. blaxel/api/workspaces/__init__.py +0 -0
  98. blaxel/api/workspaces/accept_workspace_invitation.py +161 -0
  99. blaxel/api/workspaces/create_worspace.py +163 -0
  100. blaxel/api/workspaces/decline_workspace_invitation.py +158 -0
  101. blaxel/api/workspaces/delete_workspace.py +154 -0
  102. blaxel/api/workspaces/get_workspace.py +154 -0
  103. blaxel/api/workspaces/invite_workspace_user.py +174 -0
  104. blaxel/api/workspaces/leave_workspace.py +161 -0
  105. blaxel/api/workspaces/list_workspace_users.py +139 -0
  106. blaxel/api/workspaces/list_workspaces.py +139 -0
  107. blaxel/api/workspaces/remove_workspace_user.py +101 -0
  108. blaxel/api/workspaces/update_workspace.py +176 -0
  109. blaxel/api/workspaces/update_workspace_user_role.py +187 -0
  110. blaxel/authentication/__init__.py +45 -0
  111. blaxel/authentication/apikey.py +50 -0
  112. blaxel/authentication/authentication.py +176 -0
  113. blaxel/authentication/clientcredentials.py +103 -0
  114. blaxel/authentication/credentials.py +295 -0
  115. blaxel/authentication/device_mode.py +197 -0
  116. blaxel/client.py +281 -0
  117. blaxel/common/__init__.py +17 -0
  118. blaxel/common/error.py +27 -0
  119. blaxel/common/instrumentation.py +317 -0
  120. blaxel/common/logger.py +60 -0
  121. blaxel/common/secrets.py +39 -0
  122. blaxel/common/settings.py +150 -0
  123. blaxel/common/slugify.py +18 -0
  124. blaxel/common/utils.py +34 -0
  125. blaxel/deploy/__init__.py +8 -0
  126. blaxel/deploy/deploy.py +316 -0
  127. blaxel/deploy/format.py +46 -0
  128. blaxel/deploy/parser.py +192 -0
  129. blaxel/errors.py +16 -0
  130. blaxel/functions/__init__.py +7 -0
  131. blaxel/functions/common.py +228 -0
  132. blaxel/functions/decorator.py +64 -0
  133. blaxel/functions/local/local.py +48 -0
  134. blaxel/functions/mcp/client.py +96 -0
  135. blaxel/functions/mcp/mcp.py +168 -0
  136. blaxel/functions/mcp/utils.py +56 -0
  137. blaxel/functions/remote/remote.py +183 -0
  138. blaxel/models/__init__.py +233 -0
  139. blaxel/models/acl.py +133 -0
  140. blaxel/models/agent.py +126 -0
  141. blaxel/models/agent_chain.py +88 -0
  142. blaxel/models/agent_spec.py +346 -0
  143. blaxel/models/api_key.py +142 -0
  144. blaxel/models/configuration.py +85 -0
  145. blaxel/models/continent.py +70 -0
  146. blaxel/models/core_event.py +97 -0
  147. blaxel/models/core_spec.py +249 -0
  148. blaxel/models/core_spec_configurations.py +77 -0
  149. blaxel/models/country.py +70 -0
  150. blaxel/models/create_api_key_for_service_account_body.py +69 -0
  151. blaxel/models/create_workspace_service_account_body.py +71 -0
  152. blaxel/models/create_workspace_service_account_response_200.py +105 -0
  153. blaxel/models/delete_workspace_service_account_response_200.py +96 -0
  154. blaxel/models/entrypoint.py +96 -0
  155. blaxel/models/entrypoint_env.py +45 -0
  156. blaxel/models/flavor.py +70 -0
  157. blaxel/models/form.py +120 -0
  158. blaxel/models/form_config.py +45 -0
  159. blaxel/models/form_oauthomitempty.py +45 -0
  160. blaxel/models/form_secrets.py +45 -0
  161. blaxel/models/function.py +126 -0
  162. blaxel/models/function_kit.py +97 -0
  163. blaxel/models/function_spec.py +310 -0
  164. blaxel/models/get_trace_ids_response_200.py +45 -0
  165. blaxel/models/get_trace_logs_response_200.py +45 -0
  166. blaxel/models/get_trace_response_200.py +45 -0
  167. blaxel/models/get_workspace_service_accounts_response_200_item.py +96 -0
  168. blaxel/models/histogram_bucket.py +79 -0
  169. blaxel/models/histogram_stats.py +88 -0
  170. blaxel/models/integration_connection.py +96 -0
  171. blaxel/models/integration_connection_spec.py +114 -0
  172. blaxel/models/integration_connection_spec_config.py +45 -0
  173. blaxel/models/integration_connection_spec_secret.py +45 -0
  174. blaxel/models/integration_model.py +162 -0
  175. blaxel/models/integration_repository.py +88 -0
  176. blaxel/models/invite_workspace_user_body.py +60 -0
  177. blaxel/models/knowledgebase.py +126 -0
  178. blaxel/models/knowledgebase_spec.py +163 -0
  179. blaxel/models/knowledgebase_spec_options.py +45 -0
  180. blaxel/models/last_n_requests_metric.py +79 -0
  181. blaxel/models/latency_metric.py +144 -0
  182. blaxel/models/location_response.py +113 -0
  183. blaxel/models/mcp_definition.py +188 -0
  184. blaxel/models/mcp_definition_entrypoint.py +45 -0
  185. blaxel/models/mcp_definition_form.py +45 -0
  186. blaxel/models/metadata.py +139 -0
  187. blaxel/models/metadata_labels.py +45 -0
  188. blaxel/models/metric.py +79 -0
  189. blaxel/models/metrics.py +169 -0
  190. blaxel/models/metrics_models.py +45 -0
  191. blaxel/models/metrics_request_total_per_code.py +45 -0
  192. blaxel/models/metrics_rps_per_code.py +45 -0
  193. blaxel/models/model.py +126 -0
  194. blaxel/models/model_private_cluster.py +79 -0
  195. blaxel/models/model_spec.py +249 -0
  196. blaxel/models/o_auth.py +72 -0
  197. blaxel/models/owner_fields.py +70 -0
  198. blaxel/models/pending_invitation.py +124 -0
  199. blaxel/models/pending_invitation_accept.py +85 -0
  200. blaxel/models/pending_invitation_render.py +147 -0
  201. blaxel/models/pending_invitation_render_invited_by.py +88 -0
  202. blaxel/models/pending_invitation_render_workspace.py +70 -0
  203. blaxel/models/pending_invitation_workspace_details.py +72 -0
  204. blaxel/models/pod_template_spec.py +45 -0
  205. blaxel/models/policy.py +96 -0
  206. blaxel/models/policy_location.py +70 -0
  207. blaxel/models/policy_max_tokens.py +106 -0
  208. blaxel/models/policy_spec.py +151 -0
  209. blaxel/models/private_cluster.py +183 -0
  210. blaxel/models/private_location.py +61 -0
  211. blaxel/models/repository.py +70 -0
  212. blaxel/models/request_duration_over_time_metric.py +97 -0
  213. blaxel/models/request_duration_over_time_metrics.py +80 -0
  214. blaxel/models/request_total_by_origin_metric.py +115 -0
  215. blaxel/models/request_total_by_origin_metric_request_total_by_origin.py +45 -0
  216. blaxel/models/request_total_by_origin_metric_request_total_by_origin_and_code.py +45 -0
  217. blaxel/models/request_total_metric.py +123 -0
  218. blaxel/models/request_total_metric_request_total_per_code.py +45 -0
  219. blaxel/models/request_total_metric_rps_per_code.py +45 -0
  220. blaxel/models/resource_log.py +79 -0
  221. blaxel/models/resource_metrics.py +270 -0
  222. blaxel/models/resource_metrics_request_total_per_code.py +45 -0
  223. blaxel/models/resource_metrics_rps_per_code.py +45 -0
  224. blaxel/models/revision_configuration.py +97 -0
  225. blaxel/models/revision_metadata.py +124 -0
  226. blaxel/models/runtime.py +196 -0
  227. blaxel/models/runtime_startup_probe.py +45 -0
  228. blaxel/models/serverless_config.py +80 -0
  229. blaxel/models/spec_configuration.py +70 -0
  230. blaxel/models/store_agent.py +178 -0
  231. blaxel/models/store_agent_labels.py +45 -0
  232. blaxel/models/store_configuration.py +151 -0
  233. blaxel/models/store_configuration_option.py +79 -0
  234. blaxel/models/store_function.py +211 -0
  235. blaxel/models/store_function_kit.py +97 -0
  236. blaxel/models/store_function_labels.py +45 -0
  237. blaxel/models/store_function_parameter.py +88 -0
  238. blaxel/models/time_fields.py +70 -0
  239. blaxel/models/token_rate_metric.py +88 -0
  240. blaxel/models/token_rate_metrics.py +120 -0
  241. blaxel/models/token_total_metric.py +106 -0
  242. blaxel/models/trace_ids_response.py +45 -0
  243. blaxel/models/update_workspace_service_account_body.py +69 -0
  244. blaxel/models/update_workspace_service_account_response_200.py +96 -0
  245. blaxel/models/update_workspace_user_role_body.py +60 -0
  246. blaxel/models/websocket_channel.py +88 -0
  247. blaxel/models/workspace.py +148 -0
  248. blaxel/models/workspace_labels.py +45 -0
  249. blaxel/models/workspace_user.py +115 -0
  250. blaxel/py.typed +1 -0
  251. blaxel/run.py +108 -0
  252. blaxel/serve/app.py +131 -0
  253. blaxel/serve/middlewares/__init__.py +10 -0
  254. blaxel/serve/middlewares/accesslog.py +32 -0
  255. blaxel/serve/middlewares/processtime.py +28 -0
  256. blaxel/types.py +46 -0
  257. blaxel-0.64.0.dist-info/METADATA +96 -0
  258. blaxel-0.64.0.dist-info/RECORD +261 -0
  259. blaxel-0.64.0.dist-info/WHEEL +4 -0
  260. blaxel-0.64.0.dist-info/entry_points.txt +2 -0
  261. 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